Completed
Push — 8.x-1.x ( 36574f...05bb7c )
by
unknown
24:36
created

TemplateEventSubscriber::resolveParametersWithReflection()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 17
ccs 11
cts 11
cp 1
rs 8.8571
cc 5
eloc 12
nc 6
nop 2
crap 5
1
<?php
2
3
namespace Drupal\controller_annotations\EventSubscriber;
4
5
use Drupal\controller_annotations\Configuration\Template;
6
use Drupal\controller_annotations\Templating\TemplateResolver;
7
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
8
use Symfony\Component\HttpFoundation\Request;
9
use Symfony\Component\HttpFoundation\Response;
10
use Symfony\Component\HttpFoundation\StreamedResponse;
11
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
12
use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
13
use Symfony\Component\HttpKernel\Event\KernelEvent;
14
use Symfony\Component\HttpKernel\KernelEvents;
15
16
class TemplateEventSubscriber implements EventSubscriberInterface
17
{
18
    /**
19
     * @var \Twig_Environment
20
     */
21
    private $twig;
22
23
    /**
24
     * @var TemplateResolver
25
     */
26
    private $resolver;
27
28
    /**
29
     * @param \Twig_Environment $twig
30
     * @param TemplateResolver $resolver
31
     */
32 11
    public function __construct(\Twig_Environment $twig, TemplateResolver $resolver)
33
    {
34 11
        $this->twig = $twig;
35 11
        $this->resolver = $resolver;
36 11
    }
37
38
    /**
39
     * Guesses the template name to render and its variables and adds them to
40
     * the request object.
41
     *
42
     * @param FilterControllerEvent $event A FilterControllerEvent instance
43
     */
44 9
    public function onKernelController(FilterControllerEvent $event)
45
    {
46 9
        $template = $this->getTemplateFromRequest($event);
47 9
        if (!$template instanceof Template) {
48 6
            return;
49
        }
50
51 3
        $template->setOwner($event->getController());
0 ignored issues
show
Documentation introduced by
$event->getController() is of type callable, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
52 3
        $this->normalizeTemplate($template);
53 3
    }
54
55
    /**
56
     * Renders the template and initializes a new response object with the
57
     * rendered template content.
58
     *
59
     * @param GetResponseForControllerResultEvent $event
60
     */
61 8
    public function onKernelView(GetResponseForControllerResultEvent $event)
62
    {
63 8
        $template = $this->getTemplateFromRequest($event);
64 8
        if (!$template instanceof Template) {
65 5
            return;
66
        }
67
68 3
        $this->setResponse($event, $template, $this->getParameters($event, $template));
69 3
    }
70
71
    /**
72
     * @param KernelEvent $event
73
     * @return mixed
74
     */
75 11
    private function getTemplateFromRequest(KernelEvent $event)
76
    {
77 11
        return $event->getRequest()->attributes->get('_template');
78
    }
79
80
    /**
81
     * @param Template $template
82
     */
83 3
    private function normalizeTemplate(Template $template)
84
    {
85 3
        if (is_null($template->getTemplate())) {
86 2
            $templateFile = $this->resolver->resolveByControllerAndAction(
87 2
                get_class($template->getOwner()[0]),
88 2
                $template->getOwner()[1]
89
            );
90
        } else {
91 2
            $templateFile = $this->resolver->normalize($template->getTemplate());
92
        }
93
94 3
        $template->setTemplate($templateFile);
95 3
    }
96
97
    /**
98
     * @param GetResponseForControllerResultEvent $event
99
     * @param Template $template
100
     * @param $parameters
101
     */
102 3
    private function setResponse(GetResponseForControllerResultEvent $event, Template $template, $parameters)
103
    {
104
        // make sure the owner (controller+dependencies) is not cached or stored elsewhere
105 3
        $template->setOwner([]);
106
107 3
        if ($template->isStreamable()) {
108 1
            $callback = function () use ($template, $parameters) {
109 1
                $this->twig->display($template->getTemplate(), $parameters);
110 1
            };
111
112 1
            $event->setResponse(new StreamedResponse($callback));
113
        } else {
114 2
            $event->setResponse(new Response($this->twig->render($template->getTemplate(), $parameters)));
115
        }
116 3
    }
117
118
    /**
119
     * @param GetResponseForControllerResultEvent $event
120
     * @param Template $template
121
     * @return array|mixed
122
     */
123 3
    private function getParameters(GetResponseForControllerResultEvent $event, Template $template)
124
    {
125 3
        $parameters = $event->getControllerResult();
126
127 3
        $owner = $template->getOwner();
128 3
        list($controller, $action) = $owner;
129
130
        // when the annotation declares no default vars and the action returns
131
        // null, all action method arguments are used as default vars
132 3
        if (null === $parameters) {
133 1
            $parameters = $this->resolveDefaultParameters($event->getRequest(), $template, $controller, $action);
134
        }
135
136 3
        return $parameters;
137
    }
138
139
    /**
140
     * @param Request $request
141
     * @param Template $template
142
     * @param object $controller
143
     * @param string $action
144
     * @return array
145
     */
146 1
    private function resolveDefaultParameters(Request $request, Template $template, $controller, $action)
147
    {
148 1
        $arguments = $template->getVars();
149
150 1
        if (0 === count($arguments)) {
151 1
            $r = new \ReflectionObject($controller);
152
153 1
            $arguments = [];
154 1
            foreach ($r->getMethod($action)->getParameters() as $param) {
155 1
                $arguments[] = $param;
156
            }
157
        }
158
159 1
        return $this->resolveParametersWithReflection($request, $arguments);
160
    }
161
162
    /**
163
     * fetch the arguments of @Template.vars or everything if desired
164
     * and assign them to the designated template
165
     *
166
     * @param Request $request
167
     * @param array $arguments
168
     * @return array
169
     */
170 1
    private function resolveParametersWithReflection(Request $request, array $arguments)
171
    {
172 1
        $parameters = [];
173 1
        foreach ($arguments as $argument) {
174 1
            if ($argument instanceof \ReflectionParameter) {
175 1
                $name = $argument->getName();
176 1
                $parameters[$name] = !$request->attributes->has($name)
177 1
                && $argument->isDefaultValueAvailable()
178 1
                    ? $argument->getDefaultValue()
179 1
                    : $request->attributes->get($name);
180
            } else {
181 1
                $parameters[$argument] = $request->attributes->get($argument);
182
            }
183
        }
184
185 1
        return $parameters;
186
    }
187
188
    /**
189
     * @return array
190
     */
191 5
    public static function getSubscribedEvents()
192
    {
193
        return [
194 5
            KernelEvents::CONTROLLER => ['onKernelController', 100],
195
            KernelEvents::VIEW => ['onKernelView', 10],
196
        ];
197
    }
198
}
199