Completed
Push — refonte ( 322718...b4ae29 )
by Arnaud
02:53 queued 34s
created

ActionConfiguration::getDefaultResponder()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

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