ILIAS  release_8 Revision v8.24
class.ilConditionHandler.php
Go to the documentation of this file.
1<?php
2
3declare(strict_types=1);
4
78{
79 public const OPERATOR_PASSED = 'passed';
80 public const OPERATOR_FINISHED = 'finished';
81 public const OPERATOR_NOT_FINISHED = 'not_finished';
82 public const OPERATOR_NOT_MEMBER = 'not_member';
83 public const OPERATOR_FAILED = 'failed';
84 public const OPERATOR_LP = 'learning_progress';
85 public const OPERATOR_ACCREDITED_OR_PASSED = 'accredited_or_passed';
86
87 public const UNIQUE_CONDITIONS = 1;
88
89 // conditions are used for all tree references of the target object.
90 // This is currently only used for lm chapters and likely to be abandonded in the future
91 public const SHARED_CONDITIONS = 0;
92
93 public static array $cond_for_target_cache = array();
94 public static array $cond_target_rows = array();
95
96 protected ilDBInterface $db;
97 protected ilLanguage $lng;
99 protected ilTree $tree;
100 protected ilLogger $logger;
101
102 protected string $error_message = '';
103
104 protected int $target_obj_id = 0;
105 protected int $target_ref_id = 0;
106 protected string $target_type = '';
107 protected int $trigger_obj_id = 0;
108 protected int $trigger_ref_id = 0;
109 protected string $trigger_type = '';
111 protected string $operator = '';
112 protected string $value = '';
113 protected bool $validation = true;
114 private bool $circle = false;
115
116 private bool $obligatory = true;
117 private bool $hidden_status = false;
118
119 public function __construct()
120 {
121 global $DIC;
122
123 $this->db = $DIC->database();
124 $this->lng = $DIC->language();
125 $this->objDefinition = $DIC['objDefinition'];
126 $this->tree = $DIC->repositoryTree();
127 $this->logger = $DIC->logger()->ac();
128 $this->validation = true;
129 }
130
131 public static function resetCache(): void
132 {
133 self::$cond_for_target_cache = [];
134 self::$cond_target_rows = [];
135 }
136
140 public static function _isReferenceHandlingOptional(string $a_type): bool
141 {
142 return $a_type === 'st';
143 }
144
148 public static function lookupEffectiveHiddenStatusByTarget(int $a_target_ref_id): bool
149 {
150 global $DIC;
151
152 $obj_definition = $DIC['objDefinition'];
153 $tree = $DIC->repositoryTree();
154
155 // check if parent takes over control of condition
156 $parent_ref_id = $tree->getParentId($a_target_ref_id);
157 $parent_obj_id = ilObject::_lookupObjId($parent_ref_id);
158 $parent_type = ilObject::_lookupType($parent_obj_id);
159
160 $class = $obj_definition->getClassName($parent_type);
161 $class_name = "il" . $class . "ConditionController";
162 $location = $obj_definition->getLocation($parent_type);
163
164 // if yes, get from parent
165 if ($class !== "" && is_file($location . "/class." . $class_name . ".php")) {
167 $controller = new $class_name();
168 if ($controller->isContainerConditionController($parent_ref_id)) {
169 return (bool) $controller->getConditionSetForRepositoryObject($a_target_ref_id)->getHiddenStatus();
170 }
171 }
172 return self::lookupPersistedHiddenStatusByTarget($a_target_ref_id);
173 }
174
175 public static function lookupPersistedHiddenStatusByTarget(int $a_target_ref_id): bool
176 {
177 global $DIC;
178
179 $ilDB = $DIC->database();
180
181 $query = 'SELECT hidden_status FROM conditions ' .
182 'WHERE target_ref_id = ' . $ilDB->quote($a_target_ref_id, 'integer');
183 $res = $ilDB->query($query);
184 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
185 return (bool) $row->hidden_status;
186 }
187 return false;
188 }
189
196 public static function _adjustMovedObjectConditions(int $a_ref_id): bool
197 {
198 return true;
199 }
200
204 protected static function _getDistinctTargetRefIds(): array
205 {
206 global $DIC;
207
208 $ilDB = $DIC['ilDB'];
209
210 $query = "SELECT DISTINCT target_ref_id ref FROM conditions ";
211 $res = $ilDB->query($query);
212 $ref_ids = [];
213 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
214 $ref_ids[] = (int) $row->ref;
215 }
216 return $ref_ids;
217 }
218
224 protected static function _deleteTargetConditionsByRefId(int $a_target_ref_id): bool
225 {
226 global $DIC;
227
228 $ilDB = $DIC['ilDB'];
229
230 $query = "DELETE FROM conditions " .
231 "WHERE target_ref_id = " . $ilDB->quote($a_target_ref_id, 'integer') . " " .
232 "AND target_type != 'st' ";
233 $res = $ilDB->manipulate($query);
234 return true;
235 }
236
237 public function setReferenceHandlingType(int $a_type): void
238 {
239 $this->condition_reference_type = $a_type;
240 }
241
242 public function getReferenceHandlingType(): int
243 {
245 }
246
247 public function setErrorMessage(string $a_msg): void
248 {
249 $this->error_message = $a_msg;
250 }
251
252 public function getErrorMessage(): string
253 {
255 }
256
257 public function setTargetRefId(int $a_target_ref_id): void
258 {
259 $this->target_ref_id = $a_target_ref_id;
260 }
261
262 public function getTargetRefId(): int
263 {
265 }
266
267 public function setTargetObjId(int $a_target_obj_id): void
268 {
269 $this->target_obj_id = $a_target_obj_id;
270 }
271
272 public function getTargetObjId(): int
273 {
275 }
276
280 public function setTargetType(string $a_target_type): void
281 {
282 $this->target_type = $a_target_type;
283 }
284
288 public function getTargetType(): string
289 {
290 return $this->target_type;
291 }
292
293 public function setTriggerRefId(int $a_trigger_ref_id): void
294 {
295 $this->trigger_ref_id = $a_trigger_ref_id;
296 }
297
298 public function getTriggerRefId(): int
299 {
301 }
302
303 public function setTriggerObjId(int $a_trigger_obj_id): void
304 {
305 $this->trigger_obj_id = $a_trigger_obj_id;
306 }
307
308 public function getTriggerObjId(): int
309 {
311 }
312
316 public function setTriggerType(string $a_trigger_type): void
317 {
318 $this->trigger_type = $a_trigger_type;
319 }
320
324 public function getTriggerType(): string
325 {
326 return $this->trigger_type;
327 }
328
329 public function setOperator(string $a_operator): void
330 {
331 $this->operator = $a_operator;
332 }
333
334 public function getOperator(): string
335 {
336 return $this->operator;
337 }
338
339 public function setValue(string $a_value): void
340 {
341 $this->value = $a_value;
342 }
343
344 public function getValue(): string
345 {
346 return $this->value;
347 }
348
352 public function setObligatory(bool $a_obl): void
353 {
354 $this->obligatory = $a_obl;
355 }
356
360 public function getObligatory(): bool
361 {
362 return $this->obligatory;
363 }
364
365 public function setHiddenStatus(bool $a_status): void
366 {
367 $this->hidden_status = $a_status;
368 }
369
370 public function getHiddenStatus(): bool
371 {
373 }
374
375 public function enableAutomaticValidation(bool $a_validate = true): void
376 {
377 $this->validation = $a_validate;
378 }
379
380 public function getTriggerTypes(): array
381 {
382 $trigger_types = array('crs', 'exc', 'tst', 'sahs', 'svy', 'lm', 'iass', 'prg', 'copa', 'lti', 'cmix');
383
384 // Add operator lp trigger
386 // only if object type has lp
387 foreach ($this->objDefinition->getAllRepositoryTypes() as $t) {
388 if (ilObjectLP::isSupportedObjectType($t) && !in_array($t, $trigger_types, true)) {
389 $trigger_types[] = $t;
390 }
391 }
392 }
393 foreach ($this->objDefinition->getPlugins() as $p_type => $p_info) {
394 try {
395 $name = 'ilObj' . $p_info['class_name'] . 'Access';
396 $reflection = new ReflectionClass($name);
397 if ($reflection->implementsInterface('ilConditionHandling')) {
398 $trigger_types[] = $p_type;
399 }
400 } catch (ReflectionException $e) {
401 $this->logger->warning('Cannot create instance for ' . $name);
402 $this->logger->warning($e->getMessage());
403 }
404 }
405 $active_triggers = array();
406 foreach ($trigger_types as $type) {
407 if (count($this->getOperatorsByTriggerType($type))) {
408 $active_triggers[] = $type;
409 }
410 }
411 return $active_triggers;
412 }
413
417 public function getOperatorsByTriggerType(string $a_type): array
418 {
419 global $DIC;
420
421 $objDefinition = $DIC['objDefinition'];
422
423 if ($a_type === 'crsg') {
424 return ['not_member'];
425 }
426
427 $class = $objDefinition->getClassName($a_type);
429 $full_class = "ilObj" . $class . "Access";
430 include_once($location . "/class." . $full_class . ".php");
431 $reflection = new ReflectionClass($full_class);
432 if ($reflection->implementsInterface('ilConditionHandling')) {
433 $operators = call_user_func(
434 array($full_class, 'getConditionOperators'),
435 $a_type
436 );
437 } else {
438 $operators = [];
439 }
440
441 // Add operator lp
443 // only if object type has lp
444
446 array_unshift($operators, self::OPERATOR_LP);
447 }
448 }
449 return $operators;
450 }
451
455 public function storeCondition(): bool
456 {
457 // first insert, then validate: it's easier to check for circles if the new condition is in the db table
458 $next_id = $this->db->nextId('conditions');
459 $query = 'INSERT INTO conditions (condition_id,target_ref_id,target_obj_id,target_type,' .
460 'trigger_ref_id,trigger_obj_id,trigger_type,operator,value,ref_handling,obligatory,hidden_status) ' .
461 'VALUES (' .
462 $this->db->quote($next_id, 'integer') . ',' .
463 $this->db->quote($this->getTargetRefId(), 'integer') . "," .
464 $this->db->quote($this->getTargetObjId(), 'integer') . "," .
465 $this->db->quote($this->getTargetType(), 'text') . "," .
466 $this->db->quote($this->getTriggerRefId(), 'integer') . "," .
467 $this->db->quote($this->getTriggerObjId(), 'integer') . "," .
468 $this->db->quote($this->getTriggerType(), 'text') . "," .
469 $this->db->quote($this->getOperator(), 'text') . "," .
470 $this->db->quote($this->getValue(), 'text') . ", " .
471 $this->db->quote($this->getReferenceHandlingType(), 'integer') . ', ' .
472 $this->db->quote($this->getObligatory(), 'integer') . ', ' .
473 $this->db->quote($this->getHiddenStatus(), 'integer') . ' ' .
474 ')';
475
476 $res = $this->db->manipulate($query);
477
478 if ($this->validation && !$this->validate()) {
479 $this->deleteCondition($next_id);
480 return false;
481 }
482 return true;
483 }
484
485 public function checkExists(): bool
486 {
487 $query = "SELECT * FROM conditions " .
488 "WHERE target_ref_id = " . $this->db->quote($this->getTargetRefId(), 'integer') . " " .
489 "AND target_obj_id = " . $this->db->quote($this->getTargetObjId(), 'integer') . " " .
490 "AND trigger_ref_id = " . $this->db->quote($this->getTriggerRefId(), 'integer') . " " .
491 "AND trigger_obj_id = " . $this->db->quote($this->getTriggerObjId(), 'integer') . " " .
492 "AND operator = " . $this->db->quote($this->getOperator(), 'text');
493 $res = $this->db->query($query);
494 return (bool) $res->numRows();
495 }
496
497 public function updateCondition(int $a_id): void
498 {
499 $query = "UPDATE conditions SET " .
500 "target_ref_id = " . $this->db->quote($this->getTargetRefId(), 'integer') . ", " .
501 "operator = " . $this->db->quote($this->getOperator(), 'text') . ", " .
502 "value = " . $this->db->quote($this->getValue(), 'text') . ", " .
503 "ref_handling = " . $this->db->quote($this->getReferenceHandlingType(), 'integer') . ", " .
504 'obligatory = ' . $this->db->quote($this->getObligatory(), 'integer') . ' ' .
505 "WHERE condition_id = " . $this->db->quote($a_id, 'integer');
506 $res = $this->db->manipulate($query);
507 }
508
509 public function updateHiddenStatus(bool $a_status): void
510 {
511 $query = 'UPDATE conditions SET ' .
512 'hidden_status = ' . $this->db->quote($a_status, 'integer') . ' ' .
513 'WHERE target_ref_id = ' . $this->db->quote($this->getTargetRefId(), 'integer');
514 $this->db->manipulate($query);
515 }
516
520 public static function updateObligatory(int $a_id, bool $a_status): void
521 {
522 global $DIC;
523
524 $ilDB = $DIC->database();
525 $query = "UPDATE conditions SET " .
526 'obligatory = ' . $ilDB->quote($a_status, 'integer') . ' ' .
527 "WHERE condition_id = " . $ilDB->quote($a_id, 'integer');
528 $res = $ilDB->manipulate($query);
529 }
530
535 public function delete(int $a_ref_id): void
536 {
537 $query = "DELETE FROM conditions WHERE " .
538 "target_ref_id = " . $this->db->quote($a_ref_id, 'integer') . " " .
539 "OR trigger_ref_id = " . $this->db->quote($a_ref_id, 'integer');
540 $res = $this->db->manipulate($query);
541 }
542
547 public function deleteByObjId(int $a_obj_id): void
548 {
549 $query = "DELETE FROM conditions WHERE " .
550 "target_obj_id = " . $this->db->quote($a_obj_id, 'integer') . " " .
551 "OR trigger_obj_id = " . $this->db->quote($a_obj_id, 'integer');
552 $res = $this->db->manipulate($query);
553 }
554
555 public function deleteCondition(int $a_id): void
556 {
557 $query = "DELETE FROM conditions " .
558 "WHERE condition_id = " . $this->db->quote($a_id, 'integer');
559 $res = $this->db->manipulate($query);
560 }
561
565 public static function getNumberOfConditionsOfTrigger(string $a_trigger_obj_type, int $a_trigger_id): int
566 {
567 global $DIC;
568 $db = $DIC->database();
569
570 $query = 'select count(*) num from conditions ' .
571 'where trigger_obj_id = ' . $db->quote($a_trigger_id, ilDBConstants::T_INTEGER) . ' ' .
572 'and trigger_type = ' . $db->quote($a_trigger_obj_type, ilDBConstants::T_TEXT);
573 $res = $db->query($query);
574 $row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT);
575 return (int) $row->num;
576 }
577
583 public static function _getPersistedConditionsOfTrigger(string $a_trigger_obj_type, int $a_trigger_id): array
584 {
585 global $DIC;
586
587 $ilDB = $DIC['ilDB'];
588
589 $query = "SELECT * FROM conditions " .
590 "WHERE trigger_obj_id = " . $ilDB->quote($a_trigger_id, 'integer') . " " .
591 " AND trigger_type = " . $ilDB->quote($a_trigger_obj_type, 'text');
592
593 $res = $ilDB->query($query);
594 $conditions = [];
595 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
596 $tmp_array = [];
597 $tmp_array['id'] = (int) $row->condition_id;
598 $tmp_array['target_ref_id'] = (int) $row->target_ref_id;
599 $tmp_array['target_obj_id'] = (int) $row->target_obj_id;
600 $tmp_array['target_type'] = (string) $row->target_type;
601 $tmp_array['trigger_ref_id'] = (int) $row->trigger_ref_id;
602 $tmp_array['trigger_obj_id'] = (int) $row->trigger_obj_id;
603 $tmp_array['trigger_type'] = (string) $row->trigger_type;
604 $tmp_array['operator'] = (string) $row->operator;
605 $tmp_array['value'] = (string) $row->value;
606 $tmp_array['ref_handling'] = (int) $row->ref_handling;
607 $tmp_array['obligatory'] = (bool) $row->obligatory;
608 $tmp_array['hidden_status'] = (bool) $row->hidden_status;
609 $conditions[] = $tmp_array;
610 }
611 return $conditions;
612 }
613
619 public static function _getEffectiveConditionsOfTarget(
620 int $a_target_ref_id,
621 int $a_target_obj_id,
622 string $a_target_type = ""
623 ): array {
624 global $DIC;
625
626 if ($a_target_ref_id === 0) {
627 return [];
628 }
629
630 $obj_definition = $DIC["objDefinition"];
631 $tree = $DIC->repositoryTree();
632
633 // get type if no type given
634 if ($a_target_type === "") {
635 $a_target_type = ilObject::_lookupType($a_target_obj_id);
636 }
637
638 // check if parent takes over control of condition
639 $parent_ref_id = $tree->getParentId($a_target_ref_id);
640 $parent_obj_id = ilObject::_lookupObjId($parent_ref_id);
641 $parent_type = ilObject::_lookupType($parent_obj_id);
642
643 $class = $obj_definition->getClassName($parent_type);
644 $class_name = "il" . $class . "ConditionController";
645 $location = $obj_definition->getLocation($parent_type);
646
647 // if yes, get from parent
648 if ($class !== "" && is_file($location . "/class." . $class_name . ".php")
649 && $a_target_type === ilObject::_lookupType($a_target_ref_id, true)) {
651 $controller = new $class_name();
652 if ($controller->isContainerConditionController($parent_ref_id)) {
654 $set = $controller->getConditionSetForRepositoryObject($a_target_ref_id);
655
656 // convert to old structure
657 $cond = [];
658 foreach ($set->getConditions() as $c) {
659 $obligatory = $set->getAllObligatory() || $c->getObligatory();
660 $trigger = $c->getTrigger();
661 $cond[] = array(
662 "target_ref_id" => $a_target_ref_id,
663 "target_obj_id" => $a_target_obj_id,
664 "target_type" => $a_target_type,
665 "trigger_ref_id" => $trigger->getRefId(),
666 "trigger_obj_id" => $trigger->getObjId(),
667 "trigger_type" => $trigger->getType(),
668 "operator" => $c->getOperator(),
669 "value" => $c->getValue(),
670 "ref_handling" => 1,
671 "obligatory" => $obligatory,
672 "num_obligatory" => $set->getNumObligatory(),
673 "hidden_status" => $set->getHiddenStatus()
674 );
675 }
676 return $cond;
677 }
678 }
679
680 return self::_getPersistedConditionsOfTarget($a_target_ref_id, $a_target_obj_id, $a_target_type);
681 }
682
687 public static function _getPersistedConditionsOfTarget(
688 int $a_target_ref_id,
689 int $a_target_obj_id,
690 string $a_target_type = ""
691 ): array {
692 global $DIC;
693
694 $ilDB = $DIC['ilDB'];
695
696 // get type if no type given
697 if ($a_target_type === "") {
698 $a_target_type = ilObject::_lookupType($a_target_obj_id);
699 }
700
701 // check conditions for target cache
702 if (isset(self::$cond_for_target_cache[$a_target_ref_id . ":" . $a_target_obj_id . ":" .
703 $a_target_type])) {
704 return self::$cond_for_target_cache[$a_target_ref_id . ":" . $a_target_obj_id . ":" .
705 $a_target_type];
706 }
707
708 // check rows cache
709 if (isset(self::$cond_target_rows[$a_target_type . ":" . $a_target_obj_id])) {
710 $rows = self::$cond_target_rows[$a_target_type . ":" . $a_target_obj_id];
711 } else {
712 // query data from db
713 $query = "SELECT * FROM conditions " .
714 "WHERE target_obj_id = " . $ilDB->quote($a_target_obj_id, 'integer') . " " .
715 " AND target_type = " . $ilDB->quote($a_target_type, 'text');
716
717 $res = $ilDB->query($query);
718 $rows = array();
719 while ($row = $ilDB->fetchAssoc($res)) {
720 $item = [];
721 $item['condition_id'] = (int) $row['condition_id'];
722 $item['target_ref_id'] = (int) $row['target_ref_id'];
723 $item['target_obj_id'] = (int) $row['target_obj_id'];
724 $item['trigger_ref_id'] = (int) $row['trigger_ref_id'];
725 $item['trigger_obj_id'] = (int) $row['trigger_obj_id'];
726 $item['target_type'] = (string) $row['target_type'];
727 $item['trigger_type'] = (string) $row['trigger_type'];
728 $item['operator'] = (string) $row['operator'];
729 $item['value'] = (string) $row['value'];
730 $item['ref_handling'] = (int) $row['ref_handling'];
731 $item['obligatory'] = (bool) $row['obligatory'];
732 $item['num_obligatory'] = (int) $row['num_obligatory'];
733 $item['hidden_status'] = (bool) $row['hidden_status'];
734
735 $rows[] = $item;
736 }
737 }
738
739 reset($rows);
740 $conditions = [];
741 foreach ($rows as $row) {
742 if (($row["ref_handling"] == self::UNIQUE_CONDITIONS) && $row["target_ref_id"] != $a_target_ref_id) {
743 continue;
744 }
745
746 $row["id"] = $row["condition_id"];
747 $conditions[] = $row;
748 }
749 // write conditions for target cache
750 self::$cond_for_target_cache[$a_target_ref_id . ":" . $a_target_obj_id . ":" .
751 $a_target_type] = $conditions;
752 return $conditions;
753 }
754
758 public static function preloadPersistedConditionsForTargetRecords(string $a_type, array $a_obj_ids): void
759 {
760 global $DIC;
761
762 $ilDB = $DIC['ilDB'];
763
764 if (is_array($a_obj_ids) && count($a_obj_ids) > 0) {
765 $res = $ilDB->query("SELECT * FROM conditions " .
766 "WHERE " . $ilDB->in("target_obj_id", $a_obj_ids, false, "integer") .
767 " AND target_type = " . $ilDB->quote($a_type, 'text'));
768 $rows = array();
769 while ($row = $ilDB->fetchAssoc($res)) {
770 $item = [];
771 $item['condition_id'] = (int) $row['condition_id'];
772 $item['target_ref_id'] = (int) $row['target_ref_id'];
773 $item['target_obj_id'] = (int) $row['target_obj_id'];
774 $item['trigger_ref_id'] = (int) $row['trigger_ref_id'];
775 $item['trigger_obj_id'] = (int) $row['trigger_obj_id'];
776 $item['target_type'] = (string) $row['target_type'];
777 $item['trigger_type'] = (string) $row['trigger_type'];
778 $item['operator'] = (string) $row['operator'];
779 $item['value'] = (string) $row['value'];
780 $item['ref_handling'] = (int) $row['ref_handling'];
781 $item['obligatory'] = (bool) $row['obligatory'];
782 $item['num_obligatory'] = (int) $row['num_obligatory'];
783 $item['hidden_status'] = (bool) $row['hidden_status'];
784 self::$cond_target_rows[$a_type . ":" . $row["target_obj_id"]][] = $item;
785 }
786 // init obj ids without any record
787 foreach ($a_obj_ids as $obj_id) {
788 if (!isset(self::$cond_target_rows[$a_type . ":" . $obj_id])) {
789 self::$cond_target_rows[$a_type . ":" . $obj_id] = array();
790 }
791 }
792 }
793 }
794
795 public static function _getCondition(int $a_id): array
796 {
797 global $DIC;
798
799 $ilDB = $DIC['ilDB'];
800
801 $query = "SELECT * FROM conditions " .
802 "WHERE condition_id = " . $ilDB->quote($a_id, 'integer');
803
804 $res = $ilDB->query($query);
805 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
806 $tmp_array['id'] = (int) $row->condition_id;
807 $tmp_array['target_ref_id'] = (int) $row->target_ref_id;
808 $tmp_array['target_obj_id'] = (int) $row->target_obj_id;
809 $tmp_array['target_type'] = (string) $row->target_type;
810 $tmp_array['trigger_ref_id'] = (int) $row->trigger_ref_id;
811 $tmp_array['trigger_obj_id'] = (int) $row->trigger_obj_id;
812 $tmp_array['trigger_type'] = (string) $row->trigger_type;
813 $tmp_array['operator'] = (string) $row->operator;
814 $tmp_array['value'] = (string) $row->value;
815 $tmp_array['ref_handling'] = (int) $row->ref_handling;
816 $tmp_array['obligatory'] = (bool) $row->obligatory;
817 $tmp_array['hidden_status'] = (bool) $row->hidden_status;
818 $tmp_array['num_obligatory'] = (int) $row->num_obligatory;
819 return $tmp_array;
820 }
821 return [];
822 }
823
829 public static function _checkCondition(array $condition, int $a_usr_id = 0): bool
830 {
831 global $DIC;
832
833 $ilUser = $DIC['ilUser'];
834 $objDefinition = $DIC['objDefinition'];
835 $a_usr_id = $a_usr_id ?: $ilUser->getId();
836
837 // check lp
838 if ($condition['operator'] === self::OPERATOR_LP) {
839 return ilLPStatus::_hasUserCompleted($condition['trigger_obj_id'], $a_usr_id);
840 }
841 switch ($condition['trigger_type']) {
842 case 'crsg':
844 (int) $condition['trigger_obj_id'],
845 (string) $condition['operator'],
846 (string) $condition['value'],
847 (int) $a_usr_id
848 );
849 }
850 $class = $objDefinition->getClassName($condition['trigger_type']);
851 $location = $objDefinition->getLocation($condition['trigger_type']);
852 $full_class = "ilObj" . $class . "Access";
853 include_once($location . "/class." . $full_class . ".php");
854
855 if (!(is_a($full_class, "ilConditionHandling", true))) {
856 return false;
857 }
858
859 $fullfilled = call_user_func(
860 array($full_class, 'checkCondition'),
861 (int) $condition['trigger_obj_id'],
862 (string) $condition['operator'],
863 (string) $condition['value'],
864 (int) $a_usr_id
865 );
866 return $fullfilled;
867 }
868
870 int $a_target_ref_id,
871 int $a_target_obj_id,
872 string $a_obj_type = ''
873 ): array {
874 $conditions = self::_getEffectiveConditionsOfTarget($a_target_ref_id, $a_target_obj_id);
875
876 $opt = array();
877 foreach ($conditions as $con) {
878 if ($con['obligatory']) {
879 continue;
880 }
881 $opt[] = $con;
882 }
883 return $opt;
884 }
885
887 int $a_target_ref_id,
888 int $a_target_obj_id,
889 string $a_obj_type = ''
890 ): array {
891 $conditions = self::_getPersistedConditionsOfTarget($a_target_ref_id, $a_target_obj_id);
892
893 $opt = array();
894 foreach ($conditions as $con) {
895 if ($con['obligatory']) {
896 continue;
897 }
898 $opt[] = $con;
899 }
900 return $opt;
901 }
902
903 public static function lookupObligatoryConditionsOfTarget(int $a_target_ref_id, int $a_target_obj_id): int
904 {
905 global $DIC;
906
907 $ilDB = $DIC['ilDB'];
908
909 $query = 'SELECT max(num_obligatory) obl from conditions WHERE ' .
910 'target_ref_id = ' . $ilDB->quote($a_target_ref_id, 'integer') . ' ' .
911 'AND target_obj_id = ' . $ilDB->quote($a_target_obj_id, 'integer') . ' ' .
912 'GROUP BY (num_obligatory)';
913 $res = $ilDB->query($query);
914
915 $obl = 0;
916 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
917 $obl = (int) $row->obl;
918 }
919 return $obl;
920 }
921
923 int $a_target_ref_id,
924 int $a_target_obj_id,
925 string $a_target_obj_type = ''
926 ): int {
927 global $DIC;
928
929 $ilDB = $DIC['ilDB'];
930
931 // Get all conditions
932 $all = self::_getEffectiveConditionsOfTarget($a_target_ref_id, $a_target_obj_id, $a_target_obj_type);
933 $opt = self::getEffectiveOptionalConditionsOfTarget($a_target_ref_id, $a_target_obj_id, $a_target_obj_type);
934
935 $set_obl = 0;
936 if (isset($all[0])) {
937 $set_obl = $all[0]['num_obligatory'];
938 }
939
940 // existing value is valid
941 if ($set_obl > 0 &&
942 $set_obl < count($all) &&
943 $set_obl > (count($all) - count($opt) + 1)) {
944 return $set_obl;
945 }
946
947 if (count($opt)) {
948 $result = count($all) - count($opt) + 1;
949 } else {
950 $result = count($all);
951 }
952 return $result;
953 }
954
956 int $a_target_ref_id,
957 int $a_target_obj_id,
958 string $a_target_obj_type = '',
959 bool $a_force_update = false
960 ): int {
961 global $DIC;
962
963 $ilDB = $DIC['ilDB'];
964
965 // Get all conditions
966
967 self::resetCache();
968 $all = self::_getPersistedConditionsOfTarget($a_target_ref_id, $a_target_obj_id, $a_target_obj_type);
969 $opt = self::getPersistedOptionalConditionsOfTarget($a_target_ref_id, $a_target_obj_id, $a_target_obj_type);
970
971 $set_obl = 0;
972 if (isset($all[0])) {
973 $set_obl = $all[0]['num_obligatory'];
974 }
975
976 // existing value is valid
977 if ($set_obl > 0 &&
978 $set_obl < count($all) &&
979 $set_obl > (count($all) - count($opt) + 1)) {
980 return $set_obl;
981 }
982
983 if (count($opt)) {
984 $result = count($all) - count($opt) + 1;
985 } else {
986 $result = count($all);
987 }
988 if ($a_force_update) {
989 self::saveNumberOfRequiredTriggers($a_target_ref_id, $a_target_obj_id, $result);
990 }
991 return $result;
992 }
993
994 public static function saveNumberOfRequiredTriggers(int $a_target_ref_id, int $a_target_obj_id, int $a_num): void
995 {
996 global $DIC;
997
998 $ilDB = $DIC['ilDB'];
999
1000 $query = 'UPDATE conditions ' .
1001 'SET num_obligatory = ' . $ilDB->quote($a_num, 'integer') . ' ' .
1002 'WHERE target_ref_id = ' . $ilDB->quote($a_target_ref_id, 'integer') . ' ' .
1003 'AND target_obj_id = ' . $ilDB->quote($a_target_obj_id, 'integer');
1004 $ilDB->manipulate($query);
1005 }
1006
1011 public static function _checkAllConditionsOfTarget(
1012 int $a_target_ref_id,
1013 int $a_target_id,
1014 string $a_target_type = "",
1015 int $a_usr_id = 0
1016 ): bool {
1017 global $DIC;
1018
1019 $ilUser = $DIC['ilUser'];
1020 $tree = $DIC['tree'];
1021 $logger = $DIC->logger()->ac();
1022
1023 $a_usr_id = $a_usr_id ?: $ilUser->getId();
1024 $conditions = self::_getEffectiveConditionsOfTarget(
1025 $a_target_ref_id,
1026 $a_target_id,
1027 $a_target_type
1028 );
1029 if (!count($conditions)) {
1030 return true;
1031 }
1032
1033 if (ilMemberViewSettings::getInstance()->isActive()) {
1034 return true;
1035 }
1036
1037 // First check obligatory conditions
1038 $optional = self::getEffectiveOptionalConditionsOfTarget($a_target_ref_id, $a_target_id, $a_target_type);
1039 $num_required = self::calculateEffectiveRequiredTriggers($a_target_ref_id, $a_target_id, $a_target_type);
1040 $passed = 0;
1041 foreach ($conditions as $condition) {
1042 if ($tree->isDeleted($condition['trigger_ref_id'])) {
1043 continue;
1044 }
1045 $check = self::_checkCondition($condition, $a_usr_id);
1046
1047 if ($check) {
1048 ++$passed;
1049 } else {
1050 // #0027223 if condition is obligatory => return false
1051 if ($condition['obligatory']) {
1052 return false;
1053 }
1054 }
1055 }
1056 return $passed >= $num_required;
1057 }
1058
1059 // PRIVATE
1060 protected function validate(): bool
1061 {
1062 // check if obj_id is already assigned
1063 $trigger_obj = ilObjectFactory::getInstanceByRefId($this->getTriggerRefId());
1064 $target_obj = ilObjectFactory::getInstanceByRefId($this->getTargetRefId());
1065
1066 if ($trigger_obj !== null && $target_obj !== null) {
1067 $query = "SELECT * FROM conditions WHERE " .
1068 "trigger_ref_id = " . $this->db->quote($trigger_obj->getRefId(), 'integer') . " " .
1069 "AND target_ref_id = " . $this->db->quote($target_obj->getRefId(), 'integer');
1070
1071 $res = $this->db->query($query);
1072
1073 if ($res->numRows() > 1) {
1074 $this->setErrorMessage($this->lng->txt('condition_already_assigned'));
1075
1076 unset($trigger_obj, $target_obj);
1077 return false;
1078 }
1079 // check for circle
1080 $this->target_obj_id = $target_obj->getId();
1081
1082 if ($this->checkCircle($this->getTargetRefId(), $target_obj->getId())) {
1083 $this->setErrorMessage($this->lng->txt('condition_circle_created'));
1084
1085 unset($trigger_obj, $target_obj);
1086 return false;
1087 }
1088 return true;
1089 }
1090 return false;
1091 }
1092
1093 protected function checkCircle(int $a_ref_id, int $a_obj_id): bool
1094 {
1095 foreach (self::_getPersistedConditionsOfTarget($a_ref_id, $a_obj_id) as $condition) {
1096 if ($condition['trigger_obj_id'] == $this->target_obj_id && $condition['operator'] === $this->getOperator()) {
1097 $this->circle = true;
1098 break;
1099 }
1100
1101 $this->checkCircle($condition['trigger_ref_id'], $condition['trigger_obj_id']);
1102 }
1103 return $this->circle;
1104 }
1105
1106 public static function cloneDependencies(int $a_src_ref_id, int $a_target_ref_id, int $a_copy_id): void
1107 {
1108 $cwo = ilCopyWizardOptions::_getInstance($a_copy_id);
1109 $mappings = $cwo->getMappings();
1110
1111 $valid = 0;
1112 $conditions = self::_getPersistedConditionsOfTarget(
1113 $a_src_ref_id,
1114 ilObject::_lookupObjId($a_src_ref_id)
1115 );
1116 foreach ($conditions as $con) {
1117 if ($mappings[$con['trigger_ref_id']] ?? false) {
1118 $newCondition = new ilConditionHandler();
1119
1120 $target_obj = ilObject::_lookupObjId($a_target_ref_id);
1121 $target_typ = ilObject::_lookupType($target_obj);
1122
1123 $newCondition->setTargetRefId($a_target_ref_id);
1124 $newCondition->setTargetObjId($target_obj);
1125 $newCondition->setTargetType($target_typ);
1126
1127 $trigger_ref = $mappings[$con['trigger_ref_id']];
1128 $trigger_obj = ilObject::_lookupObjId($trigger_ref);
1129 $trigger_typ = ilObject::_lookupType($trigger_obj);
1130
1131 $newCondition->setTriggerRefId($trigger_ref);
1132 $newCondition->setTriggerObjId($trigger_obj);
1133 $newCondition->setTriggerType($trigger_typ);
1134 $newCondition->setOperator($con['operator']);
1135 $newCondition->setValue($con['value']);
1136 $newCondition->setReferenceHandlingType($con['ref_handling']);
1137 $newCondition->setObligatory($con['obligatory']);
1138
1139 // :TODO: not sure about this
1140 $newCondition->setHiddenStatus(self::lookupPersistedHiddenStatusByTarget($a_src_ref_id));
1141
1142 if ($newCondition->storeCondition()) {
1143 $valid++;
1144
1145 //Copy num_obligatory, to be checked below
1146 self::saveNumberOfRequiredTriggers(
1147 $a_target_ref_id,
1148 $target_obj,
1149 $con['num_obligatory']
1150 );
1151 }
1152 }
1153 }
1154 if ($valid) {
1155 $tgt_obj_id = ilObject::_lookupObjId($a_target_ref_id);
1156
1157 // num_obligatory
1158 self::calculatePersistedRequiredTriggers(
1159 $a_target_ref_id,
1160 $tgt_obj_id,
1161 ilObject::_lookupType($tgt_obj_id),
1162 true
1163 );
1164 }
1165 }
1166}
$check
Definition: buildRTE.php:81
$location
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: buildRTE.php:22
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getTargetType()
get target obj type
static getPersistedOptionalConditionsOfTarget(int $a_target_ref_id, int $a_target_obj_id, string $a_obj_type='')
static _getPersistedConditionsOfTarget(int $a_target_ref_id, int $a_target_obj_id, string $a_target_type="")
get all persisted conditions of target object
static preloadPersistedConditionsForTargetRecords(string $a_type, array $a_obj_ids)
setTargetType(string $a_target_type)
set target object type
checkCircle(int $a_ref_id, int $a_obj_id)
deleteByObjId(int $a_obj_id)
delete all trigger and target entries This method is called from ilObject::delete() if an object is r...
getTriggerType()
get trigger obj type
static saveNumberOfRequiredTriggers(int $a_target_ref_id, int $a_target_obj_id, int $a_num)
getOperatorsByTriggerType(string $a_type)
setTriggerType(string $a_trigger_type)
set trigger object type
static calculateEffectiveRequiredTriggers(int $a_target_ref_id, int $a_target_obj_id, string $a_target_obj_type='')
getObligatory()
Get obligatory status.
updateHiddenStatus(bool $a_status)
storeCondition()
store new condition in database
static _isReferenceHandlingOptional(string $a_type)
static _checkCondition(array $condition, int $a_usr_id=0)
checks wether a single condition is fulfilled every trigger object type must implement a static metho...
setOperator(string $a_operator)
static _getPersistedConditionsOfTrigger(string $a_trigger_obj_type, int $a_trigger_id)
Get all persisted conditions of trigger object Note: This only gets persisted conditions NOT (dynamic...
enableAutomaticValidation(bool $a_validate=true)
static cloneDependencies(int $a_src_ref_id, int $a_target_ref_id, int $a_copy_id)
static _adjustMovedObjectConditions(int $a_ref_id)
In the moment it is not allowed to create preconditions on objects that are located outside of a cour...
static _checkAllConditionsOfTarget(int $a_target_ref_id, int $a_target_id, string $a_target_type="", int $a_usr_id=0)
checks wether all conditions of a target object are fulfilled
static getEffectiveOptionalConditionsOfTarget(int $a_target_ref_id, int $a_target_obj_id, string $a_obj_type='')
setTriggerRefId(int $a_trigger_ref_id)
setTargetRefId(int $a_target_ref_id)
setObligatory(bool $a_obl)
Set obligatory status.
static lookupObligatoryConditionsOfTarget(int $a_target_ref_id, int $a_target_obj_id)
static _getCondition(int $a_id)
static updateObligatory(int $a_id, bool $a_status)
Toggle condition obligatory status.
static _deleteTargetConditionsByRefId(int $a_target_ref_id)
Delete conditions by target ref id Note: only conditions on the target type are deleted Conditions on...
static getNumberOfConditionsOfTrigger(string $a_trigger_obj_type, int $a_trigger_id)
get all conditions of trigger object
static calculatePersistedRequiredTriggers(int $a_target_ref_id, int $a_target_obj_id, string $a_target_obj_type='', bool $a_force_update=false)
static lookupPersistedHiddenStatusByTarget(int $a_target_ref_id)
setTriggerObjId(int $a_trigger_obj_id)
ilObjectDefinition $objDefinition
setTargetObjId(int $a_target_obj_id)
static _getInstance(int $a_copy_id)
static _hasUserCompleted(int $a_obj_id, int $a_user_id)
Lookup user object completion.
language handling
Component logger with individual log levels by component id.
static _checkCondition(int $trigger_obj_id, string $operator, $value, int $a_usr_id=0)
parses the objects.xml it handles the xml-description of all ilias objects
getClassName(string $obj_name)
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
static isSupportedObjectType(string $type)
static _lookupType(int $id, bool $reference=false)
static _lookupObjId(int $ref_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
isDeleted(int $a_node_id)
This is a wrapper for isSaved() with a more useful name.
getParentId(int $a_node_id)
get parent id of given node
$c
Definition: cli.php:38
$valid
global $DIC
Definition: feed.php:28
$ilUser
Definition: imgupload.php:34
Interface ilDBInterface.
quote($value, string $type)
query(string $query)
Run a (read-only) Query on the database.
$res
Definition: ltiservices.php:69
if($format !==null) $name
Definition: metadata.php:247
$query
$type
$rows
Definition: xhr_table.php:10