Completed
Pull Request — 3.x (#650)
by
unknown
01:57
created

ModelFilter::association()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 12
nc 2
nop 2
1
<?php
2
3
/*
4
 * This file is part of the Sonata Project package.
5
 *
6
 * (c) Thomas Rabaix <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sonata\DoctrineORMAdminBundle\Filter;
13
14
use Doctrine\Common\Collections\Collection;
15
use Doctrine\ORM\Mapping\ClassMetadataInfo;
16
use Doctrine\ORM\QueryBuilder;
17
use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
18
use Sonata\CoreBundle\Form\Type\EqualType;
19
20
class ModelFilter extends Filter
21
{
22
    /**
23
     * {@inheritdoc}
24
     */
25
    public function filter(ProxyQueryInterface $queryBuilder, $alias, $field, $data)
26
    {
27
        if (!$data || !is_array($data) || !array_key_exists('value', $data)) {
28
            return;
29
        }
30
31
        if ($data['value'] instanceof Collection) {
32
            $data['value'] = $data['value']->toArray();
33
        }
34
35
        if (is_array($data['value'])) {
36
            $this->handleMultiple($queryBuilder, $alias, $data);
37
        } else {
38
            $this->handleModel($queryBuilder, $alias, $data);
39
        }
40
    }
41
42
    /**
43
     * {@inheritdoc}
44
     */
45
    public function getDefaultOptions()
46
    {
47
        return array(
48
            'mapping_type' => false,
49
            'field_name' => false,
50
            'field_type' => method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')
51
                ? 'Symfony\Bridge\Doctrine\Form\Type\EntityType'
52
                : 'entity', // NEXT_MAJOR: Remove ternary (when requirement of Symfony is >= 2.8)
53
            'field_options' => array(),
54
            'operator_type' => method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')
55
                ? 'Sonata\CoreBundle\Form\Type\EqualType'
56
                : 'sonata_type_equal', // NEXT_MAJOR: Remove ternary (when requirement of Symfony is >= 2.8)
57
            'operator_options' => array(),
58
        );
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64
    public function getRenderSettings()
65
    {
66
        // NEXT_MAJOR: Remove this line when drop Symfony <2.8 support
67
        $type = method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')
68
            ? 'Sonata\AdminBundle\Form\Type\Filter\DefaultType'
69
            : 'sonata_type_filter_default';
70
71
        return array($type, array(
72
            'field_type' => $this->getFieldType(),
73
            'field_options' => $this->getFieldOptions(),
74
            'operator_type' => $this->getOption('operator_type'),
75
            'operator_options' => $this->getOption('operator_options'),
76
            'label' => $this->getLabel(),
77
        ));
78
    }
79
80
    /**
81
     * For the record, the $alias value is provided by the association method (and the entity join method)
82
     *  so the field value is not used here.
83
     *
84
     * @param ProxyQueryInterface|QueryBuilder $queryBuilder
85
     * @param string                           $alias
86
     * @param mixed                            $data
87
     *
88
     * @return mixed
89
     */
90
    protected function handleMultiple(ProxyQueryInterface $queryBuilder, $alias, $data)
91
    {
92
        if (count($data['value']) == 0) {
93
            return;
94
        }
95
96
        $parameterName = $this->getNewParameterName($queryBuilder);
97
98
        if (isset($data['type']) && $data['type'] == EqualType::TYPE_IS_NOT_EQUAL) {
99
            $or = $queryBuilder->expr()->orX();
100
101
            $or->add($queryBuilder->expr()->notIn($alias, ':'.$parameterName));
102
103
            $allAliases = $queryBuilder->getAllAliases();
104
            $or->add($queryBuilder->expr()->isNull(sprintf('IDENTITY(%s.%s)', $allAliases[0], $this->getFieldName())));
105
106
            $this->applyWhere($queryBuilder, $or);
107
        } else {
108
            $this->applyWhere($queryBuilder, $queryBuilder->expr()->in($alias, ':'.$parameterName));
109
        }
110
111
        $queryBuilder->setParameter($parameterName, $data['value']);
112
    }
113
114
    /**
115
     * @param ProxyQueryInterface|QueryBuilder $queryBuilder
116
     * @param string                           $alias
117
     * @param mixed                            $data
118
     *
119
     * @return mixed
120
     */
121
    protected function handleModel(ProxyQueryInterface $queryBuilder, $alias, $data)
122
    {
123
        if (empty($data['value'])) {
124
            return;
125
        }
126
127
        $parameterName = $this->getNewParameterName($queryBuilder);
128
129
        if (isset($data['type']) && $data['type'] == EqualType::TYPE_IS_NOT_EQUAL) {
130
            $or = $queryBuilder->expr()->orX();
131
132
            $or->add($queryBuilder->expr()->neq($alias, ':'.$parameterName));
133
134
            $allAliases = $queryBuilder->getAllAliases();
135
            $or->add($queryBuilder->expr()->isNull(sprintf('IDENTITY(%s.%s)', $allAliases[0], $this->getFieldName())));
136
137
            $this->applyWhere($queryBuilder, $or);
138
        } else {
139
            $this->applyWhere($queryBuilder, sprintf('%s = :%s', $alias, $parameterName));
140
        }
141
142
        $queryBuilder->setParameter($parameterName, $data['value']);
143
    }
144
145
    /**
146
     * {@inheritdoc}
147
     */
148
    protected function association(ProxyQueryInterface $queryBuilder, $data)
149
    {
150
        $types = array(
151
            ClassMetadataInfo::ONE_TO_ONE,
152
            ClassMetadataInfo::ONE_TO_MANY,
153
            ClassMetadataInfo::MANY_TO_MANY,
154
            ClassMetadataInfo::MANY_TO_ONE,
155
        );
156
157
        if (!in_array($this->getOption('mapping_type'), $types)) {
158
            throw new \RuntimeException('Invalid mapping type');
159
        }
160
161
        $associationMappings = $this->getParentAssociationMappings();
162
        $associationMappings[] = $this->getAssociationMapping();
163
        $alias = $queryBuilder->entityJoin($associationMappings);
164
165
        return array($alias, false);
166
    }
167
}
168