|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* Base query field conditions file. |
|
4
|
|
|
* |
|
5
|
|
|
* @package UIType |
|
6
|
|
|
* |
|
7
|
|
|
* @copyright YetiForce S.A. |
|
8
|
|
|
* @license YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com) |
|
9
|
|
|
* @author Mariusz Krzaczkowski <[email protected]> |
|
10
|
|
|
* @author Radosław Skrzypczak <[email protected]> |
|
11
|
|
|
*/ |
|
12
|
|
|
|
|
13
|
|
|
namespace App\Conditions\QueryFields; |
|
14
|
|
|
|
|
15
|
|
|
use App\Log; |
|
16
|
|
|
|
|
17
|
|
|
/** |
|
18
|
|
|
* Base query field conditions class. |
|
19
|
|
|
*/ |
|
20
|
|
|
class BaseField |
|
21
|
|
|
{ |
|
22
|
|
|
/** |
|
23
|
|
|
* @var \App\QueryGenerator |
|
24
|
|
|
*/ |
|
25
|
|
|
protected $queryGenerator; |
|
26
|
|
|
|
|
27
|
|
|
/** |
|
28
|
|
|
* @var \Vtiger_Field_Model |
|
29
|
|
|
*/ |
|
30
|
|
|
protected $fieldModel; |
|
31
|
|
|
|
|
32
|
|
|
/** |
|
33
|
|
|
* @var string |
|
34
|
|
|
*/ |
|
35
|
|
|
protected $fullColumnName; |
|
36
|
|
|
|
|
37
|
|
|
/** |
|
38
|
|
|
* @var string |
|
39
|
|
|
*/ |
|
40
|
|
|
protected $tableName; |
|
41
|
|
|
|
|
42
|
|
|
/** |
|
43
|
|
|
* @var array|string |
|
44
|
|
|
*/ |
|
45
|
|
|
protected $value; |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* @var string |
|
49
|
|
|
*/ |
|
50
|
|
|
protected $operator; |
|
51
|
|
|
|
|
52
|
|
|
/** |
|
53
|
|
|
* @var array Related detail |
|
54
|
|
|
*/ |
|
55
|
|
|
protected $related = []; |
|
56
|
|
|
|
|
57
|
|
|
/** |
|
58
|
|
|
* Constructor. |
|
59
|
|
|
* |
|
60
|
|
|
* @param \App\QueryGenerator $queryGenerator |
|
61
|
|
|
* @param \Vtiger_Field_Model $fieldModel |
|
62
|
4 |
|
* @param array|string $value |
|
63
|
|
|
* @param string $operator |
|
64
|
4 |
|
*/ |
|
65
|
4 |
|
public function __construct(\App\QueryGenerator $queryGenerator, $fieldModel = false) |
|
66
|
4 |
|
{ |
|
67
|
|
|
$this->queryGenerator = $queryGenerator; |
|
68
|
|
|
$this->fieldModel = $fieldModel; |
|
|
|
|
|
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
|
|
/** |
|
72
|
|
|
* Get module name. |
|
73
|
|
|
* |
|
74
|
|
|
* @return string |
|
75
|
|
|
*/ |
|
76
|
|
|
public function getModuleName(): string |
|
77
|
|
|
{ |
|
78
|
|
|
return $this->queryGenerator->getModule(); |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* Set operator. |
|
83
|
4 |
|
* |
|
84
|
|
|
* @param string $operator |
|
85
|
4 |
|
*/ |
|
86
|
4 |
|
public function setOperator(string $operator): void |
|
87
|
|
|
{ |
|
88
|
|
|
$this->operator = strtolower($operator); |
|
89
|
|
|
} |
|
90
|
|
|
|
|
91
|
|
|
/** |
|
92
|
|
|
* Set related details. |
|
93
|
|
|
* |
|
94
|
|
|
* @param array $relatedInfo |
|
95
|
|
|
*/ |
|
96
|
|
|
public function setRelated(array $relatedInfo): void |
|
97
|
|
|
{ |
|
98
|
|
|
$this->related = $relatedInfo; |
|
99
|
|
|
} |
|
100
|
|
|
|
|
101
|
|
|
/** |
|
102
|
|
|
* Get related details. |
|
103
|
1 |
|
* |
|
104
|
|
|
* @return array |
|
105
|
1 |
|
*/ |
|
106
|
|
|
public function getRelated(): array |
|
107
|
|
|
{ |
|
108
|
|
|
return $this->related; |
|
109
|
|
|
} |
|
110
|
|
|
|
|
111
|
|
|
/** |
|
112
|
|
|
* Get additional field model for list view. |
|
113
|
|
|
* |
|
114
|
|
|
* @return bool|\Vtiger_Field_Model |
|
115
|
|
|
*/ |
|
116
|
|
|
public function getListViewFields() |
|
117
|
|
|
{ |
|
118
|
|
|
return false; |
|
119
|
|
|
} |
|
120
|
|
|
|
|
121
|
|
|
/** |
|
122
|
|
|
* Get order by. |
|
123
|
|
|
* |
|
124
|
|
|
* @param mixed $order |
|
125
|
|
|
* |
|
126
|
|
|
* @return array |
|
127
|
|
|
*/ |
|
128
|
4 |
|
public function getOrderBy($order = false): array |
|
129
|
|
|
{ |
|
130
|
4 |
|
$order = $order && \App\Db::DESC === strtoupper($order) ? SORT_DESC : SORT_ASC; |
|
131
|
2 |
|
return [$this->getColumnName() => $order]; |
|
132
|
|
|
} |
|
133
|
4 |
|
|
|
134
|
|
|
/** |
|
135
|
|
|
* Get column name. |
|
136
|
|
|
* |
|
137
|
|
|
* @return string |
|
138
|
|
|
*/ |
|
139
|
|
|
public function getColumnName(): string |
|
140
|
|
|
{ |
|
141
|
4 |
|
if ($this->fullColumnName) { |
|
142
|
|
|
return $this->fullColumnName; |
|
143
|
4 |
|
} |
|
144
|
|
|
return $this->fullColumnName = $this->getTableName() . '.' . $this->fieldModel->getColumnName(); |
|
145
|
|
|
} |
|
146
|
4 |
|
|
|
147
|
4 |
|
/** |
|
148
|
|
|
* Get column name from source. |
|
149
|
|
|
* |
|
150
|
4 |
|
* @return string |
|
151
|
|
|
*/ |
|
152
|
|
|
public function getColumnNameFromSource(): string |
|
153
|
|
|
{ |
|
154
|
|
|
[$fieldName, $fieldModuleName, $sourceFieldName] = array_pad(explode(':', $this->value), 3, ''); |
|
|
|
|
|
|
155
|
|
|
if ($sourceFieldName) { |
|
156
|
|
|
$fieldModel = $this->queryGenerator->getRelatedModuleField($fieldName, $fieldModuleName); |
|
157
|
|
|
$this->queryGenerator->addRelatedJoin([ |
|
158
|
|
|
'sourceField' => $sourceFieldName, |
|
159
|
|
|
'relatedModule' => $fieldModuleName, |
|
160
|
|
|
'relatedField' => $fieldName, |
|
161
|
|
|
]); |
|
162
|
|
|
} else { |
|
163
|
|
|
$fieldModel = $this->queryGenerator->getModuleField($fieldName); |
|
164
|
|
|
$this->queryGenerator->addTableToQuery($fieldModel->getTableName()); |
|
165
|
|
|
} |
|
166
|
|
|
return $fieldModel ? ($fieldModel->getTableName() . $sourceFieldName . '.' . $fieldModel->getColumnName()) : ''; |
|
167
|
|
|
} |
|
168
|
4 |
|
|
|
169
|
|
|
/** |
|
170
|
4 |
|
* Get table name. |
|
171
|
4 |
|
* |
|
172
|
4 |
|
* @return string |
|
173
|
4 |
|
*/ |
|
174
|
|
|
public function getTableName(): string |
|
175
|
|
|
{ |
|
176
|
|
|
if ($this->tableName) { |
|
177
|
|
|
return $this->tableName; |
|
178
|
|
|
} |
|
179
|
|
|
$table = $this->fieldModel->getTableName(); |
|
180
|
|
|
if ($this->related) { |
|
|
|
|
|
|
181
|
|
|
$table .= $this->related['sourceField']; |
|
182
|
|
|
} |
|
183
|
|
|
return $this->tableName = $table; |
|
184
|
2 |
|
} |
|
185
|
|
|
|
|
186
|
2 |
|
/** |
|
187
|
|
|
* Set table name. |
|
188
|
|
|
* |
|
189
|
2 |
|
* @param string $tableName |
|
190
|
|
|
*/ |
|
191
|
|
|
public function setTableName($tableName): void |
|
192
|
2 |
|
{ |
|
193
|
|
|
$this->tableName = $tableName; |
|
194
|
|
|
} |
|
195
|
|
|
|
|
196
|
|
|
/** |
|
197
|
|
|
* Get condition. |
|
198
|
|
|
* |
|
199
|
|
|
* @param string|null $operator |
|
200
|
2 |
|
* |
|
201
|
|
|
* @return array|bool |
|
202
|
2 |
|
*/ |
|
203
|
|
|
public function getCondition(?string $operator = null) |
|
204
|
|
|
{ |
|
205
|
|
|
$fn = 'operator' . ucfirst($operator ?? $this->operator); |
|
206
|
|
|
if (method_exists($this, $fn)) { |
|
207
|
|
|
Log::trace("Entering to $fn in " . __CLASS__); |
|
208
|
|
|
return $this->{$fn}(); |
|
209
|
|
|
} |
|
210
|
4 |
|
Log::error("Not found operator: $fn in " . __CLASS__); |
|
211
|
|
|
return false; |
|
212
|
4 |
|
} |
|
213
|
4 |
|
|
|
214
|
|
|
/** |
|
215
|
|
|
* Auto operator, it allows you to use formulas: * and _. |
|
216
|
|
|
* |
|
217
|
|
|
* @return array |
|
218
|
|
|
*/ |
|
219
|
|
|
public function operatorA(): array |
|
220
|
2 |
|
{ |
|
221
|
|
|
return $this->getCondition($this->getOperator()); |
|
|
|
|
|
|
222
|
2 |
|
} |
|
223
|
|
|
|
|
224
|
|
|
/** |
|
225
|
|
|
* Search for a specified pattern in a column. |
|
226
|
|
|
* Wildcard - asterisk. |
|
227
|
|
|
* |
|
228
|
|
|
* @return array |
|
229
|
|
|
*/ |
|
230
|
2 |
|
public function operatorWca(): array |
|
231
|
|
|
{ |
|
232
|
2 |
|
return ['like', $this->getColumnName(), str_replace('*', '%', "%{$this->getValue()}%"), false]; |
|
233
|
|
|
} |
|
234
|
|
|
|
|
235
|
|
|
/** |
|
236
|
|
|
* Get value. |
|
237
|
|
|
* |
|
238
|
|
|
* @return mixed |
|
239
|
|
|
*/ |
|
240
|
|
|
public function getValue() |
|
241
|
|
|
{ |
|
242
|
|
|
return $this->value; |
|
243
|
|
|
} |
|
244
|
|
|
|
|
245
|
|
|
/** |
|
246
|
|
|
* Set value. |
|
247
|
|
|
* |
|
248
|
|
|
* @param mixed $value |
|
249
|
|
|
* |
|
250
|
2 |
|
* @return $this |
|
251
|
|
|
*/ |
|
252
|
2 |
|
public function setValue($value) |
|
253
|
2 |
|
{ |
|
254
|
2 |
|
$this->value = $value; |
|
255
|
|
|
return $this; |
|
256
|
|
|
} |
|
257
|
|
|
|
|
258
|
|
|
/** |
|
259
|
|
|
* Contains operator. |
|
260
|
|
|
* |
|
261
|
|
|
* @return array |
|
262
|
|
|
*/ |
|
263
|
|
|
public function operatorC(): array |
|
264
|
|
|
{ |
|
265
|
|
|
return ['like', $this->getColumnName(), $this->getValue()]; |
|
266
|
|
|
} |
|
267
|
|
|
|
|
268
|
|
|
/** |
|
269
|
|
|
* Equals operator. |
|
270
|
|
|
* |
|
271
|
|
|
* @return array |
|
272
|
|
|
*/ |
|
273
|
|
|
public function operatorE(): array |
|
274
|
|
|
{ |
|
275
|
|
|
return [$this->getColumnName() => $this->getValue()]; |
|
276
|
|
|
} |
|
277
|
|
|
|
|
278
|
|
|
/** |
|
279
|
|
|
* Not equal operator. |
|
280
|
|
|
* |
|
281
|
|
|
* @return array |
|
282
|
|
|
*/ |
|
283
|
|
|
public function operatorN(): array |
|
284
|
|
|
{ |
|
285
|
|
|
$value = $this->getValue(); |
|
286
|
|
|
return [(\is_array($value) ? 'not in' : '<>'), $this->getColumnName(), $value]; |
|
287
|
|
|
} |
|
288
|
|
|
|
|
289
|
|
|
/** |
|
290
|
|
|
* Starts with operator. |
|
291
|
|
|
* |
|
292
|
|
|
* @return array |
|
293
|
|
|
*/ |
|
294
|
|
|
public function operatorS() |
|
295
|
|
|
{ |
|
296
|
|
|
return ['like', $this->getColumnName(), $this->getValue() . '%', false]; |
|
|
|
|
|
|
297
|
|
|
} |
|
298
|
|
|
|
|
299
|
|
|
/** |
|
300
|
|
|
* Ends with operator. |
|
301
|
|
|
* |
|
302
|
|
|
* @return array |
|
303
|
|
|
*/ |
|
304
|
|
|
public function operatorEw() |
|
305
|
|
|
{ |
|
306
|
|
|
return ['like', $this->getColumnName(), '%' . $this->getValue(), false]; |
|
|
|
|
|
|
307
|
|
|
} |
|
308
|
|
|
|
|
309
|
|
|
/** |
|
310
|
|
|
* Is empty operator. |
|
311
|
|
|
* |
|
312
|
|
|
* @return array |
|
313
|
|
|
*/ |
|
314
|
|
|
public function operatorY(): array |
|
315
|
|
|
{ |
|
316
|
|
|
return ['or', |
|
317
|
|
|
[$this->getColumnName() => null], |
|
318
|
|
|
['=', $this->getColumnName(), ''], |
|
319
|
|
|
]; |
|
320
|
|
|
} |
|
321
|
|
|
|
|
322
|
|
|
/** |
|
323
|
|
|
* Is not empty operator. |
|
324
|
|
|
* |
|
325
|
|
|
* @return array |
|
326
|
|
|
*/ |
|
327
|
|
|
public function operatorNy(): array |
|
328
|
|
|
{ |
|
329
|
|
|
return ['and', |
|
330
|
|
|
['not', [$this->getColumnName() => null]], |
|
331
|
|
|
['<>', $this->getColumnName(), ''], |
|
332
|
|
|
]; |
|
333
|
|
|
} |
|
334
|
|
|
|
|
335
|
|
|
/** |
|
336
|
|
|
* Does not contain operator. |
|
337
|
|
|
* |
|
338
|
|
|
* @return array |
|
339
|
|
|
*/ |
|
340
|
|
|
public function operatorK(): array |
|
341
|
|
|
{ |
|
342
|
|
|
return ['not like', $this->getColumnName(), $this->getValue()]; |
|
343
|
|
|
} |
|
344
|
|
|
|
|
345
|
|
|
/** |
|
346
|
|
|
* Is equal to selected field operator. |
|
347
|
|
|
* |
|
348
|
|
|
* @return array |
|
349
|
|
|
*/ |
|
350
|
|
|
public function operatorEf(): array |
|
351
|
|
|
{ |
|
352
|
|
|
return [$this->getColumnName() => new \yii\db\Expression($this->getColumnNameFromSource())]; |
|
353
|
|
|
} |
|
354
|
|
|
|
|
355
|
|
|
/** |
|
356
|
|
|
* Is not equal to selected field operator. |
|
357
|
|
|
* |
|
358
|
|
|
* @return array |
|
359
|
|
|
*/ |
|
360
|
|
|
public function operatorNf(): array |
|
361
|
|
|
{ |
|
362
|
|
|
return ['<>', $this->getColumnName(), new \yii\db\Expression($this->getColumnNameFromSource())]; |
|
363
|
|
|
} |
|
364
|
|
|
|
|
365
|
|
|
/** |
|
366
|
|
|
* Get field model. |
|
367
|
|
|
* |
|
368
|
|
|
* @return \Vtiger_Field_Model |
|
369
|
|
|
*/ |
|
370
|
|
|
public function getField() |
|
371
|
|
|
{ |
|
372
|
|
|
return $this->fieldModel; |
|
373
|
|
|
} |
|
374
|
|
|
|
|
375
|
|
|
/** |
|
376
|
|
|
* Invoked when object is cloning. |
|
377
|
|
|
*/ |
|
378
|
|
|
public function __clone() |
|
379
|
|
|
{ |
|
380
|
|
|
$this->fullColumnName = null; |
|
381
|
|
|
$this->tableName = null; |
|
382
|
|
|
} |
|
383
|
|
|
|
|
384
|
|
|
/** |
|
385
|
|
|
* Gets real operator. |
|
386
|
|
|
* |
|
387
|
|
|
* @return string |
|
388
|
|
|
*/ |
|
389
|
|
|
public function getOperator(): string |
|
390
|
|
|
{ |
|
391
|
|
|
$operator = $this->operator; |
|
392
|
|
|
if ('a' === $this->operator) { |
|
393
|
|
|
$operator = 'c'; |
|
394
|
|
|
if (false !== strpos($this->getValue(), '*')) { |
|
|
|
|
|
|
395
|
|
|
$operator = 'wca'; |
|
396
|
|
|
} |
|
397
|
|
|
} |
|
398
|
|
|
return $operator; |
|
399
|
|
|
} |
|
400
|
|
|
} |
|
401
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountIdthat can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theidproperty of an instance of theAccountclass. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.