summaryrefslogtreecommitdiff
path: root/src/Router.php
blob: 437d995fb7beb838030afbba60e59fa3b17cd9a5 (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
69
70
<?php

namespace App;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Loader\Configurator\RouteConfigurator;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;

class Router
{
  use Singleton;

  private RouteCollection $routes;
  private RouteConfigurator $configurator;

  public function __construct()
  {
    $this->routes = new RouteCollection();
    $this->configurator = new RouteConfigurator($this->routes, $this->routes);

    $this->addRoutes();
  }

  /**
   * match the current url against the routes.
   * also add preflight CORS headers on OPTIONS requests.
   */
  public function run(): Response
  {
    $request = Request::createFromGlobals();

    if ($request->isMethod("OPTIONS")) {
      $response = new Response();
      $response->headers->add([
        "Access-Control-Allow-Origin" => "*",
        "Access-Control-Allow-Methods" => "GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD",
        "Access-Control-Allow-Headers" => "X-Requested-With, Content-Type, Authorization",
      ]);

      return $response;
    }

    $context = new RequestContext();
    $context->fromRequest($request);

    try {
      $matcher = new UrlMatcher($this->routes, $context);
      $match = $matcher->matchRequest($request);

      $class = $match["_controller"][0];
      $method = $match["_controller"][1];

      return (new $class)->$method();
    } catch (\Exception $exception) {
      return new ErrorResponse(ErrorCode::UNKNOWN, "Unknown error occured");
    }
  }

  /**
   * add routes from the routes file
   */
  private function addRoutes(): void
  {
    $routes = include_once(__DIR__ . "/routes.php");
    $routes($this->configurator);
  }
}