Completed
Push — 8.x-1.x ( 411616...2574ac )
by
unknown
20:15
created

TemplateEventSubscriber::getParameters()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 15
ccs 7
cts 7
cp 1
rs 9.4285
cc 2
eloc 7
nc 2
nop 2
crap 2
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
        $parameters = [];
149 1
        $arguments = $template->getVars();
150
151 1
        if (0 === count($arguments)) {
152 1
            $r = new \ReflectionObject($controller);
153
154 1
            $arguments = [];
155 1
            foreach ($r->getMethod($action)->getParameters() as $param) {
156 1
                $arguments[] = $param;
157
            }
158
        }
159
160
        // fetch the arguments of @Template.vars or everything if desired
161
        // and assign them to the designated template
162 1
        foreach ($arguments as $argument) {
163 1
            if ($argument instanceof \ReflectionParameter) {
164 1
                $name = $argument->getName();
1 ignored issue
show
Bug introduced by
Consider using $argument->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
165 1
                $parameters[$name] = !$request->attributes->has($name)
166 1
                && $argument->isDefaultValueAvailable()
167 1
                    ? $argument->getDefaultValue()
168 1
                    : $request->attributes->get($name);
169
            } else {
170 1
                $parameters[$argument] = $request->attributes->get($argument);
171
            }
172
        }
173
174 1
        return $parameters;
175
    }
176
177
    /**
178
     * @return array
179
     */
180 5
    public static function getSubscribedEvents()
181
    {
182
        return [
183 5
            KernelEvents::CONTROLLER => ['onKernelController', 100],
184
            KernelEvents::VIEW => ['onKernelView', 10],
185
        ];
186
    }
187
}
188