Completed
Push — master ( 2b45da...60f6b8 )
by Arnaud
16s queued 12s
created

ORMSubscriber   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 145
Duplicated Lines 0 %

Test Coverage

Coverage 98.36%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 65
c 1
b 0
f 0
dl 0
loc 145
ccs 60
cts 61
cp 0.9836
rs 10
wmc 19

6 Methods

Rating   Name   Duplication   Size   Complexity  
A addOrder() 0 22 4
A guessType() 0 26 5
A guessFormType() 0 16 4
A __construct() 0 4 1
A addFilters() 0 27 4
A getSubscribedEvents() 0 12 1
1
<?php
2
3
namespace LAG\AdminBundle\Bridge\Doctrine\ORM\Event\Subscriber;
4
5
use Doctrine\ORM\QueryBuilder;
6
use LAG\AdminBundle\Bridge\Doctrine\ORM\Event\ORMFilterEvent;
7
use LAG\AdminBundle\Bridge\Doctrine\ORM\Metadata\MetadataHelperInterface;
8
use LAG\AdminBundle\Event\Events;
9
use LAG\AdminBundle\Event\Events\FieldEvent;
10
use LAG\AdminBundle\Event\Events\FormEvent;
11
use LAG\AdminBundle\Field\Definition\FieldDefinition;
12
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
13
use Symfony\Component\HttpFoundation\RequestStack;
14
15
class ORMSubscriber implements EventSubscriberInterface
16
{
17
    /**
18
     * @var RequestStack
19
     */
20
    private $requestStack;
21
22
    /**
23
     * @var FieldDefinition[]
24
     */
25
    private $fieldDefinitions;
26
27
    /**
28
     * @var MetadataHelperInterface
29
     */
30
    private $metadataHelper;
31
32 20
    public function __construct(RequestStack $requestStack, MetadataHelperInterface $metadataHelper)
33
    {
34 20
        $this->requestStack = $requestStack;
35 20
        $this->metadataHelper = $metadataHelper;
36 20
    }
37
38 4
    public static function getSubscribedEvents(): array
39
    {
40
        return [
41
            Events::DOCTRINE_ORM_FILTER => [
42 4
                ['addOrder'],
43
                ['addFilters'],
44
            ],
45
            Events::FIELD_PRE_CREATE => [
46
                ['guessType'],
47
            ],
48
            Events::FORM_PRE_CREATE_ENTITY_FORM => [
49
                ['guessFormType'],
50
            ],
51
        ];
52
    }
53
54
    /**
55
     * Add the order to query builder according to the configuration.
56
     */
57 6
    public function addOrder(ORMFilterEvent $event)
58
    {
59 6
        $data = $event->getData();
60
61 6
        if (!$data instanceof QueryBuilder) {
62 2
            return;
63
        }
64 4
        $admin = $event->getAdmin();
65 4
        $actionConfiguration = $admin->getAction()->getConfiguration();
66
67 4
        $request = $this->requestStack->getMasterRequest();
68 4
        $sort = $request->get('sort');
69 4
        $alias = $data->getRootAliases()[0];
70
71
        // The sort from the request override the configured one
72 4
        if ($sort) {
73 2
            $order = $request->get('order', 'asc');
74
75 2
            $data->addOrderBy($alias.'.'.$sort, $order);
76
        } else {
77 2
            foreach ($actionConfiguration->getParameter('order') as $field => $order) {
78 2
                $data->addOrderBy($alias.'.'.$field, $order);
79
            }
80
        }
81 4
    }
82
83
    /**
84
     * Add filter to the query builder.
85
     */
86 2
    public function addFilters(ORMFilterEvent $event)
87
    {
88 2
        $queryBuilder = $event->getData();
89
90 2
        foreach ($event->getFilters() as $filter) {
91 2
            $alias = $queryBuilder->getRootAliases()[0];
92 2
            $parameterName = 'filter_'.$filter->getName();
93 2
            $value = $filter->getValue();
94
95 2
            if ('like' === $filter->getComparator()) {
96 2
                $value = '%'.$value.'%';
97
            }
98
99 2
            if ('and' === $filter->getOperator()) {
100
                $method = 'andWhere';
101
            } else {
102 2
                $method = 'orWhere';
103
            }
104
105 2
            $queryBuilder->$method(sprintf(
106 2
                '%s.%s %s %s',
107
                $alias,
108 2
                $filter->getName(),
109 2
                $filter->getComparator(),
110 2
                ':'.$parameterName
111
            ));
112 2
            $queryBuilder->setParameter($parameterName, $value);
113
        }
114 2
    }
115
116 8
    public function guessType(FieldEvent $event): void
117
    {
118
        // No need to guess a type when one is already defined
119 8
        if (null !== $event->getType()) {
120 2
            return;
121
        }
122
123
        // Initialize the definitions array only the first time
124 6
        if (null === $this->fieldDefinitions) {
125 6
            $this->fieldDefinitions = $this->metadataHelper->getFields($event->getEntityClass());
126
        }
127
128
        // By default, ids should be displayed as a string
129 6
        if ('id' === $event->getFieldName()) {
130 2
            $event->setType('string');
131
132 2
            return;
133
        }
134
135
        // No need to guess a type when the field is not defined
136 4
        if (!key_exists($event->getFieldName(), $this->fieldDefinitions)) {
137 2
            return;
138
        }
139 2
        $definition = $this->fieldDefinitions[$event->getFieldName()];
140 2
        $event->setType($definition->getType());
141 2
        $event->setOptions($definition->getOptions());
142 2
    }
143
144 4
    public function guessFormType(FormEvent $event): void
145
    {
146 4
        $configuration = $event->getAdmin()->getConfiguration();
147
148
        // No need to guess a type when one is already defined
149 4
        if (null !== $configuration->get('form')) {
150 2
            return;
151
        }
152
153
        // Initialize the definitions array only the first time
154 2
        if (null === $this->fieldDefinitions) {
155 2
            $this->fieldDefinitions = $this->metadataHelper->getFields($configuration->get('entity'));
156
        }
157
158 2
        foreach ($this->fieldDefinitions as $name => $definition) {
159 2
            $event->addFieldDefinition($name, $definition);
160
        }
161 2
    }
162
}
163