|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* @copyright Copyright (c) Flipbox Digital Limited |
|
5
|
|
|
* @license https://www.flipboxfactory.com/software/element-lists/license |
|
6
|
|
|
* @link https://www.flipboxfactory.com/software/element-lists/ |
|
7
|
|
|
*/ |
|
8
|
|
|
|
|
9
|
|
|
namespace flipbox\craft\element\lists\queries; |
|
10
|
|
|
|
|
11
|
|
|
use Craft; |
|
12
|
|
|
use craft\db\QueryAbortedException; |
|
13
|
|
|
use craft\helpers\Db; |
|
14
|
|
|
use flipbox\craft\ember\helpers\QueryHelper; |
|
15
|
|
|
use flipbox\craft\ember\queries\AuditAttributesTrait; |
|
16
|
|
|
use flipbox\craft\ember\queries\CacheableActiveQuery; |
|
17
|
|
|
use flipbox\craft\ember\queries\FieldAttributeTrait; |
|
18
|
|
|
use flipbox\craft\ember\queries\SiteAttributeTrait; |
|
19
|
|
|
use flipbox\craft\integration\records\IntegrationAssociation; |
|
20
|
|
|
use yii\db\Query; |
|
21
|
|
|
|
|
22
|
|
|
/** |
|
23
|
|
|
* @author Flipbox Factory <[email protected]> |
|
24
|
|
|
* @since 2.0.0 |
|
25
|
|
|
* |
|
26
|
|
|
* @method IntegrationAssociation[] getCachedResult() |
|
27
|
|
|
* @method IntegrationAssociation[] all() |
|
28
|
|
|
* @method IntegrationAssociation one() |
|
29
|
|
|
*/ |
|
30
|
|
|
class AssociationQuery extends CacheableActiveQuery |
|
31
|
|
|
{ |
|
32
|
|
|
use AuditAttributesTrait, |
|
33
|
|
|
FieldAttributeTrait, |
|
34
|
|
|
SiteAttributeTrait; |
|
35
|
|
|
|
|
36
|
|
|
/** |
|
37
|
|
|
* @var int|null Sort order |
|
38
|
|
|
*/ |
|
39
|
|
|
public $sortOrder; |
|
40
|
|
|
|
|
41
|
|
|
/** |
|
42
|
|
|
* @var string|string[]|null |
|
43
|
|
|
*/ |
|
44
|
|
|
public $target; |
|
45
|
|
|
|
|
46
|
|
|
/** |
|
47
|
|
|
* @var string|string[]|null |
|
48
|
|
|
*/ |
|
49
|
|
|
public $source; |
|
50
|
|
|
|
|
51
|
|
|
/** |
|
52
|
|
|
* @param $value |
|
53
|
|
|
* @return $this |
|
54
|
|
|
*/ |
|
55
|
|
|
public function sortOrder($value) |
|
56
|
|
|
{ |
|
57
|
|
|
$this->sortOrder = $value; |
|
58
|
|
|
return $this; |
|
59
|
|
|
} |
|
60
|
|
|
|
|
61
|
|
|
/** |
|
62
|
|
|
* @param $value |
|
63
|
|
|
* @return $this |
|
64
|
|
|
*/ |
|
65
|
|
|
public function setSortOrder($value) |
|
66
|
|
|
{ |
|
67
|
|
|
return $this->sortOrder($value); |
|
68
|
|
|
} |
|
69
|
|
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* @param int|int[]|null $value |
|
72
|
|
|
* @return static |
|
73
|
|
|
*/ |
|
74
|
|
|
public function setTargetId($value) |
|
75
|
|
|
{ |
|
76
|
|
|
return $this->setTarget($value); |
|
77
|
|
|
} |
|
78
|
|
|
|
|
79
|
|
|
/** |
|
80
|
|
|
* @param int|int[]|null $value |
|
81
|
|
|
* @return static |
|
82
|
|
|
*/ |
|
83
|
|
|
public function targetId($value) |
|
84
|
|
|
{ |
|
85
|
|
|
return $this->setTarget($value); |
|
86
|
|
|
} |
|
87
|
|
|
|
|
88
|
|
|
/** |
|
89
|
|
|
* @param int|int[]|null $value |
|
90
|
|
|
* @return static |
|
91
|
|
|
*/ |
|
92
|
|
|
public function setTarget($value) |
|
93
|
|
|
{ |
|
94
|
|
|
$this->target = $value; |
|
|
|
|
|
|
95
|
|
|
return $this; |
|
96
|
|
|
} |
|
97
|
|
|
|
|
98
|
|
|
/** |
|
99
|
|
|
* @param int|int[]|null $value |
|
100
|
|
|
* @return static |
|
101
|
|
|
*/ |
|
102
|
|
|
public function target($value) |
|
103
|
|
|
{ |
|
104
|
|
|
return $this->setTarget($value); |
|
105
|
|
|
} |
|
106
|
|
|
|
|
107
|
|
|
|
|
108
|
|
|
/** |
|
109
|
|
|
* @param int|int[]|null $value |
|
110
|
|
|
* @return static |
|
111
|
|
|
*/ |
|
112
|
|
|
public function setSourceId($value) |
|
113
|
|
|
{ |
|
114
|
|
|
return $this->setSource($value); |
|
115
|
|
|
} |
|
116
|
|
|
|
|
117
|
|
|
/** |
|
118
|
|
|
* @param int|int[]|null $value |
|
119
|
|
|
* @return static |
|
120
|
|
|
*/ |
|
121
|
|
|
public function sourceId($value) |
|
122
|
|
|
{ |
|
123
|
|
|
return $this->setSource($value); |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
/** |
|
127
|
|
|
* @param int|int[]|null $value |
|
128
|
|
|
* @return static |
|
129
|
|
|
*/ |
|
130
|
|
|
public function setSource($value) |
|
131
|
|
|
{ |
|
132
|
|
|
$this->source = $value; |
|
|
|
|
|
|
133
|
|
|
return $this; |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
|
|
/** |
|
137
|
|
|
* @param int|int[]|null $value |
|
138
|
|
|
* @return static |
|
139
|
|
|
*/ |
|
140
|
|
|
public function source($value) |
|
141
|
|
|
{ |
|
142
|
|
|
return $this->setSource($value); |
|
143
|
|
|
} |
|
144
|
|
|
|
|
145
|
|
|
/** |
|
146
|
|
|
* @inheritdoc |
|
147
|
|
|
*/ |
|
148
|
|
|
public function init() |
|
149
|
|
|
{ |
|
150
|
|
|
parent::init(); |
|
151
|
|
|
|
|
152
|
|
|
if ($this->select === null) { |
|
153
|
|
|
$this->select = ['*']; |
|
154
|
|
|
} |
|
155
|
|
|
|
|
156
|
|
|
if ($this->orderBy === null) { |
|
157
|
|
|
$this->orderBy = ['sortOrder' => SORT_ASC]; |
|
158
|
|
|
} |
|
159
|
|
|
} |
|
160
|
|
|
|
|
161
|
|
|
/** |
|
162
|
|
|
* @inheritdoc |
|
163
|
|
|
* @throws QueryAbortedException |
|
164
|
|
|
*/ |
|
165
|
|
|
public function prepare($builder) |
|
166
|
|
|
{ |
|
167
|
|
|
// Is the query already doomed? |
|
168
|
|
|
if (($this->field !== null && empty($this->field)) || |
|
169
|
|
|
($this->target !== null && empty($this->target)) || |
|
170
|
|
|
($this->source !== null && empty($this->source)) |
|
171
|
|
|
) { |
|
172
|
|
|
throw new QueryAbortedException(); |
|
173
|
|
|
} |
|
174
|
|
|
|
|
175
|
|
|
$this->applyFieldConditions(); |
|
176
|
|
|
$this->applySiteConditions(); |
|
177
|
|
|
$this->applyAuditAttributeConditions(); |
|
178
|
|
|
|
|
179
|
|
|
if ($this->sortOrder !== null) { |
|
180
|
|
|
$this->andWhere(Db::parseParam('sortOrder', $this->sortOrder)); |
|
|
|
|
|
|
181
|
|
|
} |
|
182
|
|
|
|
|
183
|
|
|
if ($this->target !== null) { |
|
184
|
|
|
$this->andWhere(Db::parseParam('targetId', $this->parseElementValue($this->target))); |
|
|
|
|
|
|
185
|
|
|
} |
|
186
|
|
|
|
|
187
|
|
|
if ($this->source !== null) { |
|
188
|
|
|
$this->andWhere(Db::parseParam('sourceId', $this->parseElementValue($this->source))); |
|
|
|
|
|
|
189
|
|
|
} |
|
190
|
|
|
|
|
191
|
|
|
return parent::prepare($builder); |
|
192
|
|
|
} |
|
193
|
|
|
|
|
194
|
|
|
/** |
|
195
|
|
|
* Apply attribute conditions |
|
196
|
|
|
*/ |
|
197
|
|
|
protected function applyFieldConditions() |
|
198
|
|
|
{ |
|
199
|
|
|
if ($this->field !== null) { |
|
200
|
|
|
$this->andWhere(Db::parseParam('fieldId', $this->parseFieldValue($this->field))); |
|
|
|
|
|
|
201
|
|
|
} |
|
202
|
|
|
} |
|
203
|
|
|
|
|
204
|
|
|
/** |
|
205
|
|
|
* Apply attribute conditions |
|
206
|
|
|
*/ |
|
207
|
|
|
protected function applySiteConditions() |
|
208
|
|
|
{ |
|
209
|
|
|
if ($this->site !== null) { |
|
210
|
|
|
$this->andWhere(Db::parseParam('siteId', $this->parseSiteValue($this->site))); |
|
|
|
|
|
|
211
|
|
|
} else { |
|
212
|
|
|
$this->andWhere(Db::parseParam('siteId', Craft::$app->getSites()->currentSite->id)); |
|
|
|
|
|
|
213
|
|
|
} |
|
214
|
|
|
} |
|
215
|
|
|
|
|
216
|
|
|
/** |
|
217
|
|
|
* @param $value |
|
218
|
|
|
* @return array|string |
|
219
|
|
|
*/ |
|
220
|
|
|
protected function parseElementValue($value) |
|
221
|
|
|
{ |
|
222
|
|
|
return QueryHelper::prepareParam( |
|
223
|
|
|
$value, |
|
224
|
|
|
function (string $uri) { |
|
225
|
|
|
$value = (new Query()) |
|
226
|
|
|
->select(['id']) |
|
227
|
|
|
->from(['{{%elements_sites}} elements_sites']) |
|
228
|
|
|
->where(['uri' => $uri]) |
|
229
|
|
|
->scalar(); |
|
230
|
|
|
return empty($value) ? false : $value; |
|
231
|
|
|
} |
|
232
|
|
|
); |
|
233
|
|
|
} |
|
234
|
|
|
} |
|
235
|
|
|
|
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.