|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/* |
|
4
|
|
|
* This file is part of the Sylius package. |
|
5
|
|
|
* |
|
6
|
|
|
* (c) Paweł Jędrzejewski |
|
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
|
|
|
declare(strict_types=1); |
|
13
|
|
|
|
|
14
|
|
|
namespace Sylius\Component\Grid\Filter; |
|
15
|
|
|
|
|
16
|
|
|
use Sylius\Component\Grid\Data\DataSourceInterface; |
|
17
|
|
|
use Sylius\Component\Grid\Data\ExpressionBuilderInterface; |
|
18
|
|
|
use Sylius\Component\Grid\Filtering\FilterInterface; |
|
19
|
|
|
|
|
20
|
|
|
/** |
|
21
|
|
|
* @author Paweł Jędrzejewski <[email protected]> |
|
22
|
|
|
*/ |
|
23
|
|
|
final class StringFilter implements FilterInterface |
|
24
|
|
|
{ |
|
25
|
|
|
public const NAME = 'string'; |
|
26
|
|
|
|
|
27
|
|
|
public const TYPE_EQUAL = 'equal'; |
|
28
|
|
|
public const TYPE_NOT_EQUAL = 'not_equal'; |
|
29
|
|
|
public const TYPE_EMPTY = 'empty'; |
|
30
|
|
|
public const TYPE_NOT_EMPTY = 'not_empty'; |
|
31
|
|
|
public const TYPE_CONTAINS = 'contains'; |
|
32
|
|
|
public const TYPE_NOT_CONTAINS = 'not_contains'; |
|
33
|
|
|
public const TYPE_STARTS_WITH = 'starts_with'; |
|
34
|
|
|
public const TYPE_ENDS_WITH = 'ends_with'; |
|
35
|
|
|
public const TYPE_IN = 'in'; |
|
36
|
|
|
public const TYPE_NOT_IN = 'not_in'; |
|
37
|
|
|
|
|
38
|
|
|
/** |
|
39
|
|
|
* {@inheritdoc} |
|
40
|
|
|
*/ |
|
41
|
|
|
public function apply(DataSourceInterface $dataSource, string $name, $data, array $options): void |
|
42
|
|
|
{ |
|
43
|
|
|
$expressionBuilder = $dataSource->getExpressionBuilder(); |
|
44
|
|
|
|
|
45
|
|
|
if (is_array($data) && !isset($data['type'])) { |
|
46
|
|
|
$data['type'] = $options['type'] ?? self::TYPE_CONTAINS; |
|
47
|
|
|
} |
|
48
|
|
|
|
|
49
|
|
|
if (!is_array($data)) { |
|
50
|
|
|
$data = ['type' => self::TYPE_CONTAINS, 'value' => $data]; |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
|
|
$fields = array_key_exists('fields', $options) ? $options['fields'] : [$name]; |
|
54
|
|
|
|
|
55
|
|
|
$type = $data['type']; |
|
56
|
|
|
$value = array_key_exists('value', $data) ? $data['value'] : null; |
|
57
|
|
|
|
|
58
|
|
|
if (!in_array($type, [self::TYPE_NOT_EMPTY, self::TYPE_EMPTY], true) && '' === trim($value)) { |
|
59
|
|
|
return; |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
if (1 === count($fields)) { |
|
63
|
|
|
$dataSource->restrict($this->getExpression($expressionBuilder, $type, current($fields), $value)); |
|
64
|
|
|
|
|
65
|
|
|
return; |
|
66
|
|
|
} |
|
67
|
|
|
|
|
68
|
|
|
$expressions = []; |
|
69
|
|
|
foreach ($fields as $field) { |
|
70
|
|
|
$expressions[] = $this->getExpression($expressionBuilder, $type, $field, $value); |
|
71
|
|
|
} |
|
72
|
|
|
|
|
73
|
|
|
if (self::TYPE_NOT_EQUAL === $type) { |
|
74
|
|
|
$dataSource->restrict($expressionBuilder->andX(...$expressions)); |
|
75
|
|
|
|
|
76
|
|
|
return; |
|
77
|
|
|
} |
|
78
|
|
|
|
|
79
|
|
|
$dataSource->restrict($expressionBuilder->orX(...$expressions)); |
|
80
|
|
|
} |
|
81
|
|
|
|
|
82
|
|
|
/** |
|
83
|
|
|
* @param ExpressionBuilderInterface $expressionBuilder |
|
84
|
|
|
* @param string $type |
|
85
|
|
|
* @param string $field |
|
86
|
|
|
* @param mixed $value |
|
87
|
|
|
* |
|
88
|
|
|
* @return mixed |
|
89
|
|
|
* |
|
90
|
|
|
* @throws \InvalidArgumentException |
|
91
|
|
|
*/ |
|
92
|
|
|
private function getExpression( |
|
93
|
|
|
ExpressionBuilderInterface $expressionBuilder, |
|
94
|
|
|
string $type, |
|
95
|
|
|
string $field, |
|
96
|
|
|
$value |
|
97
|
|
|
) { |
|
98
|
|
|
switch ($type) { |
|
99
|
|
|
case self::TYPE_EQUAL: |
|
|
|
|
|
|
100
|
|
|
return $expressionBuilder->equals($field, $value); |
|
101
|
|
|
case self::TYPE_NOT_EQUAL: |
|
|
|
|
|
|
102
|
|
|
return $expressionBuilder->notEquals($field, $value); |
|
103
|
|
|
case self::TYPE_EMPTY: |
|
104
|
|
|
return $expressionBuilder->isNull($field); |
|
105
|
|
|
case self::TYPE_NOT_EMPTY: |
|
106
|
|
|
return $expressionBuilder->isNotNull($field); |
|
107
|
|
|
case self::TYPE_CONTAINS: |
|
108
|
|
|
return $expressionBuilder->like($field, '%' . $value . '%'); |
|
109
|
|
|
case self::TYPE_NOT_CONTAINS: |
|
110
|
|
|
return $expressionBuilder->notLike($field, '%' . $value . '%'); |
|
111
|
|
|
case self::TYPE_STARTS_WITH: |
|
112
|
|
|
return $expressionBuilder->like($field, $value . '%'); |
|
113
|
|
|
case self::TYPE_ENDS_WITH: |
|
114
|
|
|
return $expressionBuilder->like($field, '%' . $value); |
|
115
|
|
|
case self::TYPE_IN: |
|
116
|
|
|
return $expressionBuilder->in($field, array_map('trim', explode(',', $value))); |
|
117
|
|
|
case self::TYPE_NOT_IN: |
|
118
|
|
|
return $expressionBuilder->notIn($field, array_map('trim', explode(',', $value))); |
|
119
|
|
|
default: |
|
120
|
|
|
throw new \InvalidArgumentException(sprintf('Could not get an expression for type "%s"!', $type)); |
|
121
|
|
|
} |
|
122
|
|
|
} |
|
123
|
|
|
} |
|
124
|
|
|
|
As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next
break.There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.