1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Bridges\ApplicationDI;
9:
10: use Nette;
11: use Tracy;
12:
13:
14: 15: 16:
17: class RoutingExtension extends Nette\DI\CompilerExtension
18: {
19: public $defaults = [
20: 'debugger' => null,
21: 'routes' => [],
22: 'routeClass' => null,
23: 'cache' => false,
24: ];
25:
26:
27: private $debugMode;
28:
29:
30: public function __construct($debugMode = false)
31: {
32: $this->defaults['debugger'] = interface_exists(Tracy\IBarPanel::class);
33: $this->debugMode = $debugMode;
34: }
35:
36:
37: public function loadConfiguration()
38: {
39: $config = $this->validateConfig($this->defaults);
40: $builder = $this->getContainerBuilder();
41:
42: $router = $builder->addDefinition($this->prefix('router'))
43: ->setClass(Nette\Application\IRouter::class)
44: ->setFactory(Nette\Application\Routers\RouteList::class);
45:
46: $routeClass = $config['routeClass'] ?: 'Nette\Application\Routers\Route';
47: foreach ($config['routes'] as $mask => $action) {
48: $router->addSetup('$service[] = new ' . $routeClass . '(?, ?)', [$mask, $action]);
49: }
50:
51: if ($this->name === 'routing') {
52: $builder->addAlias('router', $this->prefix('router'));
53: }
54: }
55:
56:
57: public function beforeCompile()
58: {
59: $builder = $this->getContainerBuilder();
60:
61: if ($this->debugMode && $this->config['debugger'] && $application = $builder->getByType(Nette\Application\Application::class)) {
62: $builder->getDefinition($application)->addSetup('@Tracy\Bar::addPanel', [
63: new Nette\DI\Statement(Nette\Bridges\ApplicationTracy\RoutingPanel::class),
64: ]);
65: }
66: }
67:
68:
69: public function afterCompile(Nette\PhpGenerator\ClassType $class)
70: {
71: if (!empty($this->config['cache'])) {
72: $method = $class->getMethod(Nette\DI\Container::getMethodName($this->prefix('router')));
73: try {
74: $router = eval($method->getBody());
75: if ($router instanceof Nette\Application\Routers\RouteList) {
76: $router->warmupCache();
77: }
78: $s = serialize($router);
79: } catch (\Exception $e) {
80: throw new Nette\DI\ServiceCreationException('Unable to cache router due to error: ' . $e->getMessage(), 0, $e);
81: } catch (\Throwable $e) {
82: throw new Nette\DI\ServiceCreationException('Unable to cache router due to error: ' . $e->getMessage(), 0, $e);
83: }
84: $method->setBody('return unserialize(?);', [$s]);
85: }
86: }
87: }
88: