Completed
Pull Request — master (#71)
by Arnaud
02:54 queued 40s
created

ActionConfiguration::configureOrder()   B

Complexity

Conditions 5
Paths 1

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 0
cts 0
cp 0
rs 8.6737
c 0
b 0
f 0
cc 5
eloc 12
nc 1
nop 1
crap 30
1
<?php
2
3
namespace LAG\AdminBundle\Action\Configuration;
4
5
use LAG\AdminBundle\Admin\AdminInterface;
6
use LAG\AdminBundle\Admin\Behaviors\TranslationKeyTrait;
7
use LAG\AdminBundle\Configuration\Configuration;
8
use LAG\AdminBundle\Menu\Configuration\MenuConfiguration;
9
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
10
use Symfony\Component\OptionsResolver\Options;
11
use Symfony\Component\OptionsResolver\OptionsResolver;
12
13
class ActionConfiguration extends Configuration
14
{
15
    use TranslationKeyTrait;
16
17
    /**
18
     * Related Action name.
19
     *
20
     * @var string
21
     */
22
    protected $actionName;
23
24
    /**
25
     * Related Admin (optional)
26
     *
27
     * @var AdminInterface
28
     */
29
    protected $admin = null;
30
31
    /**
32
     * ActionConfiguration constructor.
33
     *
34
     * @param $actionName
35
     * @param AdminInterface $admin
36
     */
37 16
    public function __construct($actionName, AdminInterface $admin)
38
    {
39 16
        parent::__construct();
40
41 16
        $this->actionName = $actionName;
42 16
        $this->admin = $admin;
43 16
    }
44
45
    /**
46
     * Define allowed parameters and values for this configuration, using optionsResolver component.
47
     *
48
     * @param OptionsResolver $resolver
49
     */
50 15
    public function configureOptions(OptionsResolver $resolver)
51
    {
52
        // action title, default to action name key
53 15
        $translationPattern = $this
54
            ->admin
55 15
            ->getConfiguration()
56 15
            ->getParameter('translation_pattern');
57
58
        $resolver
59 15
            ->setDefault('title', $this->getTranslationKey(
60 15
                $translationPattern,
61 15
                $this->actionName,
62 15
                $this->admin->getName())
63 15
            )
64 15
            ->setAllowedTypes('title', 'string');
65
66
        // displayed fields for this action
67
        $resolver
68 15
            ->setDefault('fields', [
69 15
                'id' => []
70 15
            ])
71 15
            ->setAllowedTypes('fields', 'array')
72
            ->setNormalizer('fields', function(Options $options, $fields) {
73 15
                $normalizedFields = [];
74
75 15
                foreach ($fields as $name => $field) {
76
77 15
                    if ($field === null) {
78
                        $field = [];
79
                    }
80
81 15
                    $normalizedFields[$name] = $field;
82 15
                }
83
84 15
                return $normalizedFields;
85 15
            })
86
        ;
87
88
        // action permissions. By default, only admin are allowed
89
        $resolver
90 15
            ->setDefault('permissions', [
91
                'ROLE_ADMIN'
92 15
            ]);
93
94
        // by default, all exports type are allowed
95
        $resolver
96 15
            ->setDefault('export', [
97 15
                'json',
98 15
                'html',
99 15
                'csv',
100
                'xls'
101 15
            ]);
102
103
        // retrieved entities are sorted according to this option it should be an array indexed by the field name
104
        // with its order as a value
105
        $this->configureOrder($resolver);
106 15
107 15
        // the action route should be a string
108
        $resolver
109
            ->setDefault('route', '')
110
            ->setAllowedTypes('route', 'string')
111 15
            ->setNormalizer('route', function(Options $options, $value) {
112 15
                if (!$value) {
113
                    // if no route was provided, it should be linked to an Admin
114 15
                    if (!$this->admin) {
115
                        throw new InvalidOptionsException('No route was provided for action : '.$this->actionName);
116 14
                    }
117
118
                    // generate default route from admin
119
                    return $this
120
                        ->admin
121 14
                        ->generateRouteName($this->actionName);
122
                }
123 14
124
                return $value;
125
            });
126 1
127 15
        // action parameters should be an array
128
        $resolver
129
            ->setDefault('route_parameters', [])
130
            ->setAllowedTypes('route_parameters', 'array');
131 15
132 15
        // font awesome icons
133
        $resolver
134
            ->setDefault('icon', '')
135
            ->setAllowedTypes('icon', 'string');
136 15
137 15
        // load strategy : determine which method should be called in the data provider
138
        $resolver
139
            ->setDefault('load_strategy', null)
140
            ->addAllowedValues('load_strategy', AdminInterface::LOAD_STRATEGY_NONE)
141 15
            ->addAllowedValues('load_strategy', AdminInterface::LOAD_STRATEGY_UNIQUE)
142 15
            ->addAllowedValues('load_strategy', AdminInterface::LOAD_STRATEGY_MULTIPLE)
143 15
            ->addAllowedValues('load_strategy', null)
144 15
            ->setNormalizer('load_strategy', function(Options $options, $value) {
145 15
146
                if (!$value) {
147
                    if ($this->actionName == 'create') {
148 14
                        $value = AdminInterface::LOAD_STRATEGY_NONE;
149 6
                    } else if ($this->actionName == 'list') {
150
                        $value = AdminInterface::LOAD_STRATEGY_MULTIPLE;
151 6
                    } else {
152
                        $value = AdminInterface::LOAD_STRATEGY_UNIQUE;
153
                    }
154 6
                }
155
156 6
                return $value;
157
            });
158 14
159 15
        // pagination configuration
160
        $resolver
161
            ->setDefault('pager', 'pagerfanta')
162
            ->addAllowedValues('pager', 'pagerfanta')
163 15
            ->addAllowedValues('pager', false)
164 15
        ;
165 15
166
        // criteria used to find entity in the data provider
167
        $resolver
168
            ->setDefault('criteria', [])
169
            ->setNormalizer('criteria', function(Options $options, $value) {
170 15
171
                if (!$value) {
172
                    $idActions = [
173 14
                        'edit',
174
                        'delete'
175 14
                    ];
176
177 14
                    if (in_array($this->actionName, $idActions)) {
178
                        $value = [
179 14
                            'id'
180
                        ];
181
                    }
182 1
                }
183 1
184 14
                return $value;
185
            })
186 14
        ;
187 15
188
        // filters
189
        $resolver->setDefault('filters', []);
190
191 15
        // menus
192
        $resolver
193
            ->setDefault('menus', [])
194
            ->setNormalizer('menus', function(Options $options, $menus) {
195 15
                // set default to an array
196
                if ($menus === false) {
197
                    $menus = [];
198 14
                }
199
200
                return $menus;
201
            })
202 14
        ;
203 15
204
        // batch actions
205
        $resolver
206
            // by default, the batch action is not activated
207
            ->setDefault('batch', null)
208
            ->setNormalizer('batch', function(Options $options, $batch) {
209 15
210 15
                // if batch is not activated, no more checks should be done
211
                if ($batch === false) {
212
                    return $batch;
213 14
                }
214
                // for list actions, we add a default configuration
215
                if ($batch === null) {
216
                    // delete action should be allowed in order to be place in batch actions
217 14
                    $allowedActions = array_keys($this
218
                        ->admin
219 14
                        ->getConfiguration()
220
                        ->getParameter('actions'));
221 14
222 14
                    if ($this->actionName == 'list' && in_array('delete', $allowedActions)) {
223
                        $pattern = $this
224 14
                            ->admin
225
                            ->getConfiguration()
226
                            ->getParameter('translation_pattern');
227
228
                        $batch = [
229
                            'items' => [
230
                                'delete' => [
231
                                    'admin' => $this->admin->getName(),
232
                                    'action' => 'delete',
233
                                    'text' => $this->getTranslationKey($pattern, 'delete', $this->admin->getName())
234
                                ]
235
                            ]
236
                        ];
237
                    } else {
238
                        return $batch;
239
                    }
240 14
                }
241
                $resolver = new OptionsResolver();
242
                $configuration = new MenuConfiguration();
243
                $configuration->configureOptions($resolver);
244
                $batch = $resolver->resolve($batch);
245
246
                return $batch;
247
            })
248
        ;
249 15
    }
250
251 15
    /**
252
     * Configure the order option.
253
     *
254
     * @param OptionsResolver $resolver
255
     */
256
    protected function configureOrder(OptionsResolver $resolver)
257
    {
258
        $resolver
259
            ->setDefault('order', [])
260
            ->setAllowedTypes('order', 'array')
261
            ->setNormalizer('order', function(Options $options, $order) {
262
                foreach ($order as $field => $sort) {
263
264
                    if (!is_string($sort) || !is_string($field) || !in_array(strtolower($sort), ['asc', 'desc'])) {
265
                        throw new ConfigurationException(
266
                            'Order value should be an array of string (["field" => $key]), got '.gettype($sort),
267
                            $this->actionName,
268
                            $this->admin
269
                        );
270
                    }
271
                    // TODO add test: if the field does not exists in the target entity, an exception should be thrown
272
                }
273
274
                return $order;
275
            })
276
        ;
277
    }
278
}
279