DB Entity: Inheriting/Extending
This commit is contained in:
@@ -1,157 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Core\Objects\Router;
|
||||
|
||||
use Core\API\Parameter\Parameter;
|
||||
|
||||
abstract class AbstractRoute {
|
||||
|
||||
const PARAMETER_PATTERN = "/^{([^:]+)(:(.*?)(\?)?)?}$/";
|
||||
|
||||
private string $pattern;
|
||||
private bool $exact;
|
||||
|
||||
public function __construct(string $pattern, bool $exact = true) {
|
||||
$this->pattern = $pattern;
|
||||
$this->exact = $exact;
|
||||
}
|
||||
|
||||
private static function parseParamType(?string $type): ?int {
|
||||
if ($type === null || trim($type) === "") {
|
||||
return null;
|
||||
}
|
||||
|
||||
$type = strtolower(trim($type));
|
||||
if (in_array($type, ["int", "integer"])) {
|
||||
return Parameter::TYPE_INT;
|
||||
} else if (in_array($type, ["float", "double"])) {
|
||||
return Parameter::TYPE_FLOAT;
|
||||
} else if (in_array($type, ["bool", "boolean"])) {
|
||||
return Parameter::TYPE_BOOLEAN;
|
||||
} else {
|
||||
return Parameter::TYPE_STRING;
|
||||
}
|
||||
}
|
||||
|
||||
public function getPattern(): string {
|
||||
return $this->pattern;
|
||||
}
|
||||
|
||||
public abstract function call(Router $router, array $params): string;
|
||||
|
||||
protected function getArgs(): array {
|
||||
return [$this->pattern, $this->exact];
|
||||
}
|
||||
|
||||
public function getClass(): \ReflectionClass {
|
||||
return new \ReflectionClass($this);
|
||||
}
|
||||
|
||||
public function generateCache(): string {
|
||||
$reflection = $this->getClass();
|
||||
$className = $reflection->getShortName();
|
||||
$args = implode(", ", array_map(function ($arg) {
|
||||
return var_export($arg, true);
|
||||
}, $this->getArgs()));
|
||||
return "new $className($args)";
|
||||
}
|
||||
|
||||
public function match(string $url) {
|
||||
|
||||
# /test/{abc}/{param:?}/{xyz:int}/{aaa:int?}
|
||||
$patternParts = explode("/", Router::cleanURL($this->pattern, false));
|
||||
$countPattern = count($patternParts);
|
||||
$patternOffset = 0;
|
||||
|
||||
# /test/param/optional/123
|
||||
$urlParts = explode("/", Router::cleanURL($url));
|
||||
$countUrl = count($urlParts);
|
||||
$urlOffset = 0;
|
||||
|
||||
$params = [];
|
||||
for (; $patternOffset < $countPattern; $patternOffset++) {
|
||||
if (!preg_match(self::PARAMETER_PATTERN, $patternParts[$patternOffset], $match)) {
|
||||
|
||||
// not a parameter? check if it matches
|
||||
if ($urlOffset >= $countUrl || $urlParts[$urlOffset] !== $patternParts[$patternOffset]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$urlOffset++;
|
||||
} else {
|
||||
|
||||
// we got a parameter here
|
||||
$paramName = $match[1];
|
||||
if (isset($match[2])) {
|
||||
$paramType = self::parseParamType($match[3]) ?? Parameter::TYPE_MIXED;
|
||||
$paramOptional = !empty($match[4] ?? null);
|
||||
} else {
|
||||
$paramType = Parameter::TYPE_MIXED;
|
||||
$paramOptional = false;
|
||||
}
|
||||
|
||||
$parameter = new Parameter($paramName, $paramType, $paramOptional);
|
||||
if ($urlOffset >= $countUrl || $urlParts[$urlOffset] === "") {
|
||||
if ($parameter->optional) {
|
||||
$value = $urlParts[$urlOffset] ?? null;
|
||||
if ($value === null || $value === "") {
|
||||
$params[$paramName] = null;
|
||||
} else {
|
||||
if (!$parameter->parseParam($value)) {
|
||||
return false;
|
||||
} else {
|
||||
$params[$paramName] = $parameter->value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($urlOffset < $countUrl) {
|
||||
$urlOffset++;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$value = $urlParts[$urlOffset];
|
||||
if (!$parameter->parseParam($value)) {
|
||||
return false;
|
||||
} else {
|
||||
$params[$paramName] = $parameter->value;
|
||||
$urlOffset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($urlOffset !== $countUrl && $this->exact) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
public function getUrl(array $parameters = []): string {
|
||||
$patternParts = explode("/", Router::cleanURL($this->pattern, false));
|
||||
|
||||
foreach ($patternParts as $i => $part) {
|
||||
if (preg_match(self::PARAMETER_PATTERN, $part, $match)) {
|
||||
$paramName = $match[1];
|
||||
$patternParts[$i] = $parameters[$paramName] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
return "/" . implode("/", array_filter($patternParts));
|
||||
}
|
||||
|
||||
public function getParameterNames(): array {
|
||||
$parameterNames = [];
|
||||
$patternParts = explode("/", Router::cleanURL($this->pattern, false));
|
||||
|
||||
foreach ($patternParts as $part) {
|
||||
if (preg_match(self::PARAMETER_PATTERN, $part, $match)) {
|
||||
$parameterNames[] = $match[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $parameterNames;
|
||||
}
|
||||
}
|
||||
@@ -4,13 +4,14 @@ namespace Core\Objects\Router;
|
||||
|
||||
use Core\API\Request;
|
||||
use Core\Elements\TemplateDocument;
|
||||
use Core\Objects\DatabaseEntity\Route;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
|
||||
class ApiRoute extends AbstractRoute {
|
||||
class ApiRoute extends Route {
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct("/api/{endpoint:?}/{method:?}", false);
|
||||
parent::__construct("API", "/api/{endpoint:?}/{method:?}", false);
|
||||
}
|
||||
|
||||
private static function checkClass(string $className): bool {
|
||||
|
||||
@@ -2,34 +2,44 @@
|
||||
|
||||
namespace Core\Objects\Router;
|
||||
|
||||
use Core\Driver\SQL\SQL;
|
||||
use Core\Elements\Document;
|
||||
use Core\Objects\Context;
|
||||
use Core\Objects\DatabaseEntity\Route;
|
||||
use Core\Objects\Search\Searchable;
|
||||
use Core\Objects\Search\SearchQuery;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use ReflectionException;
|
||||
|
||||
class DocumentRoute extends AbstractRoute {
|
||||
class DocumentRoute extends Route {
|
||||
|
||||
use Searchable;
|
||||
|
||||
private string $className;
|
||||
private array $args;
|
||||
private ?\ReflectionClass $reflectionClass;
|
||||
private ?\ReflectionClass $reflectionClass = null;
|
||||
|
||||
public function __construct(string $pattern, bool $exact, string $className, ...$args) {
|
||||
parent::__construct($pattern, $exact);
|
||||
$this->className = $className;
|
||||
parent::__construct("dynamic", $pattern, $className, $exact);
|
||||
$this->args = $args;
|
||||
$this->reflectionClass = null;
|
||||
$this->extra = json_encode($args);
|
||||
}
|
||||
|
||||
public function postFetch(SQL $sql, array $row) {
|
||||
parent::postFetch($sql, $row);
|
||||
$this->args = json_decode($this->extra);
|
||||
}
|
||||
|
||||
#[Pure] private function getClassName(): string {
|
||||
return $this->getTarget();
|
||||
}
|
||||
|
||||
private function loadClass(): bool {
|
||||
|
||||
if ($this->reflectionClass === null) {
|
||||
try {
|
||||
$file = getClassPath($this->className);
|
||||
$file = getClassPath($this->getClassName());
|
||||
if (file_exists($file)) {
|
||||
$this->reflectionClass = new \ReflectionClass($this->className);
|
||||
$this->reflectionClass = new \ReflectionClass($this->getClassName());
|
||||
if ($this->reflectionClass->isSubclassOf(Document::class)) {
|
||||
return true;
|
||||
}
|
||||
@@ -56,20 +66,22 @@ class DocumentRoute extends AbstractRoute {
|
||||
}
|
||||
|
||||
protected function getArgs(): array {
|
||||
return array_merge(parent::getArgs(), [$this->className], $this->args);
|
||||
return array_merge(parent::getArgs(), [$this->getClassName()], $this->args);
|
||||
}
|
||||
|
||||
public function call(Router $router, array $params): string {
|
||||
$className = $this->getClassName();
|
||||
|
||||
try {
|
||||
if (!$this->loadClass()) {
|
||||
return $router->returnStatusCode(500, [ "message" => "Error loading class: $this->className"]);
|
||||
return $router->returnStatusCode(500, [ "message" => "Error loading class: $className"]);
|
||||
}
|
||||
|
||||
$args = array_merge([$router], $this->args, $params);
|
||||
$document = $this->reflectionClass->newInstanceArgs($args);
|
||||
return $document->load($params);
|
||||
} catch (\ReflectionException $e) {
|
||||
return $router->returnStatusCode(500, [ "message" => "Error loading class $this->className: " . $e->getMessage()]);
|
||||
return $router->returnStatusCode(500, [ "message" => "Error loading class $className: " . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
namespace Core\Objects\Router;
|
||||
|
||||
class EmptyRoute extends AbstractRoute {
|
||||
use Core\Objects\DatabaseEntity\Route;
|
||||
|
||||
class EmptyRoute extends Route {
|
||||
|
||||
public function __construct(string $pattern, bool $exact = true) {
|
||||
parent::__construct($pattern, $exact);
|
||||
parent::__construct("empty", $pattern, $exact);
|
||||
}
|
||||
|
||||
public function call(Router $router, array $params): string {
|
||||
|
||||
9
Core/Objects/Router/RedirectPermanentlyRoute.class.php
Normal file
9
Core/Objects/Router/RedirectPermanentlyRoute.class.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Core\Objects\Router;
|
||||
|
||||
class RedirectPermanentlyRoute extends RedirectRoute {
|
||||
public function __construct(string $pattern, bool $exact, string $destination) {
|
||||
parent::__construct("redirect_permanently", $pattern, $exact, $destination, 308);
|
||||
}
|
||||
}
|
||||
@@ -2,24 +2,29 @@
|
||||
|
||||
namespace Core\Objects\Router;
|
||||
|
||||
class RedirectRoute extends AbstractRoute {
|
||||
use Core\Objects\DatabaseEntity\Route;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
|
||||
class RedirectRoute extends Route {
|
||||
|
||||
private string $destination;
|
||||
private int $code;
|
||||
|
||||
public function __construct(string $pattern, bool $exact, string $destination, int $code = 307) {
|
||||
parent::__construct($pattern, $exact);
|
||||
$this->destination = $destination;
|
||||
public function __construct(string $type, string $pattern, bool $exact, string $destination, int $code = 307) {
|
||||
parent::__construct($type, $pattern, $destination, $exact);
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
#[Pure] private function getDestination(): string {
|
||||
return $this->getTarget();
|
||||
}
|
||||
|
||||
public function call(Router $router, array $params): string {
|
||||
header("Location: $this->destination");
|
||||
header("Location: " . $this->getDestination());
|
||||
http_response_code($this->code);
|
||||
return "";
|
||||
}
|
||||
|
||||
protected function getArgs(): array {
|
||||
return array_merge(parent::getArgs(), [$this->destination, $this->code]);
|
||||
return array_merge(parent::getArgs(), [$this->getDestination(), $this->code]);
|
||||
}
|
||||
}
|
||||
9
Core/Objects/Router/RedirectTemporaryRoute.class.php
Normal file
9
Core/Objects/Router/RedirectTemporaryRoute.class.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Core\Objects\Router;
|
||||
|
||||
class RedirectTemporaryRoute extends RedirectRoute {
|
||||
public function __construct(string $pattern, bool $exact, string $destination) {
|
||||
parent::__construct("redirect_temporary", $pattern, $exact, $destination, 307);
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,13 @@ namespace Core\Objects\Router;
|
||||
|
||||
use Core\Driver\Logger\Logger;
|
||||
use Core\Objects\Context;
|
||||
use Core\Objects\DatabaseEntity\Route;
|
||||
|
||||
class Router {
|
||||
|
||||
private Context $context;
|
||||
private Logger $logger;
|
||||
private ?AbstractRoute $activeRoute;
|
||||
private ?Route $activeRoute;
|
||||
private ?string $requestedUri;
|
||||
protected array $routes;
|
||||
protected array $statusCodeRoutes;
|
||||
@@ -31,7 +32,7 @@ class Router {
|
||||
}
|
||||
}
|
||||
|
||||
public function getActiveRoute(): ?AbstractRoute {
|
||||
public function getActiveRoute(): ?Route {
|
||||
return $this->activeRoute;
|
||||
}
|
||||
|
||||
@@ -75,7 +76,7 @@ class Router {
|
||||
}
|
||||
}
|
||||
|
||||
public function addRoute(AbstractRoute $route) {
|
||||
public function addRoute(Route $route) {
|
||||
if (preg_match("/^\/(\d+)$/", $route->getPattern(), $re)) {
|
||||
$this->statusCodeRoutes[$re[1]] = $route;
|
||||
}
|
||||
|
||||
@@ -2,22 +2,29 @@
|
||||
|
||||
namespace Core\Objects\Router;
|
||||
|
||||
use Core\Driver\SQL\SQL;
|
||||
use Core\Objects\Context;
|
||||
use Core\Objects\DatabaseEntity\Route;
|
||||
use Core\Objects\Search\Searchable;
|
||||
use Core\Objects\Search\SearchQuery;
|
||||
use Core\Objects\Search\SearchResult;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
|
||||
class StaticFileRoute extends AbstractRoute {
|
||||
class StaticFileRoute extends Route {
|
||||
|
||||
use Searchable;
|
||||
|
||||
private string $path;
|
||||
private int $code;
|
||||
|
||||
public function __construct(string $pattern, bool $exact, string $path, int $code = 200) {
|
||||
parent::__construct($pattern, $exact);
|
||||
$this->path = $path;
|
||||
parent::__construct("static", $pattern, $path, $exact);
|
||||
$this->code = $code;
|
||||
$this->extra = json_encode($this->code);
|
||||
}
|
||||
|
||||
public function postFetch(SQL $sql, array $row) {
|
||||
parent::postFetch($sql, $row);
|
||||
$this->code = json_decode($this->extra);
|
||||
}
|
||||
|
||||
public function call(Router $router, array $params): string {
|
||||
@@ -26,12 +33,16 @@ class StaticFileRoute extends AbstractRoute {
|
||||
return "";
|
||||
}
|
||||
|
||||
#[Pure] private function getPath(): string {
|
||||
return $this->getTarget();
|
||||
}
|
||||
|
||||
protected function getArgs(): array {
|
||||
return array_merge(parent::getArgs(), [$this->path, $this->code]);
|
||||
return array_merge(parent::getArgs(), [$this->getPath(), $this->code]);
|
||||
}
|
||||
|
||||
public function getAbsolutePath(): string {
|
||||
return WEBROOT . DIRECTORY_SEPARATOR . $this->path;
|
||||
return WEBROOT . DIRECTORY_SEPARATOR . $this->getPath();
|
||||
}
|
||||
|
||||
public static function serveStatic(string $path, ?Router $router = null) {
|
||||
|
||||
@@ -2,13 +2,15 @@
|
||||
|
||||
namespace Core\Objects\Router;
|
||||
|
||||
class StaticRoute extends AbstractRoute {
|
||||
use Core\Objects\DatabaseEntity\Route;
|
||||
|
||||
class StaticRoute extends Route {
|
||||
|
||||
private string $data;
|
||||
private int $code;
|
||||
|
||||
public function __construct(string $pattern, bool $exact, string $data, int $code = 200) {
|
||||
parent::__construct($pattern, $exact);
|
||||
parent::__construct("static", $pattern, $exact);
|
||||
$this->data = $data;
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user