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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
<?php
namespace Elements;
use Elements\Controller\Card;
use Elements\Controller\Home;
use Symfony\Component\HttpFoundation\RedirectResponse;
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\Route;
use Symfony\Component\Routing\RouteCollection;
class Router
{
private ?RouteCollection $routes;
private array $routeFunctions = [];
/**
* Router constructor.
*/
public function __construct()
{
/**@var Request $request*/
$request = Request::createFromGlobals();
$response = new Response();
$this->routes = new RouteCollection();
$this->addRoute('GET', '/', [Home::class, 'index']);
$this->addRoute('GET', '/dashboard', [Home::class, 'dashboard']);
// card
$this->addRoute('GET', '/card', [Card::class, 'listCards']);
$this->addRoute('GET', '/card/add', [Card::class, 'addCard']);
$this->addRoute('GET', '/card/{id}', [Card::class, 'viewCard']);
$this->addRoute('GET', '/card/{id}/edit', [Card::class, 'editCard']);
$this->addRoute('GET', '/card/{id}/artwork/{artworkId}', [Card::class, 'viewArtwork']);
$this->addRoute('POST', '/card/add', [Card::class, 'add']);
$this->addRoute('POST', '/card/{id}/edit', [Card::class, 'edit']);
$this->addRoute('POST', '/card/{id}/vote', [Card::class, 'vote']);
$context = new RequestContext();
$context->fromRequest($request);
$matcher = new UrlMatcher($this->routes, $context);
try {
$match = $matcher->match($request->getPathInfo());
$request->attributes->set('route', $match);
// run controller function
$content = call_user_func($this->routeFunctions[$match['_route']], $request);
// set response to new response
if ($content instanceof Response) {
$response = $content;
}
// set content directly otherwise
else {
$response->setContent($content);
}
}
// catch any errors
catch (AppException $exception) {
$response->setStatusCode($exception->getCode());
$response->setContent($exception->getMessage());
} catch (\Exception $exception) {
$response->setStatusCode(Response::HTTP_BAD_REQUEST);
$response->setContent($exception->getMessage());
}
$response->send();
}
/**
* @param string|array $methods
* @param string $path
* @param callable $function
*/
public function addRoute(string|array $methods, string $path, array $function)
{
$name = "$function[0]::$function[1]";
$this->routes->add($name, new Route($path, methods: (array)$methods));
$this->routeFunctions[$name] = $function;
}
}
|