Completed
Pull Request — master (#36)
by Yann
03:06
created

ResourcesListener::throwMissingException()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
rs 9.4285
cc 2
eloc 8
nc 2
nop 2
1
<?php
2
3
namespace Knp\Rad\ResourceResolver\EventListener;
4
5
use Knp\Rad\ResourceResolver\CasterContainer;
6
use Knp\Rad\ResourceResolver\ParameterCaster;
7
use Knp\Rad\ResourceResolver\Parser;
8
use Knp\Rad\ResourceResolver\ParserContainer;
9
use Knp\Rad\ResourceResolver\ResourceContainer;
10
use Knp\Rad\ResourceResolver\ResourceResolver;
11
use Knp\Rad\ResourceResolver\RoutingNormalizer;
12
use Symfony\Component\HttpFoundation\Response;
13
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
14
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
15
use Knp\Rad\ResourceResolver\MissingResourceHandler;
16
17
class ResourcesListener implements CasterContainer, ParserContainer
18
{
19
    /** @var Parser[] */
20
    private $parsers;
21
22
    /** @var ResourceContainer */
23
    private $container;
24
25
    /** @var ResourceResolver */
26
    private $resolver;
27
28
    /** @var ParameterCaster[] */
29
    private $parameterCasters;
30
31
    /** @var RoutingNormalizer */
32
    private $normalizer;
33
34
    public function __construct(ResourceResolver $resolver, ResourceContainer $container, RoutingNormalizer $normalizer)
35
    {
36
        $this->resolver         = $resolver;
37
        $this->container        = $container;
38
        $this->parsers          = [];
39
        $this->parameterCasters = [];
40
        $this->normalizer       = $normalizer;
41
    }
42
43
    public function resolveResources(FilterControllerEvent $event)
44
    {
45
        $request = $event->getRequest();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 3 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
46
        $resources = [];
47
48
        foreach ($request->attributes->get('_resources', []) as $resourceKey => $resourceValue) {
49
            $resourceValue           = $this->parse($resourceValue) ?: $resourceValue;
50
            $resources[$resourceKey] = $resourceValue;
51
        }
52
53
        foreach ($resources as $resourceKey => $resourceDetails) {
54
            $resourceDetails = $this->normalizer->normalizeDeclaration($resourceDetails);
55
            $parameters      = [];
56
57
            foreach ($resourceDetails['arguments'] as $parameter) {
58
                $parameter    = $this->castParameter($parameter) ?: $parameter;
59
                $parameters[] = $parameter;
60
            }
61
62
            $resource = $this
63
                ->resolver
64
                ->resolveResource(
65
                    $resourceDetails['service'],
66
                    $resourceDetails['method'],
67
                    $parameters
68
                )
69
            ;
70
71
            if (false !== $resourceDetails['required'] && null === $resource) {
72
                if (!array_key_exists('on-missing', $resourceDetails)) {
73
                    throw new NotFoundHttpException(sprintf('The resource %s could not be found', $resourceKey));
74
                }
75
76
                if (!is_array($resourceDetails['on-missing']) || !array_key_exists('throw', $resourceDetails['on-missing'])) {
77
                    throw new \InvalidArgumentException('"on-missing" must be an array and contain "throw" parameter.');
78
                }
79
                $this->throwMissingException($resourceDetails['on-missing'], $resourceKey);
80
            }
81
82
            $request->attributes->set($resourceKey, $resource);
83
84
            $this->container->addResource($resourceKey, $resource);
85
        }
86
87
        return $event;
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    public function addParser(Parser $parser)
94
    {
95
        $this->parsers[] = $parser;
96
97
        return $this;
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103
    public function addParameterCaster(ParameterCaster $parameterCaster)
104
    {
105
        $this->parameterCasters[] = $parameterCaster;
106
107
        return $this;
108
    }
109
110
    private function throwMissingException(array $configuration, $resourceKey)
111
    {
112
        if (!in_array($configuration['throw'], array_keys($this->exceptions))) {
113
            throw new \InvalidArgumentException(sprintf(
114
                '%s is not an available HTTP return code. Available are %s.',
115
                $configuration['throw'],
116
                implode(', ', array_keys($this->exceptions))
0 ignored issues
show
Bug introduced by
The property exceptions does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
117
            ));
118
        }
119
120
        $message = sprintf('The resource %s was not found.', $resourceKey);
121
122
        throw new $this->exceptions[$configuration['throw']]($message);
123
    }
124
125
    /**
126
     * @return null|array
127
     */
128
    private function parse($resourceDetails)
129
    {
130
        foreach ($this->parsers as $parser) {
131
            if (true === $parser->supports($resourceDetails)) {
132
                return $parser->parse($resourceDetails);
133
            }
134
        }
135
    }
136
137
    /**
138
     * @return mixed
139
     */
140
    private function castParameter($parameter)
141
    {
142
        foreach ($this->parameterCasters as $parameterCaster) {
143
            if (true === $parameterCaster->supports($parameter)) {
144
                return $parameterCaster->cast($parameter);
145
            }
146
        }
147
    }
148
}
149