web-base/Core/Objects/DatabaseEntity/Route.class.php

266 lines
7.8 KiB
PHP
Raw Permalink Normal View History

2022-06-01 09:47:31 +02:00
<?php
2022-11-27 12:33:27 +01:00
namespace Core\Objects\DatabaseEntity;
2022-06-01 09:47:31 +02:00
2022-11-18 18:06:46 +01:00
use Core\API\Parameter\Parameter;
2022-11-27 15:58:44 +01:00
use Core\Driver\SQL\SQL;
2022-11-27 12:33:27 +01:00
use Core\Objects\DatabaseEntity\Attribute\DefaultValue;
use Core\Objects\DatabaseEntity\Attribute\ExtendingEnum;
use Core\Objects\DatabaseEntity\Attribute\MaxLength;
use Core\Objects\DatabaseEntity\Attribute\Unique;
use Core\Objects\DatabaseEntity\Controller\DatabaseEntity;
use Core\Objects\Router\DocumentRoute;
use Core\Objects\Router\RedirectPermanentlyRoute;
use Core\Objects\Router\RedirectTemporaryRoute;
2022-11-27 12:33:27 +01:00
use Core\Objects\Router\Router;
use Core\Objects\Router\StaticFileRoute;
abstract class Route extends DatabaseEntity {
2022-06-01 09:47:31 +02:00
2022-08-20 22:17:17 +02:00
const PARAMETER_PATTERN = "/^{([^:]+)(:(.*?)(\?)?)?}$/";
2022-11-27 15:58:44 +01:00
const TYPE_DYNAMIC = "dynamic";
const TYPE_STATIC = "static";
const TYPE_REDIRECT_PERMANENTLY = "redirect_permanently";
const TYPE_REDIRECT_TEMPORARY = "redirect_temporary";
2022-11-27 12:33:27 +01:00
const ROUTE_TYPES = [
self::TYPE_REDIRECT_TEMPORARY => RedirectTemporaryRoute::class,
self::TYPE_REDIRECT_PERMANENTLY => RedirectPermanentlyRoute::class,
2022-11-27 15:58:44 +01:00
self::TYPE_STATIC => StaticFileRoute::class,
self::TYPE_DYNAMIC => DocumentRoute::class
2022-11-27 12:33:27 +01:00
];
#[MaxLength(128)]
#[Unique]
2022-06-01 09:47:31 +02:00
private string $pattern;
2022-11-27 12:33:27 +01:00
#[ExtendingEnum(self::ROUTE_TYPES)]
private string $type;
#[MaxLength(128)]
private string $target;
#[MaxLength(64)]
protected ?string $extra;
#[DefaultValue(true)]
private bool $active;
2022-06-01 09:47:31 +02:00
private bool $exact;
2022-11-27 12:33:27 +01:00
public function __construct(string $type, string $pattern, string $target, bool $exact = true) {
parent::__construct();
$this->target = $target;
2022-06-01 09:47:31 +02:00
$this->pattern = $pattern;
$this->exact = $exact;
2022-11-27 12:33:27 +01:00
$this->type = $type;
$this->active = true;
2022-06-01 09:47:31 +02:00
}
2024-03-27 20:50:57 +01:00
public function isActive(): bool {
return $this->active;
}
public function isExact(): bool {
return $this->exact;
}
2022-06-01 09:47:31 +02:00
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;
}
2022-11-27 12:33:27 +01:00
public function getTarget(): string {
return $this->target;
}
2022-06-01 09:47:31 +02:00
public abstract function call(Router $router, array $params): string;
2022-11-27 15:58:44 +01:00
protected function readExtra() { }
public function postFetch(SQL $sql, array $row) {
parent::postFetch($sql, $row);
$this->readExtra();
}
2022-06-01 09:47:31 +02:00
protected function getArgs(): array {
return [$this->pattern, $this->exact];
}
2022-11-18 18:06:46 +01:00
public function getClass(): \ReflectionClass {
return new \ReflectionClass($this);
}
2022-06-01 09:47:31 +02:00
public function generateCache(): string {
2022-11-18 18:06:46 +01:00
$reflection = $this->getClass();
$className = $reflection->getShortName();
2022-06-01 09:47:31 +02:00
$args = implode(", ", array_map(function ($arg) {
return var_export($arg, true);
}, $this->getArgs()));
2022-11-18 18:06:46 +01:00
return "new $className($args)";
2022-06-01 09:47:31 +02:00
}
2023-01-25 14:15:34 +01:00
private static function getParts(string $url): array {
if ($url === "/" || $url === "") {
return [];
} else {
return explode("/", $url);
}
}
2024-03-27 20:50:57 +01:00
public function match(string $url): bool|array {
2022-06-01 09:47:31 +02:00
# /test/{abc}/{param:?}/{xyz:int}/{aaa:int?}
2023-01-25 14:15:34 +01:00
$patternParts = self::getParts(Router::cleanURL($this->pattern, false));
2022-06-01 09:47:31 +02:00
$countPattern = count($patternParts);
$patternOffset = 0;
# /test/param/optional/123
2023-01-25 14:15:34 +01:00
$urlParts = self::getParts(Router::cleanURL($url));
2022-06-01 09:47:31 +02:00
$countUrl = count($urlParts);
$urlOffset = 0;
$params = [];
for (; $patternOffset < $countPattern; $patternOffset++) {
2022-08-20 22:17:17 +02:00
if (!preg_match(self::PARAMETER_PATTERN, $patternParts[$patternOffset], $match)) {
2022-06-01 09:47:31 +02:00
// not a parameter? check if it matches
if ($urlOffset >= $countUrl || $urlParts[$urlOffset] !== $patternParts[$patternOffset]) {
return false;
}
$urlOffset++;
} else {
// we got a parameter here
2022-06-01 12:28:50 +02:00
$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;
2022-06-01 09:47:31 +02:00
}
2022-06-01 12:28:50 +02:00
$parameter = new Parameter($paramName, $paramType, $paramOptional);
2022-06-01 09:47:31 +02:00
if ($urlOffset >= $countUrl || $urlParts[$urlOffset] === "") {
2022-06-01 12:28:50 +02:00
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;
}
2022-06-01 09:47:31 +02:00
}
if ($urlOffset < $countUrl) {
$urlOffset++;
}
} else {
return false;
}
} else {
2022-06-01 12:28:50 +02:00
$value = $urlParts[$urlOffset];
if (!$parameter->parseParam($value)) {
2022-06-01 09:47:31 +02:00
return false;
2022-06-01 12:28:50 +02:00
} else {
$params[$paramName] = $parameter->value;
$urlOffset++;
2022-06-01 09:47:31 +02:00
}
}
}
}
if ($urlOffset !== $countUrl && $this->exact) {
return false;
}
return $params;
}
2022-08-20 22:17:17 +02:00
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;
}
2022-11-27 12:33:27 +01:00
2022-11-27 15:58:44 +01:00
public function setActive(bool $active) {
$this->active = $active;
}
public function getType(): string {
return $this->type;
}
public function setPattern(string $pattern) {
$this->pattern = $pattern;
}
public function setExtra(string $extra) {
$this->extra = $extra;
}
public function setTarget(string $target) {
$this->target = $target;
}
public function setExact(bool $exact) {
$this->exact = $exact;
}
2023-01-17 20:54:58 +01:00
public static function getPredefinedValues(): array {
return [
new DocumentRoute("/admin", false, \Core\Documents\Admin::class),
new DocumentRoute("/register", true, \Core\Documents\Account::class, "account/register.twig"),
new DocumentRoute("/confirmEmail", true, \Core\Documents\Account::class, "account/confirm_email.twig"),
2023-01-25 14:15:34 +01:00
new DocumentRoute("/confirmGPG", true, \Core\Documents\Account::class, "account/confirm_gpg.twig"),
2023-01-17 20:54:58 +01:00
new DocumentRoute("/acceptInvite", true, \Core\Documents\Account::class, "account/accept_invite.twig"),
new DocumentRoute("/resetPassword", true, \Core\Documents\Account::class, "account/reset_password.twig"),
new DocumentRoute("/login", true, \Core\Documents\Account::class, "account/login.twig"),
new DocumentRoute("/resendConfirmEmail", true, \Core\Documents\Account::class, "account/resend_confirm_email.twig"),
new DocumentRoute("/debug", true, \Core\Documents\Info::class),
2023-03-05 15:30:06 +01:00
new DocumentRoute("/.well-known/security.txt", true, \Core\Documents\Security::class),
new DocumentRoute("/.well-known/gpg-key.txt", true, \Core\Documents\Security::class),
2023-01-17 20:54:58 +01:00
new StaticFileRoute("/", true, "/static/welcome.html"),
];
}
2022-06-01 09:47:31 +02:00
}