From b9aadd41ee32bcb5308c8db6bd579967e9df357b Mon Sep 17 00:00:00 2001 From: Dave Mc Nicoll Date: Sat, 21 Jan 2023 18:38:18 +0000 Subject: [PATCH] - WIP on Attributes conversion from annotations --- src/Annotation/Method/Route.php | 2 +- src/Attribute/Method/Route.php | 1 - src/RouteFetcher.php | 143 ++++++++++++++++---------------- 3 files changed, 71 insertions(+), 75 deletions(-) diff --git a/src/Annotation/Method/Route.php b/src/Annotation/Method/Route.php index 2afa274..f6c135d 100644 --- a/src/Annotation/Method/Route.php +++ b/src/Annotation/Method/Route.php @@ -14,7 +14,7 @@ class Route implements \Notes\Annotation { */ public string $route; - public string $method; + public /*string*/ $method; public string $base; diff --git a/src/Attribute/Method/Route.php b/src/Attribute/Method/Route.php index 637f8ab..8388c1f 100644 --- a/src/Attribute/Method/Route.php +++ b/src/Attribute/Method/Route.php @@ -4,7 +4,6 @@ namespace Notes\Route\Attribute\Method; #[\Attribute] class Route implements \Notes\Attribute { - public function __construct( public string $name, public string $route, diff --git a/src/RouteFetcher.php b/src/RouteFetcher.php index 29efe56..704b43f 100644 --- a/src/RouteFetcher.php +++ b/src/RouteFetcher.php @@ -3,6 +3,7 @@ use Notes\ObjectReflection, Notes\ObjectResolver; +use Psr\SimpleCache\CacheInterface; use RuntimeException, DirectoryIterator, Generator, Closure; class RouteFetcher { @@ -19,10 +20,13 @@ class RouteFetcher { protected array $annotations; - public function __construct(?Closure $callback = null, ? array $folderList = null, ? array $annotations = null, bool $debug = false) + protected CacheInterface $cache; + + protected bool $forceCacheWrite; + + public function __construct(?Closure $callback = null, ? array $folderList = null, ? array $annotations = null, ? CacheInterface $cache = null, bool $forceCacheWrite = false) { - // Handles if we must fetch or store in cache - $this->debug = $debug; + $this->cache = $cache; if ($callback !== null) { $this->callback = $callback; @@ -37,22 +41,12 @@ class RouteFetcher { } else { $this->annotations = [ - 'object' => Annotation\Object\Route::class, - 'method' => Annotation\Method\Route::class, + 'object' => [ Annotation\Object\Route::class, Attribute\Object\Route::class ], + 'method' => [ Annotation\Method\Route::class ], ]; } - } - public function __destruct() { - if ($this->debug) { - foreach ($this->list as $key => $item) { - $cacheKey = sprintf("%s:routes.%s", basename(__CLASS__), $key); - - if (function_exists('apcu_enabled') && apcu_enabled()) { - apcu_store($cacheKey, $item, 3600); - } - } - } + $this->forceCacheWrite = $forceCacheWrite; } public function addFolder($folder) : void @@ -91,78 +85,81 @@ class RouteFetcher { { $annotations ??= $this->annotations; - if ( $cacheValue = $this->fetchFromCache($this->generateListKey($annotations)) ) { - return $cacheValue; - } + return $this->handleCaching(substr(md5(serialize($annotations)), 0, 7), function() use ($annotations) : array { + $list = []; - foreach($this->scan() as $namespace => $file) { - if ( $file->getExtension() !== "php" ) { - continue; - } - - $base = ""; - $class = $this->generateClassname($file->getBasename(".php"), $namespace); - $methods = $this->defaultMethods; - - $objectResolver = new ObjectResolver($class, true, true, false, true); - - if ( isset($annotations['object']) && (null !== ( $object = $objectResolver->getAnnotationFromClassname($annotations['object']) )) ){ - if ( $object->methods ?? false ) { - $methods = $object->methods; + foreach($this->scan() as $namespace => $file) { + if ( $file->getExtension() !== "php" ) { + continue; } - $base = $object->base ?? ""; - } + $base = ""; + $class = $this->generateClassname($file->getBasename(".php"), $namespace); + $methods = $this->defaultMethods; - if ( isset($annotations['method']) ) { - $routeList = $objectResolver->getAnnotationListFromClassname( $annotations['method'] ); + $objectResolver = new ObjectResolver($class, true, true, false, true); - foreach($routeList as $func => $routes) { - foreach($routes as $route) { - $route->base = $base; - $route->class = $class; - $route->classMethod = $func; + if ( isset($annotations['object']) ) { + $object = $objectResolver->getAttributeFromClassname($annotations['object'], false) ?: $objectResolver->getAnnotationFromClassname($annotations['object'], false); - if (false === ($route->methods ?? false)) { - $route->methods = $methods; + if ( $object->methods ?? false ) { + $methods = $object->methods; + } + elseif ($object->method ?? false ) { + $methods = (array) $object->method; + } + + $base = $object->base ?? ""; + } + + if ( isset($annotations['method']) ) { + $routeList = $objectResolver->getAnnotationListFromClassname( $annotations['method'], false ); +; + foreach($routeList as $func => $routes) { + if (is_array($routes)) { + foreach ($routes as $route) { + $route->base = $base; + $route->class = $class; + $route->classMethod = $func; + + if (false === ($route->methods ?? false)) { + $route->methods = $methods; + } + + if (false !== ($this->callback ?? false)) { + call_user_func_array($this->callback, [$route]); + } + + $list[] = $route; + } } - - if (false !== ($this->callback ?? false)) { - call_user_func_array($this->callback, [ $route ]); - } - - $list[] = $route; } } } - } - return $this->debug ? $this->list[$this->generateListKey($annotations)] = $list : $list; - } - - protected function fetchFromCache(string $key) : array|null - { - if (! $this->debug) { - if (!isset($this->list[$key]) && function_exists('apcu_enabled') && apcu_enabled()) { - $cacheKey = sprintf("%s:routes.%s", basename(__CLASS__), $key); - - $fetch = apcu_fetch($cacheKey, $success); - - if ($success) { - return $fetch; - } - } - } - - return $this->list[$key] ?? null; - } - - protected function generateListKey(array $annotations) { - return ($annotations['object'] ?? "") . ($annotations['method'] ?? ""); + return $list; + }); } protected function generateClassname($file, $namespace) { return "\\$namespace\\$file"; } + + protected function handleCaching(string $key, callable $callback, null|int|\DateInterval $ttl = null) : mixed + { + static $internalCache = []; + + if ( isset($internalCache[$key]) ) { + return $internalCache[$key]; + } + + if ($this->forceCacheWrite || null === ( $internalCache[$key] = $this->cache->get($key) )) { + $internalCache[$key] = call_user_func($callback); + + $this->cache->set($key, $internalCache[$key], $ttl); + } + + return $internalCache[$key]; + } }