DatasourceConfigurator::callDatasource()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5

Importance

Changes 0
Metric Value
eloc 9
c 0
b 0
f 0
dl 0
loc 16
ccs 9
cts 9
cp 1
rs 9.6111
cc 5
nc 3
nop 3
crap 5
1
<?php
2
3
namespace Khusseini\PimcoreRadBrickBundle\Configurator;
4
5
use ArrayObject;
6
use Khusseini\PimcoreRadBrickBundle\ContextInterface;
7
use Khusseini\PimcoreRadBrickBundle\DatasourceRegistry;
8
use Khusseini\PimcoreRadBrickBundle\RenderArgument;
9
use Khusseini\PimcoreRadBrickBundle\RenderArgumentEmitter;
10
use PHP_CodeSniffer\Config;
11
use Symfony\Component\OptionsResolver\OptionsResolver;
12
13
class DatasourceConfigurator extends AbstractConfigurator
14
{
15 7
    public function preCreateEditables(string $brickName, ConfiguratorData $data): void
16
    {
17 7
        $config = $this->resolveConfig($data->getConfig());
18 7
        $context = $data->getContext();
19 7
        $contextArray = $context->toArray();
20
21 7
        $brickConfig = $this->resolveBrickconfig($config['areabricks'][$brickName]);
22 7
        $registry = new DatasourceRegistry();
23 7
        foreach ($brickConfig['datasources'] as $id => $datasourceConfig) {
24 7
            $dsId = $datasourceConfig['id'];
25 7
            $dataSource = $config['datasources'][$dsId];
26 7
            $serviceId = $dataSource['service_id'];
27 7
            $serviceObject = $serviceId;
28
29 7
            if (\is_string($serviceId)) {
30
                $serviceObject = $this
31 7
                    ->getExpressionWrapper()
32 7
                    ->evaluateExpression($serviceId, $contextArray)
33
                ;
34
            }
35
36 7
            if (!\is_object($serviceObject)) {
37 1
                throw new \InvalidArgumentException(sprintf('Service with id "%s" is not an object. %s given.', $serviceId, \gettype($serviceObject)));
38
            }
39
40 6
            $dataCall = $registry->createMethodCall(
41 6
                $serviceObject,
42 6
                $dataSource['method'],
43 6
                $dataSource['args']
44
            );
45
46
            $wrappedCall = function () use ($context, $dataCall, $datasourceConfig) {
47 6
                return $this->callDatasource($context, $dataCall, $datasourceConfig);
48 6
            };
49
50 6
            $registry->add($id, $wrappedCall);
51
        }
52
53 6
        $data->getContext()->setDatasources($registry);
54 6
    }
55
56
    /**
57
     * @param array<string, array<string, mixed>> $config
58
     *
59
     * @return mixed
60
     */
61 6
    protected function callDatasource(ContextInterface $context, callable $dataCall, array $config)
62
    {
63 6
        $input = [];
64
        if (
65 6
                isset($config['conditions'])
66 6
                && \is_array($config['conditions'])
67 6
                && !$this->evaluateConditions($config['conditions'], $context)
68
        ) {
69 1
            return [];
70
        }
71
72 5
        foreach ($config['args'] as $name => $value) {
73 5
            $input[$name] = $this->recurseExpression($value, $context->toArray());
74
        }
75
76 5
        return $dataCall($input);
77
    }
78
79
    /**
80
     * @param string[] $conditions
81
     */
82 2
    protected function evaluateConditions(array $conditions, ContextInterface $context): bool
83
    {
84 2
        $result = true;
85 2
        $contextArray = $context->toArray();
86 2
        foreach ($conditions as $condition) {
87 2
            $value = $this->getExpressionWrapper()->evaluateExpression($condition, $contextArray);
88 2
            $result = ($value !== $condition) && (bool) $value;
89 2
            if (!$result) {
90 1
                return $result;
91
            }
92
        }
93
94 1
        return $result;
95
    }
96
97
    /**
98
     * @param mixed                $value
99
     * @param array<string, mixed> $context
100
     *
101
     * @return mixed
102
     */
103 5
    protected function recurseExpression($value, array $context)
104
    {
105 5
        if (\is_string($value)) {
106
            return $this
107 5
                ->getExpressionWrapper()
108 5
                ->evaluateExpression($value, $context);
109
        }
110
111 1
        if (\is_array($value)) {
112 1
            foreach ($value as $key => $item) {
113 1
                $value[$key] = $this->recurseExpression($item, $context);
114
            }
115
        }
116
117 1
        return $value;
118
    }
119
120 6
    public function generateDatasources(RenderArgumentEmitter $emitter, ConfiguratorData $data): void
121
    {
122 6
        $datasources = $data->getContext()->getDatasources();
123 6
        if (!$datasources) {
124 1
            return;
125
        }
126
127 5
        $data = $datasources->executeAll();
128 5
        foreach ($data as $name => $value) {
129 5
            $argument = new RenderArgument('data', $name, $value);
130 5
            $emitter->emitArgument($argument);
131
        }
132 5
    }
133
134 4
    public function doCreateEditables(RenderArgumentEmitter $emitter, string $name, ConfiguratorData $data): void
135
    {
136 4
        if (!$data->getContext()->getDatasources()) {
137 1
            return;
138
        }
139
140 3
        $editable = $data->getConfig();
141
        if (
142 3
            !isset($editable['datasource'])
143 3
            || !isset($editable['datasource']['name'])
144
        ) {
145 1
            return;
146
        }
147
148 2
        $this->generateDatasources($emitter, $data);
149
150 2
        $datasourceName = $editable['datasource']['name'];
151 2
        $datasourceIdExpression = @$editable['datasource']['id'];
152
153 2
        if (!$emitter->has($datasourceName)) {
154 1
            return;
155
        }
156
157 1
        $dataArgument = $emitter->get($datasourceName);
158
159 1
        unset($editable['datasource']);
160 1
        $items = new ArrayObject();
161
162 1
        foreach ($dataArgument->getValue() as $i => $item) {
163
            //@codeCoverageIgnoreStart
164
            if ($datasourceIdExpression) {
165
                $i = $this
166
                        ->getExpressionWrapper()
167
                        ->evaluateExpression($datasourceIdExpression, ['item' => $item]);
168
            }
169
            //@codeCoverageIgnoreEnd
170
171 1
            $itemArgument = new RenderArgument(
172 1
                'editable',
173
                /* @scrutinizer ignore-type */ $i,
174
                $editable
175
            );
176
177 1
            $items[] = $itemArgument;
178
        }
179
180 1
        $argument = new RenderArgument(
181 1
            'collection',
182
            $name,
183
            $items
184
        );
185
186 1
        $emitter->emitArgument($argument);
187 1
    }
188
189 2
    public function supportsEditable(string $editableName, array $config): bool
190
    {
191 2
        return isset($config['datasource']) && isset($config['datasource']['id']);
192
    }
193
194 1
    public function configureEditableOptions(OptionsResolver $optionsResolver): void
195
    {
196 1
        $optionsResolver->setDefault('datasource', []);
197 1
    }
198
199 1
    public function postCreateEditables(string $brickName, ConfiguratorData $data, RenderArgumentEmitter $emitter): void
200
    {
201 1
        $this->generateDatasources($emitter, $data);
202 1
    }
203
204
    /**
205
     * @param array<mixed> $config
206
     *
207
     * @return array<mixed>
208
     * @codeCoverageIgnore
209
     */
210
    protected function resolveBrickconfig(array $config): array
211
    {
212
        $or = new OptionsResolver();
213
        $or->setDefaults(['datasources' => [], 'editables' => []]);
214
        $or->setDefined(array_keys($config));
215
216
        return $or->resolve($config);
217
    }
218
219
    /**
220
     * @param array<mixed> $config
221
     *
222
     * @return array<mixed>
223
     * @codeCoverageIgnore
224
     */
225
    protected function resolveConfig(array $config): array
226
    {
227
        $or = new OptionsResolver();
228
        $or->setDefaults(['datasources' => [], 'areabricks' => []]);
229
        $or->setDefined(array_keys($config));
230
231
        return $or->resolve($config);
232
    }
233
}
234