Passed
Pull Request — master (#116)
by Arnaud
05:44 queued 02:35
created

ActionConfiguration::getTitleNormalizer()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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