Completed
Push — master ( 1de9b7...830752 )
by Kristof
38:46 queued 24:09
created

Configurator/AbstractAdminListConfigurator.php (2 issues)

Check that @param annotations have the correct type.

Documentation Informational

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 = null;
60
61
    /**
62
     * @var array
63
     */
64
    private $typeOptions = array();
65
66
    /**
67
     * @var string
68
     */
69
    private $listTemplate = 'KunstmaanAdminListBundle:Default:list.html.twig';
70
71
    /**
72
     * @var string
73
     */
74
    private $addTemplate = 'KunstmaanAdminListBundle:Default:add_or_edit.html.twig';
75
76
    /**
77
     * @var string
78
     */
79
    private $editTemplate = 'KunstmaanAdminListBundle:Default:add_or_edit.html.twig';
80
81
    /**
82
     * @var string
83
     */
84
    private $viewTemplate = 'KunstmaanAdminListBundle:Default:view.html.twig';
85
86
    /**
87
     * @var string
88
     */
89
    private $deleteTemplate = 'KunstmaanAdminListBundle:Default:delete.html.twig';
90
91
    /**
92
     * @var FilterBuilder
93
     */
94
    private $filterBuilder = null;
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
    public function getRepositoryName()
131
    {
132
        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
    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
        if (empty($this->fields)) {
167
            $this->buildFields();
168
        }
169
    }
170
171
    /**
172
     * Build iterator (if needed)
173
     */
174
    public function buildIterator()
175
    {
176
    }
177
178
    /**
179
     * Reset all built members
180
     */
181
    public function resetBuilds()
182
    {
183
        $this->fields = array();
184
        $this->exportFields = array();
185
        $this->filterBuilder = null;
186
        $this->itemActions = array();
187
        $this->listActions = array();
188
    }
189
190
    /**
191
     * Configure the types of items you can add
192
     *
193
     * @param array $params
194
     *
195
     * @return array
196
     */
197
    public function getAddUrlFor(array $params = array())
198
    {
199
        $params = array_merge($params, $this->getExtraParameters());
200
201
        $friendlyName = explode('\\', $this->getEntityName());
202
        $friendlyName = array_pop($friendlyName);
203
        $re = '/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/';
204
        $a = preg_split($re, $friendlyName);
205
        $superFriendlyName = implode(' ', $a);
206
207
        return array(
208
            $superFriendlyName => array(
209
                'path' => $this->getPathByConvention($this::SUFFIX_ADD),
210
                'params' => $params,
211
            ),
212
        );
213
    }
214
215
    /**
216
     * Get the url to export the listed items
217
     *
218
     * @return array
219
     */
220
    public function getExportUrl()
221
    {
222
        $params = $this->getExtraParameters();
223
224
        return array(
225
            'path' => $this->getPathByConvention($this::SUFFIX_EXPORT),
226
            'params' => array_merge(array('_format' => 'csv'), $params),
227
        );
228
    }
229
230
    public function getViewUrlFor($item)
231
    {
232
        if (is_object($item)) {
233
            $id = $item->getid();
234
        } else {
235
            $id = $item['id'];
236
        }
237
        $params = array('id' => $id);
238
        $params = array_merge($params, $this->getExtraParameters());
239
240
        return array(
241
            'path' => $this->getPathByConvention($this::SUFFIX_VIEW),
242
            'params' => $params,
243
        );
244
    }
245
246
    /**
247
     * Return the url to list all the items
248
     *
249
     * @return array
250
     */
251
    public function getIndexUrl()
252
    {
253
        $params = $this->getExtraParameters();
254
255
        return array(
256
            'path' => $this->getPathByConvention(),
257
            'params' => $params,
258
        );
259
    }
260
261
    /**
262
     * @param object $entity
263
     *
264
     * @throws InvalidArgumentException
265
     *
266
     * @return string
267
     */
268
    public function getAdminType($entity)
269
    {
270
        if (null !== $this->type) {
271
            return $this->type;
272
        }
273
274
        if (method_exists($entity, 'getAdminType')) {
275
            return $entity->getAdminType();
276
        }
277
278
        throw new InvalidArgumentException(
279
            'You need to implement the getAdminType method in '.
280
            get_class($this).' or '.get_class($entity)
281
        );
282
    }
283
284
    /**
285
     * @param string $type
286
     *
287
     * @return AbstractAdminListConfigurator
288
     */
289
    public function setAdminType($type)
290
    {
291
        $this->type = $type;
292
293
        return $this;
294
    }
295
296
    /**
297
     * @param array $typeOptions
298
     *
299
     * @return AbstractAdminListConfigurator
300
     */
301
    public function setAdminTypeOptions($typeOptions)
302
    {
303
        $this->typeOptions = $typeOptions;
304
305
        return $this;
306
    }
307
308
    /**
309
     * Return the default form admin type options
310
     *
311
     * @return array
312
     */
313
    public function getAdminTypeOptions()
314
    {
315
        return $this->typeOptions;
316
    }
317
318
    /**
319
     * @param object|array $item
320
     *
321
     * @return bool
322
     */
323
    public function canEdit($item)
324
    {
325
        return true;
326
    }
327
328
    /**
329
     * Configure if it's possible to delete the given $item
330
     *
331
     * @param object|array $item
332
     *
333
     * @return bool
334
     */
335
    public function canDelete($item)
336
    {
337
        return true;
338
    }
339
340
    /**
341
     * Configure if it's possible to add new items
342
     *
343
     * @return bool
344
     */
345
    public function canAdd()
346
    {
347
        return true;
348
    }
349
350
    public function canView($item)
351
    {
352
        return false;
353
    }
354
355
    /**
356
     * Configure if it's possible to add new items
357
     *
358
     * @return bool
359
     */
360
    public function canExport()
361
    {
362
        return false;
363
    }
364
365
    /**
366
     * @param string     $name     The field name
367
     * @param string     $header   The header title
368
     * @param string     $sort     Sortable column or not
369
     * @param string     $template The template
370
     * @param FieldAlias $alias    The alias
0 ignored issues
show
Should the type for parameter $alias not be null|FieldAlias?

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

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...
386
     *
387
     * @return AbstractAdminListConfigurator
388
     */
389
    public function addExportField($name, $header, $template = null, FieldAlias $alias = null)
390
    {
391
        $this->exportFields[] = new Field($name, $header, false, $template, $alias);
392
393
        return $this;
394
    }
395
396
    /**
397
     * @param string              $columnName The column name
398
     * @param FilterTypeInterface $type       The filter type
399
     * @param string              $filterName The name of the filter
400
     * @param array               $options    Options
401
     *
402
     * @return AbstractAdminListConfigurator
403
     */
404
    public function addFilter(
405
        $columnName,
406
        FilterTypeInterface $type = null,
407
        $filterName = null,
408
        array $options = array()
409
    ) {
410
        $this->getFilterBuilder()->add($columnName, $type, $filterName, $options);
411
412
        return $this;
413
    }
414
415
    /**
416
     * @return int
417
     */
418
    public function getLimit()
419
    {
420
        return 10;
421
    }
422
423
    /**
424
     * @return array
425
     */
426
    public function getSortFields()
427
    {
428
        $array = array();
429
        foreach ($this->getFields() as $field) {
430
            if ($field->isSortable()) {
431
                $array[] = $field->getName();
432
            }
433
        }
434
435
        return $array;
436
    }
437
438
    /**
439
     * @return Field[]
440
     */
441
    public function getFields()
442
    {
443
        return $this->fields;
444
    }
445
446
    /**
447
     * @return Field[]
448
     */
449
    public function getExportFields()
450
    {
451
        if (empty($this->exportFields)) {
452
            return $this->fields;
453
        } else {
454
            return $this->exportFields;
455
        }
456
    }
457
458
    /**
459
     * @param string   $label          The label, only used when the template equals null
460
     * @param callable $routeGenerator The generator used to generate the url of an item, when generating the item will
461
     *                                 be provided
462
     * @param string   $icon           The icon, only used when the template equals null
463
     * @param string   $template       The template, when not specified the label is shown
464
     *
465
     * @return AbstractAdminListConfigurator
466
     */
467
    public function addSimpleItemAction($label, $routeGenerator, $icon, $template = null)
468
    {
469
        return $this->addItemAction(new SimpleItemAction($routeGenerator, $icon, $label, $template));
470
    }
471
472
    /**
473
     * @param ItemActionInterface $itemAction
474
     *
475
     * @return AbstractAdminListConfigurator
476
     */
477
    public function addItemAction(ItemActionInterface $itemAction)
478
    {
479
        $this->itemActions[] = $itemAction;
480
481
        return $this;
482
    }
483
484
    /**
485
     * @return bool
486
     */
487
    public function hasItemActions()
488
    {
489
        return !empty($this->itemActions);
490
    }
491
492
    /**
493
     * @return ItemActionInterface[]
494
     */
495
    public function getItemActions()
496
    {
497
        return $this->itemActions;
498
    }
499
500
    /**
501
     * @param ListActionInterface $listAction
502
     *
503
     * @return AdminListConfiguratorInterface
504
     */
505
    public function addListAction(ListActionInterface $listAction)
506
    {
507
        $this->listActions[] = $listAction;
508
509
        return $this;
510
    }
511
512
    /**
513
     * @return bool
514
     */
515
    public function hasListActions()
516
    {
517
        return !empty($this->listActions);
518
    }
519
520
    /**
521
     * @return ListActionInterface[]
522
     */
523
    public function getListActions()
524
    {
525
        return $this->listActions;
526
    }
527
528
    /**
529
     * @param BulkActionInterface $bulkAction
530
     *
531
     * @return AdminListConfiguratorInterface
532
     */
533
    public function addBulkAction(BulkActionInterface $bulkAction)
534
    {
535
        $this->bulkActions[] = $bulkAction;
536
537
        return $this;
538
    }
539
540
    /**
541
     * @return bool
542
     */
543
    public function hasBulkActions()
544
    {
545
        return !empty($this->bulkActions);
546
    }
547
548
    /**
549
     * @return BulkActionInterface[]
550
     */
551
    public function getBulkActions()
552
    {
553
        return $this->bulkActions;
554
    }
555
556
    /**
557
     * @return string
558
     */
559
    public function getListTemplate()
560
    {
561
        return $this->listTemplate;
562
    }
563
564
    /**
565
     * @param string $template
566
     *
567
     * @return AdminListConfiguratorInterface
568
     */
569
    public function setListTemplate($template)
570
    {
571
        $this->listTemplate = $template;
572
573
        return $this;
574
    }
575
576
    /**
577
     * @param array|object $item       The item
578
     * @param string       $columnName The column name
579
     *
580
     * @return mixed
581
     */
582
    public function getValue($item, $columnName)
583
    {
584
        if (is_array($item)) {
585
            if (isset($item[$columnName])) {
586
                return $item[$columnName];
587
            } else {
588
                return '';
589
            }
590
        }
591
592
        $accessor = PropertyAccess::createPropertyAccessor();
593
594
        if ($accessor->isReadable($item, $columnName)) {
595
            $result = $accessor->getValue($item, $columnName);
596
        } else {
597
            return sprintf('undefined function [get/is/has]%s()', $columnName);
598
        }
599
600
        return $result;
601
    }
602
603
    /**
604
     * @param array|object $item       The item
605
     * @param string       $columnName The column name
606
     *
607
     * @return string
608
     */
609
    public function getStringValue($item, $columnName)
610
    {
611
        $result = $this->getValue($item, $columnName);
612
        if (is_bool($result)) {
613
            return $result ? 'true' : 'false';
614
        }
615
        if ($result instanceof \DateTime) {
616
            return $result->format('Y-m-d H:i:s');
617
        } else {
618
            if ($result instanceof PersistentCollection) {
619
                $results = [];
620
                /* @var Object $entry */
621
                foreach ($result as $entry) {
622
                    $results[] = $entry->getName();
623
                }
624
                if (empty($results)) {
625
                    return '';
626
                }
627
628
                return implode(', ', $results);
629
            } else {
630
                if (is_array($result)) {
631
                    return implode(', ', $result);
632
                } else {
633
                    return $result;
634
                }
635
            }
636
        }
637
    }
638
639
    /**
640
     * @return string
641
     */
642
    public function getAddTemplate()
643
    {
644
        return $this->addTemplate;
645
    }
646
647
    /**
648
     * @param string $template
649
     *
650
     * @return AdminListConfiguratorInterface
651
     */
652
    public function setAddTemplate($template)
653
    {
654
        $this->addTemplate = $template;
655
656
        return $this;
657
    }
658
659
    /**
660
     * @return string
661
     */
662
    public function getViewTemplate()
663
    {
664
        return $this->viewTemplate;
665
    }
666
667
    /**
668
     * @param string $template
669
     *
670
     * @return AdminListConfiguratorInterface
671
     */
672
    public function setViewTemplate($template)
673
    {
674
        $this->viewTemplate = $template;
675
676
        return $this;
677
    }
678
679
    /**
680
     * @return string
681
     */
682
    public function getEditTemplate()
683
    {
684
        return $this->editTemplate;
685
    }
686
687
    /**
688
     * @param string $template
689
     *
690
     * @return AdminListConfiguratorInterface
691
     */
692
    public function setEditTemplate($template)
693
    {
694
        $this->editTemplate = $template;
695
696
        return $this;
697
    }
698
699
    /**
700
     * @return string
701
     */
702
    public function getDeleteTemplate()
703
    {
704
        return $this->deleteTemplate;
705
    }
706
707
    /**
708
     * @param string $template
709
     *
710
     * @return AdminListConfiguratorInterface
711
     */
712
    public function setDeleteTemplate($template)
713
    {
714
        $this->deleteTemplate = $template;
715
716
        return $this;
717
    }
718
719
    /**
720
     * You can override this method to do some custom things you need to do when adding an entity
721
     *
722
     * @param object $entity
723
     *
724
     * @return mixed
725
     */
726
    public function decorateNewEntity($entity)
727
    {
728
        return $entity;
729
    }
730
731
    /**
732
     * @return FilterBuilder
733
     */
734
    public function getFilterBuilder()
735
    {
736
        if (is_null($this->filterBuilder)) {
737
            $this->filterBuilder = new FilterBuilder();
738
        }
739
740
        return $this->filterBuilder;
741
    }
742
743
    /**
744
     * @param FilterBuilder $filterBuilder
745
     *
746
     * @return AbstractAdminListConfigurator
747
     */
748
    public function setFilterBuilder(FilterBuilder $filterBuilder)
749
    {
750
        $this->filterBuilder = $filterBuilder;
751
752
        return $this;
753
    }
754
755
    /**
756
     * Bind current request.
757
     *
758
     * @param Request $request
759
     */
760
    public function bindRequest(Request $request)
761
    {
762
        $query = $request->query;
763
        $session = $request->getSession();
764
765
        $adminListName = 'listconfig_'.$request->get('_route');
766
767
        $this->page = $request->query->getInt('page', 1);
768
        // Allow alphanumeric, _ & . in order by parameter!
769
        $this->orderBy = preg_replace('/[^[a-zA-Z0-9\_\.]]/', '', $request->query->get('orderBy', ''));
770
        $this->orderDirection = $request->query->getAlpha('orderDirection', '');
771
772
        // there is a session and the filter param is not set
773 View Code Duplication
        if ($session->has($adminListName) && !$query->has('filter')) {
774
            $adminListSessionData = $request->getSession()->get($adminListName);
775
            if (!$query->has('page')) {
776
                $this->page = $adminListSessionData['page'];
777
            }
778
779
            if (!$query->has('orderBy')) {
780
                $this->orderBy = $adminListSessionData['orderBy'];
781
            }
782
783
            if (!$query->has('orderDirection')) {
784
                $this->orderDirection = $adminListSessionData['orderDirection'];
785
            }
786
        }
787
788
        // save current parameters
789
        $session->set(
790
            $adminListName,
791
            array(
792
                'page' => $this->page,
793
                'orderBy' => $this->orderBy,
794
                'orderDirection' => $this->orderDirection,
795
            )
796
        );
797
798
        $this->getFilterBuilder()->bindRequest($request);
799
    }
800
801
    /**
802
     * Return current page.
803
     *
804
     * @return int
805
     */
806
    public function getPage()
807
    {
808
        return $this->page;
809
    }
810
811
    /**
812
     * Return current sorting column.
813
     *
814
     * @return string
815
     */
816
    public function getOrderBy()
817
    {
818
        return $this->orderBy;
819
    }
820
821
    /**
822
     * Return current sorting direction.
823
     *
824
     * @return string
825
     */
826
    public function getOrderDirection()
827
    {
828
        return $this->orderDirection;
829
    }
830
831
    /**
832
     * @param string $suffix
833
     *
834
     * @return string
835
     */
836
    public function getPathByConvention($suffix = null)
837
    {
838
        $entityName = strtolower($this->getEntityName());
839
        $entityName = str_replace('\\', '_', $entityName);
840
        if (empty($suffix)) {
841
            return sprintf('%s_admin_%s', strtolower($this->getBundleName()), $entityName);
842
        }
843
844
        return sprintf('%s_admin_%s_%s', strtolower($this->getBundleName()), $entityName, $suffix);
845
    }
846
847
    /**
848
     * Get controller path.
849
     *
850
     * @return string
851
     */
852
    public function getControllerPath()
853
    {
854
        return sprintf('%s:%s', $this->getBundleName(), $this->getEntityName());
855
    }
856
857
    /**
858
     * Return extra parameters for use in list actions.
859
     *
860
     * @return array
861
     */
862
    public function getExtraParameters()
863
    {
864
        return array();
865
    }
866
}
867