ORMRequirementsProvider::processRow()   A
last analyzed

Complexity

Conditions 5
Paths 7

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 5.0406

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 17
c 1
b 0
f 0
nc 7
nop 3
dl 0
loc 27
ccs 15
cts 17
cp 0.8824
crap 5.0406
rs 9.3888
1
<?php
2
3
namespace LAG\SmokerBundle\Bridge\Doctrine\ORM\RequirementsProvider;
4
5
use LAG\SmokerBundle\Contracts\DataProvider\DataProviderInterface;
6
use LAG\SmokerBundle\Contracts\Requirements\Mapping\MappingResolverInterface;
7
use LAG\SmokerBundle\Contracts\Requirements\Provider\RequirementsProviderInterface;
8
use LAG\SmokerBundle\Exception\Exception;
9
use LAG\SmokerBundle\Exception\Url\UnsupportedUrlException;
10
use Symfony\Component\OptionsResolver\OptionsResolver;
11
use Symfony\Component\PropertyAccess\PropertyAccess;
12
use Symfony\Component\Routing\RouterInterface;
13
use Traversable;
14
15
class ORMRequirementsProvider implements RequirementsProviderInterface
16
{
17
    private $name = 'default';
18
19
    /**
20
     * @var RouterInterface
21
     */
22
    protected $router;
23
24
    /**
25
     * @var MappingResolverInterface
26
     */
27
    protected $mappingResolver;
28
29
    /**
30
     * @var DataProviderInterface
31
     */
32
    protected $dataProvider;
33
34
    /**
35
     * RequirementsProvider constructor.
36
     */
37 7
    public function __construct(
38
        MappingResolverInterface $mappingResolver,
39
        RouterInterface $router,
40
        DataProviderInterface $dataProvider
41
    ) {
42 7
        $this->mappingResolver = $mappingResolver;
43 7
        $this->router = $router;
44 7
        $this->dataProvider = $dataProvider;
45 7
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50 1
    public function getName(): string
51
    {
52 1
        return $this->name;
53
    }
54
55
    /**
56
     * {@inheritdoc}
57
     */
58 3
    public function supports(string $routeName): bool
59
    {
60 3
        $mapping = $this->mappingResolver->resolve($routeName);
61
62 3
        if ([] === $mapping) {
63 2
            return false;
64
        }
65
66 1
        return $this->name === $mapping['provider'];
67
    }
68
69
    /**
70
     * {@inheritdoc}
71
     */
72 1
    public function getRequirementsData(string $routeName, array $options = []): Traversable
73
    {
74 1
        $options = $this->resolveOptions($options);
75 1
        $mapping = $this->mappingResolver->resolve($routeName);
76
77 1
        if ([] === $mapping) {
78
            throw new UnsupportedUrlException($routeName, $this->name);
79
        }
80
81 1
        if ($this->name !== $mapping['provider']) {
82
            throw new Exception('The provider "'.$this->name.'" does not support the route "'.$routeName.'"');
83
        }
84
85 1
        if (!key_exists('where', $mapping['options'])) {
86 1
            $mapping['options']['where'] = [];
87
        }
88
89 1
        if (!is_array($mapping['options']['where'])) {
90
            $mapping['options']['where'] = [
91
                $mapping['options']['where'],
92
            ];
93
        }
94
        // Allow optional dynamic criteria to find specific entities
95 1
        $mapping['options']['where'] = array_merge($mapping['options']['where'], $options['where']);
96
97
        $entities = $this
98 1
            ->dataProvider
99 1
            ->getData($mapping['entity'], $mapping['options'])
100
        ;
101
102 1
        foreach ($entities as $row) {
103 1
            $values = $this->processRow($row, $routeName, $mapping);
104
105 1
            yield $values;
106
        }
107 1
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112 3
    public function getRequirements(string $routeName): array
113
    {
114
        $route = $this
115 3
            ->router
116 3
            ->getRouteCollection()
117 3
            ->get($routeName)
118
        ;
119 3
        $requirements = $route->getRequirements();
120
121 3
        if (0 === count($requirements)) {
122 2
            $matches = [];
123 2
            preg_match_all('/{(.*?)}/', $route->getPath(), $matches);
124
125 2
            $requirements = array_flip($matches[1]);
126
        }
127
128 3
        return $requirements;
129
    }
130
131
    /**
132
     * {@inheritdoc}
133
     */
134
    public function getDataProvider(): DataProviderInterface
135
    {
136
        return $this->dataProvider;
137
    }
138
139
    /**
140
     * @throws Exception
141
     */
142 1
    private function processRow(array $row, string $routeName, array $mapping): array
143
    {
144 1
        $requirements = $this->getRequirements($routeName);
145 1
        $entity = $row[0];
146 1
        $values = [];
147 1
        $accessor = PropertyAccess::createPropertyAccessor();
148
149 1
        foreach ($requirements as $name => $requirement) {
150 1
            if (!key_exists($name, $mapping['requirements'])) {
151
                throw new Exception(sprintf('The requirement "%s" for the route "%s" is not provided', $name, $routeName));
152
            }
153 1
            $property = $mapping['requirements'][$name];
154
155 1
            if ('@' === substr($property, 0, 1)) {
156 1
                $values[$name] = substr($property, 1);
157
            } else {
158 1
                $values[$name] = $accessor->getValue($entity, $property);
159
            }
160
        }
161 1
        $identifiers = $this->dataProvider->getIdentifier($mapping['entity']);
162 1
        $values['_identifiers'] = [];
163
164 1
        foreach ($identifiers as $identifier) {
165
            $values['_identifiers'][$identifier] = $accessor->getValue($entity, $identifier);
166
        }
167
168 1
        return $values;
169
    }
170
171 1
    private function resolveOptions(array $options): array
172
    {
173 1
        $resolver = new OptionsResolver();
174
        $resolver
175 1
            ->setDefaults([
176 1
                'where' => [],
177
            ])
178 1
            ->setAllowedTypes('where', 'array')
179
        ;
180
181 1
        return $resolver->resolve($options);
182
    }
183
}
184