Completed
Push — master ( 53c52b...b733d6 )
by Arnaud
15s queued 11s
created

ActionConfiguration::getLoadStrategy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace LAG\AdminBundle\Configuration;
4
5
use Closure;
6
use JK\Configuration\Configuration;
7
use LAG\AdminBundle\Admin\Action;
8
use LAG\AdminBundle\Exception\Exception;
9
use LAG\AdminBundle\Form\Type\DeleteType;
10
use LAG\AdminBundle\LAGAdminBundle;
11
use LAG\AdminBundle\Routing\RoutingLoader;
12
use LAG\AdminBundle\Utils\TranslationUtils;
13
use LAG\Component\StringUtils\StringUtils;
14
use Symfony\Component\OptionsResolver\Options;
15
use Symfony\Component\OptionsResolver\OptionsResolver;
16
17
class ActionConfiguration extends Configuration
18
{
19
    /**
20
     * Related Action name.
21
     *
22
     * @var string
23
     */
24
    protected $actionName;
25
26
    /**
27
     * @var AdminConfiguration
28
     */
29
    protected $adminConfiguration;
30
31
    /**
32
     * @var string
33
     */
34
    protected $adminName;
35
36
    /**
37
     * ActionConfiguration constructor.
38
     */
39 4
    public function __construct(string $actionItemName, string $adminName, AdminConfiguration $adminConfiguration)
40
    {
41 4
        parent::__construct();
42
43 4
        $this->actionName = $actionItemName;
44 4
        $this->adminConfiguration = $adminConfiguration;
45 4
        $this->adminName = $adminName;
46 4
    }
47
48
    /**
49
     * Define allowed parameters and values for this configuration, using optionsResolver component.
50
     */
51 4
    public function configureOptions(OptionsResolver $resolver)
52
    {
53
        $resolver
54 4
            ->setDefaults([
55 4
                'title' => null,
56
                'class' => Action::class,
57
                'fields' => [],
58
                'permissions' => [
59
                    'ROLE_ADMIN',
60
                ],
61
                'export' => [],
62
                'order' => [],
63
                'icon' => null,
64 4
                'load_strategy' => LAGAdminBundle::LOAD_STRATEGY_NONE,
65 4
                'pager' => $this->adminConfiguration->get('pager'),
66 4
                'page_parameter' => $this->adminConfiguration->get('page_parameter'),
67 4
                'max_per_page' => 30,
68
                'criteria' => [],
69
                'filters' => [],
70 4
                'template' => $this->getDefaultTemplate(),
71
                'sortable' => false,
72 4
                'string_length' => $this->adminConfiguration->get('string_length'),
73 4
                'string_length_truncate' => $this->adminConfiguration->get('string_length_truncate'),
74 4
                'date_format' => $this->adminConfiguration->get('date_format'),
75
                'use_form' => true,
76
                'form' => null,
77
                'menus' => $this->adminConfiguration->get('menus'),
78 4
            ])
79 4
            ->setAllowedTypes('title', [
80
                'string',
81
                'null',
82 4
            ])
83 4
            ->setAllowedTypes('class', 'string')
84 4
            ->setAllowedTypes('fields', 'array')
85 4
            ->setAllowedTypes('permissions', 'array')
86 4
            ->setAllowedTypes('export', 'array')
87 4
            ->setAllowedTypes('order', 'array')
88 4
            ->setAllowedTypes('string_length', 'integer')
89 4
            ->setAllowedTypes('string_length_truncate', 'string')
90 4
            ->setNormalizer('fields', $this->getFieldsNormalizer())
91 4
            ->setNormalizer('order', $this->getOrderNormalizer())
92 4
            ->setNormalizer('load_strategy', $this->getLoadStrategyNormalizer())
93 4
            ->setNormalizer('criteria', $this->getCriteriaNormalizer())
94 4
            ->setNormalizer('filters', $this->getFiltersNormalizer())
95 4
            ->setNormalizer('form', $this->getFormNormalizer())
96 4
            ->setNormalizer('title', $this->getTitleNormalizer())
97 4
            ->setAllowedValues('load_strategy', [
98 4
                LAGAdminBundle::LOAD_STRATEGY_NONE,
99 4
                LAGAdminBundle::LOAD_STRATEGY_UNIQUE,
100
                LAGAdminBundle::LOAD_STRATEGY_MULTIPLE,
101 4
            ])
102 4
            ->setAllowedValues('pager', [
103
                'pagerfanta',
104
                false,
105
                null,
106
            ])
107
        ;
108 4
109 4
        $this->configureMenu($resolver);
110 4
        $this->configureRepository($resolver);
111 2
        $this->configureRouting($resolver);
112
    }
113
114
    /**
115
     * Generate an admin route name using the pattern in the configuration.
116
     *
117
     * @throws Exception
118 4
     */
119
    protected function generateRouteName(): string
120 4
    {
121 2
        if (!array_key_exists($this->actionName, $this->adminConfiguration->get('actions'))) {
122
            throw new Exception(sprintf('Invalid action name %s for admin %s (available action are: %s)', $this->actionName, $this->adminName, implode(', ', array_keys($this->adminConfiguration->get('actions')))));
123
        }
124 2
125 2
        return RoutingLoader::generateRouteName(
126 2
            $this->adminName,
127 2
            $this->actionName,
128
            $this->adminConfiguration->get('routing_name_pattern')
129
        );
130
    }
131
132
    /**
133
     * Return the field normalizer. It will transform null configuration into array to allow field type guessing
134
     * working.
135
     *
136
     * @return Closure
137 4
     */
138
    protected function getFieldsNormalizer()
139
    {
140 2
        return function (Options $options, $fields) {
141
            $normalizedFields = [];
142 2
143
            foreach ($fields as $name => $field) {
144
                if (null === $field) {
145
                    $field = [];
146
                }
147
148
                $normalizedFields[$name] = $field;
149
            }
150 2
151 4
            return $normalizedFields;
152
        };
153
    }
154
155
    /**
156
     * Return the order normalizer. It will check if the order value passed are valid.
157
     *
158
     * @return Closure
159 4
     */
160
    protected function getOrderNormalizer()
161
    {
162 2
        return function (Options $options, $order) {
163
            foreach ($order as $field => $sort) {
164
                if (!is_string($sort) || !is_string($field) || !in_array(strtolower($sort), ['asc', 'desc'])) {
165
                    throw new Exception('Order value should be an array of string (["field" => $key]), got '.gettype($sort));
166
                }
167
            }
168 2
169 4
            return $order;
170
        };
171
    }
172
173
    /**
174
     * Return the load strategy normalizer. It will set the default strategy according to the action name, if no value
175
     * is provided.
176
     *
177
     * @return Closure
178 4
     */
179
    protected function getLoadStrategyNormalizer()
180
    {
181 2
        return function (Options $options, $value) {
182
            if (!$value) {
183
                if ('create' == $this->actionName) {
184
                    $value = LAGAdminBundle::LOAD_STRATEGY_NONE;
185
                } elseif ('list' == $this->actionName) {
186
                    $value = LAGAdminBundle::LOAD_STRATEGY_MULTIPLE;
187
                } else {
188
                    $value = LAGAdminBundle::LOAD_STRATEGY_UNIQUE;
189
                }
190
            }
191 2
192 4
            return $value;
193
        };
194
    }
195
196
    /**
197
     * Return the criteria normalizer. It will add the id parameters for the edit and delete actions if no value is
198
     * provided.
199
     *
200
     * @return Closure
201 4
     */
202
    protected function getCriteriaNormalizer()
203
    {
204 2
        return function (Options $options, $value) {
205
            if (!$value) {
206 2
                $idActions = [
207
                    'edit',
208
                    'delete',
209
                ];
210 2
211
                if (in_array($this->actionName, $idActions)) {
212
                    $value = [
213
                        'id',
214
                    ];
215
                }
216
            }
217 2
218 4
            return $value;
219
        };
220
    }
221
222
    public function getAdminName(): string
223
    {
224
        return $this->adminName;
225
    }
226
227
    public function getActionName(): string
228
    {
229
        return $this->actionName;
230
    }
231
232
    public function getAdminConfiguration(): AdminConfiguration
233
    {
234
        return $this->adminConfiguration;
235
    }
236
237
    public function getLoadStrategy(): string
238
    {
239 4
        return $this->parameters->get('load_strategy');
240
    }
241
242 2
    /**
243
     * Return the filters normalizer.
244 2
     */
245
    protected function getFiltersNormalizer(): Closure
246
    {
247
        return function (Options $options, $data) {
248
            $normalizedData = [];
249
250
            foreach ($data as $name => $field) {
251
                if (is_string($field)) {
252
                    $field = [
253
                        'type' => $field,
254
                        'options' => [],
255
                    ];
256
                }
257
                $field['name'] = $name;
258
259
                $resolver = new OptionsResolver();
260
                $filterConfiguration = new FilterConfiguration();
261 2
                $filterConfiguration->configureOptions($resolver);
262 4
                $filterConfiguration->setParameters($resolver->resolve($field));
263
264
                $normalizedData[$name] = $filterConfiguration->getParameters();
265 4
            }
266
267
            return $normalizedData;
268 2
        };
269
    }
270
271
    protected function getFormNormalizer(): Closure
272 2
    {
273 2
        return function (Options $options, $value) {
274
            if (null !== $value) {
275
                return $value;
276
            }
277 2
            $mapping = [
278
                'create' => $this->adminConfiguration->get('form'),
279
                'edit' => $this->adminConfiguration->get('form'),
280
                'delete' => DeleteType::class,
281 2
            ];
282 4
283
            if (key_exists($this->actionName, $mapping)) {
284
                $value = $mapping[$this->actionName];
285 4
            }
286
287
            return $value;
288
        };
289 2
    }
290 2
291 2
    protected function getTitleNormalizer(): Closure
292
    {
293
        return function (Options $options, $value) {
294
            // If the translation system is not used, return the provided value as is
295
            if (!$this->adminConfiguration->isTranslationEnabled()) {
296
                if (null === $value) {
297
                    return StringUtils::camelize($this->actionName);
298
                }
299
300
                return $value;
301
            }
302
303
            // If a value is defined, we should return the value
304
            if (null !== $value) {
305
                return $value;
306
            }
307
            // By default, the action title is action name using the configured translation pattern
308
            $value = TranslationUtils::getTranslationKey(
309 4
                $this->adminConfiguration->getTranslationPattern(),
310
                $this->adminName,
311
                $this->actionName
312
            );
313
314
            return $value;
315 2
        };
316
    }
317
318 2
    /**
319 2
     * Return the default route path according to the action name.
320
     */
321 2
    protected function getDefaultRoutePath(): string
322 2
    {
323
        $pattern = $this
324 2
            ->adminConfiguration
325
            ->get('routing_url_pattern')
326
        ;
327
        $path = str_replace('{admin}', $this->adminName, $pattern);
328 2
        $path = str_replace('{action}', $this->actionName, $path);
329
330
        if (in_array($this->actionName, ['edit', 'delete'])) {
331 4
            $path .= '/{id}';
332
        }
333
334 4
        return $path;
335 4
    }
336 4
337 4
    protected function getDefaultTemplate(): ?string
338
    {
339
        $mapping = [
340 4
            'list' => $this->adminConfiguration->get('list_template'),
341 4
            'edit' => $this->adminConfiguration->get('edit_template'),
342
            'create' => $this->adminConfiguration->get('create_template'),
343
            'delete' => $this->adminConfiguration->get('delete_template'),
344
        ];
345
346
        if (!$this->isActionInMapping($mapping)) {
347 4
            return null;
348
        }
349 4
350
        return $mapping[$this->actionName];
351
    }
352 4
353
    protected function isActionInMapping(array $mapping): bool
354
    {
355 4
        return array_key_exists($this->actionName, $mapping);
356 4
    }
357
358
    protected function configureMenu(OptionsResolver $resolver): void
359 4
    {
360
        $resolver
361 2
            ->setDefaults([
362
                'add_return' => in_array($this->actionName, ['create', 'edit', 'delete']),
363
                'menus' => [],
364
            ])
365 2
            ->setAllowedTypes('add_return', 'boolean')
366
            ->setNormalizer('menus', function (Options $options, $value) {
367
                if (false === $value) {
368
                    $value = [];
369 2
                }
370 2
371
                return $value;
372
            })
373 2
        ;
374 2
    }
375
376
    protected function configureRepository(OptionsResolver $resolver): void
377
    {
378 2
        $resolver
379 2
            ->setDefaults([
380
                'repository_method' => null,
381 2
            ])
382
        ;
383
    }
384
385
    protected function configureRouting(OptionsResolver $resolver): void
386
    {
387
        $resolver
388
            ->setDefaults([
389
                'controller' => $this->adminConfiguration->get('controller'),
390 2
                'route' => $this->generateRouteName(),
391 2
                'route_parameters' => [],
392 2
                'route_path' => $this->getDefaultRoutePath(),
393
                'route_requirements' => [],
394
                'route_defaults' => [],
395 2
            ])
396 2
            ->setAllowedTypes('route', 'string')
397
            ->setAllowedTypes('route_parameters', 'array')
398
            ->setAllowedTypes('route_path', 'string')
399
            ->setAllowedTypes('route_defaults', 'array')
400 2
            ->setAllowedTypes('route_requirements', 'array')
401 4
            ->setNormalizer('route_defaults', function (Options $options, $value) {
402
                if (!$value || is_array($value)) {
403 4
                    $value = [];
404
                }
405 4
406
                if (!key_exists('_controller', $value) || !$value['_controller']) {
407
                    $value['_controller'] = $options->offsetGet('controller');
408 4
                }
409 4
                $value['_admin'] = $this->adminName;
410
                $value['_action'] = $this->actionName;
411
412 4
                return $value;
413
            })
414 4
        ;
415
    }
416
}
417