Completed
Push — 3.x-dev-kit ( 4fe8f1 )
by
unknown
11:30 queued 08:33
created

AbstractDateFilter   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 171
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 7
Bugs 4 Features 0
Metric Value
wmc 33
c 7
b 4
f 0
lcom 1
cbo 1
dl 0
loc 171
rs 9.3999

4 Methods

Rating   Name   Duplication   Size   Complexity  
F filter() 0 95 27
A getDefaultOptions() 0 6 1
A getRenderSettings() 0 18 3
A getOperator() 0 16 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 Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
15
use Sonata\AdminBundle\Form\Type\Filter\DateRangeType;
16
use Sonata\AdminBundle\Form\Type\Filter\DateType;
17
18
abstract class AbstractDateFilter extends Filter
19
{
20
    /**
21
     * Flag indicating that filter will have range.
22
     *
23
     * @var bool
24
     */
25
    protected $range = false;
26
27
    /**
28
     * Flag indicating that filter will filter by datetime instead by date.
29
     *
30
     * @var bool
31
     */
32
    protected $time = false;
33
34
    /**
35
     * {@inheritdoc}
36
     */
37
    public function filter(ProxyQueryInterface $queryBuilder, $alias, $field, $data)
38
    {
39
        // check data sanity
40
        if (!$data || !is_array($data) || !array_key_exists('value', $data)) {
41
            return;
42
        }
43
44
        if ($this->range) {
45
            // additional data check for ranged items
46
            if (!array_key_exists('start', $data['value']) || !array_key_exists('end', $data['value'])) {
47
                return;
48
            }
49
50
            if (!$data['value']['start'] || !$data['value']['end']) {
51
                return;
52
            }
53
54
            // date filter should filter records for the whole days
55
            if ($this->time === false) {
56
                if ($data['value']['start'] instanceof \DateTime) {
57
                    $data['value']['start']->setTime(0, 0, 0);
58
                }
59
                if ($data['value']['end'] instanceof \DateTime) {
60
                    $data['value']['end']->setTime(23, 59, 59);
61
                }
62
            }
63
64
            // transform types
65
            if ($this->getOption('input_type') === 'timestamp') {
66
                $data['value']['start'] = $data['value']['start'] instanceof \DateTime ? $data['value']['start']->getTimestamp() : 0;
67
                $data['value']['end'] = $data['value']['end'] instanceof \DateTime ? $data['value']['end']->getTimestamp() : 0;
68
            }
69
70
            // default type for range filter
71
            $data['type'] = !isset($data['type']) || !is_numeric($data['type']) ?  DateRangeType::TYPE_BETWEEN : $data['type'];
72
73
            $startDateParameterName = $this->getNewParameterName($queryBuilder);
74
            $endDateParameterName = $this->getNewParameterName($queryBuilder);
75
76
            if ($data['type'] == DateRangeType::TYPE_NOT_BETWEEN) {
77
                $this->applyWhere($queryBuilder, sprintf('%s.%s < :%s OR %s.%s > :%s', $alias, $field, $startDateParameterName, $alias, $field, $endDateParameterName));
78
            } else {
79
                $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, '>=', $startDateParameterName));
80
                $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, '<=', $endDateParameterName));
81
            }
82
83
            $queryBuilder->setParameter($startDateParameterName, $data['value']['start']);
84
            $queryBuilder->setParameter($endDateParameterName, $data['value']['end']);
85
        } else {
86
            if (!$data['value']) {
87
                return;
88
            }
89
90
            // default type for simple filter
91
            $data['type'] = !isset($data['type']) || !is_numeric($data['type']) ? DateType::TYPE_EQUAL : $data['type'];
92
93
            // just find an operator and apply query
94
            $operator = $this->getOperator($data['type']);
95
96
            // transform types
97
            if ($this->getOption('input_type') === 'timestamp') {
98
                $data['value'] = $data['value'] instanceof \DateTime ? $data['value']->getTimestamp() : 0;
99
            }
100
101
            // null / not null only check for col
102
            if (in_array($operator, array('NULL', 'NOT NULL'))) {
103
                $this->applyWhere($queryBuilder, sprintf('%s.%s IS %s ', $alias, $field, $operator));
104
105
                return;
106
            }
107
108
            $parameterName = $this->getNewParameterName($queryBuilder);
109
110
            // date filter should filter records for the whole day
111
            if ($this->time === false && $data['type'] == DateType::TYPE_EQUAL) {
112
                $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, '>=', $parameterName));
113
                $queryBuilder->setParameter($parameterName, $data['value']);
114
115
                $endDateParameterName = $this->getNewParameterName($queryBuilder);
116
                $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, '<', $endDateParameterName));
117
                if ($this->getOption('input_type') === 'timestamp') {
118
                    $endValue = strtotime('+1 day', $data['value']);
119
                } else {
120
                    $endValue = clone $data['value'];
121
                    $endValue->add(new \DateInterval('P1D'));
122
                }
123
                $queryBuilder->setParameter($endDateParameterName, $endValue);
124
125
                return;
126
            }
127
128
            $this->applyWhere($queryBuilder, sprintf('%s.%s %s :%s', $alias, $field, $operator, $parameterName));
129
            $queryBuilder->setParameter($parameterName, $data['value']);
130
        }
131
    }
132
133
    /**
134
     * {@inheritdoc}
135
     */
136
    public function getDefaultOptions()
137
    {
138
        return array(
139
            'input_type' => 'datetime',
140
        );
141
    }
142
143
    /**
144
     * {@inheritdoc}
145
     */
146
    public function getRenderSettings()
147
    {
148
        $name = 'sonata_type_filter_date';
149
150
        if ($this->time) {
151
            $name .= 'time';
152
        }
153
154
        if ($this->range) {
155
            $name .= '_range';
156
        }
157
158
        return array($name, array(
159
            'field_type' => $this->getFieldType(),
160
            'field_options' => $this->getFieldOptions(),
161
            'label' => $this->getLabel(),
162
        ));
163
    }
164
165
    /**
166
     * Resolves DataType:: constants to SQL operators.
167
     *
168
     * @param int $type
169
     *
170
     * @return string
171
     */
172
    protected function getOperator($type)
173
    {
174
        $type = intval($type);
175
176
        $choices = array(
177
            DateType::TYPE_EQUAL => '=',
178
            DateType::TYPE_GREATER_EQUAL => '>=',
179
            DateType::TYPE_GREATER_THAN => '>',
180
            DateType::TYPE_LESS_EQUAL => '<=',
181
            DateType::TYPE_LESS_THAN => '<',
182
            DateType::TYPE_NULL => 'NULL',
183
            DateType::TYPE_NOT_NULL => 'NOT NULL',
184
        );
185
186
        return isset($choices[$type]) ? $choices[$type] : '=';
187
    }
188
}
189