diff --git a/.phive/phars.xml b/.phive/phars.xml index 4d447d1a..be9ae394 100644 --- a/.phive/phars.xml +++ b/.phive/phars.xml @@ -1,4 +1,4 @@ - + diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon deleted file mode 100644 index 3143a09f..00000000 --- a/phpstan-baseline.neon +++ /dev/null @@ -1,31 +0,0 @@ -parameters: - ignoreErrors: - - - message: '#^Creating callable from array\{mixed, non\-falsy\-string\} but it might not be a callable\.$#' - identifier: callable.nonCallable - count: 2 - path: src/AuthorizationService.php - - - - message: '#^Method Authorization\\Controller\\Component\\AuthorizationComponent\:\:can\(\) should return bool but returns Authorization\\Policy\\ResultInterface\|bool\.$#' - identifier: return.type - count: 1 - path: src/Controller/Component/AuthorizationComponent.php - - - - message: '#^Method Authorization\\Controller\\Component\\AuthorizationComponent\:\:canResult\(\) should return Authorization\\Policy\\ResultInterface but returns Authorization\\Policy\\ResultInterface\|bool\.$#' - identifier: return.type - count: 1 - path: src/Controller/Component/AuthorizationComponent.php - - - - message: '#^Cannot call method getIdentifier\(\) on array\|Authentication\\IdentityInterface\.$#' - identifier: method.nonObject - count: 1 - path: src/Identity.php - - - - message: '#^Cannot call method getOriginalData\(\) on array\|Authentication\\IdentityInterface\.$#' - identifier: method.nonObject - count: 1 - path: src/Identity.php diff --git a/phpstan.neon b/phpstan.neon index 0aa3b1cd..1c08d537 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,11 +1,5 @@ -includes: - - phpstan-baseline.neon - parameters: level: 8 treatPhpDocTypesAsCertain: false paths: - src/ - ignoreErrors: - - identifier: missingType.generics - - identifier: missingType.iterableValue diff --git a/src/AuthorizationService.php b/src/AuthorizationService.php index 7f76d1e9..41b97ae3 100644 --- a/src/AuthorizationService.php +++ b/src/AuthorizationService.php @@ -147,6 +147,7 @@ protected function getCanHandler(mixed $policy, string $action): Closure new MissingMethodException([$method, $action, get_class($policy)]), ); + /** @phpstan-ignore callable.nonCallable */ return [$policy, $method](...); } @@ -167,6 +168,7 @@ protected function getScopeHandler(mixed $policy, string $action): Closure new MissingMethodException([$method, $action, get_class($policy)]), ); + /** @phpstan-ignore callable.nonCallable */ return [$policy, $method](...); } diff --git a/src/Controller/Component/AuthorizationComponent.php b/src/Controller/Component/AuthorizationComponent.php index 6daa50d3..37b4bcfb 100644 --- a/src/Controller/Component/AuthorizationComponent.php +++ b/src/Controller/Component/AuthorizationComponent.php @@ -118,7 +118,7 @@ public function canResult(mixed $resource, ?string $action = null): ResultInterf * @param mixed $resource The resource to check authorization on. * @param string|null $action The action to check authorization for. * @param string $method The method to use, either "can" or "canResult". - * @return \Authorization\Policy\ResultInterface|bool + * @return ($method is 'can' ? bool : \Authorization\Policy\ResultInterface) */ protected function performCheck( mixed $resource, diff --git a/src/Exception/ForbiddenException.php b/src/Exception/ForbiddenException.php index 6daaef5f..4ad27085 100644 --- a/src/Exception/ForbiddenException.php +++ b/src/Exception/ForbiddenException.php @@ -42,7 +42,7 @@ class ForbiddenException extends Exception * Constructor * * @param \Authorization\Policy\ResultInterface|null $result Policy check result. - * @param array|string $message Either the string of the error message, or an array of attributes + * @param array|string $message Either the string of the error message, or an array of attributes * that are made available in the view, and sprintf()'d into Exception::$_messageTemplate * @param int|null $code The code of the error, is also the HTTP status code for the error. * @param \Throwable|null $previous the previous exception. diff --git a/src/Identity.php b/src/Identity.php index 0d2ab25c..5996bc49 100644 --- a/src/Identity.php +++ b/src/Identity.php @@ -25,13 +25,6 @@ class Identity extends IdentityDecorator implements AuthenIdentityInterface { - /** - * Identity data - * - * @var \Authentication\IdentityInterface - */ - protected ArrayAccess|array $identity; - /** * Constructor * @@ -51,6 +44,8 @@ public function __construct(AuthorizationServiceInterface $service, AuthenIdenti */ public function getIdentifier(): string|int|array|null { + assert($this->identity instanceof AuthenIdentityInterface); + return $this->identity->getIdentifier(); } @@ -59,6 +54,8 @@ public function getIdentifier(): string|int|array|null */ public function getOriginalData(): ArrayAccess|array { + assert($this->identity instanceof AuthenIdentityInterface); + return $this->identity->getOriginalData(); } } diff --git a/src/IdentityDecorator.php b/src/IdentityDecorator.php index 64ad190a..77d8da2b 100644 --- a/src/IdentityDecorator.php +++ b/src/IdentityDecorator.php @@ -33,7 +33,7 @@ class IdentityDecorator implements IdentityInterface /** * Identity data * - * @var \ArrayAccess|array + * @var \ArrayAccess|array */ protected ArrayAccess|array $identity; @@ -48,7 +48,7 @@ class IdentityDecorator implements IdentityInterface * Constructor * * @param \Authorization\AuthorizationServiceInterface $service The authorization service. - * @param \ArrayAccess|array $identity Identity data + * @param \ArrayAccess|array $identity Identity data */ public function __construct(AuthorizationServiceInterface $service, ArrayAccess|array $identity) { @@ -86,8 +86,7 @@ public function applyScope(string $action, mixed $resource, mixed ...$optionalAr public function getOriginalData(): ArrayAccess|array { if ( - $this->identity - && !is_array($this->identity) + is_object($this->identity) && method_exists($this->identity, 'getOriginalData') ) { return $this->identity->getOriginalData(); @@ -100,7 +99,7 @@ public function getOriginalData(): ArrayAccess|array * Delegate unknown methods to decorated identity. * * @param string $method The method being invoked. - * @param array $args The arguments for the method. + * @param array $args The arguments for the method. * @return mixed */ public function __call(string $method, array $args): mixed @@ -108,10 +107,17 @@ public function __call(string $method, array $args): mixed if (!is_object($this->identity)) { throw new BadMethodCallException("Cannot call `{$method}`. Identity data is not an object."); } - $call = [$this->identity, $method]; + + if (!method_exists($this->identity, $method)) { + throw new BadMethodCallException(sprintf( + 'Method `%s` does not exist on `%s`.', + $method, + $this->identity::class, + )); + } /** @phpstan-ignore callable.nonCallable */ - return $call(...$args); + return [$this->identity, $method](...$args); } /** diff --git a/src/IdentityInterface.php b/src/IdentityInterface.php index 15f5d488..28165b24 100644 --- a/src/IdentityInterface.php +++ b/src/IdentityInterface.php @@ -26,7 +26,7 @@ * and uses ArrayAccess to expose public properties of the wrapped identity * implementation. * - * @extends \ArrayAccess + * @extends \ArrayAccess */ interface IdentityInterface extends ArrayAccess { @@ -64,7 +64,7 @@ public function applyScope(string $action, mixed $resource, mixed ...$optionalAr * If the decorated identity implements `getOriginalData()` * that method should be invoked to expose the original data. * - * @return \ArrayAccess|array + * @return \ArrayAccess|array */ public function getOriginalData(): ArrayAccess|array; } diff --git a/src/Middleware/AuthorizationMiddleware.php b/src/Middleware/AuthorizationMiddleware.php index 98626503..ecdc8def 100644 --- a/src/Middleware/AuthorizationMiddleware.php +++ b/src/Middleware/AuthorizationMiddleware.php @@ -58,7 +58,7 @@ class AuthorizationMiddleware implements MiddlewareInterface * check authorization. It is intended as a development aid and not to be relied upon * in production. Defaults to `true`. * - * @var array + * @var array */ protected array $_defaultConfig = [ 'identityDecorator' => null, @@ -179,7 +179,7 @@ protected function getAuthorizationService( * Builds the identity object. * * @param \Authorization\AuthorizationServiceInterface $service Authorization service. - * @param \ArrayAccess|array $identity Identity data + * @param \ArrayAccess|array $identity Identity data * @return \Authorization\IdentityInterface */ protected function buildIdentity( diff --git a/src/Middleware/RequestAuthorizationMiddleware.php b/src/Middleware/RequestAuthorizationMiddleware.php index b25faaca..0808bab7 100644 --- a/src/Middleware/RequestAuthorizationMiddleware.php +++ b/src/Middleware/RequestAuthorizationMiddleware.php @@ -45,7 +45,7 @@ class RequestAuthorizationMiddleware implements MiddlewareInterface /** * Default Config * - * @var array + * @var array */ protected array $_defaultConfig = [ 'authorizationAttribute' => 'authorization', diff --git a/src/Middleware/UnauthorizedHandler/RedirectHandler.php b/src/Middleware/UnauthorizedHandler/RedirectHandler.php index cd9498bc..ccc53578 100644 --- a/src/Middleware/UnauthorizedHandler/RedirectHandler.php +++ b/src/Middleware/UnauthorizedHandler/RedirectHandler.php @@ -37,7 +37,7 @@ class RedirectHandler implements HandlerInterface * - `allowedRedirectExtensions` - If true, redirects are allowed for all extensions. * Pass specific ones to allow list, or false to disallow redirects for any extension. * - * @var array + * @var array */ protected array $defaultOptions = [ 'exceptions' => [ @@ -123,7 +123,7 @@ protected function getUrl(ServerRequestInterface $request, array $options): stri /** * @param \Psr\Http\Message\ServerRequestInterface $request - * @param array $options + * @param array $options * @return bool */ protected function redirectAllowed(ServerRequestInterface $request, array $options): bool diff --git a/src/Middleware/UnauthorizedHandler/UnauthorizedHandlerTrait.php b/src/Middleware/UnauthorizedHandler/UnauthorizedHandlerTrait.php index b3e10c3b..65ed800d 100644 --- a/src/Middleware/UnauthorizedHandler/UnauthorizedHandlerTrait.php +++ b/src/Middleware/UnauthorizedHandler/UnauthorizedHandlerTrait.php @@ -28,7 +28,7 @@ trait UnauthorizedHandlerTrait * * @param \Authorization\Exception\Exception $exception Exception to handle. * @param \Psr\Http\Message\ServerRequestInterface $request Request instance. - * @param array|string $handler Handler config. + * @param array|string $handler Handler config. * @return \Psr\Http\Message\ResponseInterface */ protected function handleException( diff --git a/src/Policy/Exception/MissingPolicyException.php b/src/Policy/Exception/MissingPolicyException.php index 9b01c21a..484e510c 100644 --- a/src/Policy/Exception/MissingPolicyException.php +++ b/src/Policy/Exception/MissingPolicyException.php @@ -30,7 +30,7 @@ class MissingPolicyException extends Exception protected string $_messageTemplate = 'Policy for `%s` has not been defined.'; /** - * @param object|array|string $resource Either the resource instance, a string of the error message, or an array of attributes + * @param object|array|string $resource Either the resource instance, a string of the error message, or an array of attributes * that are made available in the view, and sprintf()'d into Exception::$_messageTemplate * @param int|null $code The code of the error, is also the HTTP status code for the error. * @param \Throwable|null $previous the previous exception. diff --git a/src/Policy/MapResolver.php b/src/Policy/MapResolver.php index 74e6b84f..10c2f085 100644 --- a/src/Policy/MapResolver.php +++ b/src/Policy/MapResolver.php @@ -29,7 +29,7 @@ class MapResolver implements ResolverInterface /** * Resource to policy class name map. * - * @var array + * @var array */ protected array $map = []; @@ -52,7 +52,7 @@ class MapResolver implements ResolverInterface * ] * ``` * - * @param array $map Resource class name to policy map. + * @param array $map Resource class name to policy map. * @param \Cake\Core\ContainerInterface|null $container The DIC instance from the application */ public function __construct(array $map = [], ?ContainerInterface $container = null) @@ -71,7 +71,7 @@ public function __construct(array $map = [], ?ContainerInterface $container = nu * @return $this * @throws \InvalidArgumentException When a resource class does not exist or policy is invalid. */ - public function map(string $resourceClass, string|object|callable $policy) + public function map(string $resourceClass, callable|object|string $policy) { if (!class_exists($resourceClass)) { $message = sprintf('Resource class `%s` does not exist.', $resourceClass);