Completed
Push — master ( 6d6774...64f3ed )
by Jeroen
11:23 queued 05:13
created

Configurator/AbstractAdminListConfigurator.php (4 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
namespace Kunstmaan\AdminListBundle\AdminList\Configurator;
4
5
use Doctrine\ORM\PersistentCollection;
6
use InvalidArgumentException;
7
use Kunstmaan\AdminListBundle\AdminList\BulkAction\BulkActionInterface;
8
use Kunstmaan\AdminListBundle\AdminList\Field;
9
use Kunstmaan\AdminListBundle\AdminList\FieldAlias;
10
use Kunstmaan\AdminListBundle\AdminList\FilterBuilder;
11
use Kunstmaan\AdminListBundle\AdminList\FilterType\FilterTypeInterface;
12
use Kunstmaan\AdminListBundle\AdminList\ItemAction\ItemActionInterface;
13
use Kunstmaan\AdminListBundle\AdminList\ItemAction\SimpleItemAction;
14
use Kunstmaan\AdminListBundle\AdminList\ListAction\ListActionInterface;
15
use Symfony\Component\Form\AbstractType;
16
use Symfony\Component\HttpFoundation\Request;
17
use Symfony\Component\PropertyAccess\PropertyAccess;
18
19
/**
20
 * Abstract admin list configurator, this implements the most common functionality from the
21
 * AdminListConfiguratorInterface and ExportListConfiguratorInterface
22
 */
23
abstract class AbstractAdminListConfigurator implements AdminListConfiguratorInterface, ExportListConfiguratorInterface
24
{
25
    const SUFFIX_ADD = 'add';
26
    const SUFFIX_EDIT = 'edit';
27
    const SUFFIX_EXPORT = 'export';
28
    const SUFFIX_DELETE = 'delete';
29
    const SUFFIX_VIEW = 'view';
30
31
    /**
32
     * @var Field[]
33
     */
34
    private $fields = array();
35
36
    /**
37
     * @var Field[]
38
     */
39
    private $exportFields = array();
40
41
    /**
42
     * @var ItemActionInterface[]
43
     */
44
    private $itemActions = array();
45
46
    /**
47
     * @var ListActionInterface[]
48
     */
49
    private $listActions = array();
50
51
    /**
52
     * @var BulkActionInterface[]
53
     */
54
    private $bulkActions = array();
55
56
    /**
57
     * @var AbstractType
58
     */
59
    private $type;
60
61
    /**
62
     * @var array
63
     */
64
    private $typeOptions = array();
65
66
    /**
67
     * @var string
68
     */
69
    private $listTemplate = '@KunstmaanAdminList/Default/list.html.twig';
70
71
    /**
72
     * @var string
73
     */
74
    private $addTemplate = '@KunstmaanAdminList/Default/add_or_edit.html.twig';
75
76
    /**
77
     * @var string
78
     */
79
    private $editTemplate = '@KunstmaanAdminList/Default/add_or_edit.html.twig';
80
81
    /**
82
     * @var string
83
     */
84
    private $viewTemplate = '@KunstmaanAdminList/Default/view.html.twig';
85
86
    /**
87
     * @var string
88
     */
89
    private $deleteTemplate = '@KunstmaanAdminList/Default/delete.html.twig';
90
91
    /**
92
     * @var FilterBuilder
93
     */
94
    private $filterBuilder;
95
96
    /**
97
     * @var int
98
     */
99
    protected $page = 1;
100
101
    /**
102
     * @var string
103
     */
104
    protected $orderBy = '';
105
106
    /**
107
     * @var string
108
     */
109
    protected $orderDirection = '';
110
111
    /**
112
     * Return current bundle name.
113
     *
114
     * @return string
115
     */
116
    abstract public function getBundleName();
117
118
    /**
119
     * Return current entity name.
120
     *
121
     * @return string
122
     */
123
    abstract public function getEntityName();
124
125
    /**
126
     * Return default repository name.
127
     *
128
     * @return string
129
     */
130 8
    public function getRepositoryName()
131
    {
132 8
        return sprintf('%s:%s', $this->getBundleName(), $this->getEntityName());
133
    }
134
135
    /**
136
     * Configure the fields you can filter on
137
     */
138
    public function buildFilters()
139
    {
140
    }
141
142
    /**
143
     * Configure the actions for each line
144
     */
145
    public function buildItemActions()
146
    {
147
    }
148
149
    /**
150
     * Configure the actions that can be executed on the whole list
151
     */
152
    public function buildListActions()
153
    {
154
    }
155
156
    /**
157
     * Configure the export fields
158
     */
159 1
    public function buildExportFields()
160
    {
161
        /*
162
         * This is only here to prevent a BC break!!!
163
         *
164
         * Just override this function if you want to set your own fields...
165
         */
166 1
        if (empty($this->fields)) {
167 1
            $this->buildFields();
168
        }
169 1
    }
170
171
    /**
172
     * Build iterator (if needed)
173
     */
174
    public function buildIterator()
175
    {
176
    }
177
178
    /**
179
     * Reset all built members
180
     */
181 1
    public function resetBuilds()
182
    {
183 1
        $this->fields = array();
184 1
        $this->exportFields = array();
185 1
        $this->filterBuilder = null;
186 1
        $this->itemActions = array();
187 1
        $this->listActions = array();
188 1
    }
189
190
    /**
191
     * Configure the types of items you can add
192
     *
193
     * @param array $params
194
     *
195
     * @return array
196
     */
197 1
    public function getAddUrlFor(array $params = array())
198
    {
199 1
        $params = array_merge($params, $this->getExtraParameters());
200
201 1
        $friendlyName = explode('\\', $this->getEntityName());
202 1
        $friendlyName = array_pop($friendlyName);
203 1
        $re = '/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/';
204 1
        $a = preg_split($re, $friendlyName);
205 1
        $superFriendlyName = implode(' ', $a);
206
207
        return array(
208
            $superFriendlyName => array(
209 1
                'path' => $this->getPathByConvention($this::SUFFIX_ADD),
210 1
                'params' => $params,
211
            ),
212
        );
213
    }
214
215
    /**
216
     * Get the url to export the listed items
217
     *
218
     * @return array
219
     */
220 1
    public function getExportUrl()
221
    {
222 1
        $params = $this->getExtraParameters();
223
224
        return array(
225 1
            'path' => $this->getPathByConvention($this::SUFFIX_EXPORT),
226 1
            'params' => array_merge(array('_format' => 'csv'), $params),
227
        );
228
    }
229
230
    /**
231
     * Get the view url for the given $item
232
     *
233
     * @param object|array $item
234
     *
235
     * @return array
236
     */
237 1
    public function getViewUrlFor($item)
238
    {
239 1
        if (\is_object($item)) {
240 1
            $id = $item->getid();
241
        } else {
242 1
            $id = $item['id'];
243
        }
244 1
        $params = ['id' => $id];
245 1
        $params = array_merge($params, $this->getExtraParameters());
246
247
        return [
248 1
            'path' => $this->getPathByConvention($this::SUFFIX_VIEW),
249 1
            'params' => $params,
250
        ];
251
    }
252
253
    /**
254
     * Return the url to list all the items
255
     *
256
     * @return array
257
     */
258 1
    public function getIndexUrl()
259
    {
260 1
        $params = $this->getExtraParameters();
261
262
        return array(
263 1
            'path' => $this->getPathByConvention(),
264 1
            'params' => $params,
265
        );
266
    }
267
268
    /**
269
     * @param object $entity
270
     *
271
     * @throws InvalidArgumentException
272
     *
273
     * @return string
274
     */
275 3
    public function getAdminType($entity)
276
    {
277 3
        if (null !== $this->type) {
278 1
            return $this->type;
279
        }
280
281 2
        if (method_exists($entity, 'getAdminType')) {
282 1
            return $entity->getAdminType();
283
        }
284
285 1
        throw new InvalidArgumentException('You need to implement the getAdminType method in '. \get_class($this).' or '. \get_class($entity));
286
    }
287
288
    /**
289
     * @param string $type
290
     *
291
     * @return AbstractAdminListConfigurator
292
     */
293 6
    public function setAdminType($type)
294
    {
295 6
        $this->type = $type;
0 ignored issues
show
Documentation Bug introduced by
It seems like $type of type string is incompatible with the declared type object<Symfony\Component\Form\AbstractType> of property $type.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
296
297 6
        return $this;
298
    }
299
300
    /**
301
     * @param array $typeOptions
302
     *
303
     * @return AbstractAdminListConfigurator
304
     */
305 5
    public function setAdminTypeOptions($typeOptions)
306
    {
307 5
        $this->typeOptions = $typeOptions;
308
309 5
        return $this;
310
    }
311
312
    /**
313
     * Return the default form admin type options
314
     *
315
     * @return array
316
     */
317 1
    public function getAdminTypeOptions()
318
    {
319 1
        return $this->typeOptions;
320
    }
321
322
    /**
323
     * @param object|array $item
324
     *
325
     * @return bool
326
     */
327 1
    public function canEdit($item)
328
    {
329 1
        return true;
330
    }
331
332
    /**
333
     * Configure if it's possible to delete the given $item
334
     *
335
     * @param object|array $item
336
     *
337
     * @return bool
338
     */
339 1
    public function canDelete($item)
340
    {
341 1
        return true;
342
    }
343
344
    /**
345
     * Configure if it's possible to add new items
346
     *
347
     * @return bool
348
     */
349 1
    public function canAdd()
350
    {
351 1
        return true;
352
    }
353
354 1
    public function canView($item)
355
    {
356 1
        return false;
357
    }
358
359
    /**
360
     * Configure if it's possible to add new items
361
     *
362
     * @return bool
363
     */
364 1
    public function canExport()
365
    {
366 1
        return false;
367
    }
368
369
    /**
370
     * @param string     $name     The field name
371
     * @param string     $header   The header title
372
     * @param bool       $sort     Sortable column or not
373
     * @param string     $template The template
0 ignored issues
show
Should the type for parameter $template not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
374
     * @param FieldAlias $alias    The alias
375
     *
376
     * @return AbstractAdminListConfigurator
377
     */
378 8
    public function addField($name, $header, $sort, $template = null, FieldAlias $alias = null)
379
    {
380 8
        $this->fields[] = new Field($name, $header, $sort, $template, $alias);
381
382 8
        return $this;
383
    }
384
385
    /**
386
     * @param string     $name     The field name
387
     * @param string     $header   The header title
388
     * @param string     $template The template
0 ignored issues
show
Should the type for parameter $template not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
389
     * @param FieldAlias $alias    The alias
390
     *
391
     * @return AbstractAdminListConfigurator
392
     */
393 1
    public function addExportField($name, $header, $template = null, FieldAlias $alias = null)
394
    {
395 1
        $this->exportFields[] = new Field($name, $header, false, $template, $alias);
396
397 1
        return $this;
398
    }
399
400
    /**
401
     * @param string              $columnName The column name
402
     * @param FilterTypeInterface $type       The filter type
403
     * @param string              $filterName The name of the filter
404
     * @param array               $options    Options
405
     *
406
     * @return AbstractAdminListConfigurator
407
     */
408 5
    public function addFilter(
409
        $columnName,
410
        FilterTypeInterface $type = null,
411
        $filterName = null,
412
        array $options = array()
413
    ) {
414 5
        $this->getFilterBuilder()->add($columnName, $type, $filterName, $options);
415
416 5
        return $this;
417
    }
418
419
    /**
420
     * @return int
421
     */
422 3
    public function getLimit()
423
    {
424 3
        return 10;
425
    }
426
427
    /**
428
     * @return array
429
     */
430 1
    public function getSortFields()
431
    {
432 1
        $array = array();
433 1
        foreach ($this->getFields() as $field) {
434 1
            if ($field->isSortable()) {
435 1
                $array[] = $field->getName();
436
            }
437
        }
438
439 1
        return $array;
440
    }
441
442
    /**
443
     * @return Field[]
444
     */
445 9
    public function getFields()
446
    {
447 9
        return $this->fields;
448
    }
449
450
    /**
451
     * @return Field[]
452
     */
453 2
    public function getExportFields()
454
    {
455 2
        if (empty($this->exportFields)) {
456 1
            return $this->fields;
457
        }
458
459 1
        return $this->exportFields;
460
    }
461
462
    /**
463
     * @param string   $label          The label, only used when the template equals null
464
     * @param callable $routeGenerator The generator used to generate the url of an item, when generating the item will
465
     *                                 be provided
466
     * @param string   $icon           The icon, only used when the template equals null
467
     * @param string   $template       The template, when not specified the label is shown
468
     *
469
     * @return AbstractAdminListConfigurator
470
     */
471 1
    public function addSimpleItemAction($label, $routeGenerator, $icon, $template = null)
472
    {
473 1
        return $this->addItemAction(new SimpleItemAction($routeGenerator, $icon, $label, $template));
474
    }
475
476
    /**
477
     * @param ItemActionInterface $itemAction
478
     *
479
     * @return AbstractAdminListConfigurator
480
     */
481 4
    public function addItemAction(ItemActionInterface $itemAction)
482
    {
483 4
        $this->itemActions[] = $itemAction;
484
485 4
        return $this;
486
    }
487
488
    /**
489
     * @return bool
490
     */
491 1
    public function hasItemActions()
492
    {
493 1
        return !empty($this->itemActions);
494
    }
495
496
    /**
497
     * @return ItemActionInterface[]
498
     */
499 3
    public function getItemActions()
500
    {
501 3
        return $this->itemActions;
502
    }
503
504
    /**
505
     * @param ListActionInterface $listAction
506
     *
507
     * @return AdminListConfiguratorInterface
508
     */
509 1
    public function addListAction(ListActionInterface $listAction)
510
    {
511 1
        $this->listActions[] = $listAction;
512
513 1
        return $this;
514
    }
515
516
    /**
517
     * @return bool
518
     */
519 1
    public function hasListActions()
520
    {
521 1
        return !empty($this->listActions);
522
    }
523
524
    /**
525
     * @return ListActionInterface[]
526
     */
527 1
    public function getListActions()
528
    {
529 1
        return $this->listActions;
530
    }
531
532
    /**
533
     * @param BulkActionInterface $bulkAction
534
     *
535
     * @return AdminListConfiguratorInterface
536
     */
537 1
    public function addBulkAction(BulkActionInterface $bulkAction)
538
    {
539 1
        $this->bulkActions[] = $bulkAction;
540
541 1
        return $this;
542
    }
543
544
    /**
545
     * @return bool
546
     */
547 1
    public function hasBulkActions()
548
    {
549 1
        return !empty($this->bulkActions);
550
    }
551
552
    /**
553
     * @return BulkActionInterface[]
554
     */
555 1
    public function getBulkActions()
556
    {
557 1
        return $this->bulkActions;
558
    }
559
560
    /**
561
     * @return string
562
     */
563 2
    public function getListTemplate()
564
    {
565 2
        return $this->listTemplate;
566
    }
567
568
    /**
569
     * @param string $template
570
     *
571
     * @return AdminListConfiguratorInterface
572
     */
573 1
    public function setListTemplate($template)
574
    {
575 1
        $this->listTemplate = $template;
576
577 1
        return $this;
578
    }
579
580
    /**
581
     * @param array|object $item       The item
582
     * @param string       $columnName The column name
583
     *
584
     * @return mixed
585
     */
586 2
    public function getValue($item, $columnName)
587
    {
588 2
        if (\is_array($item)) {
589 2
            if (isset($item[$columnName])) {
590 2
                return $item[$columnName];
591
            }
592
593 1
            return '';
594
        }
595
596 1
        $accessor = PropertyAccess::createPropertyAccessor();
597
598 1
        if ($accessor->isReadable($item, $columnName)) {
599 1
            $result = $accessor->getValue($item, $columnName);
600
        } else {
601 1
            return sprintf('undefined function [get/is/has]%s()', $columnName);
602
        }
603
604 1
        return $result;
605
    }
606
607
    /**
608
     * @param array|object $item       The item
609
     * @param string       $columnName The column name
610
     *
611
     * @return string
612
     */
613 1
    public function getStringValue($item, $columnName)
614
    {
615 1
        $result = $this->getValue($item, $columnName);
616 1
        if (\is_bool($result)) {
617 1
            return $result ? 'true' : 'false';
618
        }
619 1
        if ($result instanceof \DateTimeInterface) {
620 1
            return $result->format('Y-m-d H:i:s');
621
        }
622
623 1
        if ($result instanceof PersistentCollection) {
624 1
            $results = [];
625
            /* @var Object $entry */
626 1
            foreach ($result as $entry) {
627 1
                $results[] = $entry->getName();
628
            }
629 1
            if (empty($results)) {
630 1
                return '';
631
            }
632
633 1
            return implode(', ', $results);
634
        }
635
636 1
        if (is_array($result)) {
637 1
            return implode(', ', $result);
638
        }
639
640 1
        return $result;
641
    }
642
643
    /**
644
     * @return string
645
     */
646 1
    public function getAddTemplate()
647
    {
648 1
        return $this->addTemplate;
649
    }
650
651
    /**
652
     * @param string $template
653
     *
654
     * @return AdminListConfiguratorInterface
655
     */
656 1
    public function setAddTemplate($template)
657
    {
658 1
        $this->addTemplate = $template;
659
660 1
        return $this;
661
    }
662
663
    /**
664
     * @return string
665
     */
666 1
    public function getViewTemplate()
667
    {
668 1
        return $this->viewTemplate;
669
    }
670
671
    /**
672
     * @param string $template
673
     *
674
     * @return AdminListConfiguratorInterface
675
     */
676 1
    public function setViewTemplate($template)
677
    {
678 1
        $this->viewTemplate = $template;
679
680 1
        return $this;
681
    }
682
683
    /**
684
     * @return string
685
     */
686 1
    public function getEditTemplate()
687
    {
688 1
        return $this->editTemplate;
689
    }
690
691
    /**
692
     * @param string $template
693
     *
694
     * @return AdminListConfiguratorInterface
695
     */
696 1
    public function setEditTemplate($template)
697
    {
698 1
        $this->editTemplate = $template;
699
700 1
        return $this;
701
    }
702
703
    /**
704
     * @return string
705
     */
706 1
    public function getDeleteTemplate()
707
    {
708 1
        return $this->deleteTemplate;
709
    }
710
711
    /**
712
     * @param string $template
713
     *
714
     * @return AdminListConfiguratorInterface
715
     */
716 1
    public function setDeleteTemplate($template)
717
    {
718 1
        $this->deleteTemplate = $template;
719
720 1
        return $this;
721
    }
722
723
    /**
724
     * You can override this method to do some custom things you need to do when adding an entity
725
     *
726
     * @param object $entity
727
     *
728
     * @return mixed
0 ignored issues
show
Consider making the return type a bit more specific; maybe use object.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
729
     */
730 1
    public function decorateNewEntity($entity)
731
    {
732 1
        return $entity;
733
    }
734
735
    /**
736
     * @return FilterBuilder
737
     */
738 10
    public function getFilterBuilder()
739
    {
740 10
        if (\is_null($this->filterBuilder)) {
741 9
            $this->filterBuilder = new FilterBuilder();
742
        }
743
744 10
        return $this->filterBuilder;
745
    }
746
747
    /**
748
     * @param FilterBuilder $filterBuilder
749
     *
750
     * @return AbstractAdminListConfigurator
751
     */
752 2
    public function setFilterBuilder(FilterBuilder $filterBuilder)
753
    {
754 2
        $this->filterBuilder = $filterBuilder;
755
756 2
        return $this;
757
    }
758
759
    /**
760
     * Bind current request.
761
     *
762
     * @param Request $request
763
     */
764 4
    public function bindRequest(Request $request)
765
    {
766 4
        $query = $request->query;
767 4
        $session = $request->getSession();
768
769 4
        $adminListName = 'listconfig_'.$request->get('_route');
770
771 4
        $this->page = $request->query->getInt('page', 1);
772
        // Allow alphanumeric, _ & . in order by parameter!
773 4
        $this->orderBy = preg_replace('/[^[a-zA-Z0-9\_\.]]/', '', $request->query->get('orderBy', ''));
774 4
        $this->orderDirection = $request->query->getAlpha('orderDirection');
775
776
        // there is a session and the filter param is not set
777 4 View Code Duplication
        if ($session->has($adminListName) && !$query->has('filter')) {
778 3
            $adminListSessionData = $request->getSession()->get($adminListName);
779 3
            if (!$query->has('page')) {
780 1
                $this->page = $adminListSessionData['page'];
781
            }
782
783 3
            if (!$query->has('orderBy')) {
784 3
                $this->orderBy = $adminListSessionData['orderBy'];
785
            }
786
787 3
            if (!$query->has('orderDirection')) {
788 3
                $this->orderDirection = $adminListSessionData['orderDirection'];
789
            }
790
        }
791
792
        // save current parameters
793 4
        $session->set(
794 4
            $adminListName,
795
            array(
796 4
                'page' => $this->page,
797 4
                'orderBy' => $this->orderBy,
798 4
                'orderDirection' => $this->orderDirection,
799
            )
800
        );
801
802 4
        $this->getFilterBuilder()->bindRequest($request);
803 4
    }
804
805
    /**
806
     * Return current page.
807
     *
808
     * @return int
809
     */
810 3
    public function getPage()
811
    {
812 3
        return $this->page;
813
    }
814
815
    /**
816
     * Return current sorting column.
817
     *
818
     * @return string
819
     */
820 1
    public function getOrderBy()
821
    {
822 1
        return $this->orderBy;
823
    }
824
825
    /**
826
     * Return current sorting direction.
827
     *
828
     * @return string
829
     */
830 1
    public function getOrderDirection()
831
    {
832 1
        return $this->orderDirection;
833
    }
834
835
    /**
836
     * @param string $suffix
837
     *
838
     * @return string
839
     */
840 9
    public function getPathByConvention($suffix = null)
841
    {
842 9
        $entityName = strtolower($this->getEntityName());
843 9
        $entityName = str_replace('\\', '_', $entityName);
844 9
        if (empty($suffix)) {
845 1
            return sprintf('%s_admin_%s', strtolower($this->getBundleName()), $entityName);
846
        }
847
848 8
        return sprintf('%s_admin_%s_%s', strtolower($this->getBundleName()), $entityName, $suffix);
849
    }
850
851
    /**
852
     * Get controller path.
853
     *
854
     * @return string
855
     */
856 1
    public function getControllerPath()
857
    {
858 1
        return sprintf('%s:%s', $this->getBundleName(), $this->getEntityName());
859
    }
860
861
    /**
862
     * Return extra parameters for use in list actions.
863
     *
864
     * @return array
865
     */
866 9
    public function getExtraParameters()
867
    {
868 9
        return array();
869
    }
870
}
871