1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Pinq\Queries\Builders; |
4
|
|
|
|
5
|
|
|
use Pinq\Expressions as O; |
6
|
|
|
use Pinq\PinqException; |
7
|
|
|
use Pinq\Queries; |
8
|
|
|
use Pinq\Queries\Builders\Interpretations\IOperationInterpretation; |
9
|
|
|
|
10
|
|
|
class OperationQueryInterpreter extends QueryInterpreter implements IOperationQueryInterpreter |
11
|
|
|
{ |
12
|
|
|
/** |
13
|
|
|
* @var IOperationInterpretation |
14
|
|
|
*/ |
15
|
|
|
protected $interpretation; |
16
|
|
|
|
17
|
|
|
public function __construct( |
18
|
|
|
IOperationInterpretation $interpretation, |
19
|
|
|
IScopeInterpreter $scopeInterpreter, |
20
|
|
|
O\IEvaluationContext $evaluationContext = null |
21
|
|
|
) { |
22
|
|
|
parent::__construct('operation', $scopeInterpreter, $evaluationContext); |
23
|
|
|
|
24
|
|
|
$this->interpretation = $interpretation; |
25
|
|
|
} |
26
|
|
|
|
27
|
|
|
public function getInterpretation() |
28
|
|
|
{ |
29
|
|
|
return $this->interpretation; |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
public function interpret(O\Expression $expression) |
33
|
|
|
{ |
34
|
|
|
if ($expression instanceof O\MethodCallExpression) { |
35
|
|
|
$this->{'visit' . $this->getMethodName($expression)}($expression); |
36
|
|
|
} elseif ($expression instanceof O\AssignmentExpression |
37
|
|
|
&& ($assignTo = $expression->getAssignTo()) instanceof O\IndexExpression |
38
|
|
|
) { |
39
|
|
|
/** @var $assignTo O\IndexExpression */ |
40
|
|
|
if (!$assignTo->hasIndex() || $this->getValue($assignTo->getIndex()) === null) { |
41
|
|
|
$this->{'visitAdd'}($expression); |
42
|
|
|
} else { |
43
|
|
|
$this->{'visitOffsetSet'}($expression); |
44
|
|
|
} |
45
|
|
|
} elseif ($expression instanceof O\UnsetExpression) { |
46
|
|
|
$this->{'visitOffsetUnset'}($expression); |
47
|
|
|
} else { |
48
|
|
|
$this->scopeInterpreter->interpretScope($expression); |
49
|
|
|
} |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
final protected function interpretSource($id, O\Expression $expression) |
53
|
|
|
{ |
54
|
|
|
$sourceInterpreter = $this->scopeInterpreter->buildSourceInterpreter($id); |
55
|
|
|
$sourceInterpreter->interpretSource($expression); |
56
|
|
|
|
57
|
|
|
return $sourceInterpreter->getInterpretation(); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
final protected function interpretSingleValueSource($sourceId, $value) |
61
|
|
|
{ |
62
|
|
|
$sourceInterpretation = $this->scopeInterpreter->buildSourceInterpreter('')->getInterpretation(); |
63
|
|
|
$sourceInterpretation->interpretSingleValue($sourceId, $value); |
64
|
|
|
|
65
|
|
|
return $sourceInterpretation; |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
final protected function visitApply(O\MethodCallExpression $expression) |
69
|
|
|
{ |
70
|
|
|
$sourceExpression = $expression->getValue(); |
71
|
|
|
|
72
|
|
|
//Determine whether this was a join/groupJoin apply operation |
73
|
|
|
if ($sourceExpression instanceof O\MethodCallExpression) { |
74
|
|
|
$methodName = $this->getMethodName($sourceExpression); |
75
|
|
|
if (in_array(strtolower($methodName), ['withdefault', 'on', 'onequality', 'join', 'groupjoin'], true)) { |
76
|
|
|
$this->visitJoinApply($expression); |
77
|
|
|
|
78
|
|
|
return; |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
$this->interpretation->interpretApply('apply', $this->getFunctionAt('apply-function', 0, $expression)); |
83
|
|
|
$this->interpretSourceAsScope($expression); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
final protected function visitJoinApply(O\MethodCallExpression $expression) |
87
|
|
|
{ |
88
|
|
|
$applyFunction = $this->getFunctionAt($this->getId('apply-function'), 0, $expression); |
89
|
|
|
$expression = $this->getSourceMethodCall($expression); |
90
|
|
|
$optionsInterpreter = $this->scopeInterpreter->buildJoinOptionsInterpreter($this->getId('join-apply')); |
91
|
|
|
$optionsInterpreter->interpretJoinOptions($expression, $sourceExpression); |
92
|
|
|
$this->interpretation->interpretJoinApply( |
93
|
|
|
$this->getId('join-apply'), |
94
|
|
|
$optionsInterpreter->getInterpretation(), |
95
|
|
|
$applyFunction |
96
|
|
|
); |
97
|
|
|
|
98
|
|
|
$this->interpretSourceAsScope($sourceExpression); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
final protected function visitAdd(O\AssignmentExpression $expression) |
102
|
|
|
{ |
103
|
|
|
$this->interpretation->interpretAddRange( |
104
|
|
|
$this->getId('add-value'), |
105
|
|
|
$this->interpretSingleValueSource($this->getId('add-value-source'), $this->getValue($expression->getAssignmentValue())) |
106
|
|
|
); |
107
|
|
|
|
108
|
|
|
/** @var $assignTo O\IndexExpression */ |
109
|
|
|
$assignTo = $expression->getAssignTo(); |
110
|
|
|
$this->interpretSourceAsScope($assignTo); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
View Code Duplication |
final protected function visitAddRange(O\MethodCallExpression $expression) |
|
|
|
|
114
|
|
|
{ |
115
|
|
|
$this->interpretation->interpretAddRange( |
116
|
|
|
$this->getId('add-range'), |
117
|
|
|
$this->interpretSource($this->getId('add-range-source'), $this->getArgumentAt(0, $expression)) |
118
|
|
|
); |
119
|
|
|
$this->interpretSourceAsScope($expression); |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
final protected function visitRemove(O\MethodCallExpression $expression) |
123
|
|
|
{ |
124
|
|
|
$this->interpretation->interpretRemoveRange( |
125
|
|
|
$this->getId('remove-value'), |
126
|
|
|
$this->interpretSingleValueSource($this->getId('remove-value-source'), $this->getArgumentValueAt(0, $expression)) |
127
|
|
|
); |
128
|
|
|
$this->interpretSourceAsScope($expression); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
View Code Duplication |
final protected function visitRemoveRange(O\MethodCallExpression $expression) |
|
|
|
|
132
|
|
|
{ |
133
|
|
|
$this->interpretation->interpretRemoveRange( |
134
|
|
|
$this->getId('remove-range'), |
135
|
|
|
$this->interpretSource($this->getId('remove-range-source'), $this->getArgumentAt(0, $expression)) |
136
|
|
|
); |
137
|
|
|
$this->interpretSourceAsScope($expression); |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
final protected function visitRemoveWhere(O\MethodCallExpression $expression) |
141
|
|
|
{ |
142
|
|
|
$this->interpretation->interpretRemoveWhere( |
143
|
|
|
$this->getId('remove-where'), |
144
|
|
|
$this->getFunctionAt($this->getId('remove-where-projection'), 0, $expression) |
145
|
|
|
); |
146
|
|
|
$this->interpretSourceAsScope($expression); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
final protected function visitClear(O\MethodCallExpression $expression) |
150
|
|
|
{ |
151
|
|
|
$this->interpretation->interpretClear($this->getId('clear')); |
152
|
|
|
$this->interpretSourceAsScope($expression); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
final protected function visitOffsetSet(O\Expression $expression) |
156
|
|
|
{ |
157
|
|
|
if ($expression instanceof O\MethodCallExpression) { |
158
|
|
|
$index = $this->getArgumentValueAt(0, $expression); |
159
|
|
|
$value = $this->getArgumentValueAt(1, $expression); |
160
|
|
|
$sourceExpression = $expression; |
161
|
|
|
} elseif ($expression instanceof O\AssignmentExpression) { |
162
|
|
|
$sourceExpression = $expression->getAssignTo(); |
163
|
|
|
if ($sourceExpression instanceof O\IndexExpression) { |
164
|
|
|
$index = $this->getValue($sourceExpression->getIndex()); |
165
|
|
|
$value = $this->getValue($expression->getAssignmentValue()); |
166
|
|
|
} else { |
167
|
|
|
throw new PinqException( |
168
|
|
|
'Cannot interpret set index operation: invalid source expression type, expecting %s, %s given', |
169
|
|
|
O\IndexExpression::getType(), |
170
|
|
|
$expression->getType()); |
171
|
|
|
} |
172
|
|
|
} else { |
173
|
|
|
throw new PinqException( |
174
|
|
|
'Cannot interpret set index operation: invalid expression type, expecting %s, %s given', |
175
|
|
|
O\MethodCallExpression::getType() . ' or ' . O\AssignmentExpression::getType(), |
176
|
|
|
$expression->getType()); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
$this->interpretation->interpretOffsetSet( |
180
|
|
|
$this->getId('offset-set'), |
181
|
|
|
$this->getId('set-index'), |
182
|
|
|
$index, |
183
|
|
|
$this->getId('set-value'), |
184
|
|
|
$value |
185
|
|
|
); |
186
|
|
|
$this->interpretSourceAsScope($sourceExpression); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
View Code Duplication |
final protected function visitOffsetUnset(O\Expression $expression) |
|
|
|
|
190
|
|
|
{ |
191
|
|
|
$operationId = $this->getId('offset-unset'); |
192
|
|
|
$indexId = $this->getId('unset-index'); |
193
|
|
|
if ($expression instanceof O\MethodCallExpression) { |
194
|
|
|
$this->interpretation->interpretOffsetUnset( |
195
|
|
|
$operationId, |
196
|
|
|
$indexId, |
197
|
|
|
$this->getArgumentValueAt(0, $expression) |
198
|
|
|
); |
199
|
|
|
$this->interpretSourceAsScope($expression); |
200
|
|
|
|
201
|
|
|
return; |
202
|
|
|
} elseif ($expression instanceof O\UnsetExpression) { |
203
|
|
|
$unsetArguments = $expression->getValues(); |
204
|
|
|
|
205
|
|
|
if (count($unsetArguments) === 1 && $unsetArguments[0] instanceof O\IndexExpression) { |
206
|
|
|
$this->interpretation->interpretOffsetUnset( |
207
|
|
|
$operationId, |
208
|
|
|
$indexId, |
209
|
|
|
$this->getValue($unsetArguments[0]->getIndex()) |
210
|
|
|
); |
211
|
|
|
$this->interpretSourceAsScope($unsetArguments[0]); |
212
|
|
|
|
213
|
|
|
return; |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
throw new PinqException( |
218
|
|
|
'Cannot interpret offset unset operation: invalid expression type, expecting %s, %s given', |
219
|
|
|
O\MethodCallExpression::getType() . ' or ' . O\IssetExpression::getType( |
220
|
|
|
) . ' with a single parameter index', |
221
|
|
|
$expression->getType()); |
222
|
|
|
} |
223
|
|
|
} |
224
|
|
|
|
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.