Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
35 | class QueryExpressionVisitor extends ExpressionVisitor |
||
36 | { |
||
37 | /** |
||
38 | * @var array |
||
39 | */ |
||
40 | private static $operatorMap = [ |
||
41 | Comparison::GT => Expr\Comparison::GT, |
||
42 | Comparison::GTE => Expr\Comparison::GTE, |
||
43 | Comparison::LT => Expr\Comparison::LT, |
||
44 | Comparison::LTE => Expr\Comparison::LTE |
||
45 | ]; |
||
46 | |||
47 | /** |
||
48 | * @var array |
||
49 | */ |
||
50 | private $queryAliases; |
||
51 | |||
52 | /** |
||
53 | * @var Expr |
||
54 | */ |
||
55 | private $expr; |
||
56 | |||
57 | /** |
||
58 | * @var array |
||
59 | */ |
||
60 | private $parameters = []; |
||
61 | |||
62 | /** |
||
63 | * Constructor |
||
64 | * |
||
65 | * @param array $queryAliases |
||
66 | */ |
||
67 | 34 | public function __construct($queryAliases) |
|
72 | |||
73 | /** |
||
74 | * Gets bound parameters. |
||
75 | * Filled after {@link dispach()}. |
||
76 | * |
||
77 | * @return \Doctrine\Common\Collections\Collection |
||
78 | */ |
||
79 | 24 | public function getParameters() |
|
83 | |||
84 | /** |
||
85 | * Clears parameters. |
||
86 | * |
||
87 | * @return void |
||
88 | */ |
||
89 | 1 | public function clearParameters() |
|
93 | |||
94 | /** |
||
95 | * Converts Criteria expression to Query one based on static map. |
||
96 | * |
||
97 | * @param string $criteriaOperator |
||
98 | * |
||
99 | * @return string|null |
||
100 | */ |
||
101 | 11 | private static function convertComparisonOperator($criteriaOperator) |
|
105 | |||
106 | /** |
||
107 | * {@inheritDoc} |
||
108 | */ |
||
109 | 10 | public function walkCompositeExpression(CompositeExpression $expr) |
|
110 | { |
||
111 | 10 | $expressionList = []; |
|
112 | |||
113 | 10 | foreach ($expr->getExpressionList() as $child) { |
|
114 | 10 | $expressionList[] = $this->dispatch($child); |
|
115 | } |
||
116 | |||
117 | 10 | switch($expr->getType()) { |
|
118 | 10 | case CompositeExpression::TYPE_AND: |
|
119 | 9 | return new Expr\Andx($expressionList); |
|
120 | |||
121 | 1 | case CompositeExpression::TYPE_OR: |
|
122 | 1 | return new Expr\Orx($expressionList); |
|
123 | |||
124 | default: |
||
125 | throw new \RuntimeException("Unknown composite " . $expr->getType()); |
||
126 | } |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * {@inheritDoc} |
||
131 | */ |
||
132 | 28 | public function walkComparison(Comparison $comparison) |
|
133 | { |
||
134 | |||
135 | 28 | if ( ! isset($this->queryAliases[0])) { |
|
136 | throw new QueryException('No aliases are set before invoking walkComparison().'); |
||
137 | } |
||
138 | |||
139 | 28 | $field = $this->queryAliases[0] . '.' . $comparison->getField(); |
|
140 | |||
141 | 28 | foreach($this->queryAliases as $alias) { |
|
142 | 28 | if(strpos($comparison->getField() . '.', $alias . '.') === 0) { |
|
143 | 5 | $field = $comparison->getField(); |
|
144 | 5 | break; |
|
145 | } |
||
146 | } |
||
147 | |||
148 | 28 | $parameterName = str_replace('.', '_', $comparison->getField()); |
|
149 | |||
150 | 28 | foreach ($this->parameters as $parameter) { |
|
151 | 10 | if ($parameter->getName() === $parameterName) { |
|
152 | 4 | $parameterName .= '_' . count($this->parameters); |
|
153 | 4 | break; |
|
154 | } |
||
155 | } |
||
156 | |||
157 | 28 | $parameter = new Parameter($parameterName, $this->walkValue($comparison->getValue())); |
|
158 | 28 | $placeholder = ':' . $parameterName; |
|
159 | |||
160 | 28 | switch ($comparison->getOperator()) { |
|
161 | 28 | case Comparison::IN: |
|
162 | 1 | $this->parameters[] = $parameter; |
|
163 | |||
164 | 1 | return $this->expr->in($field, $placeholder); |
|
165 | 27 | case Comparison::NIN: |
|
166 | 1 | $this->parameters[] = $parameter; |
|
167 | |||
168 | 1 | return $this->expr->notIn($field, $placeholder); |
|
169 | 26 | case Comparison::EQ: |
|
170 | 16 | View Code Duplication | case Comparison::IS: |
|
|||
171 | 17 | if ($this->walkValue($comparison->getValue()) === null) { |
|
172 | 2 | return $this->expr->isNull($field); |
|
173 | } |
||
174 | 15 | $this->parameters[] = $parameter; |
|
175 | |||
176 | 15 | return $this->expr->eq($field, $placeholder); |
|
177 | 16 | View Code Duplication | case Comparison::NEQ: |
178 | 2 | if ($this->walkValue($comparison->getValue()) === null) { |
|
179 | 1 | return $this->expr->isNotNull($field); |
|
180 | } |
||
181 | 1 | $this->parameters[] = $parameter; |
|
182 | |||
183 | 1 | return $this->expr->neq($field, $placeholder); |
|
184 | 14 | View Code Duplication | case Comparison::CONTAINS: |
185 | 1 | $parameter->setValue('%' . $parameter->getValue() . '%', $parameter->getType()); |
|
186 | 1 | $this->parameters[] = $parameter; |
|
187 | |||
188 | 1 | return $this->expr->like($field, $placeholder); |
|
189 | 13 | View Code Duplication | case Comparison::STARTS_WITH: |
190 | 1 | $parameter->setValue($parameter->getValue() . '%', $parameter->getType()); |
|
191 | 1 | $this->parameters[] = $parameter; |
|
192 | |||
193 | 1 | return $this->expr->like($field, $placeholder); |
|
194 | 12 | View Code Duplication | case Comparison::ENDS_WITH: |
195 | 1 | $parameter->setValue('%' . $parameter->getValue(), $parameter->getType()); |
|
196 | 1 | $this->parameters[] = $parameter; |
|
197 | |||
198 | 1 | return $this->expr->like($field, $placeholder); |
|
199 | default: |
||
200 | 11 | $operator = self::convertComparisonOperator($comparison->getOperator()); |
|
201 | 11 | if ($operator) { |
|
202 | 11 | $this->parameters[] = $parameter; |
|
203 | |||
204 | 11 | return new Expr\Comparison( |
|
205 | 11 | $field, |
|
206 | 11 | $operator, |
|
207 | 11 | $placeholder |
|
208 | ); |
||
209 | } |
||
210 | |||
211 | throw new \RuntimeException("Unknown comparison operator: " . $comparison->getOperator()); |
||
212 | } |
||
213 | } |
||
214 | |||
215 | /** |
||
216 | * {@inheritDoc} |
||
217 | */ |
||
218 | 29 | public function walkValue(Value $value) |
|
222 | } |
||
223 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.