Completed
Push — master ( 003c1a...870291 )
by Tomáš
06:24
created

autowireControllerTraits()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
c 0
b 0
f 0
rs 8.8571
cc 5
eloc 9
nc 3
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Symplify
7
 * Copyright (c) 2016 Tomas Votruba (http://tomasvotruba.cz).
8
 */
9
10
namespace Symplify\ControllerAutowire\DependencyInjection\Compiler;
11
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 Symplify\ControllerAutowire\Contract\DependencyInjection\ControllerClassMapInterface;
17
use Symplify\ControllerAutowire\Controller\ControllerTrait;
18
use Symplify\ControllerAutowire\Controller\Doctrine\ControllerDoctrineTrait;
19
use Symplify\ControllerAutowire\Controller\Form\ControllerFormTrait;
20
use Symplify\ControllerAutowire\Controller\HttpKernel\ControllerHttpKernelTrait;
21
use Symplify\ControllerAutowire\Controller\Routing\ControllerRoutingTrait;
22
use Symplify\ControllerAutowire\Controller\Security\ControllerSecurityTrait;
23
use Symplify\ControllerAutowire\Controller\Serializer\ControllerSerializerTrait;
24
use Symplify\ControllerAutowire\Controller\Session\ControllerFlashTrait;
25
use Symplify\ControllerAutowire\Controller\Templating\ControllerRenderTrait;
26
27
final class AutowireControllerDependenciesPass implements CompilerPassInterface
28
{
29
    /**
30
     * @var ControllerClassMapInterface
31
     */
32
    private $controllerClassMap;
33
34
    /**
35
     * @var ContainerBuilder
36
     */
37
    private $containerBuilder;
38
39
    /**
40
     * @var array[]
41
     */
42
    private $traitsToSettersToServiceNameList = [
43
        ControllerFlashTrait::class => [
44
            'setSession' => 'session',
45
        ],
46
        ControllerDoctrineTrait::class => [
47
            'setDoctrine' => 'doctrine',
48
        ],
49
        ControllerRoutingTrait::class => [
50
            'setRouter' => 'router',
51
        ],
52
        ControllerHttpKernelTrait::class => [
53
            'setHttpKernel' => 'http_kernel',
54
            'setRequestStack' => 'request_stack',
55
        ],
56
        ControllerSerializerTrait::class => [
57
            'setSerializer' => 'serializer',
58
        ],
59
        ControllerSecurityTrait::class => [
60
            'setAuthorizationChecker' => 'security.authorization_checker',
61
            'setTokenStorage' => 'security.token_storage',
62
            'setCsrfTokenManager' => 'security.csrf.token_manager',
63
        ],
64
        ControllerRenderTrait::class => [
65
            'setTemplating' => 'templating',
66
            'setTwig' => 'twig',
67
        ],
68
        ControllerFormTrait::class => [
69
            'setFormFactory' => 'form.factory',
70
        ],
71
    ];
72
73
    public function __construct(ControllerClassMapInterface $controllerClassMap)
74
    {
75
        $this->controllerClassMap = $controllerClassMap;
76
    }
77
78
    public function process(ContainerBuilder $containerBuilder)
79
    {
80
        $this->containerBuilder = $containerBuilder;
81
82
        foreach ($this->controllerClassMap->getControllers() as $serviceId => $className) {
83
            $controllerDefinition = $containerBuilder->getDefinition($serviceId);
84
            $this->autowireControllerTraits($controllerDefinition);
85
        }
86
    }
87
88
    private function autowireControllerTraits(Definition $controllerDefinition)
89
    {
90
        $usedTraits = class_uses($controllerDefinition->getClass());
91
92
        foreach ($this->traitsToSettersToServiceNameList as $traitClass => $setterToServiceNames) {
93
            if (! $this->isTraitIncluded($traitClass, $usedTraits)) {
94
                continue;
95
            }
96
97
            foreach ($setterToServiceNames as $setter => $serviceName) {
98
                if (! $this->containerBuilder->has($serviceName)) {
99
                    continue;
100
                }
101
102
                $controllerDefinition->addMethodCall($setter, [new Reference($serviceName)]);
103
            }
104
        }
105
    }
106
107
    private function isTraitIncluded(string $traitClass, array $usedTraits) : bool
108
    {
109
        if (array_key_exists($traitClass, $usedTraits)) {
110
            return true;
111
        }
112
113
        if (isset($usedTraits[ControllerTrait::class])) {
114
            return true;
115
        }
116
117
        return false;
118
    }
119
}
120