Complex classes like CoreQueryBuilder often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use CoreQueryBuilder, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
56 | class CoreQueryBuilder extends NC22ExtendedQueryBuilder { |
||
57 | |||
58 | |||
59 | use TArrayTools; |
||
60 | |||
61 | |||
62 | const SINGLE = 'single'; |
||
63 | const CIRCLE = 'circle'; |
||
64 | const MEMBER = 'member'; |
||
65 | const MEMBER_COUNT = 'membercount'; |
||
66 | const OWNER = 'owner'; |
||
67 | const FEDERATED_EVENT = 'federatedevent'; |
||
68 | const REMOTE = 'remote'; |
||
69 | const BASED_ON = 'basedon'; |
||
70 | const INITIATOR = 'initiator'; |
||
71 | const MEMBERSHIPS = 'memberships'; |
||
72 | const UPSTREAM_MEMBERSHIPS = 'upstreammemberships'; |
||
73 | const INHERITANCE_FROM = 'inheritancefrom'; |
||
74 | const INHERITED_BY = 'inheritedby'; |
||
75 | const INVITED_BY = 'invitedby'; |
||
76 | const MOUNT = 'mount'; |
||
77 | const MOUNTPOINT = 'mountpoint'; |
||
78 | const SHARE = 'share'; |
||
79 | const FILE_CACHE = 'filecache'; |
||
80 | const STORAGES = 'storages'; |
||
81 | const OPTIONS = 'options'; |
||
82 | const HELPER = 'circleshelper'; |
||
83 | |||
84 | |||
85 | public static $SQL_PATH = [ |
||
86 | self::SINGLE => [ |
||
87 | self::MEMBER |
||
88 | ], |
||
89 | self::CIRCLE => [ |
||
90 | self::OPTIONS => [ |
||
91 | 'getPersonalCircle' => true |
||
92 | ], |
||
93 | self::MEMBER, |
||
94 | self::MEMBER_COUNT, |
||
95 | self::OWNER => [ |
||
96 | self::BASED_ON |
||
97 | ], |
||
98 | self::MEMBERSHIPS, |
||
99 | self::INITIATOR => [ |
||
100 | self::BASED_ON, |
||
101 | self::INHERITED_BY => [ |
||
102 | self::MEMBERSHIPS |
||
103 | ] |
||
104 | ], |
||
105 | self::REMOTE => [ |
||
106 | self::MEMBER, |
||
107 | self::CIRCLE => [ |
||
108 | self::OWNER |
||
109 | ] |
||
110 | ] |
||
111 | ], |
||
112 | self::MEMBER => [ |
||
113 | self::MEMBERSHIPS, |
||
114 | self::INHERITANCE_FROM, |
||
115 | self::CIRCLE => [ |
||
116 | self::OPTIONS => [ |
||
117 | 'getData' => true |
||
118 | ], |
||
119 | self::OWNER, |
||
120 | self::MEMBERSHIPS, |
||
121 | self::INITIATOR => [ |
||
122 | self::OPTIONS => [ |
||
123 | 'mustBeMember' => true, |
||
124 | 'canBeVisitor' => false |
||
125 | ], |
||
126 | self::BASED_ON, |
||
127 | self::INHERITED_BY => [ |
||
128 | self::MEMBERSHIPS |
||
129 | ], |
||
130 | self::INVITED_BY => [ |
||
131 | self::OWNER, |
||
132 | self::BASED_ON |
||
133 | ] |
||
134 | ] |
||
135 | ], |
||
136 | self::BASED_ON => [ |
||
137 | self::OWNER, |
||
138 | self::MEMBERSHIPS, |
||
139 | self::INITIATOR => [ |
||
140 | self::BASED_ON, |
||
141 | self::INHERITED_BY => [ |
||
142 | self::MEMBERSHIPS |
||
143 | ] |
||
144 | ] |
||
145 | ], |
||
146 | self::REMOTE => [ |
||
147 | self::MEMBER, |
||
148 | self::CIRCLE => [ |
||
149 | self::OWNER |
||
150 | ] |
||
151 | ], |
||
152 | self::INVITED_BY => [ |
||
153 | self::OWNER, |
||
154 | self::BASED_ON |
||
155 | ] |
||
156 | ], |
||
157 | self::SHARE => [ |
||
158 | self::SHARE, |
||
159 | self::FILE_CACHE => [ |
||
160 | self::STORAGES |
||
161 | ], |
||
162 | self::UPSTREAM_MEMBERSHIPS => [ |
||
163 | self::MEMBERSHIPS, |
||
164 | self::INHERITED_BY => [ |
||
165 | self::BASED_ON |
||
166 | ], |
||
167 | self::SHARE, |
||
168 | ], |
||
169 | self::MEMBERSHIPS, |
||
170 | self::INHERITANCE_FROM, |
||
171 | self::INHERITED_BY => [ |
||
172 | self::BASED_ON |
||
173 | ], |
||
174 | self::CIRCLE => [ |
||
175 | self::OWNER |
||
176 | ], |
||
177 | self::INITIATOR => [ |
||
178 | self::BASED_ON, |
||
179 | self::INHERITED_BY => [ |
||
180 | self::MEMBERSHIPS |
||
181 | ] |
||
182 | ] |
||
183 | ], |
||
184 | self::REMOTE => [ |
||
185 | self::MEMBER |
||
186 | ], |
||
187 | self::MOUNT => [ |
||
188 | self::MEMBER => [ |
||
189 | self::REMOTE |
||
190 | ], |
||
191 | self::INITIATOR => [ |
||
192 | self::INHERITED_BY => [ |
||
193 | self::MEMBERSHIPS |
||
194 | ] |
||
195 | ], |
||
196 | self::MOUNTPOINT, |
||
197 | self::MEMBERSHIPS |
||
198 | ], |
||
199 | self::HELPER => [ |
||
200 | self::MEMBERSHIPS, |
||
201 | self::INITIATOR => [ |
||
202 | self::INHERITED_BY => [ |
||
203 | self::MEMBERSHIPS |
||
204 | ] |
||
205 | ], |
||
206 | self::CIRCLE => [ |
||
207 | self::OPTIONS => [ |
||
208 | 'getPersonalCircle' => true |
||
209 | ], |
||
210 | self::MEMBER, |
||
211 | self::OWNER => [ |
||
212 | self::BASED_ON |
||
213 | ] |
||
214 | ] |
||
215 | ] |
||
216 | ]; |
||
217 | |||
218 | |||
219 | /** @var ConfigService */ |
||
220 | private $configService; |
||
221 | |||
222 | |||
223 | /** @var array */ |
||
224 | private $options = []; |
||
225 | |||
226 | |||
227 | /** |
||
228 | * CoreQueryBuilder constructor. |
||
229 | */ |
||
230 | public function __construct() { |
||
231 | parent::__construct(); |
||
232 | |||
233 | $this->configService = OC::$server->get(ConfigService::class); |
||
234 | } |
||
235 | |||
236 | |||
237 | /** |
||
238 | * @param IFederatedModel $federatedModel |
||
239 | * |
||
240 | * @return string |
||
241 | */ |
||
242 | public function getInstance(IFederatedModel $federatedModel): string { |
||
243 | $instance = $federatedModel->getInstance(); |
||
244 | |||
245 | return ($this->configService->isLocalInstance($instance)) ? '' : $instance; |
||
246 | } |
||
247 | |||
248 | |||
249 | /** |
||
250 | * @param string $id |
||
251 | */ |
||
252 | public function limitToCircleId(string $id): void { |
||
253 | $this->limitToDBField('circle_id', $id, true); |
||
254 | } |
||
255 | |||
256 | /** |
||
257 | * @param string $name |
||
258 | */ |
||
259 | public function limitToName(string $name): void { |
||
260 | $this->limit('name', $name); |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * @param string $name |
||
265 | */ |
||
266 | public function limitToDisplayName(string $name): void { |
||
267 | $this->limit('display_name', $name, '', false); |
||
268 | } |
||
269 | |||
270 | /** |
||
271 | * @param string $name |
||
272 | */ |
||
273 | public function limitToSanitizedName(string $name): void { |
||
274 | $this->limit('sanitized_name', $name, '', false); |
||
275 | } |
||
276 | |||
277 | /** |
||
278 | * @param int $config |
||
279 | */ |
||
280 | public function limitToConfig(int $config): void { |
||
281 | $this->limitToDBFieldInt('config', $config); |
||
282 | } |
||
283 | |||
284 | /** |
||
285 | * @param int $source |
||
286 | */ |
||
287 | public function limitToSource(int $source): void { |
||
288 | $this->limitToDBFieldInt('source', $source); |
||
289 | } |
||
290 | |||
291 | /** |
||
292 | * @param int $config |
||
293 | * @param string $alias |
||
294 | */ |
||
295 | public function limitToConfigFlag(int $config, string $alias = ''): void { |
||
296 | $this->limitBitwise('config', $config, $alias); |
||
297 | } |
||
298 | |||
299 | |||
300 | /** |
||
301 | * @param string $singleId |
||
302 | */ |
||
303 | public function limitToSingleId(string $singleId): void { |
||
304 | $this->limitToDBField('single_id', $singleId, true); |
||
305 | } |
||
306 | |||
307 | |||
308 | /** |
||
309 | * @param string $itemId |
||
310 | */ |
||
311 | public function limitToItemId(string $itemId): void { |
||
312 | $this->limitToDBField('item_id', $itemId, true); |
||
313 | } |
||
314 | |||
315 | |||
316 | /** |
||
317 | * @param string $host |
||
318 | */ |
||
319 | public function limitToInstance(string $host): void { |
||
320 | $this->limitToDBField('instance', $host, false); |
||
321 | } |
||
322 | |||
323 | |||
324 | /** |
||
325 | * @param int $userType |
||
326 | */ |
||
327 | public function limitToUserType(int $userType): void { |
||
328 | $this->limitToDBFieldInt('user_type', $userType); |
||
329 | } |
||
330 | |||
331 | |||
332 | /** |
||
333 | * @param int $shareType |
||
334 | */ |
||
335 | public function limitToShareType(int $shareType): void { |
||
336 | $this->limitToDBFieldInt('share_type', $shareType); |
||
337 | } |
||
338 | |||
339 | |||
340 | /** |
||
341 | * @param string $shareWith |
||
342 | */ |
||
343 | public function limitToShareWith(string $shareWith): void { |
||
344 | $this->limitToDBField('share_with', $shareWith); |
||
345 | } |
||
346 | |||
347 | |||
348 | /** |
||
349 | * @param int $nodeId |
||
350 | */ |
||
351 | public function limitToFileSource(int $nodeId): void { |
||
352 | $this->limitToDBFieldInt('file_source', $nodeId); |
||
353 | } |
||
354 | |||
355 | /** |
||
356 | * @param array $files |
||
357 | */ |
||
358 | public function limitToFileSourceArray(array $files): void { |
||
359 | $this->limitToDBFieldInArray('file_source', $files); |
||
360 | } |
||
361 | |||
362 | |||
363 | /** |
||
364 | * @param int $shareId |
||
365 | */ |
||
366 | public function limitToShareParent(int $shareId): void { |
||
367 | $this->limitToDBFieldInt('parent', $shareId); |
||
368 | } |
||
369 | |||
370 | |||
371 | /** |
||
372 | * @param Circle $circle |
||
373 | */ |
||
374 | public function filterCircle(Circle $circle): void { |
||
375 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
376 | return; |
||
377 | } |
||
378 | |||
379 | if ($circle->getDisplayName() !== '') { |
||
380 | $this->searchInDBField('display_name', '%' . $circle->getDisplayName() . '%'); |
||
381 | } |
||
382 | if ($circle->getConfig() > 0) { |
||
383 | $this->limitBitwise('config', $circle->getConfig()); |
||
384 | } |
||
385 | } |
||
386 | |||
387 | |||
388 | /** |
||
389 | * left join RemoteInstance based on a Member |
||
390 | */ |
||
391 | public function leftJoinRemoteInstance(string $alias): void { |
||
392 | $expr = $this->expr(); |
||
393 | |||
394 | try { |
||
395 | $aliasRemoteInstance = $this->generateAlias($alias, self::REMOTE); |
||
396 | $this->generateRemoteInstanceSelectAlias($aliasRemoteInstance) |
||
397 | ->leftJoin( |
||
398 | $alias, CoreRequestBuilder::TABLE_REMOTE, $aliasRemoteInstance, |
||
399 | $expr->eq($alias . '.instance', $aliasRemoteInstance . '.instance') |
||
400 | ); |
||
401 | } catch (RequestBuilderException $e) { |
||
402 | } |
||
403 | } |
||
404 | |||
405 | |||
406 | /** |
||
407 | * @param string $alias |
||
408 | * @param RemoteInstance $remoteInstance |
||
409 | * @param bool $filterSensitiveData |
||
410 | * @param string $aliasCircle |
||
411 | * |
||
412 | * @throws RequestBuilderException |
||
413 | */ |
||
414 | public function limitToRemoteInstance( |
||
415 | string $alias, |
||
416 | RemoteInstance $remoteInstance, |
||
417 | bool $filterSensitiveData = true, |
||
418 | string $aliasCircle = '' |
||
419 | ): void { |
||
420 | |||
421 | if ($aliasCircle === '') { |
||
422 | $aliasCircle = $alias; |
||
423 | } |
||
424 | |||
425 | $this->leftJoinRemoteInstanceIncomingRequest($alias, $remoteInstance); |
||
426 | $this->leftJoinMemberFromInstance($alias, $remoteInstance, $aliasCircle); |
||
427 | $this->leftJoinMemberFromRemoteCircle($alias, $remoteInstance, $aliasCircle); |
||
428 | $this->limitRemoteVisibility($alias, $filterSensitiveData, $aliasCircle); |
||
429 | } |
||
430 | |||
431 | |||
432 | /** |
||
433 | * Left join RemoteInstance based on an incoming request |
||
434 | * |
||
435 | * @param string $alias |
||
436 | * @param RemoteInstance $remoteInstance |
||
437 | * |
||
438 | * @throws RequestBuilderException |
||
439 | */ |
||
440 | public function leftJoinRemoteInstanceIncomingRequest( |
||
441 | string $alias, |
||
442 | RemoteInstance $remoteInstance |
||
443 | ): void { |
||
444 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
445 | return; |
||
446 | } |
||
447 | |||
448 | $aliasRemote = $this->generateAlias($alias, self::REMOTE); |
||
449 | $expr = $this->expr(); |
||
450 | $this->leftJoin( |
||
451 | $this->getDefaultSelectAlias(), CoreRequestBuilder::TABLE_REMOTE, $aliasRemote, |
||
452 | $expr->eq($aliasRemote . '.instance', $this->createNamedParameter($remoteInstance->getInstance())) |
||
453 | ); |
||
454 | } |
||
455 | |||
456 | |||
457 | /** |
||
458 | * left join members to check memberships of someone from instance |
||
459 | * |
||
460 | * @param string $alias |
||
461 | * @param RemoteInstance $remoteInstance |
||
462 | * @param string $aliasCircle |
||
463 | * |
||
464 | * @throws RequestBuilderException |
||
465 | */ |
||
466 | private function leftJoinMemberFromInstance( |
||
467 | string $alias, RemoteInstance $remoteInstance, string $aliasCircle |
||
468 | ) { |
||
469 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
470 | return; |
||
471 | } |
||
472 | |||
473 | $aliasRemote = $this->generateAlias($alias, self::REMOTE); |
||
474 | $aliasRemoteMember = $this->generateAlias($aliasRemote, self::MEMBER); |
||
475 | |||
476 | $expr = $this->expr(); |
||
477 | $this->leftJoin( |
||
478 | $this->getDefaultSelectAlias(), CoreRequestBuilder::TABLE_MEMBER, $aliasRemoteMember, |
||
479 | $expr->andX( |
||
480 | $expr->eq($aliasRemoteMember . '.circle_id', $aliasCircle . '.unique_id'), |
||
481 | $expr->eq( |
||
482 | $aliasRemoteMember . '.instance', |
||
483 | $this->createNamedParameter($remoteInstance->getInstance()) |
||
484 | ), |
||
485 | $expr->gte($aliasRemoteMember . '.level', $this->createNamedParameter(Member::LEVEL_MEMBER)) |
||
486 | ) |
||
487 | ); |
||
488 | } |
||
489 | |||
490 | |||
491 | /** |
||
492 | * left join circle is member of a circle from remote instance |
||
493 | * |
||
494 | * @param string $alias |
||
495 | * @param RemoteInstance $remoteInstance |
||
496 | * @param string $aliasCircle |
||
497 | * |
||
498 | * @throws RequestBuilderException |
||
499 | */ |
||
500 | private function leftJoinMemberFromRemoteCircle( |
||
501 | string $alias, |
||
502 | RemoteInstance $remoteInstance, |
||
503 | string $aliasCircle |
||
504 | ) { |
||
505 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
506 | return; |
||
507 | } |
||
508 | |||
509 | $aliasRemote = $this->generateAlias($alias, self::REMOTE); |
||
510 | $aliasRemoteCircle = $this->generateAlias($aliasRemote, self::CIRCLE); |
||
511 | $aliasRemoteCircleOwner = $this->generateAlias($aliasRemoteCircle, self::OWNER); |
||
512 | |||
513 | $expr = $this->expr(); |
||
514 | $this->leftJoin( |
||
515 | $this->getDefaultSelectAlias(), CoreRequestBuilder::TABLE_MEMBER, $aliasRemoteCircle, |
||
516 | $expr->andX( |
||
517 | $expr->eq($aliasRemoteCircle . '.single_id', $aliasCircle . '.unique_id'), |
||
518 | $expr->emptyString($aliasRemoteCircle . '.instance'), |
||
519 | $expr->gte($aliasRemoteCircle . '.level', $this->createNamedParameter(Member::LEVEL_MEMBER)) |
||
520 | ) |
||
521 | ); |
||
522 | $this->leftJoin( |
||
523 | $this->getDefaultSelectAlias(), CoreRequestBuilder::TABLE_MEMBER, $aliasRemoteCircleOwner, |
||
524 | $expr->andX( |
||
525 | $expr->eq($aliasRemoteCircle . '.circle_id', $aliasRemoteCircleOwner . '.circle_id'), |
||
526 | $expr->eq( |
||
527 | $aliasRemoteCircleOwner . '.instance', |
||
528 | $this->createNamedParameter($remoteInstance->getInstance()) |
||
529 | ), |
||
530 | $expr->eq( |
||
531 | $aliasRemoteCircleOwner . '.level', $this->createNamedParameter(Member::LEVEL_OWNER) |
||
532 | ) |
||
533 | ) |
||
534 | ); |
||
535 | } |
||
536 | |||
537 | |||
538 | /** |
||
539 | * - global_scale: visibility on all Circles |
||
540 | * - trusted: visibility on all FEDERATED Circle if owner is local |
||
541 | * - external: visibility on all FEDERATED Circle if owner is local and: |
||
542 | * - with if Circle contains at least one member from the remote instance |
||
543 | * - one circle from the remote instance contains the local circle as member, and confirmed (using |
||
544 | * sync locally) |
||
545 | * - passive: like external, but the members list will only contains member from the local instance and |
||
546 | * from the remote instance. |
||
547 | * |
||
548 | * @param string $alias |
||
549 | * @param bool $sensitive |
||
550 | * @param string $aliasCircle |
||
551 | * |
||
552 | * @throws RequestBuilderException |
||
553 | */ |
||
554 | protected function limitRemoteVisibility(string $alias, bool $sensitive, string $aliasCircle) { |
||
555 | $aliasRemote = $this->generateAlias($alias, self::REMOTE); |
||
556 | $aliasOwner = $this->generateAlias($aliasCircle, self::OWNER); |
||
557 | $aliasRemoteMember = $this->generateAlias($aliasRemote, self::MEMBER); |
||
558 | $aliasRemoteCircle = $this->generateAlias($aliasRemote, self::CIRCLE); |
||
559 | $aliasRemoteCircleOwner = $this->generateAlias($aliasRemoteCircle, self::OWNER); |
||
560 | |||
561 | $expr = $this->expr(); |
||
562 | $orX = $expr->orX(); |
||
563 | $orX->add( |
||
564 | $expr->eq($aliasRemote . '.type', $this->createNamedParameter(RemoteInstance::TYPE_GLOBALSCALE)) |
||
565 | ); |
||
566 | |||
567 | $orExtOrPassive = $expr->orX(); |
||
568 | $orExtOrPassive->add( |
||
569 | $expr->eq($aliasRemote . '.type', $this->createNamedParameter(RemoteInstance::TYPE_EXTERNAL)) |
||
570 | ); |
||
571 | if (!$sensitive) { |
||
572 | $orExtOrPassive->add( |
||
573 | $expr->eq($aliasRemote . '.type', $this->createNamedParameter(RemoteInstance::TYPE_PASSIVE)) |
||
574 | ); |
||
575 | } else { |
||
576 | if ($this->getDefaultSelectAlias() === CoreQueryBuilder::MEMBER) { |
||
577 | $orExtOrPassive->add($this->limitRemoteVisibility_Sensitive_Members($aliasRemote)); |
||
578 | } |
||
579 | } |
||
580 | |||
581 | $orInstance = $expr->orX(); |
||
582 | $orInstance->add($expr->isNotNull($aliasRemoteMember . '.instance')); |
||
583 | $orInstance->add($expr->isNotNull($aliasRemoteCircleOwner . '.instance')); |
||
584 | |||
585 | $andExternal = $expr->andX(); |
||
586 | $andExternal->add($orExtOrPassive); |
||
587 | $andExternal->add($orInstance); |
||
588 | |||
589 | $orExtOrTrusted = $expr->orX(); |
||
590 | $orExtOrTrusted->add($andExternal); |
||
591 | $orExtOrTrusted->add( |
||
592 | $expr->eq($aliasRemote . '.type', $this->createNamedParameter(RemoteInstance::TYPE_TRUSTED)) |
||
593 | ); |
||
594 | |||
595 | $andTrusted = $expr->andX(); |
||
596 | $andTrusted->add($orExtOrTrusted); |
||
597 | $andTrusted->add($this->exprLimitBitwise('config', Circle::CFG_FEDERATED, $aliasCircle)); |
||
598 | $andTrusted->add($expr->emptyString($aliasOwner . '.instance')); |
||
599 | $orX->add($andTrusted); |
||
600 | |||
601 | $this->andWhere($orX); |
||
602 | } |
||
603 | |||
604 | |||
605 | /** |
||
606 | * @param string $alias |
||
607 | * @param Member $member |
||
608 | * |
||
609 | * @throws RequestBuilderException |
||
610 | */ |
||
611 | public function limitToDirectMembership(string $alias, Member $member): void { |
||
612 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
613 | return; |
||
614 | } |
||
615 | |||
616 | $aliasMember = $this->generateAlias($alias, self::MEMBER, $options); |
||
617 | $getData = $this->getBool('getData', $options, false); |
||
618 | |||
619 | $expr = $this->expr(); |
||
620 | if ($getData) { |
||
621 | $this->generateMemberSelectAlias($aliasMember); |
||
622 | } |
||
623 | $this->leftJoin( |
||
624 | $this->getDefaultSelectAlias(), CoreRequestBuilder::TABLE_MEMBER, $aliasMember, |
||
625 | $expr->eq($aliasMember . '.circle_id', $alias . '.unique_id') |
||
626 | ); |
||
627 | |||
628 | $this->filterDirectMembership($aliasMember, $member); |
||
629 | } |
||
630 | |||
631 | |||
632 | /** |
||
633 | * @param string $aliasMember |
||
634 | * @param Member $member |
||
635 | */ |
||
636 | public function filterDirectMembership(string $aliasMember, Member $member): void { |
||
637 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
638 | return; |
||
639 | } |
||
640 | |||
641 | $expr = $this->expr(); |
||
642 | $andX = $expr->andX(); |
||
643 | |||
644 | if ($member->getUserId() !== '') { |
||
645 | $andX->add( |
||
646 | $expr->eq($aliasMember . '.user_id', $this->createNamedParameter($member->getUserId())) |
||
647 | ); |
||
648 | } |
||
649 | |||
650 | if ($member->getSingleId() !== '') { |
||
651 | $andX->add( |
||
652 | $expr->eq($aliasMember . '.single_id', $this->createNamedParameter($member->getSingleId())) |
||
653 | ); |
||
654 | } |
||
655 | |||
656 | if ($member->getUserType() > 0) { |
||
657 | $andX->add( |
||
658 | $expr->eq($aliasMember . '.user_type', $this->createNamedParameter($member->getUserType())) |
||
659 | ); |
||
660 | } |
||
661 | |||
662 | $andX->add( |
||
663 | $expr->eq($aliasMember . '.instance', $this->createNamedParameter($this->getInstance($member))) |
||
664 | ); |
||
665 | |||
666 | if ($member->getLevel() > 0) { |
||
667 | $andX->add( |
||
668 | $expr->gte( |
||
669 | $aliasMember . '.level', |
||
670 | $this->createNamedParameter($member->getLevel(), IQueryBuilder::PARAM_INT) |
||
671 | ) |
||
672 | ); |
||
673 | } |
||
674 | |||
675 | $this->andWhere($andX); |
||
676 | } |
||
677 | |||
678 | |||
679 | /** |
||
680 | * @param string $alias |
||
681 | */ |
||
682 | public function countMembers(string $alias): void { |
||
683 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
684 | return; |
||
685 | } |
||
686 | |||
687 | try { |
||
688 | $aliasMemberCount = $this->generateAlias($alias, self::MEMBER_COUNT, $options); |
||
689 | } catch (RequestBuilderException $e) { |
||
690 | return; |
||
691 | } |
||
692 | |||
693 | $getData = $this->getBool('getData', $options, false); |
||
694 | if (!$getData) { |
||
695 | return; |
||
696 | } |
||
697 | |||
698 | $expr = $this->expr(); |
||
699 | $this->selectAlias( |
||
700 | $this->createFunction('COUNT(`' . $aliasMemberCount . '`.`member_id`)'), |
||
701 | (($alias !== $this->getDefaultSelectAlias()) ? $alias . '_' : '') . 'population' |
||
702 | ); |
||
703 | $this->leftJoin( |
||
704 | $alias, CoreRequestBuilder::TABLE_MEMBER, $aliasMemberCount, |
||
705 | $expr->eq($alias . '.unique_id', $aliasMemberCount . '.circle_id') |
||
706 | ); |
||
707 | } |
||
708 | |||
709 | |||
710 | /** |
||
711 | * @param string $alias |
||
712 | * @param IFederatedUser|null $initiator |
||
713 | * @param string $field |
||
714 | * @param string $helperAlias |
||
715 | * |
||
716 | * @throws RequestBuilderException |
||
717 | */ |
||
718 | public function leftJoinCircle( |
||
719 | string $alias, |
||
720 | ?IFederatedUser $initiator = null, |
||
721 | string $field = 'circle_id', |
||
722 | string $helperAlias = '' |
||
723 | ): void { |
||
724 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
725 | return; |
||
726 | } |
||
727 | |||
728 | $helperAlias = ($helperAlias !== '') ? $helperAlias : $alias; |
||
729 | $aliasCircle = $this->generateAlias($alias, self::CIRCLE, $options); |
||
730 | $getData = $this->getBool('getData', $options, false); |
||
731 | $expr = $this->expr(); |
||
732 | |||
733 | if ($getData) { |
||
734 | $this->generateCircleSelectAlias($aliasCircle); |
||
735 | } |
||
736 | |||
737 | $this->leftJoin( |
||
738 | $helperAlias, |
||
739 | CoreRequestBuilder::TABLE_CIRCLE, |
||
740 | $aliasCircle, |
||
741 | $expr->eq($aliasCircle . '.unique_id', $helperAlias . '.' . $field) |
||
742 | ); |
||
743 | |||
744 | if (!is_null($initiator)) { |
||
745 | $this->limitToInitiator($aliasCircle, $initiator); |
||
746 | } |
||
747 | |||
748 | $this->leftJoinOwner($aliasCircle); |
||
749 | } |
||
750 | |||
751 | |||
752 | /** |
||
753 | * @param string $aliasMember |
||
754 | * |
||
755 | * @throws RequestBuilderException |
||
756 | */ |
||
757 | public function leftJoinInvitedBy(string $aliasMember): void { |
||
758 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
759 | return; |
||
760 | } |
||
761 | |||
762 | try { |
||
763 | $aliasInvitedBy = $this->generateAlias($aliasMember, self::INVITED_BY); |
||
764 | } catch (RequestBuilderException $e) { |
||
765 | return; |
||
766 | } |
||
767 | |||
768 | $expr = $this->expr(); |
||
769 | $this->generateCircleSelectAlias($aliasInvitedBy) |
||
770 | ->leftJoin( |
||
771 | $aliasMember, CoreRequestBuilder::TABLE_CIRCLE, $aliasInvitedBy, |
||
772 | $expr->eq($aliasMember . '.invited_by', $aliasInvitedBy . '.unique_id') |
||
773 | ); |
||
774 | |||
775 | $this->leftJoinOwner($aliasInvitedBy); |
||
776 | } |
||
777 | |||
778 | |||
779 | /** |
||
780 | * @param string $aliasMember |
||
781 | * @param IFederatedUser|null $initiator |
||
782 | * |
||
783 | * @throws RequestBuilderException |
||
784 | */ |
||
785 | public function leftJoinBasedOn( |
||
786 | string $aliasMember, |
||
787 | ?IFederatedUser $initiator = null |
||
788 | ): void { |
||
789 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
790 | return; |
||
791 | } |
||
792 | |||
793 | try { |
||
794 | $aliasBasedOn = $this->generateAlias($aliasMember, self::BASED_ON, $options); |
||
795 | } catch (RequestBuilderException $e) { |
||
796 | return; |
||
797 | } |
||
798 | |||
799 | $expr = $this->expr(); |
||
800 | $this->generateCircleSelectAlias($aliasBasedOn) |
||
801 | ->leftJoin( |
||
802 | $aliasMember, CoreRequestBuilder::TABLE_CIRCLE, $aliasBasedOn, |
||
803 | $expr->eq($aliasBasedOn . '.unique_id', $aliasMember . '.single_id') |
||
804 | ); |
||
805 | |||
806 | if (!is_null($initiator)) { |
||
807 | $this->leftJoinInitiator($aliasBasedOn, $initiator); |
||
808 | $this->leftJoinOwner($aliasBasedOn); |
||
809 | } |
||
810 | } |
||
811 | |||
812 | |||
813 | /** |
||
814 | * @param string $alias |
||
815 | * @param string $field |
||
816 | * |
||
817 | * @throws RequestBuilderException |
||
818 | */ |
||
819 | public function leftJoinOwner(string $alias, string $field = 'unique_id'): void { |
||
820 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
821 | return; |
||
822 | } |
||
823 | |||
824 | try { |
||
825 | $aliasMember = $this->generateAlias($alias, self::OWNER, $options); |
||
826 | $getData = $this->getBool('getData', $options, false); |
||
827 | } catch (RequestBuilderException $e) { |
||
828 | return; |
||
829 | } |
||
830 | |||
831 | $expr = $this->expr(); |
||
832 | $this->generateMemberSelectAlias($aliasMember) |
||
833 | ->leftJoin( |
||
834 | $alias, CoreRequestBuilder::TABLE_MEMBER, $aliasMember, |
||
835 | $expr->andX( |
||
836 | $expr->eq($aliasMember . '.circle_id', $alias . '.' . $field), |
||
837 | $expr->eq( |
||
838 | $aliasMember . '.level', |
||
839 | $this->createNamedParameter(Member::LEVEL_OWNER, self::PARAM_INT) |
||
840 | ) |
||
841 | ) |
||
842 | ); |
||
843 | |||
844 | $this->leftJoinBasedOn($aliasMember); |
||
845 | } |
||
846 | |||
847 | |||
848 | /** |
||
849 | * @param string $alias |
||
850 | * @param string $fieldCircleId |
||
851 | * @param string $fieldSingleId |
||
852 | * |
||
853 | * @throws RequestBuilderException |
||
854 | */ |
||
855 | public function leftJoinMember( |
||
856 | string $alias, |
||
857 | string $fieldCircleId = 'circle_id', |
||
858 | string $fieldSingleId = 'single_id' |
||
859 | ): void { |
||
860 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
861 | return; |
||
862 | } |
||
863 | |||
864 | try { |
||
865 | $aliasMember = $this->generateAlias($alias, self::MEMBER, $options); |
||
866 | $getData = $this->getBool('getData', $options, false); |
||
867 | } catch (RequestBuilderException $e) { |
||
868 | return; |
||
869 | } |
||
870 | |||
871 | $expr = $this->expr(); |
||
872 | $this->generateMemberSelectAlias($aliasMember) |
||
873 | ->leftJoin( |
||
874 | $alias, CoreRequestBuilder::TABLE_MEMBER, $aliasMember, |
||
875 | $expr->andX( |
||
876 | $expr->eq($aliasMember . '.circle_id', $alias . '.' . $fieldCircleId), |
||
877 | $expr->eq($aliasMember . '.single_id', $alias . '.' . $fieldSingleId), |
||
878 | $expr->gte( |
||
879 | $aliasMember . '.level', |
||
880 | $this->createNamedParameter(Member::LEVEL_MEMBER, self::PARAM_INT) |
||
881 | ) |
||
882 | ) |
||
883 | ); |
||
884 | |||
885 | $this->leftJoinRemoteInstance($aliasMember); |
||
886 | $this->leftJoinBasedOn($aliasMember); |
||
887 | } |
||
888 | |||
889 | |||
890 | /** |
||
891 | * if 'getData' is true, will returns 'inheritanceBy': the Member at the end of a sub-chain of |
||
892 | * memberships (based on $field for Top Circle's singleId) |
||
893 | * |
||
894 | * @param string $alias |
||
895 | * @param string $field |
||
896 | * @param string $aliasInheritedBy |
||
897 | * |
||
898 | * @throws RequestBuilderException |
||
899 | */ |
||
900 | public function leftJoinInheritedMembers( |
||
901 | string $alias, |
||
902 | string $field = '', |
||
903 | string $aliasInheritedBy = '' |
||
904 | ): void { |
||
905 | $expr = $this->expr(); |
||
906 | |||
907 | $field = ($field === '') ? 'circle_id' : $field; |
||
908 | $aliasMembership = $this->generateAlias($alias, self::MEMBERSHIPS, $options); |
||
909 | |||
910 | $this->leftJoin( |
||
911 | $alias, CoreRequestBuilder::TABLE_MEMBERSHIP, $aliasMembership, |
||
912 | $expr->eq($aliasMembership . '.circle_id', $alias . '.' . $field) |
||
913 | ); |
||
914 | |||
915 | // if (!$this->getBool('getData', $options, false)) { |
||
916 | // return; |
||
917 | // } |
||
918 | |||
919 | if ($aliasInheritedBy === '') { |
||
920 | $aliasInheritedBy = $this->generateAlias($alias, self::INHERITED_BY); |
||
921 | } |
||
922 | $this->generateMemberSelectAlias($aliasInheritedBy) |
||
923 | ->leftJoin( |
||
924 | $alias, CoreRequestBuilder::TABLE_MEMBER, $aliasInheritedBy, |
||
925 | $expr->andX( |
||
926 | $expr->eq($aliasMembership . '.inheritance_last', $aliasInheritedBy . '.circle_id'), |
||
927 | $expr->eq($aliasMembership . '.single_id', $aliasInheritedBy . '.single_id') |
||
928 | ) |
||
929 | ); |
||
930 | |||
931 | $this->leftJoinBasedOn($aliasInheritedBy); |
||
932 | } |
||
933 | |||
934 | |||
935 | /** |
||
936 | * @throws RequestBuilderException |
||
937 | */ |
||
938 | public function limitToInheritedMemberships(string $alias, string $singleId, string $field = ''): void { |
||
939 | $expr = $this->expr(); |
||
940 | $field = ($field === '') ? 'circle_id' : $field; |
||
941 | $aliasUpstreamMembership = $this->generateAlias($alias, self::UPSTREAM_MEMBERSHIPS, $options); |
||
942 | $this->leftJoin( |
||
943 | $alias, CoreRequestBuilder::TABLE_MEMBERSHIP, $aliasUpstreamMembership, |
||
944 | $expr->eq($aliasUpstreamMembership . '.single_id', $this->createNamedParameter($singleId)) |
||
945 | ); |
||
946 | |||
947 | $orX = $expr->orX( |
||
948 | $expr->eq($aliasUpstreamMembership . '.circle_id', $alias . '.' . $field), |
||
949 | $expr->eq($alias . '.' . $field, $this->createNamedParameter($singleId)) |
||
950 | ); |
||
951 | |||
952 | $this->andWhere($orX); |
||
953 | } |
||
954 | |||
955 | |||
956 | /** |
||
957 | * limit the request to Members and Sub Members of a Circle. |
||
958 | * |
||
959 | * @param string $alias |
||
960 | * @param string $singleId |
||
961 | * @param int $level |
||
962 | * |
||
963 | * @throws RequestBuilderException |
||
964 | */ |
||
965 | public function limitToMembersByInheritance(string $alias, string $singleId, int $level = 0): void { |
||
966 | $this->leftJoinMembersByInheritance($alias); |
||
967 | |||
968 | $expr = $this->expr(); |
||
969 | $aliasMembership = $this->generateAlias($alias, self::MEMBERSHIPS); |
||
970 | $this->andWhere($expr->eq($aliasMembership . '.circle_id', $this->createNamedParameter($singleId))); |
||
971 | if ($level > 1) { |
||
972 | $this->andWhere( |
||
973 | $expr->gte( |
||
974 | $aliasMembership . '.level', |
||
975 | $this->createNamedParameter($level, IQueryBuilder::PARAM_INT) |
||
976 | ) |
||
977 | ); |
||
978 | } |
||
979 | } |
||
980 | |||
981 | |||
982 | /** |
||
983 | * if 'getData' is true, will returns 'inheritanceFrom': the Circle-As-Member of the Top Circle |
||
984 | * that explain the membership of a Member (based on $field for singleId) to a specific Circle |
||
985 | * |
||
986 | * // TODO: returns the link/path ? |
||
987 | * |
||
988 | * @param string $alias |
||
989 | * @param string $field |
||
990 | * |
||
991 | * @throws RequestBuilderException |
||
992 | */ |
||
993 | public function leftJoinMembersByInheritance(string $alias, string $field = ''): void { |
||
994 | $expr = $this->expr(); |
||
995 | |||
996 | $field = ($field === '') ? 'circle_id' : $field; |
||
997 | $aliasMembership = $this->generateAlias($alias, self::MEMBERSHIPS, $options); |
||
998 | |||
999 | $this->leftJoin( |
||
1000 | $alias, CoreRequestBuilder::TABLE_MEMBERSHIP, $aliasMembership, |
||
1001 | $expr->andX( |
||
1002 | $expr->eq($aliasMembership . '.inheritance_last', $alias . '.' . $field), |
||
1003 | $expr->eq($aliasMembership . '.single_id', $alias . '.single_id') |
||
1004 | ) |
||
1005 | ); |
||
1006 | |||
1007 | if (!$this->getBool('getData', $options, false)) { |
||
1008 | return; |
||
1009 | } |
||
1010 | |||
1011 | $aliasInheritanceFrom = $this->generateAlias($alias, self::INHERITANCE_FROM); |
||
1012 | $this->generateMemberSelectAlias($aliasInheritanceFrom) |
||
1013 | ->leftJoin( |
||
1014 | $aliasMembership, CoreRequestBuilder::TABLE_MEMBER, $aliasInheritanceFrom, |
||
1015 | $expr->andX( |
||
1016 | $expr->eq($aliasMembership . '.circle_id', $aliasInheritanceFrom . '.circle_id'), |
||
1017 | $expr->eq($aliasMembership . '.inheritance_first', $aliasInheritanceFrom . '.single_id') |
||
1018 | ) |
||
1019 | ); |
||
1020 | } |
||
1021 | |||
1022 | |||
1023 | /** |
||
1024 | * limit the result to the point of view of a FederatedUser |
||
1025 | * |
||
1026 | * @param string $alias |
||
1027 | * @param IFederatedUser $user |
||
1028 | * @param string $field |
||
1029 | * @param string $helperAlias |
||
1030 | * |
||
1031 | * @return ICompositeExpression |
||
1032 | * @throws RequestBuilderException |
||
1033 | */ |
||
1034 | public function limitToInitiator( |
||
1035 | string $alias, |
||
1036 | IFederatedUser $user, |
||
1037 | string $field = '', |
||
1038 | string $helperAlias = '' |
||
1039 | ): ICompositeExpression { |
||
1040 | $this->leftJoinInitiator($alias, $user, $field, $helperAlias); |
||
1041 | $where = $this->limitInitiatorVisibility($alias); |
||
1042 | |||
1043 | $aliasInitiator = $this->generateAlias($alias, self::INITIATOR, $options); |
||
1044 | if ($this->getBool('getData', $options, false)) { |
||
1045 | $this->leftJoinBasedOn($aliasInitiator); |
||
1046 | } |
||
1047 | |||
1048 | return $where; |
||
1049 | } |
||
1050 | |||
1051 | |||
1052 | /** |
||
1053 | * Left join members to filter userId as initiator. |
||
1054 | * |
||
1055 | * @param string $alias |
||
1056 | * @param IFederatedUser $initiator |
||
1057 | * @param string $field |
||
1058 | * @param string $helperAlias |
||
1059 | * |
||
1060 | * @throws RequestBuilderException |
||
1061 | */ |
||
1062 | public function leftJoinInitiator( |
||
1063 | string $alias, |
||
1064 | IFederatedUser $initiator, |
||
1065 | string $field = '', |
||
1066 | string $helperAlias = '' |
||
1067 | ): void { |
||
1068 | if ($this->getType() !== QueryBuilder::SELECT) { |
||
1069 | return; |
||
1070 | } |
||
1071 | |||
1072 | $expr = $this->expr(); |
||
1073 | $field = ($field === '') ? 'unique_id' : $field; |
||
1074 | $helperAlias = ($helperAlias !== '') ? $helperAlias : $alias; |
||
1075 | $aliasMembership = $this->generateAlias($alias, self::MEMBERSHIPS, $options); |
||
1076 | |||
1077 | $this->leftJoin( |
||
1078 | $helperAlias, |
||
1079 | CoreRequestBuilder::TABLE_MEMBERSHIP, |
||
1080 | $aliasMembership, |
||
1081 | $expr->andX( |
||
1082 | $this->exprLimit('single_id', $initiator->getSingleId(), $aliasMembership), |
||
1083 | $expr->eq($aliasMembership . '.circle_id', $helperAlias . '.' . $field) |
||
1084 | ) |
||
1085 | ); |
||
1086 | |||
1087 | if (!$this->getBool('getData', $options, false)) { |
||
1088 | return; |
||
1089 | } |
||
1090 | |||
1091 | try { |
||
1092 | $aliasInitiator = $this->generateAlias($alias, self::INITIATOR, $options); |
||
1093 | $this->leftJoin( |
||
1094 | $aliasMembership, CoreRequestBuilder::TABLE_MEMBER, $aliasInitiator, |
||
1095 | $expr->andX( |
||
1096 | $expr->eq($aliasMembership . '.inheritance_first', $aliasInitiator . '.single_id'), |
||
1097 | $expr->eq($aliasMembership . '.circle_id', $aliasInitiator . '.circle_id') |
||
1098 | ) |
||
1099 | ); |
||
1100 | |||
1101 | $aliasInheritedBy = $this->generateAlias($aliasInitiator, self::INHERITED_BY); |
||
1102 | $this->leftJoin( |
||
1103 | $aliasInitiator, CoreRequestBuilder::TABLE_MEMBER, $aliasInheritedBy, |
||
1104 | $expr->andX( |
||
1105 | $expr->eq($aliasMembership . '.single_id', $aliasInheritedBy . '.single_id'), |
||
1106 | $expr->eq($aliasMembership . '.inheritance_last', $aliasInheritedBy . '.circle_id') |
||
1107 | ) |
||
1108 | ); |
||
1109 | |||
1110 | $default = []; |
||
1111 | if ($this->getBool('canBeVisitor', $options, false)) { |
||
1112 | $default = [ |
||
1113 | 'user_id' => $initiator->getUserId(), |
||
1114 | 'single_id' => $initiator->getSingleId(), |
||
1115 | 'user_type' => $initiator->getUserType(), |
||
1116 | 'cached_name' => $initiator->getDisplayName(), |
||
1117 | 'instance' => $initiator->getInstance() |
||
1118 | ]; |
||
1119 | } |
||
1120 | $this->generateMemberSelectAlias($aliasInitiator, $default); |
||
1121 | |||
1122 | $this->generateMemberSelectAlias($aliasInheritedBy); |
||
1123 | $aliasInheritedByMembership = $this->generateAlias($aliasInheritedBy, self::MEMBERSHIPS); |
||
1124 | $this->generateMembershipSelectAlias($aliasMembership, $aliasInheritedByMembership); |
||
1125 | } catch (RequestBuilderException $e) { |
||
1126 | } |
||
1127 | } |
||
1128 | |||
1129 | |||
1130 | /** |
||
1131 | * @param string $alias |
||
1132 | * |
||
1133 | * @return ICompositeExpression |
||
1134 | * @throws RequestBuilderException |
||
1135 | */ |
||
1136 | protected function limitInitiatorVisibility(string $alias): ICompositeExpression { |
||
1137 | $aliasMembership = $this->generateAlias($alias, self::MEMBERSHIPS, $options); |
||
1138 | $getPersonalCircle = $this->getBool('getPersonalCircle', $options, false); |
||
1139 | |||
1140 | $expr = $this->expr(); |
||
1141 | |||
1142 | // Visibility to non-member is |
||
1143 | // - 0 (default), if initiator is member |
||
1144 | // - 2 (Personal), if initiator is owner) |
||
1145 | // - 4 (Visible to everyone) |
||
1146 | $orX = $expr->orX(); |
||
1147 | $orX->add( |
||
1148 | $expr->andX( |
||
1149 | $expr->gte($aliasMembership . '.level', $this->createNamedParameter(Member::LEVEL_MEMBER)) |
||
1150 | $this->exprFilterBitwise('config', Circle::CFG_PERSONAL, $alias) |
||
|
|||
1151 | ) |
||
1152 | ); |
||
1153 | |||
1154 | if ($getPersonalCircle) { |
||
1155 | $orX->add( |
||
1156 | $expr->andX( |
||
1157 | $this->exprLimitBitwise('config', Circle::CFG_PERSONAL, $alias), |
||
1158 | $expr->eq($aliasMembership . '.level', $this->createNamedParameter(Member::LEVEL_OWNER)) |
||
1159 | ) |
||
1160 | ); |
||
1161 | } |
||
1162 | if (!$this->getBool('mustBeMember', $options, true)) { |
||
1163 | $orX->add($this->exprLimitBitwise('config', Circle::CFG_VISIBLE, $alias)); |
||
1164 | } |
||
1165 | if ($this->getBool('canBeVisitor', $options, false)) { |
||
1166 | // TODO: should find a better way, also filter on remote initiator on non-federated ? |
||
1167 | $orX->add($expr->gte($alias . '.config', $this->createNamedParameter(0))); |
||
1168 | } |
||
1169 | if ($this->getBool('canBeVisitorOnOpen', $options, false)) { |
||
1170 | $andOpen = $expr->andX(); |
||
1171 | $andOpen->add($this->exprLimitBitwise('config', Circle::CFG_OPEN, $alias)); |
||
1172 | $andOpen->add($this->exprFilterBitwise('config', Circle::CFG_REQUEST, $alias)); |
||
1173 | $orX->add($andOpen); |
||
1174 | } |
||
1175 | |||
1176 | $this->andWhere($orX); |
||
1177 | |||
1178 | return $orX; |
||
1179 | // $orTypes = $this->generateLimit($qb, $circleUniqueId, $userId, $type, $name, $forceAll); |
||
1180 | // if (sizeof($orTypes) === 0) { |
||
1181 | // throw new ConfigNoCircleAvailableException( |
||
1182 | // $this->l10n->t( |
||
1183 | // 'You cannot use the Circles Application until your administrator has allowed at least one type of circles' |
||
1184 | // ) |
||
1185 | // ); |
||
1186 | // } |
||
1187 | |||
1188 | // $orXTypes = $this->expr() |
||
1189 | // ->orX(); |
||
1190 | // foreach ($orTypes as $orType) { |
||
1191 | // $orXTypes->add($orType); |
||
1192 | // } |
||
1193 | // |
||
1194 | // $qb->andWhere($orXTypes); |
||
1195 | } |
||
1196 | |||
1197 | |||
1198 | /** |
||
1199 | * CFG_SINGLE, CFG_HIDDEN and CFG_BACKEND means hidden from listing. |
||
1200 | * |
||
1201 | * @param string $aliasCircle |
||
1202 | * @param int $flag |
||
1203 | */ |
||
1204 | public function filterCircles( |
||
1205 | string $aliasCircle, |
||
1206 | int $flag = Circle::CFG_SINGLE | Circle::CFG_HIDDEN | Circle::CFG_BACKEND |
||
1207 | ): void { |
||
1208 | if ($flag === 0) { |
||
1209 | return; |
||
1210 | } |
||
1211 | |||
1212 | $expr = $this->expr(); |
||
1213 | $hide = $expr->andX(); |
||
1214 | foreach (Circle::$DEF_CFG as $cfg => $v) { |
||
1215 | if ($flag & $cfg) { |
||
1216 | $hide->add($this->exprFilterBitwise('config', $cfg, $aliasCircle)); |
||
1217 | } |
||
1218 | } |
||
1219 | |||
1220 | $this->andWhere($hide); |
||
1221 | } |
||
1222 | |||
1223 | |||
1224 | /** |
||
1225 | * Limit visibility on Sensitive information when search for members. |
||
1226 | * |
||
1227 | * @param string $alias |
||
1228 | * |
||
1229 | * @return ICompositeExpression |
||
1230 | */ |
||
1231 | private function limitRemoteVisibility_Sensitive_Members(string $alias): ICompositeExpression { |
||
1232 | $expr = $this->expr(); |
||
1233 | $andPassive = $expr->andX(); |
||
1234 | $andPassive->add( |
||
1235 | $expr->eq($alias . '.type', $this->createNamedParameter(RemoteInstance::TYPE_PASSIVE)) |
||
1236 | ); |
||
1237 | |||
1238 | $orMemberOrLevel = $expr->orX(); |
||
1239 | $orMemberOrLevel->add( |
||
1240 | $expr->eq($this->getDefaultSelectAlias() . '.instance', $alias . '.instance') |
||
1241 | ); |
||
1242 | // TODO: do we need this ? (display members from the local instance) |
||
1243 | $orMemberOrLevel->add( |
||
1244 | $expr->emptyString($this->getDefaultSelectAlias() . '.instance') |
||
1245 | ); |
||
1246 | |||
1247 | $orMemberOrLevel->add( |
||
1248 | $expr->eq( |
||
1249 | $this->getDefaultSelectAlias() . '.level', |
||
1250 | $this->createNamedParameter(Member::LEVEL_OWNER) |
||
1251 | ) |
||
1252 | ); |
||
1253 | $andPassive->add($orMemberOrLevel); |
||
1254 | |||
1255 | return $andPassive; |
||
1256 | } |
||
1257 | |||
1258 | |||
1259 | /** |
||
1260 | * Link to storage/filecache |
||
1261 | * |
||
1262 | * @param string $aliasShare |
||
1263 | * |
||
1264 | * @throws RequestBuilderException |
||
1265 | */ |
||
1266 | public function leftJoinFileCache(string $aliasShare) { |
||
1267 | $expr = $this->expr(); |
||
1268 | |||
1269 | $aliasFileCache = $this->generateAlias($aliasShare, self::FILE_CACHE); |
||
1270 | $aliasStorages = $this->generateAlias($aliasFileCache, self::STORAGES); |
||
1271 | |||
1272 | $this->generateSelectAlias( |
||
1273 | CoreRequestBuilder::$outsideTables[CoreRequestBuilder::TABLE_FILE_CACHE], |
||
1274 | $aliasFileCache, |
||
1275 | $aliasFileCache, |
||
1276 | [] |
||
1277 | ) |
||
1278 | ->generateSelectAlias( |
||
1279 | CoreRequestBuilder::$outsideTables[CoreRequestBuilder::TABLE_STORAGES], |
||
1280 | $aliasStorages, |
||
1281 | $aliasStorages, |
||
1282 | [] |
||
1283 | ) |
||
1284 | ->leftJoin( |
||
1285 | $aliasShare, CoreRequestBuilder::TABLE_FILE_CACHE, $aliasFileCache, |
||
1286 | $expr->eq($aliasShare . '.file_source', $aliasFileCache . '.fileid') |
||
1287 | ) |
||
1288 | ->leftJoin( |
||
1289 | $aliasFileCache, CoreRequestBuilder::TABLE_STORAGES, $aliasStorages, |
||
1290 | $expr->eq($aliasFileCache . '.storage', $aliasStorages . '.numeric_id') |
||
1291 | ); |
||
1292 | } |
||
1293 | |||
1294 | |||
1295 | /** |
||
1296 | * @param string $aliasShare |
||
1297 | * @param string $aliasShareMemberships |
||
1298 | * |
||
1299 | * @throws RequestBuilderException |
||
1300 | */ |
||
1301 | public function leftJoinShareChild(string $aliasShare, string $aliasShareMemberships = '') { |
||
1302 | $expr = $this->expr(); |
||
1303 | |||
1304 | $aliasShareChild = $this->generateAlias($aliasShare, self::SHARE); |
||
1305 | if ($aliasShareMemberships === '') { |
||
1306 | $aliasShareMemberships = $this->generateAlias($aliasShare, self::MEMBERSHIPS, $options); |
||
1307 | } |
||
1308 | |||
1309 | $this->leftJoin( |
||
1310 | $aliasShareMemberships, CoreRequestBuilder::TABLE_SHARE, $aliasShareChild, |
||
1311 | $expr->andX( |
||
1312 | $expr->eq($aliasShareChild . '.parent', $aliasShare . '.id'), |
||
1313 | $expr->eq($aliasShareChild . '.share_with', $aliasShareMemberships . '.single_id') |
||
1314 | ) |
||
1315 | ); |
||
1316 | |||
1317 | $this->generateSelectAlias( |
||
1318 | ['id', 'file_target', 'permissions'], |
||
1319 | $aliasShareChild, |
||
1320 | 'child_', |
||
1321 | [] |
||
1322 | ); |
||
1323 | |||
1324 | // $this->selectAlias($aliasShareParent . '.permissions', 'parent_perms'); |
||
1325 | } |
||
1326 | |||
1327 | |||
1328 | /** |
||
1329 | * @param string $alias |
||
1330 | * @param FederatedUser $federatedUser |
||
1331 | * @param bool $reshares |
||
1332 | */ |
||
1333 | public function limitToShareOwner(string $alias, FederatedUser $federatedUser, bool $reshares): void { |
||
1334 | $expr = $this->expr(); |
||
1335 | |||
1336 | $orX = $expr->orX($this->exprLimit('uid_initiator', $federatedUser->getUserId(), $alias)); |
||
1337 | |||
1338 | if ($reshares) { |
||
1339 | $orX->add($this->exprLimit('uid_owner', $federatedUser->getUserId(), $alias)); |
||
1340 | } |
||
1341 | |||
1342 | $this->andWhere($orX); |
||
1343 | } |
||
1344 | |||
1345 | |||
1346 | /** |
||
1347 | * @param string $aliasMount |
||
1348 | * @param string $aliasMountMemberships |
||
1349 | * |
||
1350 | * @throws RequestBuilderException |
||
1351 | */ |
||
1352 | public function leftJoinMountpoint(string $aliasMount, string $aliasMountMemberships = '') { |
||
1353 | $expr = $this->expr(); |
||
1354 | |||
1355 | $aliasMountpoint = $this->generateAlias($aliasMount, self::MOUNTPOINT); |
||
1356 | if ($aliasMountMemberships === '') { |
||
1357 | $aliasMountMemberships = $this->generateAlias($aliasMount, self::MEMBERSHIPS, $options); |
||
1358 | } |
||
1359 | |||
1360 | $this->leftJoin( |
||
1361 | $aliasMountMemberships, CoreRequestBuilder::TABLE_MOUNTPOINT, $aliasMountpoint, |
||
1362 | $expr->andX( |
||
1363 | $expr->eq($aliasMountpoint . '.mount_id', $aliasMount . '.mount_id'), |
||
1364 | $expr->eq($aliasMountpoint . '.single_id', $aliasMountMemberships . '.single_id') |
||
1365 | ) |
||
1366 | ); |
||
1367 | |||
1368 | $this->selectAlias($aliasMountpoint . '.mountpoint', $aliasMountpoint . '_mountpoint'); |
||
1369 | $this->selectAlias($aliasMountpoint . '.mountpoint_hash', $aliasMountpoint . '_mountpoint_hash'); |
||
1370 | } |
||
1371 | |||
1372 | |||
1373 | /** |
||
1374 | * @param string $alias |
||
1375 | * @param array $default |
||
1376 | * |
||
1377 | * @return CoreQueryBuilder |
||
1378 | */ |
||
1379 | private function generateCircleSelectAlias(string $alias, array $default = []): self { |
||
1380 | $this->generateSelectAlias( |
||
1381 | CoreRequestBuilder::$tables[CoreRequestBuilder::TABLE_CIRCLE], |
||
1382 | $alias, |
||
1383 | $alias, |
||
1384 | $default |
||
1385 | ); |
||
1386 | |||
1387 | return $this; |
||
1388 | } |
||
1389 | |||
1390 | /** |
||
1391 | * @param string $alias |
||
1392 | * @param array $default |
||
1393 | * |
||
1394 | * @return $this |
||
1395 | */ |
||
1396 | private function generateMemberSelectAlias(string $alias, array $default = []): self { |
||
1397 | $this->generateSelectAlias( |
||
1398 | CoreRequestBuilder::$tables[CoreRequestBuilder::TABLE_MEMBER], |
||
1399 | $alias, |
||
1400 | $alias, |
||
1401 | $default |
||
1402 | ); |
||
1403 | |||
1404 | return $this; |
||
1405 | } |
||
1406 | |||
1407 | |||
1408 | /** |
||
1409 | * @param string $alias |
||
1410 | * @param array $default |
||
1411 | * @param string $prefix |
||
1412 | * |
||
1413 | * @return $this |
||
1414 | */ |
||
1415 | private function generateMembershipSelectAlias( |
||
1416 | string $alias, |
||
1417 | string $prefix = '', |
||
1418 | array $default = [] |
||
1419 | ): self { |
||
1420 | $this->generateSelectAlias( |
||
1421 | CoreRequestBuilder::$tables[CoreRequestBuilder::TABLE_MEMBERSHIP], |
||
1422 | $alias, |
||
1423 | ($prefix === '') ? $alias : $prefix, |
||
1424 | $default |
||
1425 | ); |
||
1426 | |||
1427 | return $this; |
||
1428 | } |
||
1429 | |||
1430 | |||
1431 | /** |
||
1432 | * @param string $alias |
||
1433 | * @param array $default |
||
1434 | * |
||
1435 | * @return $this |
||
1436 | */ |
||
1437 | private function generateRemoteInstanceSelectAlias(string $alias, array $default = []): self { |
||
1438 | $this->generateSelectAlias( |
||
1439 | CoreRequestBuilder::$tables[CoreRequestBuilder::TABLE_REMOTE], |
||
1440 | $alias, |
||
1441 | $alias, |
||
1442 | $default |
||
1443 | ); |
||
1444 | |||
1445 | return $this; |
||
1446 | } |
||
1447 | |||
1448 | |||
1449 | /** |
||
1450 | * @param array $path |
||
1451 | * @param array $options |
||
1452 | */ |
||
1453 | public function setOptions(array $path, array $options): void { |
||
1454 | $options = [self::OPTIONS => $options]; |
||
1455 | foreach (array_reverse($path) as $item) { |
||
1456 | $options = [$item => $options]; |
||
1457 | } |
||
1458 | |||
1459 | $this->options = $options; |
||
1460 | } |
||
1461 | |||
1462 | |||
1463 | /** |
||
1464 | * @param string $base |
||
1465 | * @param string $extension |
||
1466 | * @param array|null $options |
||
1467 | * |
||
1468 | * @return string |
||
1469 | * @throws RequestBuilderException |
||
1470 | */ |
||
1471 | public function generateAlias(string $base, string $extension, ?array &$options = []): string { |
||
1472 | $search = str_replace('_', '.', $base); |
||
1473 | $path = $search . '.' . $extension; |
||
1474 | if (!$this->validKey($path, self::$SQL_PATH) |
||
1475 | && !in_array($extension, $this->getArray($search, self::$SQL_PATH))) { |
||
1476 | throw new RequestBuilderException($extension . ' not found in ' . $search); |
||
1477 | } |
||
1478 | |||
1479 | if (!is_array($options)) { |
||
1480 | $options = []; |
||
1481 | } |
||
1482 | |||
1483 | $optionPath = ''; |
||
1484 | foreach (explode('.', $path) as $p) { |
||
1485 | $optionPath = trim($optionPath . '.' . $p, '.'); |
||
1486 | $options = array_merge( |
||
1487 | $options, |
||
1488 | $this->getArray($optionPath . '.' . self::OPTIONS, self::$SQL_PATH), |
||
1489 | $this->getArray($optionPath . '.' . self::OPTIONS, $this->options) |
||
1490 | ); |
||
1491 | } |
||
1492 | |||
1493 | return $base . '_' . $extension; |
||
1494 | } |
||
1495 | |||
1496 | |||
1497 | /** |
||
1498 | * @param string $prefix |
||
1499 | * |
||
1500 | * @return array |
||
1501 | */ |
||
1502 | public function getAvailablePath(string $prefix): array { |
||
1503 | $prefix = trim($prefix, '_'); |
||
1504 | $search = str_replace('_', '.', $prefix); |
||
1505 | |||
1506 | $path = []; |
||
1507 | foreach ($this->getArray($search, self::$SQL_PATH) as $arr => $item) { |
||
1508 | if (is_numeric($arr)) { |
||
1509 | $k = $item; |
||
1510 | } else { |
||
1511 | $k = $arr; |
||
1512 | } |
||
1513 | $path[$k] = $prefix . '_' . $k . '_'; |
||
1514 | } |
||
1515 | |||
1516 | return $path; |
||
1517 | } |
||
1518 | |||
1519 | } |
||
1520 | |||
1521 |