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);