Completed
Push — master ( 1e3fe5...2c0ff3 )
by
unknown
02:52
created

src/Admin/CoreAdmin.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * This file is part of the Blast Project package.
5
 *
6
 * Copyright (C) 2015-2017 Libre Informatique
7
 *
8
 * This file is licenced under the GNU LGPL v3.
9
 * For the full copyright and license information, please view the LICENSE.md
10
 * file that was distributed with this source code.
11
 */
12
13
namespace Blast\CoreBundle\Admin;
14
15
use Sonata\AdminBundle\Datagrid\DatagridMapper;
16
use Sonata\AdminBundle\Datagrid\ListMapper;
17
use Sonata\AdminBundle\Form\FormMapper;
18
use Sonata\AdminBundle\Mapper\BaseMapper;
19
use Sonata\AdminBundle\Show\ShowMapper;
20
use Sonata\AdminBundle\Route\RouteCollection;
21
use Sonata\AdminBundle\Admin\AbstractAdmin as SonataAdmin;
22
use Sonata\DoctrineORMAdminBundle\Admin\FieldDescription;
23
use Blast\CoreBundle\Tools\Reflection\ClassAnalyzer;
24
use Blast\CoreBundle\Admin\Traits\CollectionsManager;
25
use Blast\CoreBundle\Admin\Traits\Mapper;
26
use Blast\CoreBundle\Admin\Traits\Templates;
27
use Blast\CoreBundle\Admin\Traits\PreEvents;
28
use Blast\CoreBundle\Admin\Traits\ManyToManyManager;
29
use Blast\CoreBundle\Admin\Traits\Actions;
30
use Blast\CoreBundle\Admin\Traits\ListActions;
31
use Blast\CoreBundle\CodeGenerator\CodeGeneratorRegistry;
32
use Symfony\Component\PropertyAccess\PropertyAccess;
33
34
abstract class CoreAdmin extends SonataAdmin implements \JsonSerializable
35
{
36
    use CollectionsManager,
37
        ManyToManyManager,
38
        Mapper,
39
        Templates,
40
        PreEvents,
41
        Actions,
42
        ListActions
43
    ;
44
45
    protected $extraTemplates = [];
46
47
    /**
48
     * Configure routes for list actions.
49
     *
50
     * @param RouteCollection $collection
51
     */
52
    protected function configureRoutes(RouteCollection $collection)
53
    {
54
        parent::configureRoutes($collection);
55
        $collection->add('duplicate', $this->getRouterIdParameter() . '/duplicate');
56
        $collection->add('generateEntityCode');
57
    }
58
59 View Code Duplication
    public function getBaseRouteName()
0 ignored issues
show
This method seems to be duplicated in 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...
60
    {
61
        $configuredBaseRoute = $this->getBaseRouteMapping();
62
63
        if (count($configuredBaseRoute) > 0) {
64
            $this->cachedBaseRouteName = null;
65
            if (isset($configuredBaseRoute['name']) && $this->baseRouteName === null) {
66
                $this->baseRouteName = $configuredBaseRoute['name'];
67
            }
68
        }
69
70
        return parent::getBaseRouteName();
71
    }
72
73 View Code Duplication
    public function getBaseRoutePattern()
0 ignored issues
show
This method seems to be duplicated in 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...
74
    {
75
        $configuredBaseRoute = $this->getBaseRouteMapping();
76
77
        if (count($configuredBaseRoute) > 0) {
78
            $this->cachedBaseRoutePattern = null;
79
            if (isset($configuredBaseRoute['pattern']) && $this->baseRoutePattern === null) {
80
                $this->baseRoutePattern = $configuredBaseRoute['pattern'];
81
            }
82
        }
83
84
        return parent::getBaseRoutePattern();
85
    }
86
87
    public function getFormTheme()
88
    {
89
        return array_merge($this->formTheme, $this->getFormThemeMapping());
90
    }
91
92
    /**
93
     * @param DatagridMapper $mapper
94
     */
95
    protected function configureDatagridFilters(DatagridMapper $mapper)
96
    {
97
        if (!$this->configureMapper($mapper)) {
98
            $this->fallbackConfiguration($mapper, __FUNCTION__);
99
        }
100
    }
101
102
    /**
103
     * @param ListMapper $mapper
104
     */
105
    protected function configureListFields(ListMapper $mapper)
106
    {
107
        if (!$this->configureMapper($mapper)) {
108
            $this->fallbackConfiguration($mapper, __FUNCTION__);
109
        }
110
    }
111
112
    /**
113
     * @param FormMapper $mapper
114
     */
115
    protected function configureFormFields(FormMapper $mapper)
116
    {
117
        if (!$this->configureMapper($mapper)) {
118
            $this->fallbackConfiguration($mapper, __FUNCTION__);
119
        }
120
    }
121
122
    /**
123
     * @param ShowMapper $mapper
124
     */
125
    protected function configureShowFields(ShowMapper $mapper)
126
    {
127
        if (!$this->configureMapper($mapper)) {
128
            $this->fallbackConfiguration($mapper, __FUNCTION__);
129
        }
130
    }
131
132
    /**
133
     * @param BaseMapper $mapper
134
     */
135
    protected function fixShowRoutes(BaseMapper $mapper)
0 ignored issues
show
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...
136
    {
137
        foreach (['getShow', 'getList'] as $fct) {
138
            foreach ($this->$fct()->getElements() as $field) {
139
                if ($field instanceof FieldDescription) {
140
                    $options = $field->getOptions();
141
                    if ($options['route']['name'] != 'edit') {
142
                        continue;
143
                    }
144
145
                    $options['route']['name'] = 'show';
146
                    $field->setOptions($options);
147
                }
148
            }
149
        }
150
151
        return $this;
152
    }
153
154
    protected function getCurrentComposition()
155
    {
156
        // traits of the current Entity
157
        $classes = ClassAnalyzer::getTraits($this->getClass());
158
        // inheritance of the current Entity
159
        foreach (array_reverse([$this->getClass()] + class_parents($this->getClass())) as $class) {
160
            $classes[] = $class;
161
        }
162
        // inheritance of the current Admin
163
        foreach (array_reverse([$this->getOriginalClass()] + $this->getParentClasses()) as $admin) {
164
            $classes[] = $admin;
165
        }
166
167
        return $classes;
168
    }
169
170
    private function fallbackConfiguration(BaseMapper $mapper, $function)
171
    {
172
        // fallback
173
        $rm = new \ReflectionMethod($this->getParentClass(), $function);
174
        if ($rm->class == $this->getParentClass()) {
175
            $this->configureFields($function, $mapper, $this->getParentClass());
176
        }
177
    }
178
179
    /**
180
     * Returns the level of depth of an array.
181
     *
182
     * @param array $array
183
     * @param int   $level : do not use, just used for recursivity
184
     *
185
     * @return int : depth
186
     */
187
    private static function arrayDepth($array, $level = 0)
188
    {
189
        if (!$array) {
190
            return $level;
191
        }
192
193
        if (!is_array($array)) {
194
            return $level;
195
        }
196
197
        ++$level;
198
        foreach ($array as $key => $value) {
199
            if (is_array($value)) {
200
                $level = $level < self::arrayDepth($value, $level) ? self::arrayDepth($value, $level) : $level;
201
            }
202
        }
203
204
        return $level;
205
    }
206
207
    protected function getOriginalClass()
208
    {
209
        return get_called_class();
210
    }
211
212
    protected function getParentClasses()
213
    {
214
        return class_parents($this->getOriginalClass());
215
    }
216
217
    protected function getParentClass()
218
    {
219
        return get_parent_class($this->getOriginalClass());
220
    }
221
222
    protected function getGrandParentClass()
223
    {
224
        return get_parent_class(get_parent_class($this->getOriginalClass()));
225
    }
226
227
    /**
228
     * @param string $view     'list', 'show', 'form', etc
229
     * @param string $template template name
230
     */
231
    public function addExtraTemplate($view, $template)
232
    {
233
        if (empty($this->extraTemplates[$view])) {
234
            $this->extraTemplates[$view] = [];
235
        }
236
        if (!in_array($template, $this->extraTemplates[$view])) {
237
            $this->extraTemplates[$view][] = $template;
238
        }
239
    }
240
241
    /**
242
     * @param string $view 'list', 'show', 'form', etc
243
     *
244
     * @return array array of template names
245
     */
246
    public function getExtraTemplates($view)
247
    {
248
        if (empty($this->extraTemplates[$view])) {
249
            $this->extraTemplates[$view] = [];
250
        }
251
252
        return $this->extraTemplates[$view];
253
    }
254
255
    /**
256
     * @param string $view 'list', 'show', 'form', etc
257
     * @param array  $link link (array keys should be: 'label', 'url', 'class', 'title')
258
     */
259
    public function addHelperLink($view, $link)
260
    {
261
        if (empty($this->helperLinks[$view])) {
262
            $this->helperLinks[$view] = [];
263
        }
264
265
        // Do not add links without URL
266
        if (empty($link['url'])) {
267
            return;
268
        }
269
270
        // Do not add two links with the same URL
271
        foreach ($this->helperLinks[$view] as $l) {
272
            if ($l['url'] == $link['url']) {
273
                return;
274
            }
275
        }
276
277
        $this->helperLinks[$view][] = $link;
278
    }
279
280
    /**
281
     * @param string $view 'list', 'show', 'form', etc
282
     *
283
     * @return array array of links (each link is an array with keys 'label', 'url', 'class' and 'title')
284
     */
285
    public function getHelperLinks($view)
286
    {
287
        if (empty($this->helperLinks[$view])) {
288
            $this->helperLinks[$view] = [];
289
        }
290
291
        return $this->helperLinks[$view];
292
    }
293
294
    /**
295
     * Checks if a Bundle is installed.
296
     *
297
     * @param string $bundle Bundle name or class FQN
298
     */
299
    public function bundleExists($bundle)
300
    {
301
        $kernelBundles = $this->getConfigurationPool()->getContainer()->getParameter('kernel.bundles');
302
        if (array_key_exists($bundle, $kernelBundles)) {
303
            return true;
304
        }
305
        if (in_array($bundle, $kernelBundles)) {
306
            return true;
307
        }
308
309
        return false;
310
    }
311
312
    /**
313
     * Rename a form tab after form fields have been configured.
314
     *
315
     * TODO: groups of the renamed tab are still prefixed with the old tab name
316
     *
317
     * @param type $tabName    the name of the tab to be renamed
318
     * @param type $newTabName the new name for the tab
319
     */
320 View Code Duplication
    public function renameFormTab($tabName, $newTabName, $keepOrder = true)
0 ignored issues
show
This method seems to be duplicated in 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...
321
    {
322
        $tabs = $this->getFormTabs();
323
324
        if (!$tabs) {
325
            return;
326
        }
327
328
        if (!isset($tabs[$tabName])) {
329
            throw new \Exception(sprintf('Tab %s does not exist.', $tabName));
330
        }
331
        if (isset($tabs[$newTabName])) {
332
            return;
333
        }
334
335
        if ($keepOrder) {
336
            $keys = array_keys($tabs);
337
            $keys[array_search($tabName, $keys)] = $newTabName;
338
            $tabs = array_combine($keys, $tabs);
339
        } else {
340
            $tabs[$newTabName] = $tabs[$tabName];
341
            unset($tabs[$tabName]);
342
        }
343
344
        $this->setFormTabs($tabs);
345
    }
346
347
    /**
348
     * Rename a show tab after show fields have been configured.
349
     *
350
     * TODO: groups of the renamed tab are still prefixed with the old tab name
351
     *
352
     * @param type $tabName    the name of the tab to be renamed
353
     * @param type $newTabName the new name for the tab
354
     */
355 View Code Duplication
    public function renameShowTab($tabName, $newTabName, $keepOrder = true)
0 ignored issues
show
This method seems to be duplicated in 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...
356
    {
357
        $tabs = $this->getShowTabs();
358
359
        if (!$tabs) {
360
            return;
361
        }
362
363
        if (!isset($tabs[$tabName])) {
364
            throw new \Exception(sprintf('Tab %s does not exist.', $tabName));
365
        }
366
        if (isset($tabs[$newTabName])) {
367
            return;
368
        }
369
370
        if ($keepOrder) {
371
            $keys = array_keys($tabs);
372
            $keys[array_search($tabName, $keys)] = $newTabName;
373
            $tabs = array_combine($keys, $tabs);
374
        } else {
375
            $tabs[$newTabName] = $tabs[$tabName];
376
            unset($tabs[$tabName]);
377
        }
378
379
        $this->setShowTabs($tabs);
380
    }
381
382
    /**
383
     * Rename a form group.
384
     *
385
     * @param string $group        the old group name
386
     * @param string $tab          the tab the group belongs to
387
     * @param string $newGroupName the new group name
388
     *
389
     * @return self
390
     */
391
    public function renameFormGroup($group, $tab, $newGroupName)
392
    {
393
        $groups = $this->getFormGroups();
394
395
        // When the default tab is used, the tabname is not prepended to the index in the group array
396
        if ($tab !== 'default') {
397
            $group = $tab . '.' . $group;
398
        }
399
        $newGroup = ($tab !== 'default') ? $tab . '.' . $newGroupName : $newGroupName;
400
401
        if (isset($groups[$newGroup])) {
402
            throw new \Exception(sprintf('%s form group already exists.', $newGroup));
403
        }
404
        if (!array_key_exists($group, $groups)) {
405
            throw new \Exception(sprintf('form group « %s » doesn\'t exist.', $group));
406
        }
407
408
        $groups[$newGroup] = $groups[$group];
409
        $groups[$newGroup]['name'] = $newGroupName;
410
        unset($groups[$group]);
411
412
        $tabs = $this->getFormTabs();
413
        $key = array_search($group, $tabs[$tab]['groups']);
414
415
        if (false !== $key) {
416
            $tabs[$tab]['groups'][$key] = $newGroup;
417
        }
418
419
        $this->setFormTabs($tabs);
420
        $this->setFormGroups($groups);
421
422
        return $this;
423
    }
424
425
    /**
426
     * Removes tab in current form Mapper.
427
     *
428
     * @param string|array $tabNames name or array of names of tabs to be removed
429
     * @param FormMapper   $mapper   Sonata Admin form mapper
430
     */
431
    public function removeTab($tabNames, $mapper)
432
    {
433
        $currentTabs = $this->getFormTabs();
434
        foreach ($currentTabs as $k => $item) {
435
            if (is_array($tabNames) && in_array($item['name'], $tabNames) || !is_array($tabNames) && $item['name'] === $tabNames) {
436
                foreach ($item['groups'] as $groupName) {
437
                    $this->removeAllFieldsFromFormGroup($groupName, $mapper);
438
                }
439
                unset($currentTabs[$k]);
440
            }
441
        }
442
        $this->setFormTabs($currentTabs);
443
    }
444
445
    /**
446
     * Removes all fields from form groups and remove them from mapper.
447
     *
448
     * @param string     $groupName Name of the group to remove
449
     * @param FormMapper $mapper    Sonata Admin form mapper
450
     */
451
    public function removeAllFieldsFromFormGroup($groupName, $mapper)
452
    {
453
        $formGroups = $this->getFormGroups();
454
        foreach ($formGroups as $name => $formGroup) {
455
            if ($name === $groupName) {
456
                foreach ($formGroups[$name]['fields'] as $key => $field) {
457
                    $mapper->remove($key);
458
                }
459
            }
460
        }
461
    }
462
463
    public function jsonSerialize()
464
    {
465
        $propertiesToShow = [
466
            'baseRouteName',
467
            'baseRoutePattern',
468
            'extraTemplates',
469
            'listFieldDescriptions',
470
            'showFieldDescriptions',
471
            'formFieldDescriptions',
472
            'filterFieldDescriptions',
473
            'maxPerPage',
474
            'maxPageLinks',
475
            'classnameLabel',
476
            'translationDomain',
477
            'formOptions',
478
            'datagridValues',
479
            'perPageOptions',
480
            'pagerType',
481
            'code',
482
            'label',
483
            'routes',
484
            'subject',
485
            'children',
486
            'parent',
487
            'baseCodeRoute',
488
            'uniqid',
489
            'extensions',
490
            'class',
491
            'subClasses',
492
            'list',
493
            'show',
494
            'form',
495
            'filter',
496
            'formGroups',
497
            'formTabs',
498
            'showGroups',
499
            'showTabs',
500
            'managedCollections',
501
            'helperLinks',
502
            'titles',
503
        ];
504
505
        $properties = [];
506
        foreach ($this as $key => $value) {
507
            if (in_array($key, $propertiesToShow)) {
508
                $properties[$key] = $value;
509
            }
510
        }
511
512
        return $properties;
513
    }
514
515
    /**
516
     * {@inheritdoc}
517
     */
518
    public function prePersist($object)
519
    {
520
        parent::prePersist($object);
521
522
        $hasCodeGenerator = CodeGeneratorRegistry::hasGeneratorForClass(get_class($object));
523
        if ($hasCodeGenerator) {
524
            $accessor = PropertyAccess::createPropertyAccessor();
525
            foreach (CodeGeneratorRegistry::getCodeGenerators(get_class($object)) as $name => $generator) {
526
                $accessor->setValue($object, $name, $generator->generate($object));
527
            }
528
        }
529
    }
530
}
531