summaryrefslogtreecommitdiff
path: root/src/Router
diff options
context:
space:
mode:
Diffstat (limited to 'src/Router')
-rw-r--r--src/Router/Route.php39
-rw-r--r--src/Router/Router.php68
-rw-r--r--src/Router/RoutesDefinitionInterface.php11
3 files changed, 118 insertions, 0 deletions
diff --git a/src/Router/Route.php b/src/Router/Route.php
new file mode 100644
index 0000000..ee9637b
--- /dev/null
+++ b/src/Router/Route.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace ERPHP\Router;
+
+use Symfony\Component\Routing\Route as SymfonyRoute;
+
+class Route extends SymfonyRoute
+{
+ public function __construct(
+ string $path,
+ callable $action,
+ private string $name = "",
+ array $defaults = [],
+ array $requirements = [],
+ array $options = [],
+ ?string $host = '',
+ string|array $schemes = [],
+ string|array $methods = [],
+ ?string $condition = '',
+ )
+ {
+ if (empty($name)) {
+ $this->name = $path;
+ }
+
+ $defaults = array_merge([
+ "_" => [
+ "action" => $action,
+ ],
+ ], $defaults);
+
+ parent::__construct($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
+ }
+
+ public function getName(): string
+ {
+ return $this->name;
+ }
+}
diff --git a/src/Router/Router.php b/src/Router/Router.php
new file mode 100644
index 0000000..d770f15
--- /dev/null
+++ b/src/Router/Router.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace ERPHP\Router;
+
+use ERPHP\Hook;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Matcher\UrlMatcher;
+use Symfony\Component\Routing\RequestContext;
+use Symfony\Component\Routing\RouteCollection;
+
+class Router
+{
+ private RouteCollection $routes;
+
+ private static self $instance;
+
+ public static function getInstance(): self
+ {
+ if (! isset(self::$instance)) {
+ self::$instance = new self();
+ }
+
+ return self::$instance;
+ }
+
+ public function __construct()
+ {
+ $this->routes = new RouteCollection();
+ }
+
+ public function run(): void
+ {
+ // get defined routes
+ $routeFiles = [];
+ $routeFiles = Hook::applyFilter("Router::getRouteFiles", $routeFiles);
+
+ foreach ($routeFiles as $routesFile) {
+ /** @var RoutesDefinitionInterface $routesDefinition */
+ $routesDefinition = include $routesFile;
+ $routes = $routesDefinition->get();
+
+ foreach ($routes as $route) {
+ /** @var Route[] $route */
+ if (! is_null($this->routes->get($route->getName()))) {
+ throw new \Exception("Route \"{$route->getName()}\" already defined.");
+ }
+
+ $this->routes->add($route->getName(), $route);
+ }
+ }
+
+ $request = Request::createFromGlobals();
+ $response = new Response();
+
+ // set semantically correct request method
+ if ($request->get("_method", false)) {
+ $request->setMethod($request->get("_method"));
+ }
+
+ $matcher = new UrlMatcher($this->routes, new RequestContext());
+ $match = $matcher->matchRequest($request);
+
+ /** @var Response $response */
+ $response = call_user_func_array($match["_"]["action"], [$request]);
+ $response->send();
+ }
+}
diff --git a/src/Router/RoutesDefinitionInterface.php b/src/Router/RoutesDefinitionInterface.php
new file mode 100644
index 0000000..614c7cd
--- /dev/null
+++ b/src/Router/RoutesDefinitionInterface.php
@@ -0,0 +1,11 @@
+<?php
+
+namespace ERPHP\Router;
+
+interface RoutesDefinitionInterface
+{
+ /**
+ * @return Route[]
+ */
+ public function get(): array;
+}