1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* @copyright Copyright (c) Flipbox Digital Limited |
5
|
|
|
* @license https://flipboxfactory.com/software/organization/license |
6
|
|
|
* @link https://www.flipboxfactory.com/software/organization/ |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
namespace flipbox\organization\elements\db; |
10
|
|
|
|
11
|
|
|
use Craft; |
12
|
|
|
use craft\db\Query; |
13
|
|
|
use craft\elements\db\ElementQuery; |
14
|
|
|
use craft\elements\User as UserElement; |
15
|
|
|
use craft\helpers\ArrayHelper; |
16
|
|
|
use craft\helpers\Db; |
17
|
|
|
use craft\models\UserGroup; |
18
|
|
|
use craft\records\UserGroup as UserGroupRecord; |
19
|
|
|
use craft\records\UserGroup_User as UserGroupUsersRecord; |
20
|
|
|
use flipbox\organization\elements\Organization as OrganizationElement; |
21
|
|
|
use flipbox\organization\helpers\Query as QueryHelper; |
22
|
|
|
use flipbox\organization\models\Type; |
23
|
|
|
use flipbox\organization\Organization as OrganizationPlugin; |
24
|
|
|
use flipbox\organization\records\Organization as OrganizationRecord; |
25
|
|
|
use flipbox\organization\records\OrganizationType as OrganizationTypeOrganizationRecord; |
26
|
|
|
use flipbox\organization\records\User as OrganizationUserRecord; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* @author Flipbox Factory <[email protected]> |
30
|
|
|
* @since 1.0.0 |
31
|
|
|
* |
32
|
|
|
* @method OrganizationElement|null one($db = null) |
33
|
|
|
* @method OrganizationElement[] all($db = null) |
34
|
|
|
*/ |
35
|
|
|
class Organization extends ElementQuery |
36
|
|
|
{ |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @var int|int[]|null The user ID(s) that the resulting organizations’ owners must have. |
40
|
|
|
*/ |
41
|
|
|
public $ownerId; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @var int|int[]|null The user group ID(s) that the resulting organizations’ owners must be in. |
45
|
|
|
*/ |
46
|
|
|
public $ownerGroupId; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @var int|int[]|null The organization type ID(s) that the resulting organizations must have. |
50
|
|
|
*/ |
51
|
|
|
public $typeId; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @var int|int[]|null The organization type ID(s) that the resulting organizations must have. |
55
|
|
|
*/ |
56
|
|
|
public $userId; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @var int|int[]|null The organization type ID(s) that the resulting organizations must have. |
60
|
|
|
*/ |
61
|
|
|
public $memberId; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* @var mixed The Join Date that the resulting organization must have. |
65
|
|
|
*/ |
66
|
|
|
public $dateJoined; |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* @inheritdoc |
70
|
|
|
*/ |
71
|
|
|
public function __set($name, $value) |
72
|
|
|
{ |
73
|
|
|
|
74
|
|
|
switch ($name) { |
75
|
|
|
case 'owner': |
76
|
|
|
case 'ownerId': |
77
|
|
|
$this->setOwner($value); |
78
|
|
|
break; |
79
|
|
|
case 'ownerGroup': |
80
|
|
|
$this->ownerGroup($value); |
81
|
|
|
break; |
82
|
|
|
case 'type': |
83
|
|
|
case 'typeId': |
84
|
|
|
$this->setType($value); |
85
|
|
|
break; |
86
|
|
|
case 'user': |
87
|
|
|
case 'userId': |
88
|
|
|
$this->setUser($value); |
89
|
|
|
break; |
90
|
|
|
case 'member': |
91
|
|
|
case 'memberId': |
92
|
|
|
$this->setMember($value); |
93
|
|
|
break; |
94
|
|
|
default: |
95
|
|
|
parent::__set($name, $value); |
96
|
|
|
} |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Sets the [[typeId]] property based on a given element owner. |
102
|
|
|
* |
103
|
|
|
* @param string|string[]|integer|integer[]|Type|Type[] $value The property value |
104
|
|
|
* |
105
|
|
|
* @return self The query object itself |
106
|
|
|
*/ |
107
|
|
|
public function setType($value) |
108
|
|
|
{ |
109
|
|
|
|
110
|
|
|
$this->typeId = $this->parseTypeValue($value); |
111
|
|
|
|
112
|
|
|
return $this; |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* Sets the [[typeId]] property. |
117
|
|
|
* |
118
|
|
|
* @param string|string[]|integer|integer[]|Type|Type[] $type The property value |
119
|
|
|
* |
120
|
|
|
* @return self The query object itself |
121
|
|
|
*/ |
122
|
|
|
public function type($type) |
123
|
|
|
{ |
124
|
|
|
|
125
|
|
|
$this->setType($type); |
126
|
|
|
|
127
|
|
|
return $this; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @param $typeId |
132
|
|
|
* @return $this |
133
|
|
|
*/ |
134
|
|
|
public function setTypeId($typeId) |
135
|
|
|
{ |
136
|
|
|
|
137
|
|
|
$this->setType($typeId); |
138
|
|
|
|
139
|
|
|
return $this; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* Sets the [[typeId]] property. |
144
|
|
|
* |
145
|
|
|
* @param integer|integer[] $type The property value |
146
|
|
|
* |
147
|
|
|
* @return self The query object itself |
148
|
|
|
*/ |
149
|
|
|
public function typeId($type) |
150
|
|
|
{ |
151
|
|
|
|
152
|
|
|
$this->setType($type); |
153
|
|
|
|
154
|
|
|
return $this; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
/** |
158
|
|
|
* Sets the [[ownerId]] property based on a given element owner. |
159
|
|
|
* |
160
|
|
|
* @param string|string[]|integer|integer[]|UserElement|UserElement[] $value The property value |
161
|
|
|
* |
162
|
|
|
* @return self The query object itself |
163
|
|
|
*/ |
164
|
|
|
public function setOwner($value) |
165
|
|
|
{ |
166
|
|
|
|
167
|
|
|
// parse param to allow for mixed variables |
168
|
|
|
$this->ownerId = $this->parseUserValue($value); |
169
|
|
|
|
170
|
|
|
return $this; |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* Sets the [[ownerId]] property. |
175
|
|
|
* |
176
|
|
|
* @param string|string[]|integer|integer[]|UserElement|UserElement[] $owner The property value |
177
|
|
|
* |
178
|
|
|
* @return self The query object itself |
179
|
|
|
*/ |
180
|
|
|
public function owner($owner) |
181
|
|
|
{ |
182
|
|
|
|
183
|
|
|
$this->setOwner($owner); |
184
|
|
|
|
185
|
|
|
return $this; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
/** |
189
|
|
|
* @param $ownerId |
190
|
|
|
* @return $this |
191
|
|
|
*/ |
192
|
|
|
public function setOwnerId($ownerId) |
193
|
|
|
{ |
194
|
|
|
|
195
|
|
|
$this->setOwner($ownerId); |
196
|
|
|
|
197
|
|
|
return $this; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* Sets the [[ownerId]] property. |
202
|
|
|
* |
203
|
|
|
* @param integer|integer[] $owner The property value |
204
|
|
|
* |
205
|
|
|
* @return self The query object itself |
206
|
|
|
*/ |
207
|
|
|
public function ownerId($owner) |
208
|
|
|
{ |
209
|
|
|
|
210
|
|
|
$this->setOwner($owner); |
211
|
|
|
|
212
|
|
|
return $this; |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* Sets the [[ownerGroupId]] property based on a given user group(s)’s handle(s). |
218
|
|
|
* |
219
|
|
|
* @param string|string[]|null $value The property value |
220
|
|
|
* |
221
|
|
|
* @return static self reference |
222
|
|
|
*/ |
223
|
|
|
public function ownerGroup($value) |
224
|
|
|
{ |
225
|
|
|
if ($value instanceof UserGroup) { |
226
|
|
|
$this->ownerGroupId = $value->id; |
227
|
|
|
} elseif ($value !== null) { |
228
|
|
|
$this->ownerGroupId = (new Query()) |
229
|
|
|
->select(['id']) |
230
|
|
|
->from([UserGroupRecord::tableName()]) |
231
|
|
|
->where(Db::parseParam('handle', $value)) |
232
|
|
|
->column(); |
233
|
|
|
} else { |
234
|
|
|
$this->ownerGroupId = null; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
return $this; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* Sets the [[authorGroupId]] property. |
242
|
|
|
* |
243
|
|
|
* @param int|int[]|null $value The property value |
244
|
|
|
* |
245
|
|
|
* @return static self reference |
246
|
|
|
*/ |
247
|
|
|
public function ownerGroupId($value) |
248
|
|
|
{ |
249
|
|
|
$this->ownerGroupId = $value; |
250
|
|
|
|
251
|
|
|
return $this; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
|
255
|
|
|
/** |
256
|
|
|
* Sets the [[userId]] property based on a given element owner. |
257
|
|
|
* |
258
|
|
|
* @param string|string[]|integer|integer[]|UserElement|UserElement[] $value The property value |
259
|
|
|
* |
260
|
|
|
* @return self The query object itself |
261
|
|
|
*/ |
262
|
|
|
public function setUser($value) |
263
|
|
|
{ |
264
|
|
|
|
265
|
|
|
$this->userId = $this->parseUserValue($value); |
266
|
|
|
|
267
|
|
|
return $this; |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* Sets the [[userId]] property. |
272
|
|
|
* |
273
|
|
|
* @param string|string[]|integer|integer[]|UserElement|UserElement[] $users The property value |
274
|
|
|
* |
275
|
|
|
* @return self The query object itself |
276
|
|
|
*/ |
277
|
|
|
public function user($users) |
278
|
|
|
{ |
279
|
|
|
|
280
|
|
|
$this->setUser($users); |
281
|
|
|
|
282
|
|
|
return $this; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* @param $userIds |
287
|
|
|
* @return $this |
288
|
|
|
*/ |
289
|
|
|
public function setUserId($userIds) |
290
|
|
|
{ |
291
|
|
|
|
292
|
|
|
$this->setUser($userIds); |
293
|
|
|
|
294
|
|
|
return $this; |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* Sets the [[userId]] property. |
299
|
|
|
* |
300
|
|
|
* @param integer|integer[] $user The property value |
301
|
|
|
* |
302
|
|
|
* @return self The query object itself |
303
|
|
|
*/ |
304
|
|
|
public function userId($user) |
305
|
|
|
{ |
306
|
|
|
|
307
|
|
|
$this->setUser($user); |
308
|
|
|
|
309
|
|
|
return $this; |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
/** |
313
|
|
|
* Sets the [[userId]] property based on a given element owner. |
314
|
|
|
* |
315
|
|
|
* @param string|string[]|integer|integer[]|UserElement|UserElement[] $value The property value |
316
|
|
|
* |
317
|
|
|
* @return self The query object itself |
318
|
|
|
*/ |
319
|
|
|
public function setMember($value) |
320
|
|
|
{ |
321
|
|
|
|
322
|
|
|
$this->memberId = $this->parseUserValue($value); |
323
|
|
|
|
324
|
|
|
return $this; |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
/** |
328
|
|
|
* Sets the [[userId]] property. |
329
|
|
|
* |
330
|
|
|
* @param string|string[]|integer|integer[]|UserElement|UserElement[] $members The property value |
331
|
|
|
* |
332
|
|
|
* @return self The query object itself |
333
|
|
|
*/ |
334
|
|
|
public function member($members) |
335
|
|
|
{ |
336
|
|
|
|
337
|
|
|
$this->setMember($members); |
338
|
|
|
|
339
|
|
|
return $this; |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
/** |
343
|
|
|
* @param $memberIds |
344
|
|
|
* @return $this |
345
|
|
|
*/ |
346
|
|
|
public function setMemberId($memberIds) |
347
|
|
|
{ |
348
|
|
|
|
349
|
|
|
$this->setMember($memberIds); |
350
|
|
|
|
351
|
|
|
return $this; |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
/** |
355
|
|
|
* Sets the [[userId]] property. |
356
|
|
|
* |
357
|
|
|
* @param integer|integer[] $member The property value |
358
|
|
|
* |
359
|
|
|
* @return self The query object itself |
360
|
|
|
*/ |
361
|
|
|
public function memberId($member) |
362
|
|
|
{ |
363
|
|
|
|
364
|
|
|
$this->setMember($member); |
365
|
|
|
|
366
|
|
|
return $this; |
367
|
|
|
} |
368
|
|
|
|
369
|
|
|
/** |
370
|
|
|
* Sets the [[dateJoined]] property. |
371
|
|
|
* |
372
|
|
|
* @param mixed $value The property value |
373
|
|
|
* |
374
|
|
|
* @return static self reference |
375
|
|
|
*/ |
376
|
|
|
public function dateJoined($value) |
377
|
|
|
{ |
378
|
|
|
$this->dateJoined = $value; |
379
|
|
|
|
380
|
|
|
return $this; |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
/** |
384
|
|
|
* @inheritdoc |
385
|
|
|
*/ |
386
|
|
|
protected function statusCondition(string $status) |
387
|
|
|
{ |
388
|
|
|
|
389
|
|
|
$statuses = OrganizationPlugin::getInstance()->getSettings()->getStatuses(); |
390
|
|
|
|
391
|
|
|
if (array_key_exists($status, $statuses)) { |
392
|
|
|
return [OrganizationRecord::tableAlias() . '.status' => $status]; |
|
|
|
|
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
return parent::statusCondition($status); |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
/** |
399
|
|
|
* @inheritdoc |
400
|
|
|
*/ |
401
|
|
|
protected function beforePrepare(): bool |
402
|
|
|
{ |
403
|
|
|
|
404
|
|
|
// invalid handles |
405
|
|
|
if ($this->ownerGroupId === []) { |
406
|
|
|
return false; |
407
|
|
|
} |
408
|
|
|
|
409
|
|
|
$alias = OrganizationRecord::tableAlias(); |
410
|
|
|
|
411
|
|
|
$this->joinElementTable($alias); |
412
|
|
|
|
413
|
|
|
$this->query->select([ |
414
|
|
|
$alias . '.status', |
415
|
|
|
$alias . '.ownerId', |
416
|
|
|
$alias . '.dateJoined' |
417
|
|
|
]); |
418
|
|
|
|
419
|
|
|
if ($this->dateJoined) { |
420
|
|
|
$this->subQuery->andWhere(Db::parseDateParam($alias . '.dateJoined', $this->dateJoined)); |
421
|
|
|
} |
422
|
|
|
|
423
|
|
|
if ($this->typeId) { |
424
|
|
|
$this->subQuery->innerJoin( |
425
|
|
|
$this->organizationDbTableReference(), |
426
|
|
|
'elements.id = ' . OrganizationTypeOrganizationRecord::tableAlias() . '.organizationId' |
427
|
|
|
); |
428
|
|
|
|
429
|
|
|
$this->subQuery->andWhere(Db::parseParam( |
430
|
|
|
OrganizationTypeOrganizationRecord::tableAlias() . '.typeId', |
431
|
|
|
$this->typeId |
432
|
|
|
)); |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
// Owner only |
436
|
|
|
if ($this->ownerId) { |
437
|
|
|
$this->subQuery->andWhere(Db::parseParam($alias . '.ownerId', $this->ownerId)); |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
if ($this->ownerGroupId) { |
441
|
|
|
$this->subQuery |
442
|
|
|
->innerJoin( |
443
|
|
|
UserGroupUsersRecord::tableName() . ' usergroups_users', |
444
|
|
|
'[[usergroups_users.userId]] = [[' . $alias . '.ownerId]]' |
445
|
|
|
) |
446
|
|
|
->andWhere(Db::parseParam('usergroups_users.groupId', $this->ownerGroupId)); |
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
// Join user table |
450
|
|
|
if ($this->userId || $this->memberId) { |
451
|
|
|
$this->subQuery->leftJoin( |
452
|
|
|
OrganizationUserRecord::tableName() . ' ' . OrganizationUserRecord::tableAlias(), |
453
|
|
|
'elements.id = ' . OrganizationUserRecord::tableAlias() . '.organizationId' |
454
|
|
|
); |
455
|
|
|
$this->subQuery->addSelect([OrganizationUserRecord::tableAlias() . '.sortOrder']); |
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
// User only |
459
|
|
|
if ($this->userId) { |
460
|
|
|
$this->subQuery->andWhere( |
461
|
|
|
Db::parseParam(OrganizationUserRecord::tableAlias() . '.userId', $this->userId) |
462
|
|
|
); |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
// User or Owner |
466
|
|
|
if ($this->memberId) { |
467
|
|
|
$this->subQuery->distinct(true); |
468
|
|
|
$this->subQuery->andWhere([ |
469
|
|
|
'or', |
470
|
|
|
Db::parseParam(OrganizationUserRecord::tableAlias() . '.userId', $this->memberId), |
471
|
|
|
Db::parseParam($alias . '.ownerId', $this->memberId) |
472
|
|
|
]); |
473
|
|
|
} |
474
|
|
|
|
475
|
|
|
return parent::beforePrepare(); |
476
|
|
|
} |
477
|
|
|
|
478
|
|
|
/** |
479
|
|
|
* @return string |
480
|
|
|
*/ |
481
|
|
|
private function organizationDbTableReference(): string |
482
|
|
|
{ |
483
|
|
|
return OrganizationTypeOrganizationRecord::tableName() . ' ' . OrganizationTypeOrganizationRecord::tableAlias(); |
484
|
|
|
} |
485
|
|
|
|
486
|
|
|
/** |
487
|
|
|
* @param $value |
488
|
|
|
* @return array |
489
|
|
|
*/ |
490
|
|
|
private function parseTypeValue($value) |
491
|
|
|
{ |
492
|
|
|
|
493
|
|
|
// Default join type |
494
|
|
|
$join = 'or'; |
495
|
|
|
|
496
|
|
|
// Parse as single param? |
497
|
|
|
if (false === QueryHelper::parseBaseParam($value, $join)) { |
498
|
|
|
// Add one by one |
499
|
|
|
foreach ($value as $operator => &$v) { |
500
|
|
|
// attempt to assemble value (return false if it's a handle) |
501
|
|
|
if (false === QueryHelper::findParamValue($v, $operator)) { |
502
|
|
|
// create new query |
503
|
|
|
if (is_string($v)) { |
504
|
|
|
if ($model = OrganizationPlugin::getInstance()->getType()->find($v)) { |
505
|
|
|
$v = $model; |
506
|
|
|
} |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
if ($v instanceof Type) { |
510
|
|
|
$v = $v->id; |
511
|
|
|
} |
512
|
|
|
|
513
|
|
|
if ($v) { |
514
|
|
|
$v = QueryHelper::assembleParamValue($v, $operator); |
515
|
|
|
} |
516
|
|
|
} |
517
|
|
|
} |
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
// parse param to allow for mixed variables |
521
|
|
|
return array_merge([$join], ArrayHelper::filterEmptyStringsFromArray($value)); |
522
|
|
|
} |
523
|
|
|
|
524
|
|
|
/** |
525
|
|
|
* @param $value |
526
|
|
|
* @return array |
527
|
|
|
*/ |
528
|
|
|
private function parseUserValue($value) |
529
|
|
|
{ |
530
|
|
|
|
531
|
|
|
// Default join type |
532
|
|
|
$join = 'and'; |
533
|
|
|
|
534
|
|
|
// Parse as single param? |
535
|
|
|
if (false === QueryHelper::parseBaseParam($value, $join)) { |
536
|
|
|
// Add one by one |
537
|
|
|
foreach ($value as $operator => &$v) { |
538
|
|
|
// attempt to assemble value (return false if it's a handle) |
539
|
|
|
if (false === QueryHelper::findParamValue($v, $operator)) { |
540
|
|
|
// get element by string |
541
|
|
|
if (is_string($v)) { |
542
|
|
|
if ($element = Craft::$app->getUsers()->getUserByUsernameOrEmail($v)) { |
543
|
|
|
$v = $element->id; |
544
|
|
|
} |
545
|
|
|
} |
546
|
|
|
|
547
|
|
|
if ($v instanceof UserElement) { |
548
|
|
|
$v = $v->id; |
549
|
|
|
} |
550
|
|
|
|
551
|
|
|
if ($v) { |
552
|
|
|
$v = QueryHelper::assembleParamValue($v, $operator); |
553
|
|
|
} |
554
|
|
|
} |
555
|
|
|
} |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
// parse param to allow for mixed variables |
559
|
|
|
return array_merge([$join], ArrayHelper::filterEmptyStringsFromArray($value)); |
560
|
|
|
} |
561
|
|
|
} |
562
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.