summaryrefslogtreecommitdiff
path: root/src/Router/Router.php
blob: d770f151ad312c60147e6b9a3ae2c1f0d22125f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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();
  }
}