10 Commits
11 changed files with 137 additions and 52 deletions

No files matched your search

+2
View File
@@ -99,6 +99,8 @@ class AnnotationReader
case $reflect instanceof ReflectionClass :
return $reflect->name;
}
return "#UNKNOWN#";
}
protected function getObjectNamespace(Reflector $reflect) : string
+7 -1
View File
@@ -10,6 +10,8 @@ use RuntimeException, DirectoryIterator, Generator;
class Breadcrumb extends RouteFetcher {
public bool $ignoreSoleRoute = true;
public function getRouteTree(\Notes\Route\Attribute\Method\Route $route) : array
{
$tree = [];
@@ -36,7 +38,11 @@ class Breadcrumb extends RouteFetcher {
else {
$route = null;
}
};
}
if ($this->ignoreSoleRoute && count($tree) === 1) {
return [];
}
return array_reverse($tree);
}
+1 -1
View File
@@ -87,7 +87,7 @@ class CommandFetcher {
$class = $this->generateClassname($basename, $namespace);
$objectResolver = new ObjectResolver($class, true, false, false);
$objectResolver = new ObjectResolver($class, $this->cache);
$attributes = $objectResolver->getAttributeListFromClassname( $this->annotations['object'], false ) ;
+23
View File
@@ -56,4 +56,27 @@ abstract class Reflected
}
}
public function getAttributes(null|string|array $attributeType = null): array
{
if ($attributeType) {
$list = [];
foreach($this->attributes as $attribute) {
foreach((array) $attributeType as $type) {
if ($attribute->object instanceof $type) {
$list[] = $attribute;
}
}
}
return array_reverse($list);
}
return array_reverse($this->attributes);
}
public function getAttribute(string|array $attributeType): ?object
{
return $this->getAttributes($attributeType)[0] ?? null;
}
}
+40 -6
View File
@@ -14,10 +14,14 @@ class ReflectedClass implements ReflectedInterface
public array $traits = [],
) {}
public function getClassName() : string
{
return end(explode('\\', $this->name));
}
public function getProperties(bool $deep = true) : array
{
return $deep ? array_replace(
# $this->parent ? $this->parent->getProperties(true) : [],
$this->parent ? $this->parent->getProperties(true) : [],
$this->properties
) : $this->properties;
@@ -35,14 +39,33 @@ class ReflectedClass implements ReflectedInterface
) : $this->methods;
}
public function getAttributes(bool $deep = true) : array
public function getAttributes(bool $deep = true, ? string $attributeType = null) : array
{
return $deep ? array_merge(
$this->parent ? $this->parent->getAttributes(true) : [],
array_merge(...array_map(fn($e) => $e->getAttributes(true), $this->interfaces)),
array_merge(...array_map(fn($e) => $e->getAttributes(true), $this->traits)),
return array_reverse($this->getOrderedAttributes($deep, $attributeType));
}
protected function getOrderedAttributes(bool $deep = true, ? string $attributeType = null) : array
{
$attributes = $deep ? array_merge(
$this->parent ? $this->parent->getOrderedAttributes(true) : [],
array_merge(...array_map(fn($e) => $e->getOrderedAttributes(true), $this->interfaces)),
array_merge(...array_map(fn($e) => $e->getOrderedAttributes(true), $this->traits)),
$this->attributes
) : $this->attributes;
if ($attributeType) {
$list = [];
foreach($attributes as $attribute) {
if ($attribute->object instanceof $attributeType) {
$list[] = $attribute;
}
}
return $list;
}
return $attributes;
}
# Get Attributes based on Native attributes's target
@@ -146,4 +169,15 @@ class ReflectedClass implements ReflectedInterface
return $list;
}
public function getAttribute(string $attributeType): ?object
{
foreach($this->getAttributes(true, $attributeType) as $attribute) {
if ($attribute->object instanceof $attributeType) {
return $attribute;
}
}
return null;
}
}
-4
View File
@@ -15,8 +15,4 @@ class ReflectedMethod extends Reflected implements ReflectedInterface
public array $parameters = [],
) {}
public function getAttributes(): array
{
return $this->attributes;
}
}
-6
View File
@@ -14,12 +14,6 @@ class ReflectedProperty extends Reflected implements ReflectedInterface, \ArrayA
public array $attributes = [],
) {}
public function getAttributes(): array
{
return $this->attributes;
}
## BACKWARD COMPATIBILITY ONLY To be removed really soon !
public function offsetExists(mixed $offset): bool
{
+17 -12
View File
@@ -25,13 +25,18 @@ class ObjectReflection {
$this->cache = $cache;
#if ( ! $this->cache || ! $this->cache->has($class) ) {
$this->classReflection = $class instanceof ReflectionClass ? $class : new ReflectionClass($class);
# }
$this->classReflection = $class instanceof ReflectionClass ? $class : new ReflectionClass($class);
# }
}
public static function fromClass(ReflectionClass|string $class, ? CacheInterface $cache = null) : self
{
return new static($class, null, $cache);
return new static($class, $cache);
}
public function getClassReflection() : ReflectionClass
{
return $this->classReflection;
}
public function reflectClass() : ReflectedClass
@@ -48,11 +53,11 @@ class ObjectReflection {
traits: array_map(fn($trait) => static::fromClass($trait)->reflectClass(), array_keys($this->classReflection->getTraits())),
);
}
public function reflectProperties(int $filter =
ReflectionProperty::IS_PUBLIC |
ReflectionProperty::IS_PROTECTED |
ReflectionProperty::IS_PRIVATE
ReflectionProperty::IS_PUBLIC |
ReflectionProperty::IS_PROTECTED |
ReflectionProperty::IS_PRIVATE
) : array
{
$defaultValues = $this->classReflection->getDefaultProperties();
@@ -82,11 +87,11 @@ class ObjectReflection {
}
public function reflectMethods(int $filter =
ReflectionMethod::IS_PUBLIC |
ReflectionMethod::IS_PROTECTED |
ReflectionMethod::IS_PRIVATE |
ReflectionMethod::IS_STATIC |
ReflectionMethod::IS_FINAL
ReflectionMethod::IS_PUBLIC |
ReflectionMethod::IS_PROTECTED |
ReflectionMethod::IS_PRIVATE |
ReflectionMethod::IS_STATIC |
ReflectionMethod::IS_FINAL
) : array
{
$list = [];
+1 -1
View File
@@ -99,7 +99,7 @@ class RouteFetcher {
$objects = $objectResolver->reflectedClass->getClassAttributeListFromClassname($attributes['object'], true, false);
foreach(array_reverse($objects) as $object) {
foreach($objects as $object) {
if ($object->method ?? false ) {
$methods ??= (array) $object->method;
}
+1
View File
@@ -7,5 +7,6 @@ class Taxus implements \Notes\Attribute {
public function __construct(
public null|string|\BackedEnum $privilege = null,
public null|string $module = null,
public string|array $method = "*",
) {}
}
+45 -21
View File
@@ -2,11 +2,13 @@
namespace Notes\Security;
use Notes\Common\ReflectedAttribute;
use Taxus\Taxus;
use Psr\Http\Message\ResponseInterface;
use Notes\ObjectResolver;
use Taxus\TaxusGrantEnum;
class SecurityHandler {
@@ -27,10 +29,12 @@ class SecurityHandler {
return $this->isLocked($className, $methodName) ? $this->redirectResponse : null;
}
# @TODO Must HANDLE REALM !
public function isLocked(string $className, string $methodName) : bool
{
if ( $security = $this->getClassAttributes(Attribute\Security::class, $className, $methodName) ) {
return array_pop($security)->locked;
# 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;
@@ -38,15 +42,16 @@ class SecurityHandler {
public function taxus(string $className, string $methodName, object $user = null) : ? ResponseInterface
{
if ($taxus = $this->getClassAttributes(Attribute\Taxus::class, $className, $methodName)) {
if ($this->unauthorizeResponse) {
foreach ($taxus as $item) {
if (!isset($item->privilege) || $this->taxus->granted($item->privilege, $user, $item)) {
return null;
}
}
$fromObject = $this->findAttributes(Attribute\Taxus::class, $className);
$fromMethod = $this->findAttributes(Attribute\Taxus::class, $className, $methodName);
return call_user_func_array($this->unauthorizeResponse, [ $user, $taxus, $className, $methodName ]);
if ($fromMethod || $fromObject) {
if ( $this->taxusGrantPermission($fromMethod, $user) || $this->taxusGrantPermission($fromObject, $user) ) {
return null;
}
if ($this->unauthorizeResponse) {
return call_user_func_array($this->unauthorizeResponse, [ $user, ['method' => $fromMethod, 'object' => $fromObject ], $className, $methodName ]);
}
else {
throw new \ErrorException("Unauthorized response given.");
@@ -56,22 +61,41 @@ class SecurityHandler {
return null;
}
protected function getClassAttributes(string $annotationClass, string $className, string $methodName)/* : \Notes\Attribute|array */
protected function findAttributes(string $attribute, string $class, ? string $method = null) : array
{
$objectResolver = new ObjectResolver($className);
$objectResolver = new ObjectResolver($class);
try {
$method = $objectResolver->reflectedClass->getClassAttributeList( $annotationClass, true, false );
if ($method) {
$fromMethod = $objectResolver->reflectedClass->getMethods( false );
# var_dump($method);
}
catch(\Exception $e) { }
if (isset($fromMethod[$method])) {
$attributeList = $fromMethod[$method]->getAttributes($attribute);
if ( $method[$methodName] ?? false ) {
return $method[$methodName];
if ($attributeList) {
return array_map(fn(ReflectedAttribute $ref) => $ref->object, $attributeList);
}
}
}
else {
return array_filter($method, fn($e) => is_object($e));
$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, object $user = null) : bool
{
foreach ($attributeList as $item) {
if ( $grant = $this->taxus->granted($item->privilege, $user, $item) ) {
if (is_bool($grant) ? $grant : $grant === TaxusGrantEnum::Authorized) {
return true;
}
}
}
return false;
}
}