Skip to content

Commit

Permalink
Improve the error package
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Nov 25, 2023
1 parent dc7ca84 commit a51eb6d
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 65 deletions.
46 changes: 25 additions & 21 deletions src/Error/Cloak.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
use Closure;
use ErrorException;

use function error_reporting;
use function set_error_handler;
use function restore_error_handler;

use const E_ALL;
use const E_DEPRECATED;
use const E_NOTICE;
Expand All @@ -19,7 +23,7 @@
class Cloak
{
public const FOLLOW_ENV = 0;
public const BE_SILENT = 1;
public const SILENT = 1;
public const THROW = 2;

protected static bool $useException = false;
Expand All @@ -44,7 +48,7 @@ public static function throwOnError(): void
self::$useException = true;
}

public static function silenceError(): void
public static function silentOnError(): void
{
self::$useException = false;
}
Expand Down Expand Up @@ -122,7 +126,7 @@ public function __invoke(mixed ...$arguments): mixed
throw $this->exception;
}

if (self::BE_SILENT === $this->onError) {
if (self::SILENT === $this->onError) {
return $result;
}

Expand All @@ -146,50 +150,50 @@ public function errorsAreSilenced(): bool
public function errorsAreThrown(): bool
{
return self::THROW === $this->onError
|| (self::BE_SILENT !== $this->onError && true === self::$useException);
|| (self::SILENT !== $this->onError && true === self::$useException);
}

public function suppressAll(): bool
public function includeAll(): bool
{
return $this->suppress(E_ALL);
return $this->include(E_ALL);
}

public function suppressWarning(): bool
public function includeWarning(): bool
{
return $this->suppress(E_WARNING);
return $this->include(E_WARNING);
}

public function suppressNotice(): bool
public function includeNotice(): bool
{
return $this->suppress(E_NOTICE);
return $this->include(E_NOTICE);
}

public function suppressDeprecated(): bool
public function includeDeprecated(): bool
{
return $this->suppress(E_DEPRECATED);
return $this->include(E_DEPRECATED);
}

public function suppressStrict(): bool
public function includeStrict(): bool
{
return $this->suppress(E_STRICT);
return $this->include(E_STRICT);
}

public function suppressUserWarning(): bool
public function includeUserWarning(): bool
{
return $this->suppress(E_USER_WARNING);
return $this->include(E_USER_WARNING);
}

public function suppressUserNotice(): bool
public function includeUserNotice(): bool
{
return $this->suppress(E_USER_NOTICE);
return $this->include(E_USER_NOTICE);
}

public function suppressUserDeprecated(): bool
public function includeUserDeprecated(): bool
{
return $this->suppress(E_USER_DEPRECATED);
return $this->include(E_USER_DEPRECATED);
}

public function suppress(ErrorLevel|int $errorLevel): bool
public function include(ErrorLevel|int $errorLevel): bool
{
return $this->errorLevel->contains($errorLevel);
}
Expand Down
28 changes: 14 additions & 14 deletions src/Error/CloakTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ protected function setUp(): void
{
parent::setUp();

Cloak::silenceError();
Cloak::silentOnError();
}

#[Test]
Expand All @@ -29,13 +29,13 @@ public function it_returns_information_about_its_error_reporting_level(): void
$res = $lambda('/foo');

self::assertFalse($res);
self::assertTrue($lambda->suppressWarning());
self::assertFalse($lambda->suppressNotice());
self::assertTrue($lambda->includeWarning());
self::assertFalse($lambda->includeNotice());
self::assertInstanceOf(ErrorException::class, $lambda->lastError());
}

#[Test]
public function it_will_suppress_nothing_in_case_of_success(): void
public function it_will_include_nothing_in_case_of_success(): void
{
$lambda = Cloak::userWarning(strtoupper(...));
$res = $lambda('foo');
Expand All @@ -48,7 +48,7 @@ public function testGetErrorReporting(): void
{
$lambda = Cloak::deprecated(strtoupper(...));

self::assertTrue($lambda->suppressDeprecated());
self::assertTrue($lambda->includeDeprecated());
}

public function testCapturesTriggeredError(): void
Expand Down Expand Up @@ -89,7 +89,7 @@ public function testSpecificBehaviourOverrideGeneralErrorSetting(): void
{
Cloak::throwOnError();

$touch = Cloak::all(touch(...), Cloak::BE_SILENT);
$touch = Cloak::all(touch(...), Cloak::SILENT);
$touch('/foo');

self::assertInstanceOf(ErrorException::class, $touch->lastError());
Expand All @@ -104,21 +104,21 @@ public function testCaptureNothingThrowNoException(): void
}

#[Test]
public function it_can_detect_the_level_to_suppress(): void
public function it_can_detect_the_level_to_include(): void
{
$touch = new Cloak(
touch(...),
E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED,
Cloak::THROW
);

self::assertTrue($touch->suppressAll());
self::assertFalse($touch->suppressStrict());
self::assertFalse($touch->suppressDeprecated());
self::assertFalse($touch->suppressNotice());
self::assertTrue($touch->suppressUserNotice());
self::assertTrue($touch->suppressUserDeprecated());
self::assertTrue($touch->suppressUserWarning());
self::assertTrue($touch->includeAll());
self::assertFalse($touch->includeStrict());
self::assertFalse($touch->includeDeprecated());
self::assertFalse($touch->includeNotice());
self::assertTrue($touch->includeUserNotice());
self::assertTrue($touch->includeUserDeprecated());
self::assertTrue($touch->includeUserWarning());
self::assertTrue($touch->errorsAreThrown());
self::assertFalse($touch->errorsAreSilenced());
}
Expand Down
38 changes: 26 additions & 12 deletions src/Error/ErrorLevel.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@

use OutOfBoundsException;

use ValueError;

use function array_filter;
use function array_map;
use function error_reporting;
use function in_array;

use const E_ALL;
use const E_COMPILE_ERROR;
use const E_COMPILE_WARNING;
Expand All @@ -22,9 +29,9 @@
use const E_USER_WARNING;
use const E_WARNING;

final class ErrorLevel
class ErrorLevel
{
private const LEVELS = [
protected const LEVELS = [
-1,
0,
E_ERROR,
Expand All @@ -45,8 +52,11 @@ final class ErrorLevel
E_USER_DEPRECATED,
];

private function __construct(private readonly int $value)
private function __construct(protected readonly int $value)
{
if ($this->value < -1) {
throw new ValueError('The value `'.$this->value.'` is invalid as a error reporting level in PHP.');
}
}

public static function new(int $bytes = 0): self
Expand All @@ -67,21 +77,25 @@ public function toBytes(): int
return $this->value;
}

public function contains(self|int $level): bool
public function contains(self|int ...$levels): bool
{
$level = $level instanceof self ? $level->toBytes() : $level;
foreach ($levels as $level) {
$level = $level instanceof self ? $level->toBytes() : $level;
if (0 !== ($level & $this->toBytes())) {
return true;
}
}

return 0 !== ($level & $this->toBytes());
return false;
}

public function include(self|int|null ...$levels): self
public function include(self|int ...$levels): self
{
$levels = array_map(fn (self|int|null $level) => match (true) {
$levels = array_map(fn (self|int $level) => match (true) {
$level instanceof self => $level->value,
default => $level,
}, $levels);

$levels = array_filter($levels, fn (?int $level) => null !== $level);
if ([] === $levels) {
return $this;
}
Expand All @@ -106,9 +120,9 @@ public function include(self|int|null ...$levels): self
return self::new($value);
}

public function ignore(self|int|null ...$levels): self
public function ignore(self|int ...$levels): self
{
$levels = array_map(fn (self|int|null $level) => match (true) {
$levels = array_map(fn (self|int $level) => match (true) {
$level instanceof self => $level->value,
default => $level,
}, $levels);
Expand All @@ -117,7 +131,7 @@ public function ignore(self|int|null ...$levels): self
return self::new(0);
}

$levels = array_filter($levels, fn (int|null $level) => null !== $level && 0 !== $level && $this->value !== $level);
$levels = array_filter($levels, fn (int $level) => 0 !== $level && $this->value !== $level);
if ([] === $levels) {
return $this;
}
Expand Down
36 changes: 18 additions & 18 deletions src/Error/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ use Bakame\Aide\Error\Cloak;

Cloak::throwOnError(); // by default calls via Cloack should throw

if (!$touch = Cloak::warning(touch(...), Cloak::BE_SILENT)) {
if (!$touch = Cloak::warning(touch(...), Cloak::SILENT)) {
//the error is still available via `lastError`
// but no throwing will happen
$touch->lastError();
Expand All @@ -91,7 +91,7 @@ specific error will be suppressed you can do the following:

```php
$touch = Cloak::all(touch(...));
$touch->suppressWarning(); //tells if the E_WARNING is suppressed or not
$touch->includeWarning(); //tells if the E_WARNING is included or not
```

The following methods are available.
Expand All @@ -100,14 +100,14 @@ The following methods are available.
<?php
use Bakame\Aide\Error\Cloak;

Cloak::suppressAll();
Cloak::suppressWarning();
Cloak::suppressNotice();
Cloak::suppressDeprecated();
Cloak::suppressStrict();
Cloak::suppressUserWarning();
Cloak::suppressUserNotice();
Cloak::suppressUserDeprecated();
Cloak::includeAll();
Cloak::includeWarning();
Cloak::includeNotice();
Cloak::includeDeprecated();
Cloak::includeStrict();
Cloak::includeUserWarning();
Cloak::includeUserNotice();
Cloak::includeUserDeprecated();
```

### Accessing the error
Expand All @@ -122,10 +122,10 @@ last error.
The class general behaviour is controlled by two (2) static method:

- `Cloak::throwOnError`: every instance of `Cloak` will throw on error;
- `Cloak::silenceError`: every instance of `Cloak` will record the error but won't throw it;
- `Cloak::silentOnError`: every instance of `Cloak` will record the error but won't throw it;

> [!NOTE]
> to respect PHP's default behaviour by default `Cloak` uses `Cloak::silenceError`
> to respect PHP's default behaviour by default `Cloak` uses `Cloak::silentOnError`
### Named constructors

Expand Down Expand Up @@ -154,9 +154,9 @@ static method(Closure $closure, int $behaviour = Cloak::FORCE_NOTHING);

the `$behaviour` argument is used to tweak the instance behaviour on error:

- `Cloak::THROW_ON_ERROR` will override the general behaviour and force throwing an exception if available
- `Cloak::SILENCE_ERROR` will override the general behaviour and silence the error if it exists
- `Cloak::FORCE_NOTHING` will comply with the general behaviour.
- `Cloak::THROW` will override the general behaviour and force throwing an exception if available
- `Cloak::SILENT` will override the general behaviour and silence the error if it exists
- `Cloak::FOLLOW_ENV` will comply with the general behaviour.

If you really need other fined grained error level you can still use the constructor
as shown below:
Expand All @@ -172,7 +172,7 @@ $touch = new Cloak(
);
```

Tthe code above can be rewritten using the `ErrorLevel` class which ship with the package:
The code above can be rewritten using the `ErrorLevel` class which ships with the package:

```php
<?php
Expand All @@ -185,15 +185,15 @@ use Bakame\Aide\Error\ErrorLevel;
$touch = new Cloak(touch(...), $errorLevel, Cloak::THROW);
```

The class contains five (methods) to ease working with error level:
The class contains five (5) methods to ease working with error reporting level:

`ErrorLevel::new` allow instantiating the class with any value you want. Alternatively, you can
instantiate the class to match your current environment settings using `ErrorLevel::fromEnvironment`.

To ignore or include error reporting level just use the `include` or `exclude` nethods which returns a
new object on each different value given.

Last but not least you can tell which error reporting is being configured using the `contain` method.
Last but not least you can tell which error reporting is being configured using the `contains` method.

```php
<?php
Expand Down

0 comments on commit a51eb6d

Please sign in to comment.