Completed
Push — 8.x-1.x ( 99c4c7...dece3c )
by
unknown
29:31
created

ControllerEventSubscriber::mergeConfigurations()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 7.0487

Importance

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