ControllerCompilerPass::process()   B
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 35
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 5.0164

Importance

Changes 0
Metric Value
dl 0
loc 35
ccs 21
cts 23
cp 0.913
rs 8.439
c 0
b 0
f 0
cc 5
eloc 22
nc 5
nop 1
crap 5.0164
1
<?php
2
3
namespace BrainExe\Core\DependencyInjection\CompilerPass;
4
5
use BrainExe\Core\Annotations\CompilerPass;
6
use BrainExe\Core\Annotations\Route as RouteAnnotation;
7
use BrainExe\Core\Application\ControllerResolver;
8
use BrainExe\Core\Application\SerializedRouteCollection;
9
use BrainExe\Core\Traits\FileCacheTrait;
10
use Exception;
11
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
12
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
13
use Symfony\Component\DependencyInjection\ContainerBuilder;
14
use Symfony\Component\DependencyInjection\Definition;
15
use Symfony\Component\DependencyInjection\Reference;
16
use Symfony\Component\DependencyInjection\ServiceLocator;
17
use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper;
18
use Symfony\Component\Routing\Route;
19
20
/**
21
 * @CompilerPass(priority=5)
22
 */
23
class ControllerCompilerPass implements CompilerPassInterface
24
{
25
    use FileCacheTrait;
26
27
    const CONTROLLER_TAG = 'controller';
28
    const ROUTE_TAG      = 'route';
29
30
    /**
31
     * {@inheritdoc}
32
     */
33 2
    public function process(ContainerBuilder $container)
34
    {
35 2
        $controllers = $container->findTaggedServiceIds(self::ROUTE_TAG);
36
37 2
        $serialized = [];
38 2
        $consollers = [];
39 2
        foreach ($controllers as $controllerId => $tag) {
40 2
            foreach ($tag as $routeRaw) {
41
                /** @var RouteAnnotation $route */
42 2
                $route = $routeRaw[0];
43
44 2
                $name = $route->getName();
45 2
                if (empty($name)) {
46
                    throw new Exception(sprintf('"name" is missing for @Route(%s)', $controllerId));
47 2
                } elseif (isset($serialized[$name])) {
48
                    throw new Exception(sprintf('Route name %s does already exits in %s', $name, $controllerId));
49
                }
50
51 2
                $serialized[$name] = serialize($this->createRoute($route));
52
            }
53
54 2
            $controller = $container->getDefinition($controllerId);
55 2
            $controller->clearTag(self::ROUTE_TAG);
56 2
            $consollers[$controllerId] = new ServiceClosureArgument(
57 2
                new Reference($controllerId)
58
            );
59
        }
60
61 2
        $controllerResolver = $container->getDefinition(ControllerResolver::class);
62 2
        $controllerResolver->setArguments([new Definition(
63 2
            ServiceLocator::class,
64 2
            [$consollers]
65
        )]);
66 2
        $this->dumpMatcher($container, $serialized);
67 2
    }
68
69
    /**
70
     * @param RouteAnnotation $route
71
     * @return Route
72
     */
73 2
    private function createRoute(RouteAnnotation $route)
74
    {
75 2
        if ($route->isCsrf()) {
76 1
            $route->setOptions(['csrf' => true]);
77
        }
78
79 2
        return new Route(
80 2
            $route->getPath(),
81 2
            $route->getDefaults(),
82 2
            $route->getRequirements(),
83 2
            $route->getOptions(),
84 2
            $route->getHost(),
85 2
            $route->getSchemes(),
86 2
            $route->getMethods(),
87 2
            $route->getCondition()
88
        );
89
    }
90
91
    /**
92
     * @param ContainerBuilder $container
93
     * @param array $routes
94
     * @codeCoverageIgnore
95
     */
96
    protected function dumpMatcher(ContainerBuilder $container, array $routes)
97
    {
98
        ksort($routes);
99
100
        $this->dumpVariableToCache(SerializedRouteCollection::CACHE_FILE, $routes);
101
102
        /** @var SerializedRouteCollection $routerCollection */
103
        $routerCollection = $container->get(SerializedRouteCollection::class);
104
105
        $routerFile  = sprintf('%scache/router_matcher.php', ROOT);
106
        $routeDumper = new PhpMatcherDumper($routerCollection);
107
        $content     = $routeDumper->dump();
108
        file_put_contents($routerFile, $content);
109
    }
110
}
111