ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
DatabaseSearcherTest.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
23use PHPUnit\Framework\TestCase;
46
47class DatabaseSearcherTest extends TestCase
48{
49 protected const array RESULT = [
50 ['rbac_id' => 37, 'obj_id' => 55, 'obj_type' => 'type1'],
51 ['rbac_id' => 123, 'obj_id' => 85, 'obj_type' => 'type2'],
52 ['rbac_id' => 98, 'obj_id' => 4, 'obj_type' => 'type3']
53 ];
54
56 array $array,
57 RessourceIDInterface ...$ressource_ids
58 ): bool {
59 $data = [];
60 foreach ($ressource_ids as $ressource_id) {
61 $data[] = [
62 'rbac_id' => $ressource_id->obj_id,
63 'obj_id' => $ressource_id->sub_id,
64 'obj_type' => $ressource_id->type
65 ];
66 }
67
68 return $array === $data;
69 }
70
71 protected function getDatabaseSearcher(array $db_result): DatabaseSearcher
72 {
73 $ressource_factory = new class () extends NullRessourceIDFactory {
74 public function ressourceID(int $obj_id, int $sub_id, string $type): RessourceIDInterface
75 {
76 return new class ($obj_id, $sub_id, $type) extends NullRessourceID {
77 public function __construct(
78 public int $obj_id,
79 public int $sub_id,
80 public string $type
81 ) {
82 }
83 };
84 }
85 };
86
87 $paths_parser_factory = new class () extends NullDatabasePathsParserFactory {
88 public function forSearch(): DatabasePathsParserInterface
89 {
90 return new class () extends NullDatabasePathsParser {
91 protected array $paths = [];
92 protected bool $force_join_to_base_table = false;
93
94 public function addPathAndGetColumn(
96 bool $force_join_to_base_table
97 ): string {
98 if (!$this->force_join_to_base_table) {
99 $this->force_join_to_base_table = $force_join_to_base_table;
100 }
101 $path_string = $path->toString();
102 $this->paths[] = $path_string;
103 return $path_string . '_column';
104 }
105
106 public function getSelectForQuery(): string
107 {
108 if (empty($this->paths)) {
109 throw new \ilMDRepositoryException('no paths!');
110 }
111 return 'selected paths' . ($this->force_join_to_base_table ? ' (join forced)' : '') .
112 ':[' . implode('~', $this->paths) . ']';
113 }
114
115 public function getTableAliasForFilters(): string
116 {
117 if (empty($this->paths)) {
118 throw new \ilMDRepositoryException('no paths!');
119 }
120 return 'base_table';
121 }
122 };
123 }
124 };
125
126 return new class (
127 $ressource_factory,
128 $paths_parser_factory,
129 $db_result
130 ) extends DatabaseSearcher {
131 public string $exposed_last_query;
132
133 public function __construct(
134 RessourceIDFactoryInterface $ressource_factory,
135 DatabasePathsParserFactoryInterface $paths_parser_factory,
136 protected array $db_result
137 ) {
138 $this->ressource_factory = $ressource_factory;
139 $this->paths_parser_factory = $paths_parser_factory;
140 }
141
142 protected function queryDB(string $query): \Generator
143 {
144 $this->exposed_last_query = $query;
145 yield from $this->db_result;
146 }
147
148 protected function quoteIdentifier(string $identifier): string
149 {
150 return '~identifier:' . $identifier . '~';
151 }
152
153 protected function quoteText(string $text): string
154 {
155 return '~text:' . $text . '~';
156 }
157
158 protected function quoteInteger(int $integer): string
159 {
160 return '~int:' . $integer . '~';
161 }
162 };
163 }
164
165 protected function getBasicClause(
166 bool $negated,
167 string $path,
168 Mode $mode,
169 string $value,
170 bool $mode_negated
171 ): ClauseInterface {
172 return new class ($negated, $path, $mode, $value, $mode_negated) extends NullClause {
173 public function __construct(
174 protected bool $negated,
175 protected string $path,
176 protected Mode $mode,
177 protected string $value,
178 protected bool $mode_negated
179 ) {
180 }
181
182 public function isNegated(): bool
183 {
184 return $this->negated;
185 }
186
187 public function isJoin(): bool
188 {
189 return false;
190 }
191
192 public function basicProperties(): ?BasicPropertiesInterface
193 {
194 return new class (
196 $this->mode,
197 $this->value,
198 $this->mode_negated
199 ) extends NullBasicProperties {
200 public function __construct(
201 protected string $path,
202 protected Mode $mode,
203 protected string $value,
204 protected bool $mode_negated
205 ) {
206 }
207
208 public function path(): PathInterface
209 {
210 return new class ($this->path) extends NullPath {
211 public function __construct(protected string $path)
212 {
213 }
214
215 public function toString(): string
216 {
217 return $this->path;
218 }
219 };
220 }
221
222 public function isModeNegated(): bool
223 {
224 return $this->mode_negated;
225 }
226
227 public function mode(): Mode
228 {
229 return $this->mode;
230 }
231
232 public function value(): string
233 {
234 return $this->value;
235 }
236 };
237 }
238
239 public function joinProperties(): ?JoinPropertiesInterface
240 {
241 return null;
242 }
243 };
244 }
245
246 protected function getJoinedClause(
247 bool $negated,
248 Operator $operator,
249 ClauseInterface ...$clauses
250 ): ClauseInterface {
251 return new class ($negated, $operator, $clauses) extends NullClause {
252 public function __construct(
253 protected bool $negated,
254 protected Operator $operator,
255 protected array $clauses
256 ) {
257 }
258
259 public function isNegated(): bool
260 {
261 return $this->negated;
262 }
263
264 public function isJoin(): bool
265 {
266 return true;
267 }
268
269 public function basicProperties(): ?BasicPropertiesInterface
270 {
271 return null;
272 }
273
274 public function joinProperties(): ?JoinPropertiesInterface
275 {
276 return new class ($this->operator, $this->clauses) extends NullJoinProperties {
277 public function __construct(
278 protected Operator $operator,
279 protected array $clauses
280 ) {
281 }
282
283 public function operator(): Operator
284 {
285 return $this->operator;
286 }
287
288 public function subClauses(): \Generator
289 {
290 yield from $this->clauses;
291 }
292 };
293 }
294 };
295 }
296
297 protected function getFilter(
298 int|Placeholder $obj_id,
299 int|Placeholder $sub_id,
300 string|Placeholder $type
301 ): FilterInterface {
302 return new class ($obj_id, $sub_id, $type) extends NullFilter {
303 public function __construct(
304 protected int|Placeholder $obj_id,
305 protected int|Placeholder $sub_id,
306 protected string|Placeholder $type
307 ) {
308 }
309
310 public function objID(): int|Placeholder
311 {
312 return $this->obj_id;
313 }
314
315 public function subID(): int|Placeholder
316 {
317 return $this->sub_id;
318 }
319
320 public function type(): string|Placeholder
321 {
322 return $this->type;
323 }
324 };
325 }
326
327 public function testSearchWithNoResults(): void
328 {
329 $searcher = $this->getDatabaseSearcher([]);
330 $clause = $this->getBasicClause(
331 false,
332 'path',
333 Mode::EQUALS,
334 'value',
335 false
336 );
337
338 $result = $searcher->search($clause, null, null);
339 $this->assertNull($result->current());
340 }
341
342 public function testSearchWithResults(): void
343 {
344 $searcher = $this->getDatabaseSearcher(self::RESULT);
345 $clause = $this->getBasicClause(
346 false,
347 'path',
348 Mode::EQUALS,
349 'value',
350 false
351 );
352
353 $result = $searcher->search($clause, null, null);
354 $this->assertTrue(
355 $this->mockRessourceIDsMatchArrayData(self::RESULT, ...$result)
356 );
357 }
358
360 {
361 $searcher = $this->getDatabaseSearcher(self::RESULT);
362 $clause = $this->getBasicClause(
363 false,
364 'path',
365 Mode::EQUALS,
366 'value',
367 false
368 );
369
370 $result = iterator_to_array($searcher->search($clause, null, null));
371 $this->assertSame(
372 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
373 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
374 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
375 'ORDER BY rbac_id, obj_id, obj_type',
376 $searcher->exposed_last_query
377 );
378 }
379
381 {
382 $searcher = $this->getDatabaseSearcher(self::RESULT);
383 $clause = $this->getBasicClause(
384 false,
385 'path',
386 Mode::CONTAINS,
387 'value',
388 false
389 );
390
391 $result = iterator_to_array($searcher->search($clause, null, null));
392 $this->assertSame(
393 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
394 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
395 'HAVING COUNT(CASE WHEN path_column LIKE ~text:%value%~ THEN 1 END) > 0 ' .
396 'ORDER BY rbac_id, obj_id, obj_type',
397 $searcher->exposed_last_query
398 );
399 }
400
402 {
403 $searcher = $this->getDatabaseSearcher(self::RESULT);
404 $clause = $this->getBasicClause(
405 false,
406 'path',
407 Mode::STARTS_WITH,
408 'value',
409 false
410 );
411
412 $result = iterator_to_array($searcher->search($clause, null, null));
413 $this->assertSame(
414 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
415 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
416 'HAVING COUNT(CASE WHEN path_column LIKE ~text:value%~ THEN 1 END) > 0 ' .
417 'ORDER BY rbac_id, obj_id, obj_type',
418 $searcher->exposed_last_query
419 );
420 }
421
423 {
424 $searcher = $this->getDatabaseSearcher(self::RESULT);
425 $clause = $this->getBasicClause(
426 false,
427 'path',
429 'value',
430 false
431 );
432
433 $result = iterator_to_array($searcher->search($clause, null, null));
434 $this->assertSame(
435 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
436 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
437 'HAVING COUNT(CASE WHEN path_column LIKE ~text:%value~ THEN 1 END) > 0 ' .
438 'ORDER BY rbac_id, obj_id, obj_type',
439 $searcher->exposed_last_query
440 );
441 }
442
444 {
445 $searcher = $this->getDatabaseSearcher(self::RESULT);
446 $clause = $this->getBasicClause(
447 false,
448 'path',
449 Mode::EQUALS,
450 'value',
451 true
452 );
453
454 $result = iterator_to_array($searcher->search($clause, null, null));
455 $this->assertSame(
456 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
457 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
458 'HAVING COUNT(CASE WHEN NOT path_column = ~text:value~ THEN 1 END) > 0 ' .
459 'ORDER BY rbac_id, obj_id, obj_type',
460 $searcher->exposed_last_query
461 );
462 }
463
464 public function testSearchWithNegatedBasicClause(): void
465 {
466 $searcher = $this->getDatabaseSearcher(self::RESULT);
467 $clause = $this->getBasicClause(
468 true,
469 'path',
470 Mode::EQUALS,
471 'value',
472 false
473 );
474
475 $result = iterator_to_array($searcher->search($clause, null, null));
476 $this->assertSame(
477 'selected paths (join forced):[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
478 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
479 'HAVING NOT COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
480 'ORDER BY rbac_id, obj_id, obj_type',
481 $searcher->exposed_last_query
482 );
483 }
484
485
486
488 {
489 $searcher = $this->getDatabaseSearcher(self::RESULT);
490 $clause = $this->getBasicClause(
491 false,
492 'path',
493 Mode::EQUALS,
494 '',
495 false
496 );
497
498 $result = iterator_to_array($searcher->search($clause, null, null));
499 $this->assertSame(
500 'selected paths (join forced):[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
501 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
502 'HAVING COUNT(CASE WHEN path_column = ~text:~ THEN 1 END) > 0 ' .
503 'ORDER BY rbac_id, obj_id, obj_type',
504 $searcher->exposed_last_query
505 );
506 }
507
508 public function testSearchWithORJoinedClauses(): void
509 {
510 $searcher = $this->getDatabaseSearcher(self::RESULT);
511 $clause1 = $this->getBasicClause(
512 false,
513 'path1',
514 Mode::EQUALS,
515 'value1',
516 false
517 );
518 $clause2 = $this->getBasicClause(
519 false,
520 'path2',
521 Mode::STARTS_WITH,
522 'value2',
523 false
524 );
525 $joined_clause = $this->getJoinedClause(false, Operator::OR, $clause1, $clause2);
526
527 $result = iterator_to_array($searcher->search($joined_clause, null, null));
528 $this->assertSame(
529 'selected paths:[path1~path2] GROUP BY ~identifier:base_table~.rbac_id, ' .
530 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
531 'HAVING (COUNT(CASE WHEN path1_column = ~text:value1~ THEN 1 END) > 0 ' .
532 'OR COUNT(CASE WHEN path2_column LIKE ~text:value2%~ THEN 1 END) > 0) ' .
533 'ORDER BY rbac_id, obj_id, obj_type',
534 $searcher->exposed_last_query
535 );
536 }
537
538 public function testSearchWithANDJoinedClauses(): void
539 {
540 $searcher = $this->getDatabaseSearcher(self::RESULT);
541 $clause1 = $this->getBasicClause(
542 false,
543 'path1',
544 Mode::CONTAINS,
545 'value1',
546 false
547 );
548 $clause2 = $this->getBasicClause(
549 false,
550 'path2',
551 Mode::STARTS_WITH,
552 'value2',
553 false
554 );
555 $joined_clause = $this->getJoinedClause(false, Operator::AND, $clause1, $clause2);
556
557 $result = iterator_to_array($searcher->search($joined_clause, null, null));
558 $this->assertSame(
559 'selected paths:[path1~path2] GROUP BY ~identifier:base_table~.rbac_id, ' .
560 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
561 'HAVING (COUNT(CASE WHEN path1_column LIKE ~text:%value1%~ THEN 1 END) > 0 ' .
562 'AND COUNT(CASE WHEN path2_column LIKE ~text:value2%~ THEN 1 END) > 0) ' .
563 'ORDER BY rbac_id, obj_id, obj_type',
564 $searcher->exposed_last_query
565 );
566 }
567
568 public function testSearchWithNegatedJoinedClause(): void
569 {
570 $searcher = $this->getDatabaseSearcher(self::RESULT);
571 $clause1 = $this->getBasicClause(
572 false,
573 'path1',
574 Mode::CONTAINS,
575 'value1',
576 false
577 );
578 $clause2 = $this->getBasicClause(
579 false,
580 'path2',
581 Mode::EQUALS,
582 'value2',
583 false
584 );
585 $joined_clause = $this->getJoinedClause(true, Operator::AND, $clause1, $clause2);
586
587 $result = iterator_to_array($searcher->search($joined_clause, null, null));
588 $this->assertSame(
589 'selected paths:[path1~path2] GROUP BY ~identifier:base_table~.rbac_id, ' .
590 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
591 'HAVING NOT (COUNT(CASE WHEN path1_column LIKE ~text:%value1%~ THEN 1 END) > 0 ' .
592 'AND COUNT(CASE WHEN path2_column = ~text:value2~ THEN 1 END) > 0) ' .
593 'ORDER BY rbac_id, obj_id, obj_type',
594 $searcher->exposed_last_query
595 );
596 }
597
598 public function testSearchWithNestedJoinedClauses(): void
599 {
600 $searcher = $this->getDatabaseSearcher(self::RESULT);
601 $clause1 = $this->getBasicClause(
602 false,
603 'path1',
604 Mode::CONTAINS,
605 'value1',
606 false
607 );
608 $clause2 = $this->getBasicClause(
609 false,
610 'path2',
611 Mode::EQUALS,
612 'value2',
613 false
614 );
615 $clause3 = $this->getBasicClause(
616 false,
617 'path3',
619 'value3',
620 false
621 );
622 $joined_clause = $this->getJoinedClause(
623 false,
624 Operator::AND,
625 $clause1,
626 $this->getJoinedClause(
627 true,
629 $clause2,
630 $clause3
631 )
632 );
633
634 $result = iterator_to_array($searcher->search($joined_clause, null, null));
635 $this->assertSame(
636 'selected paths:[path1~path2~path3] GROUP BY ~identifier:base_table~.rbac_id, ' .
637 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
638 'HAVING (COUNT(CASE WHEN path1_column LIKE ~text:%value1%~ THEN 1 END) > 0 ' .
639 'AND NOT (COUNT(CASE WHEN path2_column = ~text:value2~ THEN 1 END) > 0 OR ' .
640 'COUNT(CASE WHEN path3_column LIKE ~text:%value3~ THEN 1 END) > 0)) ' .
641 'ORDER BY rbac_id, obj_id, obj_type',
642 $searcher->exposed_last_query
643 );
644 }
645
646 public function testSearchWithLimit(): void
647 {
648 $searcher = $this->getDatabaseSearcher(self::RESULT);
649 $clause = $this->getBasicClause(
650 false,
651 'path',
652 Mode::EQUALS,
653 'value',
654 false
655 );
656
657 $result = iterator_to_array($searcher->search($clause, 37, null));
658 $this->assertSame(
659 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
660 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
661 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
662 'ORDER BY rbac_id, obj_id, obj_type LIMIT ~int:37~',
663 $searcher->exposed_last_query
664 );
665 }
666
667 public function testSearchWithOffset(): void
668 {
669 $searcher = $this->getDatabaseSearcher(self::RESULT);
670 $clause = $this->getBasicClause(
671 false,
672 'path',
673 Mode::EQUALS,
674 'value',
675 false
676 );
677
678 $result = iterator_to_array($searcher->search($clause, null, 16));
679 $this->assertSame(
680 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
681 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
682 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
683 'ORDER BY rbac_id, obj_id, obj_type LIMIT ~int:' . PHP_INT_MAX . '~ OFFSET ~int:16~',
684 $searcher->exposed_last_query
685 );
686 }
687
688 public function testSearchWithLimitAndOffset(): void
689 {
690 $searcher = $this->getDatabaseSearcher(self::RESULT);
691 $clause = $this->getBasicClause(
692 false,
693 'path',
694 Mode::EQUALS,
695 'value',
696 false
697 );
698
699 $result = iterator_to_array($searcher->search($clause, 37, 16));
700 $this->assertSame(
701 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
702 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
703 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
704 'ORDER BY rbac_id, obj_id, obj_type LIMIT ~int:37~ OFFSET ~int:16~',
705 $searcher->exposed_last_query
706 );
707 }
708
709 public function testSearchWithEmptyFilter(): void
710 {
711 $searcher = $this->getDatabaseSearcher(self::RESULT);
712 $clause = $this->getBasicClause(
713 false,
714 'path',
715 Mode::EQUALS,
716 'value',
717 false
718 );
719 $filter = $this->getFilter(Placeholder::ANY, Placeholder::ANY, Placeholder::ANY);
720
721 $result = iterator_to_array($searcher->search($clause, null, null, $filter));
722 $this->assertSame(
723 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
724 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
725 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
726 'ORDER BY rbac_id, obj_id, obj_type',
727 $searcher->exposed_last_query
728 );
729 }
730
732 {
733 $searcher = $this->getDatabaseSearcher(self::RESULT);
734 $clause = $this->getBasicClause(
735 false,
736 'path',
737 Mode::EQUALS,
738 'value',
739 false
740 );
741 $filter = $this->getFilter(37, Placeholder::ANY, Placeholder::ANY);
742
743 $result = iterator_to_array($searcher->search($clause, null, null, $filter));
744 $this->assertSame(
745 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
746 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
747 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
748 'AND ((~identifier:base_table~.rbac_id = ~int:37~)) ' .
749 'ORDER BY rbac_id, obj_id, obj_type',
750 $searcher->exposed_last_query
751 );
752 }
753
755 {
756 $searcher = $this->getDatabaseSearcher(self::RESULT);
757 $clause = $this->getBasicClause(
758 false,
759 'path',
760 Mode::EQUALS,
761 'value',
762 false
763 );
764 $filter = $this->getFilter(Placeholder::ANY, 15, Placeholder::ANY);
765
766 $result = iterator_to_array($searcher->search($clause, null, null, $filter));
767 $this->assertSame(
768 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
769 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
770 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
771 'AND ((~identifier:base_table~.obj_id = ~int:15~)) ' .
772 'ORDER BY rbac_id, obj_id, obj_type',
773 $searcher->exposed_last_query
774 );
775 }
776
778 {
779 $searcher = $this->getDatabaseSearcher(self::RESULT);
780 $clause = $this->getBasicClause(
781 false,
782 'path',
783 Mode::EQUALS,
784 'value',
785 false
786 );
787 $filter = $this->getFilter(Placeholder::ANY, Placeholder::ANY, 'some type');
788
789 $result = iterator_to_array($searcher->search($clause, null, null, $filter));
790 $this->assertSame(
791 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
792 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
793 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
794 'AND ((~identifier:base_table~.obj_type = ~text:some type~)) ' .
795 'ORDER BY rbac_id, obj_id, obj_type',
796 $searcher->exposed_last_query
797 );
798 }
799
800 public function testSearchWithMultiValueFilter(): void
801 {
802 $searcher = $this->getDatabaseSearcher(self::RESULT);
803 $clause = $this->getBasicClause(
804 false,
805 'path',
806 Mode::EQUALS,
807 'value',
808 false
809 );
810 $filter = $this->getFilter(37, 15, 'some type');
811
812 $result = iterator_to_array($searcher->search($clause, null, null, $filter));
813 $this->assertSame(
814 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
815 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
816 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
817 'AND ((~identifier:base_table~.rbac_id = ~int:37~ AND ' .
818 '~identifier:base_table~.obj_id = ~int:15~ AND ' .
819 '~identifier:base_table~.obj_type = ~text:some type~)) ' .
820 'ORDER BY rbac_id, obj_id, obj_type',
821 $searcher->exposed_last_query
822 );
823 }
824
825 public function testSearchWithMultipleFilters(): void
826 {
827 $searcher = $this->getDatabaseSearcher(self::RESULT);
828 $clause = $this->getBasicClause(
829 false,
830 'path',
831 Mode::EQUALS,
832 'value',
833 false
834 );
835 $filter1 = $this->getFilter(37, 15, Placeholder::ANY);
836 $filter2 = $this->getFilter(Placeholder::ANY, 15, 'some type');
837 $filter3 = $this->getFilter(37, Placeholder::ANY, 'some type');
838
839 $result = iterator_to_array($searcher->search(
840 $clause,
841 null,
842 null,
843 $filter1,
844 $filter2,
845 $filter3
846 ));
847 $this->assertSame(
848 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
849 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
850 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
851 'AND ((~identifier:base_table~.rbac_id = ~int:37~ AND ~identifier:base_table~.obj_id = ~int:15~) ' .
852 'OR (~identifier:base_table~.obj_id = ~int:15~ AND ~identifier:base_table~.obj_type = ~text:some type~) ' .
853 'OR (~identifier:base_table~.rbac_id = ~int:37~ AND ~identifier:base_table~.obj_type = ~text:some type~)) ' .
854 'ORDER BY rbac_id, obj_id, obj_type',
855 $searcher->exposed_last_query
856 );
857 }
858
860 {
861 $searcher = $this->getDatabaseSearcher(self::RESULT);
862 $clause = $this->getBasicClause(
863 false,
864 'path',
865 Mode::EQUALS,
866 'value',
867 false
868 );
869 $filter = $this->getFilter(Placeholder::ANY, Placeholder::OBJ_ID, Placeholder::ANY);
870
871 $result = iterator_to_array($searcher->search($clause, null, null, $filter));
872 $this->assertSame(
873 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
874 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
875 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
876 'AND ((~identifier:base_table~.obj_id = ~identifier:base_table~.rbac_id)) ' .
877 'ORDER BY rbac_id, obj_id, obj_type',
878 $searcher->exposed_last_query
879 );
880 }
881
883 {
884 $searcher = $this->getDatabaseSearcher(self::RESULT);
885 $clause = $this->getBasicClause(
886 false,
887 'path',
888 Mode::EQUALS,
889 'value',
890 false
891 );
892 $filter = $this->getFilter(Placeholder::SUB_ID, Placeholder::ANY, Placeholder::ANY);
893
894 $result = iterator_to_array($searcher->search($clause, null, null, $filter));
895 $this->assertSame(
896 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
897 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
898 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
899 'AND ((~identifier:base_table~.rbac_id = ~identifier:base_table~.obj_id)) ' .
900 'ORDER BY rbac_id, obj_id, obj_type',
901 $searcher->exposed_last_query
902 );
903 }
904
906 {
907 $searcher = $this->getDatabaseSearcher(self::RESULT);
908 $clause = $this->getBasicClause(
909 false,
910 'path',
911 Mode::EQUALS,
912 'value',
913 false
914 );
915 $filter = $this->getFilter(Placeholder::TYPE, Placeholder::ANY, Placeholder::ANY);
916
917 $result = iterator_to_array($searcher->search($clause, null, null, $filter));
918 $this->assertSame(
919 'selected paths:[path] GROUP BY ~identifier:base_table~.rbac_id, ' .
920 '~identifier:base_table~.obj_id, ~identifier:base_table~.obj_type ' .
921 'HAVING COUNT(CASE WHEN path_column = ~text:value~ THEN 1 END) > 0 ' .
922 'AND ((~identifier:base_table~.rbac_id = ~identifier:base_table~.obj_type)) ' .
923 'ORDER BY rbac_id, obj_id, obj_type',
924 $searcher->exposed_last_query
925 );
926 }
927}
getFilter(int|Placeholder $obj_id, int|Placeholder $sub_id, string|Placeholder $type)
mockRessourceIDsMatchArrayData(array $array, RessourceIDInterface ... $ressource_ids)
getJoinedClause(bool $negated, Operator $operator, ClauseInterface ... $clauses)
getBasicClause(bool $negated, string $path, Mode $mode, string $value, bool $mode_negated)
__construct()
Constructor setup ILIAS global object @access public.
Definition: class.ilias.php:76
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$path
Definition: ltiservices.php:30
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc