Completed
Push — wip-platform ( 03cba6...2999ab )
by
unknown
05:53 queued 02:49
created

Mapper::addField()   F

Complexity

Conditions 26
Paths 18444

Size

Total Lines 95
Code Lines 51

Duplication

Lines 12
Ratio 12.63 %

Importance

Changes 0
Metric Value
dl 12
loc 95
rs 2
c 0
b 0
f 0
cc 26
eloc 51
nc 18444
nop 4

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 *
5
 * Copyright (C) 2015-2017 Libre Informatique
6
 *
7
 * This file is licenced under the GNU LGPL v3.
8
 * For the full copyright and license information, please view the LICENSE.md
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Blast\Bundle\CoreBundle\Admin\Traits;
13
14
use Sonata\AdminBundle\Datagrid\ListMapper;
15
use Sonata\AdminBundle\Form\FormMapper;
16
use Sonata\AdminBundle\Mapper\BaseGroupedMapper;
17
use Sonata\AdminBundle\Mapper\BaseMapper;
18
use Sonata\AdminBundle\Show\ShowMapper;
19
use Symfony\Component\Validator\Constraints\NotBlank;
20
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;
21
use Exception;
22
23
trait Mapper
24
{
25
    /**
26
     * Force tabulations on Show views.
27
     *
28
     * @var bool
29
     */
30
    protected $forceTabs = false;
31
32
    /**
33
     * Links in the view navbar.
34
     *
35
     * @var array
36
     */
37
    protected $helperLinks = [];
38
39
    /**
40
     * Admin titles (for list, show, edit and create).
41
     *
42
     * @var string
43
     */
44
    public $titles = [];
45
46
    /**
47
     * Admin title templates (for list, show, edit and create).
48
     *
49
     * @var array
50
     */
51
    public $titleTemplates = [];
52
53
    protected function configureMapper(BaseMapper $mapper)
54
    {
55
        $classes = $this->getCurrentComposition();
0 ignored issues
show
Bug introduced by
It seems like getCurrentComposition() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
56
        $blast = $this
0 ignored issues
show
Bug introduced by
It seems like getConfigurationPool() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
57
            ->getConfigurationPool()
58
            ->getContainer()
59
            ->getParameter('blast')
60
        ;
61
        $this
0 ignored issues
show
Bug introduced by
It seems like getConfigurationPool() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
62
            ->getConfigurationPool()
63
            ->getContainer()
64
            ->get('logger')
65
            ->debug(sprintf(
66
                '[BlastCoreBundle] Processing the configuration in this order: %s',
67
                 implode(', ', $classes)
68
            ))
69
        ;
70
71
        $fcts = [
72
            'tabs' => $mapper instanceof ShowMapper ?
73
                ['getter' => 'getShowTabs', 'setter' => 'setShowTabs'] :
74
                ['getter' => 'getFormTabs', 'setter' => 'setFormTabs'],
75
            'groups' => $mapper instanceof ShowMapper ?
76
                ['getter' => 'getShowGroups', 'setter' => 'setShowGroups'] :
77
                ['getter' => 'getFormGroups', 'setter' => 'setFormGroups'],
78
        ];
79
80
        // Figure out if we have to display tabs on the Show view
81
        $this->forceTabs = false;
82
        if ($mapper instanceof ShowMapper) {
83
            foreach ($classes as $class) {
84
                if (isset($blast[$class])) {
85
                    foreach (array_reverse($list = array_merge([get_class($mapper)], array_values(class_parents($mapper)))) as $mapper_class) {
86
                        if (!empty($blast[$class][$mapper_class]['forceTabs'])) {
87
                            $this->forceTabs = true;
88
                        }
89
                    }
90
                }
91
            }
92
        }
93
94
        // builds the configuration, based on the Mapper class
95
        foreach ($classes as $class) {
96
            if (!isset($blast[$class])) {
97
                continue;
98
            }
99
100
            // copy stuff from elsewhere
101
            foreach (array_reverse($list = array_merge([get_class($mapper)], array_values(class_parents($mapper)))) as $mapper_class) {
102
                if (isset($blast[$class][$mapper_class]) && !empty($blast[$class][$mapper_class]['_copy'])) {
103
                    if (!is_array($blast[$class][$mapper_class]['_copy'])) {
104
                        $blast[$class][$mapper_class]['_copy'] = [$blast[$class][$mapper_class]['_copy']];
105
                    }
106
                    foreach ($blast[$class][$mapper_class]['_copy'] as $copy) {
107
                        $list = array_merge(
108
                                $list, array_merge([$copy], array_values(class_parents($copy)))
109
                        );
110
                    }
111
                }
112
            }
113
114
            $specialKeys = ['_actions', '_list_actions', '_batch_actions', '_export_formats', '_extra_templates', '_helper_links'];
115
116
            // process data...
117
            foreach (array_reverse($list) as $mapper_class) {
118
                if (!isset($blast[$class][$mapper_class])) {
119
                    continue;
120
                }
121
122
                // remove fields
123
                if (isset($blast[$class][$mapper_class]['remove'])) {
124 View Code Duplication
                    if (isset($blast['all'][$mapper_class]['remove'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
125
                        $blast[$class][$mapper_class]['remove'] = array_merge_recursive(
126
                            $blast[$class][$mapper_class]['remove'],
127
                            $blast['all'][$mapper_class]['remove']
128
                        );
129
                    }
130
131
                    foreach ($blast[$class][$mapper_class]['remove'] as $key => $field) {
132
                        if (in_array($key, $specialKeys)) {
133
                            continue;
134
                        }
135
136
                        if ($mapper->has($key)) {
137
                            $mapper->remove($key);
138
139
                            // compensating the partial removal in Sonata Admin, that does not touch the groups when removing a field
140 View Code Duplication
                            if ($mapper instanceof BaseGroupedMapper) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
141
                                foreach ($groups = $this->{$fcts['groups']['getter']}() as $groupkey => $group) {
142
                                    if (isset($group['fields'][$key])) {
143
                                        unset($groups[$groupkey]['fields'][$key]);
144
                                        if (!$groups[$groupkey]['fields']) {
145
                                            unset($groups[$groupkey]);
146
                                        }
147
                                        $this->{$fcts['groups']['setter']}($groups);
148
                                    }
149
                                }
150
                            }
151
                        }
152
                    }
153
                }
154
155
                // add fields & more
156
                if (isset($blast[$class][$mapper_class]['add'])) {
157 View Code Duplication
                    if (isset($blast['all'][$mapper_class]['add'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
158
                        $blast[$class][$mapper_class]['add'] = array_merge(
159
                                    $blast[$class][$mapper_class]['add'],
160
                                    $blast['all'][$mapper_class]['add']
161
                                );
162
                    }
163
164
                    // do not parse _batch_actions & co
165
                    foreach ($specialKeys as $sk) {
166 View Code Duplication
                        if (isset($blast[$class][$mapper_class]['add'][$sk])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
167
                            unset($blast[$class][$mapper_class]['add'][$sk]);
168
                        }
169
                    }
170
171
                    $this->addContent($mapper, $blast[$class][$mapper_class]['add']);
172
                }
173
174
                // set Admin titles
175
                $titleTemplate = isset($blast[$class][$mapper_class]['titleTemplate']) ? $blast[$class][$mapper_class]['titleTemplate'] : null;
176
                $title = isset($blast[$class][$mapper_class]['title']) ? $blast[$class][$mapper_class]['title'] : null;
177
                $this->setTitles($mapper, $titleTemplate, $title);
178
            }
179
        }
180
181
        if ($mapper instanceof BaseGroupedMapper) { // ShowMapper and FormMapper
182
            // removing empty groups
183
            $groups = $this->{$fcts['groups']['getter']}();
184
            if (is_array($groups)) {
185
                foreach ($groups as $groupkey => $group) {
186
                    if (!$group['fields']) {
187
                        unset($groups[$groupkey]);
188
                    }
189
                }
190
                $this->{$fcts['groups']['setter']}($groups);
191
            }
192
193
            // removing empty tabs
194
            $tabs = $this->{$fcts['tabs']['getter']}();
195 View Code Duplication
            if (is_array($tabs)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
196
                foreach ($tabs as $tabkey => $tab) {
197
                    foreach ($tab['groups'] as $groupkey => $group) {
198
                        if (!isset($this->{$fcts['groups']['getter']}()[$group])) {
199
                            unset($tabs[$tabkey]['groups'][$groupkey]);
200
                        }
201
                    }
202
203
                    if (!$tabs[$tabkey]['groups']) {
204
                        unset($tabs[$tabkey]);
205
                    }
206
                }
207
                $this->{$fcts['tabs']['setter']}($tabs);
208
            }
209
        }
210
211
        $this->fixTemplates($mapper);
0 ignored issues
show
Bug introduced by
It seems like fixTemplates() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
212
213
        if (!$mapper instanceof FormMapper) {
214
            $this->fixShowRoutes($mapper);
0 ignored issues
show
Bug introduced by
It seems like fixShowRoutes() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
215
        }
216
217
        // Debug profiler
218
        $this->getConfigurationPool()->getContainer()->get('blast_core.profiler.collector')
0 ignored issues
show
Bug introduced by
It seems like getConfigurationPool() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
219
            ->collectOnce('Mapper', $mapper)
220
            ->collectOnce('Managed classes', $classes);
221
222
        return $this;
223
    }
224
225
    /**
226
     * @param BaseMapper $mapper
227
     * @param array      $group
228
     *
229
     * @return BaseMapper
230
     */
231
    protected function addContent(BaseMapper $mapper, $group)
232
    {
233
        // helper links
234
        $this->parseHelperLinks();
235
236
        // flat organization (DatagridMapper / ListMapper...)
237
        if (!$mapper instanceof BaseGroupedMapper) {
238
            //list actions
239
            $this->addActions();
0 ignored issues
show
Bug introduced by
It seems like addActions() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
240
            $this->removeActions();
0 ignored issues
show
Bug introduced by
It seems like removeActions() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
241
242
            // options pre-treatment
243
            $options = [];
244
            if (isset($group['_options'])) {
245
                $options = $group['_options'];
246
                unset($group['_options']);
247
            }
248
249
            // content
250
            foreach ($group as $add => $opts) {
251
                $this->addField($mapper, $add, $opts);
252
            }
253
254
            // options
255
            if (isset($options['fieldsOrder'])) {
256
                $mapper->reorder($options['fieldsOrder']);
257
            }
258
259
            // extra templates
260
            $this->parseExtraTemplates();
261
262
            return $mapper;
263
        }
264
265
        $fcts = [
266
            'tabs' => $mapper instanceof ShowMapper ?
267
            ['getter' => 'getShowTabs', 'setter' => 'setShowTabs'] :
268
            ['getter' => 'getFormTabs', 'setter' => 'setFormTabs'],
269
            'groups' => $mapper instanceof ShowMapper ?
270
            ['getter' => 'getShowGroups', 'setter' => 'setShowGroups'] :
271
            ['getter' => 'getFormGroups', 'setter' => 'setFormGroups'],
272
        ];
273
274
        // if a grouped organization can be shapped
275
        // options
276
        $tabsOptions = null;
277
        if (isset($group['_options'])) {
278
            $tabsOptions = $group['_options'];
279
            unset($group['_options']);
280
        }
281
282
        // content
283
        foreach ($group as $tab => $tabcontent) { // loop on content...
284
            if (self::arrayDepth($tabcontent) < 1) {
285
                // direct add
286
                $this->addField($mapper, $tab, $tabcontent);
287
                $mapper->end()->end();
288
            } else {
289
                // groups/withs order
290
                $groupsOrder = null;
291
                if (isset($tabcontent['_options']['groupsOrder'])) {
292
                    $groupsOrder = $tabcontent['_options']['groupsOrder'];
293
                    unset($tabcontent['_options']['groupsOrder']);
294
                }
295
296
                $endgroup = $endtab = false;
297
298
                // tab
299
                if (!empty($tabcontent['_options']['hideTitle']) || $mapper instanceof ShowMapper && !$this->forceTabs) {
300
                    // display tabs as groups
301
                    $tabs = $this->{$fcts['tabs']['getter']}();
302
                    $groups = $this->{$fcts['groups']['getter']}();
303
                    if (isset($tabs[$tab])) {
304
                        $tabs[$tab]['auto_created'] = true;
305
                        $this->{$fcts['tabs']['setter']}($tabs);
306
307
                        foreach ($groups as $groupkey => $group) {
308
                            if (!isset($groups[$group['name']])) {
309
                                $groups[$group['name']] = $group;
310
                                unset($groups[$groupkey]);
311
                            }
312
                        }
313
                        $this->{$fcts['groups']['setter']}($groups);
314
                    }
315
                } else {
316
                    $mapper->tab($tab, isset($tabcontent['_options']) ? $tabcontent['_options'] : []);
317
                    $endtab = true;
318
                }
319
320
                // adding count of collections items in tab
321
                if (isset($tabcontent['_options']['countChildItems']) && is_array($tabcontent['_options']['countChildItems'])) {
322
                    $tabs = $this->{$fcts['tabs']['getter']}();
323
                    if (strpos($tabs[$tab]['class'], 'countable-tab') === false) {
324
                        $tabs[$tab]['class'] .= ' countable-tab';
325
326
                        foreach ($tabcontent['_options']['countChildItems'] as $fieldToCount) {
327
                            if (strpos($tabs[$tab]['class'], 'count-' . $fieldToCount) === false) {
328
                                $tabs[$tab]['class'] .= ' count-' . $fieldToCount;
329
                            }
330
                        }
331
332
                        $this->{$fcts['tabs']['setter']}($tabs);
333
                    }
334
                }
335
336
                // clearing tabcontent options
337
                if (isset($tabcontent['_options'])) {
338
                    unset($tabcontent['_options']);
339
                }
340
341
                $finalOrder = null;
0 ignored issues
show
Unused Code introduced by
$finalOrder is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
342
343
                // with
344
                if (self::arrayDepth($tabcontent) > 0) {
345
                    foreach ($tabcontent as $with => $withcontent) {
346
                        $opt = isset($withcontent['_options']) ? $withcontent['_options'] : [];
347
                        $finalOrder = (isset($opt['fieldsOrder']) ? $opt['fieldsOrder'] : null);
348
349
                        if (empty($opt['hideTitle'])) {
350
                            $endtab = true;
351
                            $endgroup = true;
352
                            $mapper->with($with, $opt);
353
                        }
354
                        if (isset($withcontent['_options'])) {
355
                            unset($withcontent['_options']);
356
                        }
357
358
                        // final adds
359
                        if (self::arrayDepth($withcontent) > 0) {
360
                            foreach ($withcontent as $name => $options) {
361
                                $fieldDescriptionOptions = [];
362
                                if (isset($options['_options'])) {
363
                                    $fieldDescriptionOptions = $options['_options'];
364
                                    unset($options['_options']);
365
                                }
366
                                $this->addField($mapper, $name, $options, $fieldDescriptionOptions);
367
                                $endgroup = $endtab = true;
368
                            }
369
                        }
370
371
                        if ($finalOrder != null) {
372
                            $mapper->reorder($finalOrder);
373
                        }
374
375
                        if ($endgroup) {
376
                            $mapper->end();
377
                        }
378
                    }
379
                }
380
381
                // order groups / withs (using tabs, because they are prioritary at the end)
382
                if (isset($groupsOrder)) {
383
                    // preparing
384
                    $otabs = $mapper->getAdmin()->{$fcts['tabs']['getter']}();
385
                    $groups = $mapper->getAdmin()->{$fcts['groups']['getter']}();
0 ignored issues
show
Unused Code introduced by
$groups is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
386
387
                    // pre-ordering
388
                    $newgroups = [];
389
                    $buf = empty($otabs[$tab]['auto_created']) ? "$tab." : '';
390
                    foreach ($groupsOrder as $groupname) {
391
                        if (isset($otabs[$tab]) && in_array("$buf$groupname", $otabs[$tab]['groups'])) {
392
                            $newgroups[] = "$buf$groupname";
393
                        }
394
                    }
395
396
                    // ordering tabs
397
                    foreach (empty($otabs[$tab]['groups']) ? [] : $otabs[$tab]['groups'] as $groupname) {
398
                        if (!in_array($groupname, $newgroups)) {
399
                            $newgroups[] = $groupname;
400
                        }
401
                    }
402
                    $otabs[$tab]['groups'] = $newgroups;
403
404
                    // "persisting"
405
                    $mapper->getAdmin()->{$fcts['tabs']['setter']}($otabs);
406
                }
407
408
                if ($endtab) {
409
                    $mapper->end();
410
                }
411
            }
412
        }
413
414
        // ordering tabs
415
        if (isset($tabsOptions['tabsOrder']) && $tabs = $this->{$fcts['tabs']['getter']}()) {
416
            $newtabs = [];
417
            foreach ($tabsOptions['tabsOrder'] as $tabname) {
418
                if (isset($tabs[$tabname])) {
419
                    $newtabs[$tabname] = $tabs[$tabname];
420
                }
421
            }
422
            foreach ($tabs as $tabname => $tab) {
423
                if (!isset($newtabs[$tabname])) {
424
                    $newtabs[$tabname] = $tab;
425
                }
426
            }
427
            $this->{$fcts['tabs']['setter']}($newtabs);
428
        }
429
430
        // ordering the ShowMapper
431
        if ($mapper instanceof ShowMapper) {
432
            foreach ($group as $tabName => $tabContent) {
433
                $tabOptions = null;
434
                if (isset($tabContent['_options'])) {
435
                    $tabOptions = $tabContent['_options'];
436
                    unset($tabContent['_options']);
437
                }
438
439
                if (isset($tabOptions['groupsOrder'])) {
440
                    $tabs = $this->{$fcts['tabs']['getter']}();
441
                    $groups = $this->{$fcts['groups']['getter']}();
442
443
                    $groupOrder = $tabOptions['groupsOrder'];
444
445
                    $properOrderedArray = array_merge(array_flip($groupOrder), $groups);
446
447
                    $this->{$fcts['groups']['setter']}($properOrderedArray);
448
                    $this->{$fcts['tabs']['setter']}($tabs);
449
                }
450
            }
451
        }
452
453
        return $mapper;
454
    }
455
456
    protected function addField(BaseMapper $mapper, $name, $options = [], $fieldDescriptionOptions = [])
457
    {
458
        // avoid duplicates
459
        if ($mapper->has($name)) {
460
            $mapper->remove($name);
461
        }
462
463
        if (!is_array($options)) {
464
            $options = [];
465
        }
466
467 View Code Duplication
        if (isset($options['only_new'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
468
            if ($options['only_new'] && $this->subject && !$this->subject->isNew()) {
0 ignored issues
show
Bug introduced by
The property subject does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
469
                return $mapper;
470
            }
471
            unset($options['only_new']);
472
        }
473
474 View Code Duplication
        if (isset($options['only_not_new'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
475
            if ($options['only_not_new'] && (!$this->subject || $this->subject->isNew())) {
476
                return $mapper;
477
            }
478
            unset($options['only_not_new']);
479
        }
480
481
        $type = null;
482
        if (isset($options['type'])) {
483
            $type = $options['type'];
484
            unset($options['type']);
485
        }
486
487
        if (isset($options['constraints'])) {
488
            foreach ($options['constraints'] as $k => $constraint) {
489
                $options['constraints'][$k] = new $constraint();
490
            }
491
        }
492
493
        if (isset($options['required']) && $options['required'] === true) {
494
            $options['constraints'] = [new NotBlank()];
495
        }
496
497
        if (isset($options['query'])) {
498
            $this->manageQueryCallback($mapper, $options);
499
        }
500
501
        if (isset($options['choicesCallback'])) {
502
            $this->manageChoicesCallback($mapper, $options);
503
        }
504
505
        if (isset($options['serviceCallback'])) {
506
            $this->manageServiceCallback($mapper, $options);
507
        }
508
509
        // save-and-remove CoreBundle-specific options
510
        $extras = [];
511
        foreach ([
512
            'template' => 'setTemplate',
513
            'initializeAssociationAdmin' => null,
514
        ] as $extra => $method) {
515
            if (isset($fieldDescriptionOptions[$extra])) {
516
                $extras[$extra] = [$method, $fieldDescriptionOptions[$extra]];
517
                unset($fieldDescriptionOptions[$extra]);
518
            }
519
        }
520
521
        $mapper->add($name, $type, $options, $fieldDescriptionOptions);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Sonata\AdminBundle\Mapper\BaseMapper as the method add() does only exist in the following sub-classes of Sonata\AdminBundle\Mapper\BaseMapper: Sonata\AdminBundle\Datagrid\DatagridMapper, Sonata\AdminBundle\Datagrid\ListMapper, Sonata\AdminBundle\Form\FormMapper, Sonata\AdminBundle\Show\ShowMapper. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
522
523
        // apply extra options
524
        foreach ($extras as $extra => $call) {
525
            if ($call[0]) {
526
                $mapper->get($name)->{$call[0]}($call[1]);
527
            } else {
528
                switch ($extra) {
529
                    case 'initializeAssociationAdmin':
530
                        // only if "true"
531
                        if (!$call[1]) {
532
                            break;
533
                        }
534
535
                        // initialize the association-admin
536
                        $mapper->get($name)->getAssociationAdmin()->configureShowFields(new ShowMapper(
537
                                $mapper->get($name)->getAssociationAdmin()->getShowBuilder(), $mapper->get($name)->getAssociationAdmin()->getShow(), $mapper->get($name)->getAssociationAdmin()
538
                        ));
539
540
                        // set the efficient template
541
                        if (!isset($extras['template'])) {
542
                            $mapper->get($name)->setTemplate('BlastCoreBundle:CRUD:show_association_admin.html.twig');
543
                        }
544
                        break;
545
                }
546
            }
547
        }
548
549
        return $mapper;
550
    }
551
552
    protected function configureFields($function, BaseMapper $mapper, $class = null)
553
    {
554
        if (!$class) {
555
            $class = $this->getOriginalClass();
0 ignored issues
show
Bug introduced by
It seems like getOriginalClass() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
556
        }
557
558
        return $class::$function($mapper);
559
    }
560
561
    /**
562
     * @param array $actions
563
     * */
564
    protected function handleBatchActions(array $actions = [])
565
    {
566
        $blast = $this->getConfigurationPool()->getContainer()->getParameter('blast');
0 ignored issues
show
Bug introduced by
It seems like getConfigurationPool() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
567
        $mapperClass = ListMapper::class;
568
        $actionKey = '_batch_actions';
569
570
        foreach ($this->getCurrentComposition() as $class) {
0 ignored issues
show
Bug introduced by
It seems like getCurrentComposition() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
571
            if (isset($blast[$class][$mapperClass])) {
572
                $config = $blast[$class][$mapperClass];
573
574 View Code Duplication
                if (isset($blast['all'][$mapperClass])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
575
                    $config = array_merge_recursive(
576
                        $config,
577
                        $blast['all'][$mapperClass]
578
                    );
579
                }
580
581
                // remove / reset
582
                if (isset($config['remove'][$actionKey])) {
583
                    $actions = parent::getBatchActions();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getBatchActions() instead of handleBatchActions()). Are you sure this is correct? If so, you might want to change this to $this->getBatchActions().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
584
585
                    foreach ($config['remove'][$actionKey] as $action) {
586
                        if (isset($actions[$action])) {
587
                            unset($actions[$action]);
588
                        }
589
                    }
590
                }
591
592
                // add
593
                if (isset($config['add'][$actionKey])) {
594
                    $buf = $config['add'][$actionKey];
595
596
                    foreach ($buf as $action => $props) {
597
                        $name = 'batch_action_' . $action;
598
599
                        foreach ([
600
                            'label' => $name,
601
                            'params' => [],
602
                            'translation_domain' => $this->getTranslationDomain(),
0 ignored issues
show
Bug introduced by
It seems like getTranslationDomain() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
603
                            'action' => $name,
604
                            'route' => 'batch_' . $action,
605
                        ] as $field => $value) {
606
                            if (empty($props[$field])) {
607
                                $props[$field] = $value;
608
                            }
609
                        }
610
611
                        $actions[$action] = $props;
612
                    }
613
                }
614
            }
615
        }
616
617
        return $actions;
618
    }
619
620
    /**
621
     * @param array $actions
622
     * */
623
    protected function handleListActions(array $actions = [])
0 ignored issues
show
Unused Code introduced by
The parameter $actions is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
624
    {
625
        $this->_listActionLoaded = true;
0 ignored issues
show
Bug introduced by
The property _listActionLoaded does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
626
        $blast = $this->getConfigurationPool()->getContainer()->getParameter('blast');
0 ignored issues
show
Bug introduced by
It seems like getConfigurationPool() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
627
628
        foreach ($this->getCurrentComposition() as $class) {
0 ignored issues
show
Bug introduced by
It seems like getCurrentComposition() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
629
            // remove / reset
630 View Code Duplication
            if (isset($blast[$class][ListMapper::class]['remove']['_list_actions'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
631
                foreach ($blast[$class][ListMapper::class]['remove']['_list_actions'] as $action) {
632
                    $this->removeListAction($action);
0 ignored issues
show
Bug introduced by
It seems like removeListAction() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
633
                }
634
            }
635
636
            // add
637
            if (isset($blast[$class][ListMapper::class]['add']['_list_actions'])) {
638
                foreach ($blast[$class][ListMapper::class]['add']['_list_actions'] as $action => $props) {
639
                    $props['translation_domain'] = isset($props['translation_domain']) ? $props['translation_domain'] : $this->getTranslationDomain();
0 ignored issues
show
Bug introduced by
It seems like getTranslationDomain() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
640
                    $this->addListAction($action, $props);
0 ignored issues
show
Bug introduced by
It seems like addListAction() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
641
                }
642
            }
643
        }
644
645
        return $this->getListActions();
0 ignored issues
show
Bug introduced by
It seems like getListActions() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
646
    }
647
648
    /**
649
     * @param array $formats
650
     * */
651
    protected function addPresetExportFormats(array $formats = [])
652
    {
653
        $blast = $this->getConfigurationPool()->getContainer()->getParameter('blast');
0 ignored issues
show
Bug introduced by
It seems like getConfigurationPool() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
654
        $this->exportFields = $formats;
0 ignored issues
show
Bug introduced by
The property exportFields does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
655
656
        foreach ($this->getCurrentComposition() as $class) {
0 ignored issues
show
Bug introduced by
It seems like getCurrentComposition() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
657
            // remove / reset
658
            if (isset($blast[$class][ListMapper::class]['remove']['_export_format'])) {
659
                $this->exportFields = [];
660
            }
661
662
            // add
663
            if (isset($blast[$class][ListMapper::class]['add']['_export_format'])) {
664
                foreach ($blast[$class][ListMapper::class]['add']['_export_format'] as $format => $fields) {
665
                    // if no fields are defined (not an associative array)
666
                    if (intval($format) . '' == '' . $format && !is_array($fields)) {
667
                        $format = $fields;
668
                        $this->exportFields[$format] = $fields = [];
669
                    }
670
671
                    // if a copy of an other format is requested
672
                    if (!is_array($fields) && isset($blast[$class][ListMapper::class]['add']['_export_format'][$fields])) {
673
                        $blast[$class][ListMapper::class]['add']['_export_format'][$format] = // the global fields array
674
                                $fields = // the local  fields array
675
                                $blast[$class][ListMapper::class]['add']['_export_format'][$fields];  // the source fields array
676
                    }
677
678
                    // removes a specific format
679
                    if (substr($format, 0, 1) == '-') {
680
                        unset($this->exportFields[substr($format, 1)]);
681
                        continue;
682
                    }
683
684
                    // if an order is defined, use it to order the extracted fields
685
                    if (!$fields && isset($blast[$class][ListMapper::class]['add']['_options']['fieldsOrder'])) {
686
                        // get back default fields
687
                        $tmp = parent::getExportFields();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getExportFields() instead of addPresetExportFormats()). Are you sure this is correct? If so, you might want to change this to $this->getExportFields().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
688
                        $fields = [];
689
690
                        // takes the ordered fields
691 View Code Duplication
                        foreach ($blast[$class][ListMapper::class]['add']['_options']['fieldsOrder'] as $field) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
692
                            if (in_array($field, $tmp)) {
693
                                $fields[] = $field;
694
                            }
695
                        }
696
697
                        // then the forgotten fields as they come
698 View Code Duplication
                        foreach ($tmp as $field) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
699
                            if (!in_array($field, $blast[$class][ListMapper::class]['add']['_options']['fieldsOrder'])) {
700
                                $fields[] = $field;
701
                            }
702
                        }
703
                    }
704
                    $this->exportFields[$format] = $fields;
705
                }
706
            }
707
        }
708
709
        return $this->exportFields;
710
    }
711
712
    /**
713
     * @todo parse ShowMapper and FormMapper
714
     */
715
    protected function parseExtraTemplates()
716
    {
717
        $blast = $this->getConfigurationPool()->getContainer()->getParameter('blast');
0 ignored issues
show
Bug introduced by
It seems like getConfigurationPool() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
718
719
        foreach ($this->getCurrentComposition() as $class) {
0 ignored issues
show
Bug introduced by
It seems like getCurrentComposition() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
720
            // remove / reset
721
            if (isset($blast[$class][ListMapper::class]['remove']['_extra_templates'])) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
722
                // TODO
723
            }
724
725
            // add
726 View Code Duplication
            if (isset($blast[$class][ListMapper::class]['add']['_extra_templates'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
727
                foreach ($blast[$class][ListMapper::class]['add']['_extra_templates'] as $template) {
728
                    $this->addExtraTemplate('list', $template);
0 ignored issues
show
Bug introduced by
It seems like addExtraTemplate() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
729
                }
730
            }
731
        }
732
    }
733
734
    protected function parseHelperLinks()
735
    {
736
        $blast = $this->getConfigurationPool()->getContainer()->getParameter('blast');
0 ignored issues
show
Bug introduced by
It seems like getConfigurationPool() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
737
        $mappers = [
738
            'list' => ListMapper::class,
739
            'show' => ShowMapper::class,
740
            'form' => FormMapper::class,
741
        ];
742
743
        foreach ($this->getCurrentComposition() as $class) {
0 ignored issues
show
Bug introduced by
It seems like getCurrentComposition() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
744
            foreach ($mappers as $mapper => $mapper_class) {
745
                // remove / reset
746
                if (isset($blast[$class][$mapper_class]['remove']['_helper_links'])) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
747
                    // TODO
748
                }
749
750
                // add
751 View Code Duplication
                if (isset($blast[$class][$mapper_class]['add']['_helper_links'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
752
                    foreach ($blast[$class][$mapper_class]['add']['_helper_links'] as $link) {
753
                        $this->addHelperLink($mapper, $link);
0 ignored issues
show
Bug introduced by
It seems like addHelperLink() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
754
                    }
755
                }
756
            }
757
        }
758
    }
759
760
    protected function setTitles(BaseMapper $mapper, $titleTemplate, $title)
761
    {
762
        $contexts = [
763
            ListMapper::class => 'list',
764
            ShowMapper::class => 'show',
765
            FormMapper::class => 'form',
766
        ];
767
        if (!isset($contexts[get_class($mapper)])) {
768
            return;
769
        }
770
771
        $context = $contexts[get_class($mapper)];
772
        if ($titleTemplate) {
773
            $this->titleTemplates[$context] = $titleTemplate;
774
        }
775
        if ($title) {
776
            $this->titles[$context] = $title;
777
        }
778
    }
779
780
    protected function getFormThemeMapping()
781
    {
782
        $theme = [];
783
        $blast = $this->getConfigurationPool()->getContainer()->getParameter('blast');
0 ignored issues
show
Bug introduced by
It seems like getConfigurationPool() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
784
785
        foreach ($this->getCurrentComposition() as $class) {
0 ignored issues
show
Bug introduced by
It seems like getCurrentComposition() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
786
            if (isset($blast[$class])) {
787
                if (isset($blast[$class]['form_theme'])) {
788
                    $theme = array_merge($theme, $blast[$class]['form_theme']);
789
                }
790
            }
791
        }
792
793
        return $theme;
794
    }
795
796
    protected function getBaseRouteMapping()
797
    {
798
        $baseRoute = [];
799
        $blast = $this->getConfigurationPool()->getContainer()->getParameter('blast');
0 ignored issues
show
Bug introduced by
It seems like getConfigurationPool() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
800
801
        foreach ($this->getCurrentComposition() as $class) {
0 ignored issues
show
Bug introduced by
It seems like getCurrentComposition() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
802
            if (isset($blast[$class]) && isset($blast[$class]['baseRoute'])) {
803
                $reflexionClass = new \ReflectionClass($class);
804
                if (!$reflexionClass->isTrait()) {
805
                    $baseRoute = array_merge($baseRoute, $blast[$class]['baseRoute']);
806
                }
807
            }
808
        }
809
810
        return $baseRoute;
811
    }
812
813
    protected function manageCallback($mapper, &$options, $callbackType)
0 ignored issues
show
Unused Code introduced by
The parameter $mapper is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
814
    {
815
        $option = $options[$callbackType];
816
817
        $entityClass = isset($options['class']) ? $options['class'] : $this->getClass();
0 ignored issues
show
Bug introduced by
It seems like getClass() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
818
819
        if (!is_array($option)) {
820
            throw new Exception('« $callbackType » option must be an array : ["FQDN"=>"static method name"]');
821
        }
822
823
        list($serviceNameOrClass, $methodName) = $option;
824
825
        $targetOptions = (isset($option[2]) ? $option[2] : null);
826
827
        if ($this->getConfigurationPool()->getContainer()->has($serviceNameOrClass)) {
0 ignored issues
show
Bug introduced by
It seems like getConfigurationPool() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
828
            $callBackFunction = [$this->getConfigurationPool()->getContainer()->get($serviceNameOrClass), $methodName];
0 ignored issues
show
Bug introduced by
It seems like getConfigurationPool() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
829
        } else {
830
            $callBackFunction = call_user_func($serviceNameOrClass . '::' . $methodName, $this->getModelManager(), $entityClass);
0 ignored issues
show
Bug introduced by
It seems like getModelManager() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
831
        }
832
833
        if ($targetOptions !== null) {
834
            $options[$targetOptions] = $callBackFunction;
835
            unset($options[$callbackType]);
836
        }
837
838
        return $callBackFunction;
839
    }
840
841
    protected function manageQueryCallback($mapper, &$options)
842
    {
843
        $callback = $this->manageCallback($mapper, $options, 'query');
844
        $options['query'] = $callback;
845
    }
846
847
    protected function manageChoicesCallback($mapper, &$options)
848
    {
849
        $callback = $this->manageCallback($mapper, $options, 'choicesCallback');
850
851
        $options['choices'] = $callback;
852
        $options['choice_loader'] = new CallbackChoiceLoader(function () use ($options) {
853
            return $options['choices'];
854
        });
855
        unset($options['choicesCallback']);
856
    }
857
858
    public function manageServiceCallback($mapper, &$options)
859
    {
860
        $this->manageCallback($mapper, $options, 'serviceCallback');
861
    }
862
}
863