Completed
Push — 8.x-1.x ( 7e02f0...32484e )
by
unknown
19:54
created

ControllerEventSubscriber::getConfigurations()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.0187

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 19
ccs 10
cts 11
cp 0.9091
rs 8.8571
cc 5
eloc 12
nc 5
nop 1
crap 5.0187
1
<?php
2
3
namespace Drupal\controller_annotations\EventSubscriber;
4
5
use Doctrine\Common\Annotations\Reader;
6
use Doctrine\Common\Util\ClassUtils;
7
use Drupal\controller_annotations\Configuration\ConfigurationInterface;
8
use Drupal\controller_annotations\Configuration\ConfigurationLoader;
9
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
10
use Symfony\Component\HttpFoundation\Request;
11
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
12
use Symfony\Component\HttpKernel\KernelEvents;
13
14
class ControllerEventSubscriber implements EventSubscriberInterface
15
{
16
    /**
17
     * @var Reader
18
     */
19
    protected $reader;
20
21
    /**
22
     * Constructor.
23
     *
24
     * @param Reader $reader An Reader instance
25
     */
26 13
    public function __construct(Reader $reader)
27
    {
28 13
        $this->reader = $reader;
29
30 13
        ConfigurationLoader::load();
31 13
    }
32
33
    /**
34
     * Modifies the Request object to apply configuration information found in
35
     * controllers annotations like the template to render or HTTP caching
36
     * configuration.
37
     *
38
     * @param FilterControllerEvent $event A FilterControllerEvent instance
39
     */
40 10
    public function onKernelController(FilterControllerEvent $event)
41
    {
42 10
        $controller = $event->getController();
43
44 10
        if (!is_array($controller) && method_exists($controller, '__invoke')) {
45 2
            $controller = array($controller, '__invoke');
46
        }
47
48 10
        if (!is_array($controller)) {
49 1
            return;
50
        }
51
52 9
        $className = ClassUtils::getClass($controller[0]);
53 9
        $object = new \ReflectionClass($className);
54 9
        $method = $object->getMethod($controller[1]);
55
56 9
        $classConfigurations = $this->getConfigurations($this->reader->getClassAnnotations($object));
57 9
        $methodConfigurations = $this->getConfigurations($this->reader->getMethodAnnotations($method));
58
59 9
        $this->setRequestAttributes(
60 9
            $event->getRequest(),
61 9
            $this->mergeConfigurations($classConfigurations, $methodConfigurations)
62
        );
63 9
    }
64
65
    /**
66
     * @param Request $request
67
     * @param array $configurations
68
     */
69 9
    protected function setRequestAttributes(Request $request, array $configurations)
70
    {
71 9
        foreach ($configurations as $key => $attributes) {
72 8
            $request->attributes->set($key, $attributes);
73
        }
74 9
    }
75
76
    /**
77
     * @param array $classConfigurations
78
     * @param array $methodConfigurations
79
     *
80
     * @return array
81
     */
82 12
    protected function mergeConfigurations(array $classConfigurations, array $methodConfigurations)
83
    {
84 12
        $configurations = [];
85 12
        foreach (array_merge(array_keys($classConfigurations), array_keys($methodConfigurations)) as $key) {
86 11
            if (!array_key_exists($key, $classConfigurations)) {
87 7
                $configurations[$key] = $methodConfigurations[$key];
88 6
            } elseif (!array_key_exists($key, $methodConfigurations)) {
89 3
                $configurations[$key] = $classConfigurations[$key];
90
            } else {
91 3
                if (is_array($classConfigurations[$key])) {
92 2
                    if (!is_array($methodConfigurations[$key])) {
93 1
                        throw new \UnexpectedValueException('Configurations should both be an array or both not be an array');
94
                    }
95 1
                    $configurations[$key] = array_merge($classConfigurations[$key], $methodConfigurations[$key]);
96
                } else {
97
                    // method configuration overrides class configuration
98 10
                    $configurations[$key] = $methodConfigurations[$key];
99
                }
100
            }
101
        }
102
103 11
        return $configurations;
104
    }
105
106
    /**
107
     * @param array $annotations
108
     *
109
     * @return array
110
     */
111 9
    protected function getConfigurations(array $annotations)
112
    {
113 9
        $configurations = [];
114 9
        foreach ($annotations as $configuration) {
115 8
            if ($configuration instanceof ConfigurationInterface) {
116 8
                if ($configuration->allowArray()) {
117 2
                    $configurations['_'.$configuration->getAliasName()][] = $configuration;
118 7
                } elseif (!isset($configurations['_'.$configuration->getAliasName()])) {
119 7
                    $configurations['_'.$configuration->getAliasName()] = $configuration;
120
                } else {
121
                    throw new \LogicException(
122 8
                        sprintf('Multiple "%s" annotations are not allowed.', $configuration->getAliasName())
123
                    );
124
                }
125
            }
126
        }
127
128 9
        return $configurations;
129
    }
130
131
    /**
132
     * @return array
133
     */
134 7
    public static function getSubscribedEvents()
135
    {
136
        return [
137
            KernelEvents::CONTROLLER => [
138
                ['onKernelController', 200],
139
            ]
140 7
        ];
141
    }
142
}
143