Test Failed
Push — feature/html-code-handler ( 0406d3...1467c9 )
by Arnaud
02:28
created

DoctrineRequirementsProvider::processRow()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 16
nc 4
nop 4
dl 0
loc 25
rs 9.7333
c 0
b 0
f 0
1
<?php
2
3
namespace LAG\SmokerBundle\Bridge\Doctrine\ORM\RequirementsProvider;
4
5
use LAG\SmokerBundle\Bridge\Doctrine\ORM\DataProvider\DoctrineDataProviderInterface;
6
use LAG\SmokerBundle\Exception\Exception;
7
use LAG\SmokerBundle\Exception\Url\UnsupportedUrlException;
8
use LAG\SmokerBundle\Url\Requirements\Mapping\MappingResolverInterface;
9
use LAG\SmokerBundle\Url\Requirements\Provider\RequirementsProviderInterface;
10
use Symfony\Component\OptionsResolver\OptionsResolver;
11
use Symfony\Component\PropertyAccess\PropertyAccess;
12
use Symfony\Component\Routing\Route;
13
use Symfony\Component\Routing\RouterInterface;
14
use Traversable;
15
16
class DoctrineRequirementsProvider implements RequirementsProviderInterface
17
{
18
    private $name = 'default';
19
20
    /**
21
     * @var RouterInterface
22
     */
23
    protected $router;
24
25
    /**
26
     * @var MappingResolverInterface
27
     */
28
    protected $mappingResolver;
29
30
    /**
31
     * @var DoctrineDataProviderInterface
32
     */
33
    protected $dataProvider;
34
35
    /**
36
     * RequirementsProvider constructor.
37
     *
38
     * @param MappingResolverInterface      $mappingResolver
39
     * @param RouterInterface               $router
40
     * @param DoctrineDataProviderInterface $dataProvider
41
     */
42
    public function __construct(
43
        MappingResolverInterface $mappingResolver,
44
        RouterInterface $router,
45
        DoctrineDataProviderInterface $dataProvider
46
    ) {
47
        $this->mappingResolver = $mappingResolver;
48
        $this->router = $router;
49
        $this->dataProvider = $dataProvider;
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function getName(): string
56
    {
57
        return $this->name;
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63
    public function supports(string $routeName): bool
64
    {
65
        $mapping = $this->mappingResolver->resolve($routeName);
66
67
        if ([] === $mapping) {
68
            return false;
69
        }
70
71
        return $this->name === $mapping['provider'];
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77
    public function getRequirementsData(string $routeName, array $options = []): Traversable
78
    {
79
        $options = $this->resolveOptions($options);
80
        $mapping = $this->mappingResolver->resolve($routeName);
81
82
        if ([] === $mapping) {
83
            throw new UnsupportedUrlException($routeName, $this->name);
84
        }
85
86
        if ($this->name !== $mapping['provider']) {
87
            throw new Exception('The provider "'.$this->name.'" does not support the route "'.$routeName.'"');
88
        }
89
90
        if (!key_exists('where', $mapping['options'])) {
91
            $mapping['options']['where'] = [];
92
        }
93
        // Allow optional dynamic criteria to find specific entities
94
        $mapping['options']['where'] = array_merge($mapping['options']['where'], $options['where']);
95
96
        $entities = $this
97
            ->dataProvider
98
            ->getData($mapping['entity'], $mapping['options'])
99
        ;
100
        $route = $this
101
            ->router
102
            ->getRouteCollection()
103
            ->get($routeName)
104
        ;
105
106
        foreach ($entities as $row) {
107
            $values = $this->processRow($row, $routeName, $route, $mapping);
108
109
            yield $values;
110
        }
111
    }
112
113
    /**
114
     * @inheritDoc
115
     */
116
    public function getRequirements(string $routeName): array
117
    {
118
        $route = $this
119
            ->router
120
            ->getRouteCollection()
121
            ->get($routeName)
122
        ;
123
        $requirements = $route->getRequirements();
124
125
        if (0 === count($requirements)) {
126
            $matches = [];
127
            preg_match_all('/{(.*?)}/', $route->getPath(), $matches);
128
129
            $requirements = array_flip($matches[1]);
130
        }
131
132
        return $requirements;
133
    }
134
135
    /**
136
     * @param array $row
137
     * @param string $routeName
138
     * @param Route $route
139
     * @param array $mapping
140
     *
141
     * @return array
142
     *
143
     * @throws Exception
144
     */
145
    private function processRow(array $row, string $routeName, Route $route, array $mapping): array
0 ignored issues
show
Unused Code introduced by
The parameter $route is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

145
    private function processRow(array $row, string $routeName, /** @scrutinizer ignore-unused */ Route $route, array $mapping): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
146
    {
147
        $requirements = $this->getRequirements($routeName);
148
        $entity = $row[0];
149
        $values = [];
150
        $accessor = PropertyAccess::createPropertyAccessor();
151
152
        foreach ($requirements as $name => $requirement) {
153
            if (!key_exists($name, $mapping['requirements'])) {
154
                throw new Exception(sprintf(
155
                    'The requirement "%s" for the route "%s" is not provided',
156
                    $name,
157
                    $routeName
158
                ));
159
            }
160
            $property = $mapping['requirements'][$name];
161
162
            if ('@' === substr($property, 0, 1)) {
163
                $values[$name] = substr($property, 1);
164
            } else {
165
                $values[$name] = $accessor->getValue($entity, $property);
166
            }
167
        }
168
169
        return $values;
170
    }
171
172
    private function resolveOptions(array $options): array
173
    {
174
        $resolver = new OptionsResolver();
175
        $resolver
176
            ->setDefaults([
177
                'where' => [],
178
            ])
179
            ->setAllowedTypes('where', 'array')
180
        ;
181
182
        return $resolver->resolve($options);
183
    }
184
}
185