Skip to content
This repository has been archived by the owner on Jan 9, 2025. It is now read-only.

Refactored Router to be a non-static class #15

Merged
merged 8 commits into from
May 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ name: PHP Composer

on:
push:
branches: [ "main" ]
branches:
- '**'
pull_request:
branches: [ "main" ]
branches:
- '**'

permissions:
contents: read
Expand Down
168 changes: 84 additions & 84 deletions src/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,150 +27,150 @@ class Router
/**
* @var Route[]
*/
protected static array $routes = [];
protected static array $group = [];
protected static int $emitHttpExceptions = 0;
protected array $routes = [];
protected array $group = [];
protected int $emitHttpExceptions = 0;

/**
* @var Route[][]
*/
protected static array $catchers = [];
protected array $catchers = [];

public static function get(string $uri, string $controller): Route
public function get(string $uri, string $controller): Route
{
$route = new Route($uri, $controller, Methods::GET);
$route = new Route($this, $uri, $controller, Methods::GET);

self::addRoute($route);
$this->addRoute($route);

return $route;
}

public static function post(string $uri, string $controller): Route
public function post(string $uri, string $controller): Route
{
$route = new Route($uri, $controller, Methods::POST);
$route = new Route($this, $uri, $controller, Methods::POST);

self::addRoute($route);
$this->addRoute($route);

return $route;
}

public static function put(string $uri, string $controller): Route
public function put(string $uri, string $controller): Route
{
$route = new Route($uri, $controller, Methods::PUT);
$route = new Route($this, $uri, $controller, Methods::PUT);

self::addRoute($route);
$this->addRoute($route);

return $route;
}

public static function patch(string $uri, string $controller): Route
public function patch(string $uri, string $controller): Route
{
$route = new Route($uri, $controller, Methods::PATCH);
$route = new Route($this, $uri, $controller, Methods::PATCH);

self::addRoute($route);
$this->addRoute($route);

return $route;
}

public static function delete(string $uri, string $controller): Route
public function delete(string $uri, string $controller): Route
{
$route = new Route($uri, $controller, Methods::DELETE);
$route = new Route($this, $uri, $controller, Methods::DELETE);

self::addRoute($route);
$this->addRoute($route);

return $route;
}


public static function options(string $uri, string $controller): Route
public function options(string $uri, string $controller): Route
{
$route = new Route($uri, $controller, Methods::OPTIONS);
$route = new Route($this, $uri, $controller, Methods::OPTIONS);

self::addRoute($route);
$this->addRoute($route);

return $route;
}


public static function head(string $uri, string $controller): Route
public function head(string $uri, string $controller): Route
{
$route = new Route($uri, $controller, Methods::HEAD);
$route = new Route($this, $uri, $controller, Methods::HEAD);

self::addRoute($route);
$this->addRoute($route);

return $route;
}


public static function all(string $uri, string $controller): Route
public function all(string $uri, string $controller): Route
{
$route = new Route($uri, $controller, ...Methods::cases());
$route = new Route($this, $uri, $controller, ...Methods::cases());

self::addRoute($route);
$this->addRoute($route);

return $route;
}


public static function addRoute(Route $route): void
public function addRoute(Route $route): void
{
if (isset(self::$group)) {
foreach (self::$group["middlewares"] ?? [] as $middlware) {
if (isset($this->group)) {
foreach ($this->group["middlewares"] ?? [] as $middlware) {
$route->addMiddleware($middlware);
}

foreach (self::$group["postwares"] ?? [] as $postware) {
foreach ($this->group["postwares"] ?? [] as $postware) {
$route->addPostware($postware);
}

foreach (self::$group["parameters"] ?? [] as $name => $value) {
foreach ($this->group["parameters"] ?? [] as $name => $value) {
$route->setParameter($name, $value);
}

foreach (self::$group["staticArguments"] ?? [] as $name => $value) {
foreach ($this->group["staticArguments"] ?? [] as $name => $value) {
$route->addStaticArgument($name, $value);
}
}

self::$routes[] = &$route;
$this->routes[] = &$route;
}

public static function group(
public function group(
string $baseUri,
Closure $grouping,
array $middlewares = [],
array $postwares = [],
array $parameters = [],
array $staticArguments = []
): void {
$oldMount = self::$group;
$oldMount = $this->group;

if (empty(self::getBaseUri())) {
self::$group = compact("baseUri", "middlewares", "postwares", "parameters", "staticArguments");
if (empty($this->getBaseUri())) {
$this->group = compact("baseUri", "middlewares", "postwares", "parameters", "staticArguments");
} else {
self::$group['baseUri'] .= $baseUri;
self::$group['middlewares'] = [...self::$group['middlewares'], ...$middlewares];
self::$group['postwares'] = [...self::$group['postwares'], ...$postwares];
self::$group['parameters'] = [...self::$group['parameters'], ...$parameters];
self::$group['staticArguments'] = [...self::$group['staticArguments'], ...$staticArguments];
$this->group['baseUri'] .= $baseUri;
$this->group['middlewares'] = [...$this->group['middlewares'], ...$middlewares];
$this->group['postwares'] = [...$this->group['postwares'], ...$postwares];
$this->group['parameters'] = [...$this->group['parameters'], ...$parameters];
$this->group['staticArguments'] = [...$this->group['staticArguments'], ...$staticArguments];
}

$grouping();

self::$group = $oldMount;
$this->group = $oldMount;
}

public static function getBaseUri(): string
public function getBaseUri(): string
{
return self::$group["baseUri"] ?? "";
return $this->group["baseUri"] ?? "";
}

/**
* @param array $routes
* @param ServerRequestInterface $request
* @return ResolvedRoute|null
*/
protected static function resolveRoute(array $routes, ServerRequestInterface $request): ?ResolvedRoute
protected function resolveRoute(array $routes, ServerRequestInterface $request): ?ResolvedRoute
{
$routeMatches = static function (Route $route, string $requestUri, ?array &$matches) use (&$argNames): bool {
$argNames = [];
Expand Down Expand Up @@ -230,62 +230,62 @@ protected static function resolveRoute(array $routes, ServerRequestInterface $re
return $resolvedRoute ?? null;
}

public static function catch(string $toCatch, string $controller, ?string $uri = "/(.*)"): Route
public function catch(string $toCatch, string $controller, ?string $uri = "/(.*)"): Route
{
$catchable = array_keys(self::$catchers);
$catchable = array_keys($this->catchers);

if (!in_array($toCatch, $catchable)) {
self::makeCatchable($toCatch);
$this->makeCatchable($toCatch);
}

$route = new Route($uri, $controller, ...Methods::cases());
$route = new Route($this, $uri, $controller, ...Methods::cases());

self::$catchers[$toCatch][] = &$route;
$this->catchers[$toCatch][] = &$route;

return $route;
}

public static function makeCatchable(string $toCatch): void
public function makeCatchable(string $toCatch): void
{
if (!isset(self::$catchers[$toCatch])) {
if (!isset($this->catchers[$toCatch])) {
if (!is_subclass_of($toCatch, HttpException::class)) {
throw new InvalidArgumentException("{$toCatch} must extend " . HttpException::class);
}

self::$catchers[$toCatch] = [];
$this->catchers[$toCatch] = [];
}
}

/**
* @return Route[]
*/
public static function getRoutes(bool $sort = true): array
public function getRoutes(bool $sort = true): array
{
if ($sort) {
self::sortRoutesAndCatchers();
$this->sortRoutesAndCatchers();
}

return self::$routes;
return $this->routes;
}

/**
* @return Route[][]
*/
public static function getCatchers(bool $sort = true): array
public function getCatchers(bool $sort = true): array
{
if ($sort) {
self::sortRoutesAndCatchers();
$this->sortRoutesAndCatchers();
}

return self::$catchers;
return $this->catchers;
}

public static function emitHttpExceptions(int $type): void
public function emitHttpExceptions(int $type): void
{
self::$emitHttpExceptions = $type;
$this->emitHttpExceptions = $type;
}

protected static function invokeRoute(
protected function invokeRoute(
ResolvedRoute $resolvedRoute,
ServerRequestInterface $request
): ResponseInterface {
Expand Down Expand Up @@ -321,55 +321,55 @@ protected static function invokeRoute(
return $next($request, $response, $resolvedRoute->args);
}

protected static function sortRoutesAndCatchers(): void
protected function sortRoutesAndCatchers(): void
{
$sortByLength = static function (Route $a, Route $b) {
return (strlen($a->uri) > strlen($b->uri));
};

foreach (self::$catchers as &$catcher) {
foreach ($this->catchers as &$catcher) {
usort($catcher, $sortByLength);
}

unset($catcher);

usort(self::$routes, $sortByLength);
usort($this->routes, $sortByLength);
}

public static function clearRoutes(): void
public function clearRoutes(): void
{
self::$routes = [];
$this->routes = [];
}

public static function clearCatchers(): void
public function clearCatchers(): void
{
self::$catchers = [];
$this->catchers = [];
}

public static function clearAll(): void
public function clearAll(): void
{
self::clearRoutes();
self::clearCatchers();
$this->clearRoutes();
$this->clearCatchers();
}

public static function run(?ServerRequestInterface $request = null, ?EmitterInterface $emitter = null): void
public function run(?ServerRequestInterface $request = null, ?EmitterInterface $emitter = null): void
{
$emitter ??= new SapiEmitter();
$routes = self::getRoutes();
$catchers = self::getCatchers(false);
$routes = $this->getRoutes();
$catchers = $this->getCatchers(false);
$request ??= ServerRequestCreator::createFromGlobals();
$resolved = self::resolveRoute($routes, $request);
$resolved = $this->resolveRoute($routes, $request);

try {
if ($resolved === null) {
throw new Exceptions\HttpNotFound($request);
}

$response = self::invokeRoute($resolved, $request);
$response = $this->invokeRoute($resolved, $request);
} catch (Throwable $e) {
$resolved = array_key_exists($e::class, $catchers) ?
self::resolveRoute($catchers[$e::class], $request) :
self::resolveRoute($catchers[HttpInternalServerError::class] ?? [], $request)
$this->resolveRoute($catchers[$e::class], $request) :
$this->resolveRoute($catchers[HttpInternalServerError::class] ?? [], $request)
;

if ($resolved === null) {
Expand All @@ -379,7 +379,7 @@ public static function run(?ServerRequestInterface $request = null, ?EmitterInte

$class = $e::class;

$method = match (self::$emitHttpExceptions) {
$method = match ($this->emitHttpExceptions) {
self::EMIT_HTML_RESPONSE => "buildHtmlResponse",
self::EMIT_JSON_RESPONSE => "buildJsonResponse",
default => "buildEmptyResponse"
Expand All @@ -390,7 +390,7 @@ public static function run(?ServerRequestInterface $request = null, ?EmitterInte

if (!isset($response)) {
$resolved->args->exception = $e;
$response = self::invokeRoute($resolved, $request);
$response = $this->invokeRoute($resolved, $request);
}
}

Expand Down
Loading