Completed
Pull Request — master (#71)
by Arnaud
15:22 queued 12:55
created

ActionConfiguration::configureOrder()   B

Complexity

Conditions 5
Paths 1

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.3073

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 10
cts 13
cp 0.7692
rs 8.6737
c 0
b 0
f 0
cc 5
eloc 12
nc 1
nop 1
crap 5.3073
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 21
    public function __construct($actionName, AdminInterface $admin)
38
    {
39 21
        parent::__construct();
40
41 21
        $this->actionName = $actionName;
42 21
        $this->admin = $admin;
43 21
    }
44
45
    /**
46
     * Define allowed parameters and values for this configuration, using optionsResolver component.
47
     *
48
     * @param OptionsResolver $resolver
49
     */
50 18
    public function configureOptions(OptionsResolver $resolver)
51
    {
52
        // action title, default to action name key
53
        $translationPattern = $this
54 18
            ->admin
55 18
            ->getConfiguration()
56 18
            ->getParameter('translation_pattern');
57
58
        $resolver
59 18
            ->setDefault('title', $this->getTranslationKey(
60
                $translationPattern,
61 18
                $this->actionName,
62 18
                $this->admin->getName())
63
            )
64 18
            ->setAllowedTypes('title', 'string');
65
66
        // displayed fields for this action
67
        $resolver
68 18
            ->setDefault('fields', [
69
                'id' => []
70 18
            ])
71 18
            ->setAllowedTypes('fields', 'array')
72
            ->setNormalizer('fields', function(Options $options, $fields) {
73 18
                $normalizedFields = [];
74
75 18
                foreach ($fields as $name => $field) {
76
77 18
                    if ($field === null) {
78
                        $field = [];
79
                    }
80
81 18
                    $normalizedFields[$name] = $field;
82
                }
83
84 18
                return $normalizedFields;
85 18
            })
86
        ;
87
88
        // action permissions. By default, only admin are allowed
89
        $resolver
90 18
            ->setDefault('permissions', [
91
                'ROLE_ADMIN'
92 18
            ]);
93
94
        // by default, all exports type are allowed
95
        $resolver
96 18
            ->setDefault('export', [
97 18
                'json',
98
                'html',
99
                'csv',
100
                'xls'
101
            ]);
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 18
        $this->configureOrder($resolver);
106
107
        // the action route should be a string
108
        $resolver
109 18
            ->setDefault('route', '')
110 18
            ->setAllowedTypes('route', 'string')
111
            ->setNormalizer('route', function(Options $options, $value) {
112 18
                if (!$value) {
113
                    // if no route was provided, it should be linked to an Admin
114 17
                    if (!$this->admin) {
115
                        throw new InvalidOptionsException('No route was provided for action : '.$this->actionName);
116
                    }
117
118
                    // generate default route from admin
119
                    return $this
120 17
                        ->admin
121 17
                        ->generateRouteName($this->actionName);
122
                }
123
124 1
                return $value;
125 18
            });
126
127
        // action parameters should be an array
128
        $resolver
129 18
            ->setDefault('route_parameters', [])
130 18
            ->setAllowedTypes('route_parameters', 'array');
131
132
        // font awesome icons
133
        $resolver
134 18
            ->setDefault('icon', '')
135 18
            ->setAllowedTypes('icon', 'string');
136
137
        // load strategy : determine which method should be called in the data provider
138
        $resolver
139 18
            ->setDefault('load_strategy', null)
140 18
            ->addAllowedValues('load_strategy', AdminInterface::LOAD_STRATEGY_NONE)
141 18
            ->addAllowedValues('load_strategy', AdminInterface::LOAD_STRATEGY_UNIQUE)
142 18
            ->addAllowedValues('load_strategy', AdminInterface::LOAD_STRATEGY_MULTIPLE)
143 18
            ->addAllowedValues('load_strategy', null)
144
            ->setNormalizer('load_strategy', function(Options $options, $value) {
145
146 17
                if (!$value) {
147 8
                    if ($this->actionName == 'create') {
148
                        $value = AdminInterface::LOAD_STRATEGY_NONE;
149 8
                    } else if ($this->actionName == 'list') {
150
                        $value = AdminInterface::LOAD_STRATEGY_MULTIPLE;
151
                    } else {
152 8
                        $value = AdminInterface::LOAD_STRATEGY_UNIQUE;
153
                    }
154
                }
155
156 17
                return $value;
157 18
            });
158
159
        // pagination configuration
160
        $resolver
161 18
            ->setDefault('pager', 'pagerfanta')
162 18
            ->addAllowedValues('pager', 'pagerfanta')
163 18
            ->addAllowedValues('pager', false)
164
        ;
165
166
        // criteria used to find entity in the data provider
167
        $resolver
168 18
            ->setDefault('criteria', [])
169
            ->setNormalizer('criteria', function(Options $options, $value) {
170
171 17
                if (!$value) {
172
                    $idActions = [
173 17
                        'edit',
174
                        'delete'
175
                    ];
176
177 17
                    if (in_array($this->actionName, $idActions)) {
178
                        $value = [
179
                            'id'
180 1
                        ];
181
                    }
182
                }
183
184 17
                return $value;
185 18
            })
186
        ;
187
188
        // filters
189 18
        $resolver->setDefault('filters', []);
190
191
        // menus
192
        $resolver
193 18
            ->setDefault('menus', [])
194
            ->setNormalizer('menus', function(Options $options, $menus) {
195
                // set default to an array
196 17
                if ($menus === false) {
197
                    $menus = [];
198
                }
199
200 17
                return $menus;
201 18
            })
202
        ;
203
204
        // batch actions
205
        $resolver
206
            // by default, the batch action is not activated
207 18
            ->setDefault('batch', null)
208
            ->setNormalizer('batch', function(Options $options, $batch) {
209
210
                // if batch is not activated, no more checks should be done
211 17
                if ($batch === false) {
212
                    return $batch;
213
                }
214
                // for list actions, we add a default configuration
215 17
                if ($batch === null) {
216
                    // delete action should be allowed in order to be place in batch actions
217 17
                    $allowedActions = array_keys($this
218 17
                        ->admin
219 17
                        ->getConfiguration()
220 17
                        ->getParameter('actions'));
221
222 17
                    if ($this->actionName == 'list' && in_array('delete', $allowedActions)) {
223
                        $pattern = $this
224
                            ->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 17
                        return $batch;
239
                    }
240
                }
241
                $resolver = new OptionsResolver();
242
                $configuration = new MenuConfiguration();
243
                $configuration->configureOptions($resolver);
244
                $batch = $resolver->resolve($batch);
245
246
                return $batch;
247 18
            })
248
        ;
249 18
    }
250
251
    /**
252
     * Configure the order option.
253
     *
254
     * @param OptionsResolver $resolver
255
     */
256 18
    protected function configureOrder(OptionsResolver $resolver)
257
    {
258
        $resolver
259 18
            ->setDefault('order', [])
260 18
            ->setAllowedTypes('order', 'array')
261 18
            ->setNormalizer('order', function(Options $options, $order) {
262 18
                foreach ($order as $field => $sort) {
263
264 1
                    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 1
                            $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 18
                return $order;
275 18
            })
276
        ;
277 18
    }
278
}
279