ControllerEventSubscriber::mergeConfigurations()   B
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 6

Importance

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