redirectResponse = $redirectResponse; $this->unauthorizeResponse = $unauthorizeResponse; $this->taxus = $taxus; } public function verify(string $className, string $methodName) : ? ResponseInterface { return $this->isLocked($className, $methodName) ? $this->redirectResponse : null; } # @TODO Must HANDLE REALM ! public function isLocked(string $className, string $methodName) : bool { # Searching method first and fallbacking on object if none found if ( $list = $this->findAttributes(Attribute\Security::class, $className, $methodName) ) { return array_shift($list)->locked; } return true; } public function taxus(string $className, string $methodName, ... $arguments) : ? ResponseInterface { $granted = $this->hasGrantPermission($className , $methodName, ...$arguments); if ($granted) { return null; } else { if ($this->unauthorizeResponse) { if ($this->unauthorizeResponse instanceof ResponseInterface) { return $this->unauthorizeResponse; } return call_user_func_array($this->unauthorizeResponse, [ ...$arguments, ['method' => $methodName, 'object' => $className ], $className, $methodName ]); } else { throw new \ErrorException("Unauthorized response given."); } } } public function hasGrantPermission(string $className, string $methodName, ... $arguments) : bool { $fromObject = $this->findAttributes(Attribute\Taxus::class, $className); $fromMethod = $this->findAttributes(Attribute\Taxus::class, $className, $methodName); if ($fromMethod) { return $this->taxusGrantPermission($fromMethod, ... $arguments); } elseif ($fromObject) { return $this->taxusGrantPermission($fromObject, ... $arguments); } return true; } protected function findAttributes(string $attribute, string $class, ? string $method = null) : array { $objectResolver = new ObjectResolver($class); if ($method) { $fromMethod = $objectResolver->reflectedClass->getMethods( false ); if (isset($fromMethod[$method])) { $attributeList = $fromMethod[$method]->getAttributes($attribute); if ($attributeList) { return array_map(fn(ReflectedAttribute $ref) => $ref->object, $attributeList); } } } $attributeList = $objectResolver->reflectedClass->getAttributes(false, $attribute) ?: $objectResolver->reflectedClass->getAttributes(true, $attribute); if ($attributeList) { return array_map(fn(ReflectedAttribute $ref) => $ref->object, $attributeList); } return []; } protected function taxusGrantPermission(array $attributeList, ...$arguments) : bool { foreach ($attributeList as $item) { if ( $grant = $this->taxus->granted($item->privilege, ... array_merge($arguments, [ $item ])) ) { if (is_bool($grant) ? $grant : $grant === TaxusGrantEnum::Authorized) { return true; } } } return false; } }