19 declare(strict_types=1);
52 protected array $steps;
56 $this->steps = iterator_to_array($path->
steps());
59 public function hasNextStep():
bool 61 return count($this->steps) > 1;
66 if (!$this->hasNextStep()) {
70 array_shift($clone->steps);
76 return $this->steps[0];
81 protected function getTagForCurrentStepOfNavigator(
92 protected function quoteIdentifier(
string $identifier):
string 94 return '~identifier:' . $identifier .
'~';
97 protected function quoteText(
string $text):
string 99 return '~text:' . $text .
'~';
102 protected function quoteInteger(
int $integer):
string 104 return '~int:' . $integer .
'~';
107 protected function checkTable(
string $table):
void 109 if ($table ===
'WRONG') {
110 throw new \ilMDRepositoryException(
'Invalid MD table: ' . $table);
114 protected function table(
string $table): ?
string 116 return $table ===
'WRONG' ?
null : $table .
'_name';
119 protected function IDName(
string $table): ?
string 121 return $table ===
'WRONG' ?
null : $table .
'_id';
130 $this->
getTag(
'',
'',
'',
'root'),
133 return new class ($tags) extends
NullPath {
138 public function steps(): \Generator
140 foreach ($this->tags as $tag) {
141 yield
new class ($tag) extends
NullStep {
148 return $this->tag->step_name;
151 public function filters(): \Generator
153 yield
from $this->tag->filters;
162 foreach ($this->tags as $tag) {
163 $step_name = is_string($tag->step_name) ? $tag->step_name : $tag->step_name->value;
164 $string .=
'.' . $step_name;
165 foreach ($tag->filters as $filter) {
166 $string .=
':' . $filter->type()->value;
167 foreach ($filter->values() as $value) {
168 $string .=
'~' . $value;
187 DataType $data_type = DataType::STRING,
190 return new class ($table, $parent, $data_field, $step_name, $data_type, $filters) extends
NullTag {
192 protected string $table,
193 protected string $parent,
194 protected string $data_field,
197 public array $filters
201 public function table():
string 208 return $this->parent !==
'';
211 public function parent():
string 213 return $this->parent;
216 public function hasData():
bool 218 return $this->data_field !==
'';
221 public function dataField():
string 223 return $this->data_field;
235 protected array $values
244 public function values(): \Generator
246 yield
from $this->values;
254 $parser->addPathAndGetColumn(
259 $this->assertSame(
'p1t1', $parser->getTableAliasForFilters());
266 $this->expectException(\ilMDRepositoryException::class);
267 $parser->getTableAliasForFilters();
274 $this->expectException(\ilMDRepositoryException::class);
275 $parser->addPathAndGetColumn(
285 $this->expectException(\ilMDRepositoryException::class);
286 $parser->getSelectForQuery();
292 $data_column = $parser->addPathAndGetColumn(
294 $this->
getTag(
'table',
'',
'',
'step1'),
295 $this->
getTag(
'table',
'',
'data',
'step2')
301 "COALESCE(~identifier:p1t1~.~identifier:data~, '')",
305 'SELECT ~identifier:p1t1~.rbac_id, ~identifier:p1t1~.obj_id, ~identifier:p1t1~.obj_type ' .
306 'FROM ~identifier:table_name~ AS ~identifier:p1t1~',
307 $parser->getSelectForQuery()
314 $data_column = $parser->addPathAndGetColumn(
316 $this->
getTag(
'table',
'',
'',
'step1'),
317 $this->
getTag(
'table',
'',
'data',
'step2')
323 "COALESCE(~identifier:p1t1~.~identifier:data~, '')",
327 'SELECT ~identifier:base~.rbac_id, ~identifier:base~.obj_id, ~identifier:base~.obj_type ' .
328 'FROM il_meta_general AS base LEFT JOIN (~identifier:table_name~ AS ~identifier:p1t1~) ' .
329 'ON ~identifier:base~.rbac_id = ~identifier:p1t1~.rbac_id AND ' .
330 '~identifier:base~.obj_id = ~identifier:p1t1~.obj_id AND ' .
331 '~identifier:base~.obj_type = ~identifier:p1t1~.obj_type',
332 $parser->getSelectForQuery()
339 $data_column = $parser->addPathAndGetColumn(
341 $this->
getTag(
'table1',
'',
'',
'step1'),
342 $this->
getTag(
'table1',
'',
'',
'step2'),
343 $this->
getTag(
'table2',
'table1',
'',
'step3'),
344 $this->
getTag(
'table2',
'table1',
'data',
'step4')
350 "COALESCE(~identifier:p1t2~.~identifier:data~, '')",
354 'SELECT ~identifier:p1t1~.rbac_id, ~identifier:p1t1~.obj_id, ~identifier:p1t1~.obj_type ' .
355 'FROM ~identifier:table1_name~ AS ~identifier:p1t1~ JOIN ' .
356 '~identifier:table2_name~ AS ~identifier:p1t2~ ON ' .
357 '~identifier:p1t1~.rbac_id = ~identifier:p1t2~.rbac_id AND ' .
358 '~identifier:p1t1~.obj_id = ~identifier:p1t2~.obj_id AND ' .
359 '~identifier:p1t1~.obj_type = ~identifier:p1t2~.obj_type AND ' .
360 'p1t1.~identifier:table1_id~ = ~identifier:p1t2~.parent_id AND ' .
361 '~text:table1~ = ~identifier:p1t2~.parent_type',
362 $parser->getSelectForQuery()
369 $data_column = $parser->addPathAndGetColumn(
371 $this->
getTag(
'table',
'',
'',
'step1'),
372 $this->
getTag(
'table',
'',
'',
'step2')
382 'SELECT ~identifier:p1t1~.rbac_id, ~identifier:p1t1~.obj_id, ~identifier:p1t1~.obj_type ' .
383 'FROM ~identifier:table_name~ AS ~identifier:p1t1~',
384 $parser->getSelectForQuery()
391 $data_column_1 = $parser->addPathAndGetColumn(
393 $this->
getTag(
'table',
'',
'',
'step1'),
394 $this->
getTag(
'table',
'',
'data',
'step2')
398 $data_column_2 = $parser->addPathAndGetColumn(
400 $this->
getTag(
'table',
'',
'',
'step1'),
401 $this->
getTag(
'table',
'',
'data',
'step2')
407 "COALESCE(~identifier:p1t1~.~identifier:data~, '')",
411 "COALESCE(~identifier:p1t1~.~identifier:data~, '')",
415 'SELECT ~identifier:p1t1~.rbac_id, ~identifier:p1t1~.obj_id, ~identifier:p1t1~.obj_type ' .
416 'FROM ~identifier:table_name~ AS ~identifier:p1t1~',
417 $parser->getSelectForQuery()
424 $data_column_1 = $parser->addPathAndGetColumn(
426 $this->
getTag(
'table1',
'',
'',
'step1'),
427 $this->
getTag(
'table1',
'',
'',
'step2'),
428 $this->
getTag(
'table2',
'table2',
'',
'step3'),
429 $this->
getTag(
'table2',
'table2',
'data1',
'step4')
433 $data_column_2 = $parser->addPathAndGetColumn(
435 $this->
getTag(
'table1',
'',
'',
'step1'),
436 $this->
getTag(
'table1',
'',
'data2',
'step2'),
442 "COALESCE(~identifier:p1t2~.~identifier:data1~, '')",
446 "COALESCE(~identifier:p2t1~.~identifier:data2~, '')",
450 'SELECT ~identifier:base~.rbac_id, ~identifier:base~.obj_id, ~identifier:base~.obj_type ' .
451 'FROM il_meta_general AS base LEFT JOIN (' .
452 '~identifier:table1_name~ AS ~identifier:p1t1~ JOIN ' .
453 '~identifier:table2_name~ AS ~identifier:p1t2~ ON ' .
454 '~identifier:p1t1~.rbac_id = ~identifier:p1t2~.rbac_id AND ' .
455 '~identifier:p1t1~.obj_id = ~identifier:p1t2~.obj_id AND ' .
456 '~identifier:p1t1~.obj_type = ~identifier:p1t2~.obj_type AND ' .
457 'p1t1.~identifier:table1_id~ = ~identifier:p1t2~.parent_id AND ' .
458 '~text:table2~ = ~identifier:p1t2~.parent_type) ON ' .
459 '~identifier:base~.rbac_id = ~identifier:p1t1~.rbac_id AND ' .
460 '~identifier:base~.obj_id = ~identifier:p1t1~.obj_id AND ' .
461 '~identifier:base~.obj_type = ~identifier:p1t1~.obj_type LEFT JOIN ' .
462 '(~identifier:table1_name~ AS ~identifier:p2t1~) ON ' .
463 '~identifier:base~.rbac_id = ~identifier:p2t1~.rbac_id AND ' .
464 '~identifier:base~.obj_id = ~identifier:p2t1~.obj_id AND ' .
465 '~identifier:base~.obj_type = ~identifier:p2t1~.obj_type',
466 $parser->getSelectForQuery()
473 $data_column_1 = $parser->addPathAndGetColumn(
475 $this->
getTag(
'table1',
'',
'',
'step1'),
476 $this->
getTag(
'table1',
'',
'',
'step2'),
477 $this->
getTag(
'table2',
'table2',
'',
'step3'),
478 $this->
getTag(
'table2',
'table2',
'data1',
'step4')
482 $data_column_2 = $parser->addPathAndGetColumn(
484 $this->
getTag(
'table1',
'',
'',
'step1'),
485 $this->
getTag(
'table1',
'',
'data2',
'step2'),
491 "COALESCE(~identifier:p1t2~.~identifier:data1~, '')",
495 "COALESCE(~identifier:p2t1~.~identifier:data2~, '')",
499 'SELECT ~identifier:base~.rbac_id, ~identifier:base~.obj_id, ~identifier:base~.obj_type ' .
500 'FROM il_meta_general AS base LEFT JOIN (' .
501 '~identifier:table1_name~ AS ~identifier:p1t1~ JOIN ' .
502 '~identifier:table2_name~ AS ~identifier:p1t2~ ON ' .
503 '~identifier:p1t1~.rbac_id = ~identifier:p1t2~.rbac_id AND ' .
504 '~identifier:p1t1~.obj_id = ~identifier:p1t2~.obj_id AND ' .
505 '~identifier:p1t1~.obj_type = ~identifier:p1t2~.obj_type AND ' .
506 'p1t1.~identifier:table1_id~ = ~identifier:p1t2~.parent_id AND ' .
507 '~text:table2~ = ~identifier:p1t2~.parent_type) ON ' .
508 '~identifier:base~.rbac_id = ~identifier:p1t1~.rbac_id AND ' .
509 '~identifier:base~.obj_id = ~identifier:p1t1~.obj_id AND ' .
510 '~identifier:base~.obj_type = ~identifier:p1t1~.obj_type LEFT JOIN ' .
511 '(~identifier:table1_name~ AS ~identifier:p2t1~) ON ' .
512 '~identifier:base~.rbac_id = ~identifier:p2t1~.rbac_id AND ' .
513 '~identifier:base~.obj_id = ~identifier:p2t1~.obj_id AND ' .
514 '~identifier:base~.obj_type = ~identifier:p2t1~.obj_type',
515 $parser->getSelectForQuery()
522 $data_column = $parser->addPathAndGetColumn(
524 $this->
getTag(
'table1',
'',
'',
'step1'),
525 $this->
getTag(
'table1',
'',
'',
'step2'),
526 $this->
getTag(
'table2',
'table1',
'',
'step3'),
528 $this->
getTag(
'table2',
'table1',
'data2',
'step5')
534 "COALESCE(~identifier:p1t3~.~identifier:data2~, '')",
538 'SELECT ~identifier:p1t1~.rbac_id, ~identifier:p1t1~.obj_id, ~identifier:p1t1~.obj_type ' .
539 'FROM ~identifier:table1_name~ AS ~identifier:p1t1~ JOIN ' .
540 '~identifier:table2_name~ AS ~identifier:p1t2~ JOIN ' .
541 '~identifier:table2_name~ AS ~identifier:p1t3~ ON ' .
542 '~identifier:p1t1~.rbac_id = ~identifier:p1t2~.rbac_id AND ' .
543 '~identifier:p1t1~.obj_id = ~identifier:p1t2~.obj_id AND ' .
544 '~identifier:p1t1~.obj_type = ~identifier:p1t2~.obj_type AND ' .
545 'p1t1.~identifier:table1_id~ = ~identifier:p1t2~.parent_id AND ' .
546 '~text:table1~ = ~identifier:p1t2~.parent_type AND ' .
547 '~identifier:p1t1~.rbac_id = ~identifier:p1t3~.rbac_id AND ' .
548 '~identifier:p1t1~.obj_id = ~identifier:p1t3~.obj_id AND ' .
549 '~identifier:p1t1~.obj_type = ~identifier:p1t3~.obj_type AND ' .
550 'p1t1.~identifier:table1_id~ = ~identifier:p1t3~.parent_id AND ' .
551 '~text:table1~ = ~identifier:p1t3~.parent_type',
552 $parser->getSelectForQuery()
563 $data_column = $parser->addPathAndGetColumn(
565 $this->
getTag(
'table1',
'',
'',
'step1'),
566 $this->
getTag(
'table1',
'',
'',
'step2', DataType::STRING, $filter),
567 $this->
getTag(
'table2',
'table1',
'',
'step3'),
568 $this->
getTag(
'table2',
'table1',
'data',
'step4')
574 'SELECT ~identifier:p1t1~.rbac_id, ~identifier:p1t1~.obj_id, ~identifier:p1t1~.obj_type ' .
575 'FROM ~identifier:table1_name~ AS ~identifier:p1t1~ JOIN ' .
576 '~identifier:table2_name~ AS ~identifier:p1t2~ ON ' .
577 '~identifier:p1t1~.~identifier:table1_id~ IN (~int:13~) AND ' .
578 '~identifier:p1t1~.rbac_id = ~identifier:p1t2~.rbac_id AND ' .
579 '~identifier:p1t1~.obj_id = ~identifier:p1t2~.obj_id AND ' .
580 '~identifier:p1t1~.obj_type = ~identifier:p1t2~.obj_type AND ' .
581 'p1t1.~identifier:table1_id~ = ~identifier:p1t2~.parent_id AND ' .
582 '~text:table1~ = ~identifier:p1t2~.parent_type',
583 $parser->getSelectForQuery()
594 $data_column = $parser->addPathAndGetColumn(
596 $this->
getTag(
'table1',
'',
'',
'step1'),
597 $this->
getTag(
'table1',
'',
'filter_data',
'step2', DataType::STRING, $filter),
598 $this->
getTag(
'table2',
'table1',
'',
'step3'),
599 $this->
getTag(
'table2',
'table1',
'data',
'step4')
605 'SELECT ~identifier:p1t1~.rbac_id, ~identifier:p1t1~.obj_id, ~identifier:p1t1~.obj_type ' .
606 'FROM ~identifier:table1_name~ AS ~identifier:p1t1~ JOIN ' .
607 '~identifier:table2_name~ AS ~identifier:p1t2~ ON ' .
608 "COALESCE(~identifier:p1t1~.~identifier:filter_data~, '') IN (~text:some data~) AND " .
609 '~identifier:p1t1~.rbac_id = ~identifier:p1t2~.rbac_id AND ' .
610 '~identifier:p1t1~.obj_id = ~identifier:p1t2~.obj_id AND ' .
611 '~identifier:p1t1~.obj_type = ~identifier:p1t2~.obj_type AND ' .
612 'p1t1.~identifier:table1_id~ = ~identifier:p1t2~.parent_id AND ' .
613 '~text:table1~ = ~identifier:p1t2~.parent_type',
614 $parser->getSelectForQuery()
625 $data_column = $parser->addPathAndGetColumn(
627 $this->
getTag(
'table1',
'',
'',
'step1'),
628 $this->
getTag(
'table1',
'',
'',
'step2', DataType::STRING, $filter),
629 $this->
getTag(
'table2',
'table1',
'',
'step3'),
630 $this->
getTag(
'table2',
'table1',
'data',
'step4')
636 'SELECT ~identifier:p1t1~.rbac_id, ~identifier:p1t1~.obj_id, ~identifier:p1t1~.obj_type ' .
637 'FROM ~identifier:table1_name~ AS ~identifier:p1t1~ JOIN ' .
638 '~identifier:table2_name~ AS ~identifier:p1t2~ ON ' .
639 '~identifier:p1t1~.rbac_id = ~identifier:p1t2~.rbac_id AND ' .
640 '~identifier:p1t1~.obj_id = ~identifier:p1t2~.obj_id AND ' .
641 '~identifier:p1t1~.obj_type = ~identifier:p1t2~.obj_type AND ' .
642 'p1t1.~identifier:table1_id~ = ~identifier:p1t2~.parent_id AND ' .
643 '~text:table1~ = ~identifier:p1t2~.parent_type',
644 $parser->getSelectForQuery()
657 $data_column = $parser->addPathAndGetColumn(
659 $this->
getTag(
'table1',
'',
'',
'step1'),
660 $this->
getTag(
'table1',
'',
'filter_data',
'step2', DataType::STRING, $filter),
661 $this->
getTag(
'table2',
'table1',
'',
'step3'),
662 $this->
getTag(
'table2',
'table1',
'data',
'step4')
668 'SELECT ~identifier:p1t1~.rbac_id, ~identifier:p1t1~.obj_id, ~identifier:p1t1~.obj_type ' .
669 'FROM ~identifier:table1_name~ AS ~identifier:p1t1~ JOIN ' .
670 '~identifier:table2_name~ AS ~identifier:p1t2~ ON ' .
671 "COALESCE(~identifier:p1t1~.~identifier:filter_data~, '') " .
672 'IN (~text:some data~, ~text:some other data~, ~text:more~) AND ' .
673 '~identifier:p1t1~.rbac_id = ~identifier:p1t2~.rbac_id AND ' .
674 '~identifier:p1t1~.obj_id = ~identifier:p1t2~.obj_id AND ' .
675 '~identifier:p1t1~.obj_type = ~identifier:p1t2~.obj_type AND ' .
676 'p1t1.~identifier:table1_id~ = ~identifier:p1t2~.parent_id AND ' .
677 '~text:table1~ = ~identifier:p1t2~.parent_type',
678 $parser->getSelectForQuery()
689 $data_column = $parser->addPathAndGetColumn(
691 $this->
getTag(
'table',
'',
'filter_data',
'step1', DataType::STRING, $filter),
692 $this->
getTag(
'table',
'',
'data',
'step2'),
698 'SELECT ~identifier:p1t1~.rbac_id, ~identifier:p1t1~.obj_id, ~identifier:p1t1~.obj_type ' .
699 'FROM ~identifier:table_name~ AS ~identifier:p1t1~ WHERE ' .
700 "COALESCE(~identifier:p1t1~.~identifier:filter_data~, '') IN (~text:some data~)",
701 $parser->getSelectForQuery()
712 $data_column_1 = $parser->addPathAndGetColumn(
714 $this->
getTag(
'table',
'',
'filter_data',
'step1', DataType::STRING, $filter),
715 $this->
getTag(
'table',
'',
'data',
'step2'),
719 $data_column_2 = $parser->addPathAndGetColumn(
721 $this->
getTag(
'table1',
'',
'',
'step1'),
722 $this->
getTag(
'table1',
'',
'data2',
'step2'),
728 'SELECT ~identifier:base~.rbac_id, ~identifier:base~.obj_id, ~identifier:base~.obj_type ' .
729 'FROM il_meta_general AS base LEFT JOIN (' .
730 '~identifier:table_name~ AS ~identifier:p1t1~) ON ' .
731 '~identifier:base~.rbac_id = ~identifier:p1t1~.rbac_id AND ' .
732 '~identifier:base~.obj_id = ~identifier:p1t1~.obj_id AND ' .
733 '~identifier:base~.obj_type = ~identifier:p1t1~.obj_type AND ' .
734 "COALESCE(~identifier:p1t1~.~identifier:filter_data~, '') IN (~text:some data~) LEFT JOIN " .
735 '(~identifier:table1_name~ AS ~identifier:p2t1~) ON ' .
736 '~identifier:base~.rbac_id = ~identifier:p2t1~.rbac_id AND ' .
737 '~identifier:base~.obj_id = ~identifier:p2t1~.obj_id AND ' .
738 '~identifier:base~.obj_type = ~identifier:p2t1~.obj_type',
739 $parser->getSelectForQuery()
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
__construct()
Constructor setup ILIAS global object public.