Browse Source

Fixes, working on documentation

main
Dustin Wilson 1 year ago
parent
commit
20cb2f4f36
  1. 93
      README.md
  2. 4
      composer.json
  3. 161
      composer.lock
  4. 9
      lib/Logger.php
  5. 2
      lib/Logger/StreamHandler.php
  6. 34
      tests/cases/TestStreamHandler.php

93
README.md

@ -4,6 +4,8 @@
[d]: https://www.php-fig.org/psr/psr-3/#13-context
[e]: https://www.php-fig.org/psr/psr-3/#11-basics
[f]: http://tools.ietf.org/html/rfc5424
[g]: https://code.mensbeam.com/MensBeam/Filesystem
[h]: https://code.mensbeam.com/MensBeam/Catcher
# Logger #
@ -21,6 +23,95 @@ This library attempts what we're calling an "opinionated" implementation of PSR-
4. Also in the first item of [section 1.3][d] it states categorically that implementors must not trigger a warning when errant data is in the `$context` array and treat it with _"as much lenience as possible"_. It then states in the following ittem that if an exception is present in the context data it *must* be in the `exception` key and that implementors *must* verify the `exception` key. This is contradictory. You can't verify the `exception` key without triggering an error or exception when it's wrong. The user should be notified they've made a mistake; it's bad design otherwise. Our solution to this problem is to remove errant throwables from `$context` and also trigger warnings when they're encountered. However, `Logger->$warnOnInvalidContextThrowables` is provided to make it easy to suppress the warnings if necessary.
## Requirements ##
* PHP 8.1 or newer with the following _optional_ extensions:
* ext-ctype
* ext-mbstring
### Note ###
This library uses [mensbeam/filesystem][g] which provides polyfills for `ext-ctype` and `ext-mbstring`. If you have these extensions installed the polyfills won't be used. However, they are still installed. If you don't want the polyfills needlessly installed you can add this to your project's `composer.json`:
```json
{
"require": {
"ext-ctype": "*",
"ext-mbstring": "*"
},
"provide": {
"symfony/polyfill-ctype": "*",
"symfony/polyfill-mbstring": "*"
}
}
```
## Installation ##
```bash
composer require mensbeam/logger
```
## Usage ##
To be continued...
This library works without any configuration, but it might not be quite how you think it would work by default:
```php
use MensBeam\Logger;
$logger = new Logger();
```
This will create a logger that outputs all debug, info, notice, and warning entries to `STDOUT` while any error, critical, alert, and emergency entries are output to `STDERR`. This seems like it would be a bizarre default since it causes duplicate output to the shell on errors. However, if you accompany it with an error handler like [`Catcher`][h] it suddenly makes sense:
```php
use MensBeam\{
Catcher,
Logger
};
use MensBeam\Catcher\PlainTextHandler;
$catcher = new Catcher(new PlainTextHandler([
'logger' => new Logger('log'),
'silent' => true
]));
```
Now, _Logger_ will take care of the printing. But, _Logger_ can do far more.
## Documentation ##
### MensBeam\Logger ###
```php
namespace MensBeam;
class Logger implements Psr\Log\LoggerInterface {
public bool $warnOnInvalidContextThrowables = true;
public function __construct(?string $channel = null, Handler ...$handlers);
public function getChannel(): ?string;
public function getHandlers(): array;
public function popHandler(): Handler;
public function pushHandler(Handler ...$handlers): void;
public function setHandlers(Handler ...$handlers): void;
public function setChannel(?string $value): void;
public function shiftHandler(): Handler;
public function unshiftHandler(Handler ...$handlers): void;
public function emergency(string|\Stringable $message, array $context = []): void;
public function alert(string|\Stringable $message, array $context = []): void;
public function critical(string|\Stringable $message, array $context = []): void;
public function error(string|\Stringable $message, array $context = []): void;
public function warning(string|\Stringable $message, array $context = []): void;
public function notice(string|\Stringable $message, array $context = []): void;
public function info(string|\Stringable $message, array $context = []): void;
public function debug(string|\Stringable $message, array $context = []): void;
public function log($level, string|\Stringable $message, array $context = []): void;
}
```
#### Properties ####
_warnOnInvalidContextThrowables_: When set to true Logger will trigger warnings when invalid `Throwable`s are in the `$context` array in the logging methods.

4
composer.json

@ -5,8 +5,7 @@
"require": {
"php": ">=8.1",
"psr/log": "^3.0",
"mensbeam/filesystem": "^1.0",
"nikic/php-parser": "^4.15"
"mensbeam/filesystem": "^1.0"
},
"license": "MIT",
"autoload": {
@ -27,7 +26,6 @@
],
"require-dev": {
"ext-pcov": "*",
"docopt/docopt": "^1.0",
"phpunit/phpunit": "^10.0",
"mikey179/vfsstream": "^1.6"
}

161
composer.lock

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3d02f5002c6b62190718aa8c70a8acd1",
"content-hash": "e0336fd838352efa362298a3b61d3379",
"packages": [
{
"name": "mensbeam/filesystem",
@ -54,62 +54,6 @@
},
"time": "2023-02-19T18:05:52+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.15.4",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
"reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
}
},
"autoload": {
"psr-4": {
"PhpParser\\": "lib/PhpParser"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov"
}
],
"description": "A PHP parser written in PHP",
"keywords": [
"parser",
"php"
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4"
},
"time": "2023-03-05T19:49:14+00:00"
},
{
"name": "psr/log",
"version": "3.0.0",
@ -327,53 +271,6 @@
}
],
"packages-dev": [
{
"name": "docopt/docopt",
"version": "1.0.5",
"source": {
"type": "git",
"url": "https://github.com/docopt/docopt.php.git",
"reference": "0e3db660cf2f2eb07a83253790b7d97cdb398826"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/docopt/docopt.php/zipball/0e3db660cf2f2eb07a83253790b7d97cdb398826",
"reference": "0e3db660cf2f2eb07a83253790b7d97cdb398826",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"autoload": {
"classmap": [
"src/docopt.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Blake Williams",
"email": "code@shabbyrobe.org",
"homepage": "http://docopt.org/",
"role": "Developer"
}
],
"description": "Port of Python's docopt for PHP >=5.3",
"homepage": "http://github.com/docopt/docopt.php",
"keywords": [
"cli",
"docs"
],
"support": {
"issues": "https://github.com/docopt/docopt.php/issues",
"source": "https://github.com/docopt/docopt.php/tree/1.0.5"
},
"time": "2023-03-22T12:31:48+00:00"
},
{
"name": "mikey179/vfsstream",
"version": "v1.6.11",
@ -484,6 +381,62 @@
],
"time": "2023-03-08T13:26:56+00:00"
},
{
"name": "nikic/php-parser",
"version": "v4.15.4",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
"reference": "6bb5176bc4af8bcb7d926f88718db9b96a2d4290",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=7.0"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
"phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
},
"bin": [
"bin/php-parse"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.9-dev"
}
},
"autoload": {
"psr-4": {
"PhpParser\\": "lib/PhpParser"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov"
}
],
"description": "A PHP parser written in PHP",
"keywords": [
"parser",
"php"
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.15.4"
},
"time": "2023-03-05T19:49:14+00:00"
},
{
"name": "phar-io/manifest",
"version": "2.0.3",

9
lib/Logger.php

@ -19,15 +19,6 @@ use Psr\Log\LoggerInterface;
class Logger implements LoggerInterface {
public const EMERGENCY = 0;
public const ALERT = 1;
public const CRITICAL = 2;
public const ERROR = 3;
public const WARNING = 4;
public const NOTICE = 5;
public const INFO = 6;
public const DEBUG = 7;
/**
* Flag that causes warnings to be triggered when invalid throwables are in the
* context array

2
lib/Logger/StreamHandler.php

@ -75,7 +75,7 @@ class StreamHandler extends Handler {
$this->urlScheme = $matches['scheme'] ?: 'file';
} else {
$type = gettype($value);
$type = ($type === 'object') ? $value::class : $value;
$type = ($type === 'object') ? $value::class : $type;
throw new InvalidArgumentException(sprintf('Argument #1 ($value) must be of type resource|string, %s given', $type));
}
}

34
tests/cases/TestStreamHandler.php

@ -11,6 +11,7 @@ use MensBeam\Logger,
org\bovigo\vfs\vfsStream;
use MensBeam\Logger\{
InvalidArgumentException,
IOException,
Level,
StreamHandler
};
@ -24,11 +25,6 @@ class TestStreamHandler extends \PHPUnit\Framework\TestCase {
$this->assertEquals(1, preg_match($regex, $closure()));
}
public function testFatalErrors(): void {
$this->expectException(InvalidArgumentException::class);
new StreamHandler(42);
}
public function testGetStream(): void {
$h = new StreamHandler('ook');
$this->assertSame(CWD . '/ook', $h->getStream());
@ -47,6 +43,17 @@ class TestStreamHandler extends \PHPUnit\Framework\TestCase {
fclose($s);
}
/** @dataProvider provideFatalErrorTests */
public function testFatalErrors(string $throwableClassName, int $code, string $message, \Closure $closure): void {
$this->expectException($throwableClassName);
$this->expectExceptionMessage($message);
if ($throwableClassName === Error::class) {
$this->expectExceptionCode($code);
}
$closure(new StreamHandler());
}
public static function provideResourceTypesTests(): iterable {
$iterable = [
@ -92,4 +99,21 @@ class TestStreamHandler extends \PHPUnit\Framework\TestCase {
yield $i;
}
}
public static function provideFatalErrorTests(): iterable {
$iterable = [
[
InvalidArgumentException::class,
0,
'Argument #1 ($value) must be of type resource|string, integer given',
function (StreamHandler $h): void {
new StreamHandler(42);
}
]
];
foreach ($iterable as $i) {
yield $i;
}
}
}
Loading…
Cancel
Save