diff --git a/src/Error/Cloak.php b/src/Error/Cloak.php index 3fb53ef..9495511 100644 --- a/src/Error/Cloak.php +++ b/src/Error/Cloak.php @@ -6,10 +6,8 @@ use Closure; use ErrorException; - use ValueError; -use function error_reporting; use function restore_error_handler; use function set_error_handler; @@ -21,8 +19,8 @@ class Cloak protected static bool $useException = false; - protected CloakedErrors $errors; protected readonly ErrorLevel $errorLevel; + protected CloakedErrors $errors; /** * @throws ValueError @@ -96,24 +94,25 @@ public static function all(Closure $closure, int $onError = self::FOLLOW_ENV): s return new self($closure, $onError, 'E_ALL'); } + protected function errorHandler(int $errno, string $errstr, string $errfile, int $errline): bool + { + if (ErrorLevel::fromEnvironment()->doesNotContain($errno)) { + return false; + } + + $this->errors->unshift(new ErrorException($errstr, 0, $errno, $errfile, $errline)); + + return true; + } + /** * @throws CloakedErrors */ public function __invoke(mixed ...$arguments): mixed { $this->errors = new CloakedErrors(); - $errorHandler = function (int $errno, string $errstr, string $errfile, int $errline): bool { - if (0 === (error_reporting() & $errno)) { - return false; - } - - $this->errors->unshift(new ErrorException($errstr, 0, $errno, $errfile, $errline)); - - return true; - }; - try { - set_error_handler($errorHandler, $this->errorLevel->value()); + set_error_handler($this->errorHandler(...), $this->errorLevel->value()); $result = ($this->closure)(...$arguments); } finally { restore_error_handler(); diff --git a/src/Error/CloakedErrors.php b/src/Error/CloakedErrors.php index edf2e0e..7b0e7d2 100644 --- a/src/Error/CloakedErrors.php +++ b/src/Error/CloakedErrors.php @@ -17,13 +17,14 @@ */ final class CloakedErrors extends RuntimeException implements Countable, IteratorAggregate { - /** - * @param array $errors - */ - public function __construct( - private array $errors = [] - ) { + /** @var array */ + private array $errors; + + public function __construct(ErrorException ...$errors) + { parent::__construct(); + + $this->errors = $errors; } public function count(): int diff --git a/src/Error/ErrorLevel.php b/src/Error/ErrorLevel.php index cd72ee2..3800559 100644 --- a/src/Error/ErrorLevel.php +++ b/src/Error/ErrorLevel.php @@ -6,8 +6,8 @@ use ValueError; -use function array_key_exists; use function array_filter; +use function array_key_exists; use function array_map; use function array_reduce; use function array_search; @@ -60,11 +60,17 @@ protected function __construct(protected readonly int $value) } } + /** + * Returns a new instance by using the error reporting level value. + */ public static function fromValue(int $value): self { return new self($value); } + /** + * Returns a new instance by using the error reporting level constant name. + */ public static function fromName(string $name): self { /** @var int|false $errorLevel */ @@ -81,6 +87,9 @@ public static function fromEnvironment(): self return new self(error_reporting()); } + /** + * Returns a new instance by excluded error levels from E_ALL. + */ public static function fromExclusion(self|string|int ...$levels): self { return new self(array_reduce($levels, function (int $carry, self|string|int $level) { @@ -98,6 +107,9 @@ public static function fromExclusion(self|string|int ...$levels): self }, E_ALL)); } + /** + * Returns a new instance by adding error levels from the initial no error reporting level. + */ public static function fromInclusion(self|string|int ...$levels): self { return new self(array_reduce($levels, function (int $carry, self|string|int $level) { @@ -120,6 +132,11 @@ public function value(): int return $this->value; } + public function doesNotContain(self|string|int ...$levels): bool + { + return !$this->contains(...$levels); + } + public function contains(self|string|int ...$levels): bool { if ([] === $levels) { diff --git a/src/Error/README.md b/src/Error/README.md index dae3f7c..34fde38 100644 --- a/src/Error/README.md +++ b/src/Error/README.md @@ -195,12 +195,12 @@ The class contains five (5) methods to ease working with error reporting level: `ErrorLevel::fromValue` allow instantiating the class with any value you want. Alternatively, you can instantiate the class to match your current environment settings using `ErrorLevel::fromEnvironment`. -`ErrorLevel::fromInclusion` instantiate the error level by adding all the submitted values via a +`ErrorLevel::fromInclusion` instantiates the error level by adding all the submitted values via a bitwise `OR` operation starting at `0` meaning that no Error reporting level exists if none is added. -Conversely `ErrorLevel::fromExclusion` does the opposite, each value given will be remove from the +Conversely `ErrorLevel::fromExclusion` does the opposite, each value given will be removed from the maximum value `E_ALL`. -Last but not least you can tell which error reporting is being configured using the `contains` method. +You can tell which error reporting is being configured using the `contains` method. ```php contains(E_WARNING); // returns true if the current value in error_reporting contains `E_WARNING` // returns false otherwise. +``` + +The class also provides the `excluded` and `included` methods which returns the +error reporting level names. + +```php +value(); +ErrorLevel::fromEnvironment()->contains(E_WARNING); +// returns true if the current value in error_reporting contains `E_WARNING` +// returns false otherwise. + +$errorLevel = ErrorLevel::fromInclusion(E_NOTICE, "E_DEPRECATED"); + +$errorLevel->value(); // `value` returns the int value corresponding to the calculated error level. // the errorLevel calculated will ignore notice, and deprecated error. + +$errorLevel->excluded(); +// returns all the error reporting level name no present in the current error Level + +$errorLevel->included(); +// returns all the error reporting level name present in the current error Level +// ["E_NOTICE", "E_DEPRECATED"] ``` ## Credits