Compare commits

..

3 Commits

4 changed files with 114 additions and 33 deletions

View File

@ -14,7 +14,7 @@ class Route implements \Notes\Annotation {
*/ */
public string $route; public string $route;
public string $method; public /*string*/ $method;
public string $base; public string $base;
@ -24,6 +24,8 @@ class Route implements \Notes\Annotation {
public string $classMethod; public string $classMethod;
public bool $currentRoute = false;
public function __construct($route = null, $name = null, $method = null) public function __construct($route = null, $name = null, $method = null)
{ {
if ( $route !== null ) { if ( $route !== null ) {
@ -55,4 +57,8 @@ class Route implements \Notes\Annotation {
public function isRoute(string $name) { public function isRoute(string $name) {
return $this->name === $name; return $this->name === $name;
} }
public function currentRoute(bool|null $value = null ) {
return is_null($value) ? $value : $this->currentRoute = $value;
}
} }

View File

@ -0,0 +1,37 @@
<?php
namespace Notes\Route\Attribute\Method;
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD)]
class Route implements \Notes\Attribute {
public function __construct(
public string $route,
public string $name,
public string|array $method = [ "GET", "POST" ],
public string $base = "",
public ? string $class = null,
public ? string $classMethod = null,
public bool $currentRoute = false,
) {}
public function getRoute() : string
{
return rtrim("/" . trim(isset($this->base) ?
"/" . trim($this->base, "/") . "/" . ltrim($this->route, "/")
:
"/" . ltrim($this->route, "/"), "/"), '/');
}
public function matchRouteName(string $name) : bool
{
return strtolower($this->name) === strtolower($name);
}
public function isRoute(string $name) {
return $this->name === $name;
}
public function currentRoute(bool|null $value = null ) {
return is_null($value) ? $value : $this->currentRoute = $value;
}
}

View File

@ -0,0 +1,11 @@
<?php
namespace Notes\Route\Attribute\Object;
#[\Attribute(\Attribute::TARGET_CLASS)]
class Route implements \Notes\Annotation {
public function __construct(
public string|array $method = [ "GET", "POST" ],
public string $base = "",
){}
}

View File

@ -1,11 +1,18 @@
<?php namespace Notes\Route; <?php namespace Notes\Route;
use Kash\HandleCacheTrait;
use Notes\ObjectReflection, use Notes\ObjectReflection,
Notes\ObjectResolver; Notes\ObjectResolver;
use Psr\SimpleCache\CacheInterface;
use RuntimeException, DirectoryIterator, Generator, Closure; use RuntimeException, DirectoryIterator, Generator, Closure;
class RouteFetcher { class RouteFetcher {
use HandleCacheTrait;
public array $list = [];
protected bool $debug;
protected array $folderList; protected array $folderList;
@ -15,8 +22,10 @@ class RouteFetcher {
protected array $annotations; protected array $annotations;
public function __construct(?Closure $callback = null, ?array $folderList = null, ?array $annotations = null) public function __construct(?Closure $callback = null, ? array $folderList = null, ? array $annotations = null, ? CacheInterface $cache = null)
{ {
$this->cache = $cache;
if ($callback !== null) { if ($callback !== null) {
$this->callback = $callback; $this->callback = $callback;
} }
@ -30,8 +39,8 @@ class RouteFetcher {
} }
else { else {
$this->annotations = [ $this->annotations = [
'object' => Annotation\Object\Route::class, 'object' => [ Annotation\Object\Route::class, Attribute\Object\Route::class ],
'method' => Annotation\Method\Route::class, 'method' => [ Annotation\Method\Route::class ],
]; ];
} }
} }
@ -68,8 +77,13 @@ class RouteFetcher {
} }
} }
public function compile() : Generator public function compile(null|array $annotations = null) : array
{ {
$annotations ??= $this->annotations;
return $this->handleCaching(substr(md5(serialize($annotations)), 0, 7), function() use ($annotations) : array {
$list = [];
foreach($this->scan() as $namespace => $file) { foreach($this->scan() as $namespace => $file) {
if ( $file->getExtension() !== "php" ) { if ( $file->getExtension() !== "php" ) {
continue; continue;
@ -79,21 +93,29 @@ class RouteFetcher {
$class = $this->generateClassname($file->getBasename(".php"), $namespace); $class = $this->generateClassname($file->getBasename(".php"), $namespace);
$methods = $this->defaultMethods; $methods = $this->defaultMethods;
# Should generate an equivalent of Ulmus's object reflection here ! $objectResolver = new ObjectResolver($class, true, true, false, true, $this->cache);
$objectResolver = new ObjectResolver($class, true, true, false, true);
if ( null !== ( $object = $objectResolver->getAnnotationFromClassname( $this->annotations['object'] ) ) ) { if ( isset($annotations['object']) ) {
$object = $objectResolver->getAttributeFromClassname($annotations['object'], false) ?: $objectResolver->getAnnotationFromClassname($annotations['object'], false);
if ($object) {
if ( $object->methods ?? false ) { if ( $object->methods ?? false ) {
$methods = $object->methods; $methods = $object->methods;
} }
elseif ($object->method ?? false ) {
$methods = (array) $object->method;
}
$base = $object->base ?? ""; $base = $object->base ?? "";
} }
}
$routeList = $objectResolver->getAnnotationListFromClassname( $this->annotations['method'] ); if ( isset($annotations['method']) ) {
$routeList = $objectResolver->getAnnotationListFromClassname( $annotations['method'], false );
;
foreach($routeList as $func => $routes) { foreach($routeList as $func => $routes) {
foreach($routes as $route) { if (is_array($routes)) {
foreach ($routes as $route) {
$route->base = $base; $route->base = $base;
$route->class = $class; $route->class = $class;
$route->classMethod = $func; $route->classMethod = $func;
@ -106,11 +128,16 @@ class RouteFetcher {
call_user_func_array($this->callback, [$route]); call_user_func_array($this->callback, [$route]);
} }
yield $route; $list[] = $route;
} }
} }
} }
} }
}
return $list;
});
}
protected function generateClassname($file, $namespace) protected function generateClassname($file, $namespace)
{ {