ParamFetcherListener::getAttributeName()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 7
cts 7
cp 1
rs 9.8333
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3
1
<?php
2
3
/*
4
 * This file is part of the FOSRestBundle package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace FOS\RestBundle\EventListener;
13
14
use FOS\RestBundle\FOSRestBundle;
15
use FOS\RestBundle\Request\ParamFetcherInterface;
16
use Symfony\Component\HttpKernel\Event\ControllerEvent;
17
18
/**
19
 * This listener handles various setup tasks related to the query fetcher.
20
 *
21
 * Setting the controller callable on the query fetcher
22
 * Setting the query fetcher as a request attribute
23
 *
24
 * @author Lukas Kahwe Smith <[email protected]>
25
 *
26
 * @internal
27
 */
28
class ParamFetcherListener
29
{
30
    private $paramFetcher;
31
    private $setParamsAsAttributes;
32
33 20
    public function __construct(ParamFetcherInterface $paramFetcher, bool $setParamsAsAttributes = false)
34
    {
35 20
        $this->paramFetcher = $paramFetcher;
36 20
        $this->setParamsAsAttributes = $setParamsAsAttributes;
37 20
    }
38
39 20
    public function onKernelController(ControllerEvent $event): void
40
    {
41 20
        $request = $event->getRequest();
42
43 20
        if (!$request->attributes->get(FOSRestBundle::ZONE_ATTRIBUTE, true)) {
44 1
            return;
45
        }
46
47 19
        $controller = $event->getController();
48
49 19
        if (is_callable($controller) && method_exists($controller, '__invoke')) {
50 2
            $controller = [$controller, '__invoke'];
51
        }
52
53 19
        $this->paramFetcher->setController($controller);
54 19
        $attributeName = $this->getAttributeName($controller);
55 19
        $request->attributes->set($attributeName, $this->paramFetcher);
56
57 19
        if ($this->setParamsAsAttributes) {
58 7
            $params = $this->paramFetcher->all();
59 7
            foreach ($params as $name => $param) {
60 7
                if ($request->attributes->has($name) && null !== $request->attributes->get($name)) {
61
                    $msg = sprintf("ParamFetcher parameter conflicts with a path parameter '$name' for route '%s'", $request->attributes->get('_route'));
62
63
                    throw new \InvalidArgumentException($msg);
64
                }
65
66 7
                $request->attributes->set($name, $param);
67
            }
68
        }
69 19
    }
70
71 19
    private function getAttributeName(callable $controller): string
72
    {
73 19
        list($object, $name) = $controller;
74 19
        $method = new \ReflectionMethod($object, $name);
75 19
        foreach ($method->getParameters() as $param) {
76 18
            if ($this->isParamFetcherType($param)) {
77 15
                return $param->getName();
0 ignored issues
show
Bug introduced by
Consider using $param->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
78
            }
79
        }
80
81
        // If there is no typehint, inject the ParamFetcher using a default name.
82 5
        return 'paramFetcher';
83
    }
84
85 18
    private function isParamFetcherType(\ReflectionParameter $controllerParam): bool
86
    {
87 18
        $type = $controllerParam->getClass();
88 18
        if (null === $type) {
89 3
            return false;
90
        }
91
92 15
        return $type->implementsInterface(ParamFetcherInterface::class);
93
    }
94
}
95