Completed
Push — master ( 1fe708...6360f1 )
by Arnaud
16s queued 12s
created

ActionConfiguration::shouldAddReturnLink()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace LAG\AdminBundle\Configuration;
6
7
use Closure;
8
use JK\Configuration\Configuration;
9
use LAG\AdminBundle\Admin\Action;
10
use LAG\AdminBundle\Admin\AdminInterface;
11
use LAG\AdminBundle\Controller\AdminAction;
12
use LAG\AdminBundle\Exception\Exception;
13
use LAG\AdminBundle\Form\Type\AdminType;
14
use LAG\AdminBundle\Form\Type\DeleteType;
15
use Symfony\Component\Form\Extension\Core\Type\TextType;
16
use Symfony\Component\OptionsResolver\Options;
17
use Symfony\Component\OptionsResolver\OptionsResolver;
18
use function Symfony\Component\String\u;
19
20
class ActionConfiguration extends Configuration
21
{
22 31
    protected function configureOptions(OptionsResolver $resolver): void
23
    {
24
        $resolver
25
            // Main info
26 31
            ->setRequired('name')
27 31
            ->setAllowedTypes('name', 'string')
28 31
            ->setRequired('admin_name')
29 31
            ->setAllowedTypes('admin_name', 'string')
30 31
            ->setDefault('title', null)
31 31
            ->addNormalizer('title', $this->getTitleNormalizer())
32 31
            ->setAllowedTypes('title', ['string', 'null'])
33 31
            ->setDefault('icon', null)
34 31
            ->setAllowedTypes('icon', ['string', 'null'])
35 31
            ->setDefault('action_class', Action::class)
36 31
            ->setAllowedTypes('action_class', 'string')
37 31
            ->setRequired('template')
38 31
            ->setAllowedTypes('template', 'string')
39
40
            // Routing
41 31
            ->setDefault('controller', AdminAction::class)
42 31
            ->setAllowedTypes('controller', 'string')
43 31
            ->setRequired('route')
44 31
            ->setAllowedTypes('route', 'string')
45 31
            ->setDefault('route_parameters', [])
46 31
            ->setAllowedTypes('route_parameters', 'array')
47 31
            ->addNormalizer('route_parameters', $this->getRouteParametersNormalizer())
48 31
            ->setDefault('path', null)
49 31
            ->setAllowedTypes('path', ['string', 'null'])
50 31
            ->addNormalizer('path', $this->getPathNormalizer())
51
52
            // Fields
53 31
            ->setDefault('fields', [])
54 31
            ->setAllowedTypes('fields', 'array')
55 31
            ->addNormalizer('fields', $this->getFieldsNormalizer())
56
57
            // Filter and orders
58 31
            ->setDefault('order', [])
59 31
            ->setAllowedTypes('order', 'array')
60 31
            ->addNormalizer('order', $this->getOrderNormalizer())
61 31
            ->setDefault('criteria', [])
62 31
            ->setAllowedTypes('criteria', 'array')
63 31
            ->addNormalizer('criteria', $this->getCriteriaNormalizer())
64 31
            ->setDefault('filters', [])
65 31
            ->setAllowedTypes('filters', 'array')
66 31
            ->addNormalizer('filters', $this->getFiltersNormalizer())
67
68
            // Security
69 31
            ->setDefault('permissions', ['ROLE_ADMIN'])
70 31
            ->setAllowedTypes('permissions', 'array')
71
72
            // Export
73 31
            ->setDefault('export', ['csv', 'xml', 'yaml'])
74 31
            ->setAllowedTypes('export', 'array')
75
76
            // Data
77 31
            ->setDefault('load_strategy', null)
78 31
            ->setAllowedValues('load_strategy', [
79 31
                null,
80
                AdminInterface::LOAD_STRATEGY_NONE,
81
                AdminInterface::LOAD_STRATEGY_UNIQUE,
82
                AdminInterface::LOAD_STRATEGY_MULTIPLE,
83
            ])
84 31
            ->addNormalizer('load_strategy', $this->getLoadStrategyNormalizer())
85 31
            ->setDefault('repository_method', null)
86 31
            ->setAllowedTypes('repository_method', ['string', 'null'])
87
88
            // Pagination
89 31
            ->setDefault('pager', 'pagerfanta')
90 31
            ->setAllowedValues('pager', ['pagerfanta', false])
91 31
            ->setDefault('max_per_page', 25)
92 31
            ->setAllowedTypes('max_per_page', 'integer')
93 31
            ->setDefault('page_parameter', 'page')
94 31
            ->setAllowedTypes('page_parameter', 'string')
95
96 31
            ->setDefault('date_format', 'Y-m-d')
97 31
            ->setAllowedTypes('date_format', 'string')
98
99
            // Form
100 31
            ->setDefault('form', null)
101 31
            ->setAllowedTypes('form', ['string', 'null', 'boolean'])
102 31
            ->addNormalizer('form', $this->getFormNormalizer())
103 31
            ->setDefault('form_options', [])
104 31
            ->setAllowedTypes('form_options', 'array')
105
106
            // Menus
107 31
            ->setDefault('menus', [])
108 31
            ->setAllowedTypes('menus', 'array')
109
110
            // Redirection after success
111 31
            ->setDefault('redirect', null)
112 31
            ->setAllowedTypes('redirect', ['string', 'null'])
113 31
            ->setDefault('add_return_link', null)
114 31
            ->setAllowedTypes('add_return_link', ['boolean', 'null'])
115 31
            ->addNormalizer('add_return_link', function (Options $options, $value) {
116 29
                return $value ?? $options->offsetGet('name') !== 'list';
117 31
            })
118
        ;
119 31
    }
120
121 3
    public function getName(): string
122
    {
123 3
        return $this->getString('name');
124
    }
125
126 3
    public function getAdminName(): string
127
    {
128 3
        return $this->getString('admin_name');
129
    }
130
131 1
    public function getTitle(): string
132
    {
133 1
        return $this->getString('title');
134
    }
135
136 1
    public function getIcon(): ?string
137
    {
138 1
        return $this->get('icon');
139
    }
140
141 1
    public function getActionClass(): string
142
    {
143 1
        return $this->getString('action_class');
144
    }
145
146 3
    public function getTemplate(): string
147
    {
148 3
        return $this->get('template');
149
    }
150
151 1
    public function getController(): string
152
    {
153 1
        return $this->getString('controller');
154
    }
155
156 1
    public function getRoute(): string
157
    {
158 1
        return $this->getString('route');
159
    }
160
161 3
    public function getRouteParameters(): array
162
    {
163 3
        return $this->get('route_parameters');
164
    }
165
166 5
    public function getPath(): string
167
    {
168 5
        return $this->getString('path');
169
    }
170
171 4
    public function getFields(): array
172
    {
173 4
        return $this->get('fields');
174
    }
175
176 1
    public function getOrder(): array
177
    {
178 1
        return $this->get('order');
179
    }
180
181 1
    public function getCriteria(): array
182
    {
183 1
        return $this->get('criteria');
184
    }
185
186 3
    public function getFilters(): array
187
    {
188 3
        return $this->get('filters');
189
    }
190
191 1
    public function getPermissions(): array
192
    {
193 1
        return $this->get('permissions');
194
    }
195
196 1
    public function getExport(): array
197
    {
198 1
        return $this->get('export');
199
    }
200
201 6
    public function getLoadStrategy(): string
202
    {
203 6
        return $this->getString('load_strategy');
204
    }
205
206 3
    public function isPaginationEnabled(): bool
207
    {
208 3
        $pager = $this->get('pager');
209
210 3
        if ($pager === false) {
211 2
            return false;
212
        }
213
214 1
        return true;
215
    }
216
217 2
    public function getPager(): string
218
    {
219 2
        if (!$this->isPaginationEnabled()) {
220 1
            throw new Exception('The pagination is not enabled');
221
        }
222
223 1
        return $this->getString('pager');
224
    }
225
226 2
    public function getMaxPerPage(): int
227
    {
228 2
        if (!$this->isPaginationEnabled()) {
229 1
            throw new Exception('The pagination is not enabled');
230
        }
231
232 1
        return $this->getInt('max_per_page');
233
    }
234
235 1
    public function getPageParameter(): string
236
    {
237 1
        return $this->getString('page_parameter');
238
    }
239
240 1
    public function getDateFormat(): string
241
    {
242 1
        return $this->getString('date_format');
243
    }
244
245 10
    public function getForm(): ?string
246
    {
247 10
        return $this->get('form');
248
    }
249
250 3
    public function getFormOptions(): array
251
    {
252 3
        return $this->get('form_options');
253
    }
254
255 1
    public function getMenus(): array
256
    {
257 1
        return $this->get('menus');
258
    }
259
260
    public function getRepositoryMethod(): ?string
261
    {
262
        return $this->get('repository_method');
263
    }
264
265
    public function getRedirect(): ?string
266
    {
267
        return $this->get('redirect');
268
    }
269
270
    public function shouldAddReturnLink(): bool
271
    {
272
        return $this->getBool('add_return_link');
273
    }
274
275 31
    private function getTitleNormalizer(): Closure
276
    {
277 31
        return function (Options $options, $value) {
278 30
            if ($value === null) {
279 30
                $value = u($options->offsetGet('name'))->camel()->title()->toString();
280
            }
281
282 30
            return $value;
283 31
        };
284
    }
285
286 31
    private function getPathNormalizer(): Closure
287
    {
288 31
        return function (Options $options, $value) {
289 30
            if ($value !== null) {
290 27
                $path = u($value);
291
292 27
                if ($path->endsWith('/')) {
293 1
                    $path = $path->slice(0, -1);
294
                }
295
296 27
                return $path->toString();
297
            }
298 3
            $loadStrategy = $options->offsetGet('load_strategy');
299 3
            $path = u($options->offsetGet('admin_name'))
300 3
                ->snake()
301 3
                ->replace('_', '-')
302
            ;
303
304 3
            if (!$path->endsWith('s')) {
305 3
                $path = $path->append('s');
306
307 3
                if ($path->endsWith('ys')) {
308 2
                    $path = $path->before('ys')->append('ies');
309
                }
310
            }
311 3
            $snakeActionName = u($options->offsetGet('name'))
312 3
                ->snake()
313 3
                ->replace('_', '-')
314 3
                ->toString()
315
            ;
316
317
            // Edit the the default action. It is not append to the path (ex: articles/{id} for edit,
318
            // articles/{id}/delete for delete)
319 3
            if ($loadStrategy === AdminInterface::LOAD_STRATEGY_UNIQUE) {
320 1
                $path = $path->append('/{id}');
321
322 1
                if ($options->offsetGet('name') !== 'edit') {
323
                    $path = $path
324 1
                        ->append('/')
325 1
                        ->append($snakeActionName)
326
                    ;
327
                }
328
            }
329
330 3
            if ($loadStrategy === AdminInterface::LOAD_STRATEGY_NONE) {
331
                $path = $path
332 1
                    ->append('/')
333 1
                    ->append($snakeActionName)
334
                ;
335
            }
336
337 3
            return $path->toString();
338 31
        };
339
    }
340
341
    /**
342
     * Return the field normalizer. It will transform null configuration into array to allow field type guessing
343
     * working.
344
     */
345 31
    private function getFieldsNormalizer(): Closure
346
    {
347 31
        return function (Options $options, $fields) {
348 30
            $normalizedFields = [];
349
350 30
            foreach ($fields as $name => $field) {
351 3
                if ($field === null) {
352 1
                    $field = [];
353
                }
354
355 3
                $normalizedFields[$name] = $field;
356
            }
357
358 30
            return $normalizedFields;
359 31
        };
360
    }
361
362
    /**
363
     * Return the order normalizer. It will check if the order value passed are valid.
364
     */
365 31
    private function getOrderNormalizer(): Closure
366
    {
367 31
        return function (Options $options, $order) {
368 30
            foreach ($order as $field => $sort) {
369 1
                if (!\is_string($sort) || !\is_string($field) || !\in_array(strtolower($sort), ['asc', 'desc'])) {
370 1
                    throw new Exception('Order value should be an array of string (["field" => $key]), got '.\gettype($sort));
371
                }
372
            }
373
374 29
            return $order;
375 31
        };
376
    }
377
378 31
    private function getLoadStrategyNormalizer(): Closure
379
    {
380 31
        return function (Options $options, $value) {
381 29
            if ($value !== null) {
382 2
                return $value;
383
            }
384
385 27
            if ($options->offsetGet('name') == 'create') {
386 3
                $value = AdminInterface::LOAD_STRATEGY_NONE;
387 24
            } elseif ($options->offsetGet('name') == 'list') {
388 2
                $value = AdminInterface::LOAD_STRATEGY_MULTIPLE;
389
            } else {
390 22
                $value = AdminInterface::LOAD_STRATEGY_UNIQUE;
391
            }
392
393 27
            return $value;
394 31
        };
395
    }
396
397
    /**
398
     * Return the criteria normalizer. It will add the id parameters for the edit and delete actions if no value is
399
     * provided.
400
     */
401 31
    private function getCriteriaNormalizer(): Closure
402
    {
403 31
        return function (Options $options, $value) {
404 29
            if (!$value) {
405
                $idActions = [
406 29
                    'edit',
407
                    'delete',
408
                ];
409
410 29
                if (\in_array($options->offsetGet('name'), $idActions)) {
411
                    $value = [
412 5
                        'id',
413
                    ];
414
                }
415
            }
416
417 29
            return $value;
418 31
        };
419
    }
420
421
    /**
422
     * Return the filters normalizer.
423
     */
424 31
    private function getFiltersNormalizer(): Closure
425
    {
426 31
        return function (Options $options, $data) {
427 29
            $normalizedData = [];
428
429 29
            foreach ($data as $name => $field) {
430 2
                if (\is_string($field)) {
431
                    $field = [
432 1
                        'name' => $field,
433
                        'type' => TextType::class,
434
                        'options' => [],
435
                    ];
436
                } else {
437 1
                    $field['name'] = $name;
438
                }
439
440 2
                $filterConfiguration = new FilterConfiguration();
441 2
                $filterConfiguration->configure($field);
442
443 2
                $normalizedData[$field['name']] = $filterConfiguration->toArray();
444
            }
445
446 29
            return $normalizedData;
447 31
        };
448
    }
449
450 31
    private function getFormNormalizer(): Closure
451
    {
452 31
        return function (Options $options, $value) {
453 29
            if ($value !== null && $value !== false) {
454 3
                return $value;
455
            }
456
457 26
            if ($value === false) {
458 1
                return null;
459
            }
460
            $mapping = [
461 25
                'create' => AdminType::class,
462
                'edit' => AdminType::class,
463
                'delete' => DeleteType::class,
464
            ];
465
466 25
            if (\array_key_exists($options->offsetGet('name'), $mapping)) {
467 7
                $value = $mapping[$options->offsetGet('name')];
468
            }
469
470 25
            return $value;
471 31
        };
472
    }
473
474 31
    private function getRouteParametersNormalizer(): Closure
475
    {
476 31
        return function (Options $options, $value) {
477 30
            if (\count($value) > 0) {
478 1
                return $value;
479
            }
480
481 29
            if ($options->offsetGet('name') === 'edit' || $options->offsetGet('name') === 'delete') {
482 5
                return ['id' => null];
483
            }
484
485 24
            return [];
486 31
        };
487
    }
488
}
489