diff --git a/.gitignore b/.gitignore index b4ba050..33ad00b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,3 @@ composer.lock Thumbs.db /phpunit.xml /.idea -/.vscode diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100755 index 0000000..73e6f14 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,21 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [{ + "label": "coding-standards", + "type": "shell", + "command": "./vendor/bin/ecs check", + "problemMatcher": [] + }, { + "label": "coding-standards-fix", + "type": "shell", + "command": "./vendor/bin/ecs check --fix", + "problemMatcher": [] + }, { + "label": "phpstan", + "type": "shell", + "command": "./vendor/bin/phpstan --memory-limit=1G analyze", + "problemMatcher": [] + }] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a2d092..0892a91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## v0.3.1 (2021-04-02) +* Updated for max PHPStan conformance + ## v0.3.0 (2021-03-18) * Implement PreparedTraceException from Glitch * Enabled PHP8 testing diff --git a/README.md b/README.md index a2ccf73..ff98248 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,23 @@ Exceptional aims to offer a radically enhanced Exception framework that decouples the _meaning_ of an Exception from the underlying _implementation_ functionality. +## Installation + +Install via Composer: + +```bash +composer require decodelabs/exceptional +``` + +### PHP version + +_Please note, the final v1 releases of all Decode Labs libraries will target **PHP8** or above._ + +Current support for earlier versions of PHP will be phased out in the coming months. + + +## Usage + Exceptional exceptions can be used to greatly simplify how you generate and throw errors in your code, especially if you are writing a shared library. Pass the name of your intended exception as a static call to the Exceptional base class and have a dynamic exception class created based on the most appropriate PHP Exception class along with a set of related interfaces for easier catching. diff --git a/phpstan.neon b/phpstan.neon index 231a2ac..16f0d34 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,5 +1,4 @@ parameters: paths: - src - level: 5 - inferPrivatePropertyTypeFromConstructor: true + level: max diff --git a/src/Exceptional.php b/src/Exceptional.php index a3e5aaa..a4ef6c9 100644 --- a/src/Exceptional.php +++ b/src/Exceptional.php @@ -24,6 +24,8 @@ private function __construct() /** * Description + * + * @param array $args */ public static function __callStatic(string $type, array $args): Exception { diff --git a/src/Exceptional/AutoLoader.php b/src/Exceptional/AutoLoader.php index 02a5889..be0ebe6 100644 --- a/src/Exceptional/AutoLoader.php +++ b/src/Exceptional/AutoLoader.php @@ -11,6 +11,9 @@ class AutoLoader { + /** + * @var bool + */ protected static $registered = false; /** diff --git a/src/Exceptional/Exception.php b/src/Exceptional/Exception.php index 30ec159..2cf59ea 100644 --- a/src/Exceptional/Exception.php +++ b/src/Exceptional/Exception.php @@ -15,9 +15,21 @@ interface Exception extends Throwable, PreparedTraceException { - public function setData($data); + /** + * @param mixed $data + * @return $this + */ + public function setData($data): Exception; + + /** + * @return mixed + */ public function getData(); - public function setHttpStatus(?int $code); + /** + * @return $this + */ + public function setHttpStatus(?int $code): Exception; + public function getHttpStatus(): ?int; } diff --git a/src/Exceptional/ExceptionTrait.php b/src/Exceptional/ExceptionTrait.php index 32b9ce0..76573de 100644 --- a/src/Exceptional/ExceptionTrait.php +++ b/src/Exceptional/ExceptionTrait.php @@ -13,6 +13,8 @@ use DecodeLabs\Glitch\Stack\Frame; use DecodeLabs\Glitch\Stack\Trace; +use ErrorException; + trait ExceptionTrait { protected $http; @@ -35,7 +37,7 @@ public function __construct(string $message, array $params = []) (int)($params['code'] ?? 0) ]; - if ($this instanceof \ErrorException) { + if ($this instanceof ErrorException) { $args[] = (int)($params['severity'] ?? 0); $args[] = (string)($params['file'] ?? ''); $args[] = (int)($params['line'] ?? 0); diff --git a/src/Exceptional/Factory.php b/src/Exceptional/Factory.php index 0d95cd2..8ba988f 100644 --- a/src/Exceptional/Factory.php +++ b/src/Exceptional/Factory.php @@ -9,6 +9,9 @@ namespace DecodeLabs\Exceptional; +use DecodeLabs\Exceptional\Exception as ExceptionInterface; + +use Exception as RootException; use InvalidArgumentException; use LogicException; use Throwable; @@ -135,25 +138,72 @@ class Factory public const REWIND = 2; + /** + * @var array + */ private static $instances = []; + /** + * @var string|null + */ protected $message; + + /** + * @var array + */ protected $params = []; + + /** + * @var string|null + */ protected $baseClass; + + /** + * @var string|null + */ protected $namespace; + + /** + * @var array + */ protected $interfaces = []; + + /** + * @var array + */ protected $traits = []; + + /** + * @var array + */ protected $interfaceIndex = []; + + /** + * @var array + */ protected $interfaceDefs = []; + + /** + * @var string + */ protected $exceptionDef; + /** + * @var bool + */ protected $autoLoad = false; /** * Generate a context specific, message oriented throwable error + * + * @param array $types + * @param array $params + * @param mixed $data + * @param array $interfaces + * @param array $traits */ public static function create( array $types, @@ -189,6 +239,12 @@ public static function create( /** * Begin new factory process + * + * @param array $types + * @param array $params + * @param mixed $data + * @param array $interfaces + * @param array $traits */ protected function __construct( array $types, @@ -271,6 +327,8 @@ protected function __construct( /** * Prepare target namespace + * + * @param array|null $frame */ protected function prepareTargetNamespace(?string $namespace, ?array $frame): void { @@ -307,6 +365,8 @@ protected function prepareTargetNamespace(?string $namespace, ?array $frame): vo /** * Import type definitions + * + * @param array $types */ protected function importTypes(array $types): void { @@ -378,7 +438,7 @@ protected function importTypes(array $types): void // Named class if ( class_exists($type) && - is_a($type, \Exception::class, true) + is_a($type, RootException::class, true) ) { if ($this->baseClass !== null) { throw new InvalidArgumentException( @@ -401,6 +461,8 @@ class_exists($type) && /** * Import interface definitions + * + * @param array $interfaces */ protected function importInterfaces(array $interfaces): void { @@ -421,6 +483,8 @@ protected function importInterfaces(array $interfaces): void /** * Import trait definitions + * + * @param array $traits */ protected function importTraits(array $traits): void { @@ -498,7 +562,7 @@ protected function indexInterface(string $interface): void // Interface if ( ($classExists = class_exists($interface)) && - is_a($interface, \Exception::class, true) + is_a($interface, RootException::class, true) ) { $baseClass = trim($interface, '\\'); @@ -538,13 +602,15 @@ protected function indexInterface(string $interface): void !$classExists && !isset($this->interfaceIndex[$interface]) ) { - $this->interfaceIndex[$interface] = ['\\' . Exception::class]; + $this->interfaceIndex[$interface] = ['\\' . ExceptionInterface::class]; } } } /** * Index namespace interface + * + * @param array $parts */ protected function indexNamespaceInterfaces(array $parts): ?string { @@ -631,12 +697,14 @@ protected function indexPackageInterface(string $name): void /** * Build interface definitions + * + * @return array */ protected function buildDefinitions(): array { // Ensure base class if ($this->baseClass === null) { - $this->baseClass = \Exception::class; + $this->baseClass = RootException::class; } // Create definitions for needed interfaces @@ -658,7 +726,7 @@ protected function buildDefinitions(): array } if (empty($interfaces)) { - $interfaces[] = Exception::class; + $interfaces[] = ExceptionInterface::class; } else { $interfaces = array_keys($interfaces); } @@ -686,6 +754,8 @@ protected function buildDefinitions(): array /** * Define interface + * + * @param array $extends */ protected function defineInterface(string $interface, array $extends): void {