ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilConditionHandler.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
78{
79 public const string OPERATOR_PASSED = 'passed';
80 public const string OPERATOR_FINISHED = 'finished';
81 public const string OPERATOR_NOT_FINISHED = 'not_finished';
82 public const string OPERATOR_NOT_MEMBER = 'not_member';
83 public const string OPERATOR_FAILED = 'failed';
84 public const string OPERATOR_LP = 'learning_progress';
85 public const string OPERATOR_ACCREDITED_OR_PASSED = 'accredited_or_passed';
86
87 public const string OPERATOR_RESULT_RANGE_PERCENTAGE = 'result_range_percentage';
88
89 public const int UNIQUE_CONDITIONS = 1;
90
91 // conditions are used for all tree references of the target object.
92 // This is currently only used for lm chapters and likely to be abandonded in the future
93 public const int SHARED_CONDITIONS = 0;
94
95 public static array $cond_for_target_cache = array();
96 public static array $cond_target_rows = array();
97
98 protected ilDBInterface $db;
99 protected ilLanguage $lng;
101 protected ilTree $tree;
102 protected ilLogger $logger;
103
104 protected string $error_message = '';
105
106 protected int $target_obj_id = 0;
107 protected int $target_ref_id = 0;
108 protected string $target_type = '';
109 protected int $trigger_obj_id = 0;
110 protected int $trigger_ref_id = 0;
111 protected string $trigger_type = '';
113 protected string $operator = '';
114 protected string $value = '';
115 protected bool $validation = true;
116 private bool $circle = false;
117
118 private bool $obligatory = true;
119 private bool $hidden_status = false;
120
121 public function __construct()
122 {
123 global $DIC;
124
125 $this->db = $DIC->database();
126 $this->lng = $DIC->language();
127 $this->objDefinition = $DIC['objDefinition'];
128 $this->tree = $DIC->repositoryTree();
129 $this->logger = $DIC->logger()->ac();
130 $this->validation = true;
131 }
132
133 public static function resetCache(): void
134 {
135 self::$cond_for_target_cache = [];
136 self::$cond_target_rows = [];
137 }
138
142 public static function _isReferenceHandlingOptional(string $a_type): bool
143 {
144 return $a_type === 'st';
145 }
146
150 public static function lookupEffectiveHiddenStatusByTarget(int $a_target_ref_id): bool
151 {
152 global $DIC;
153
154 $obj_definition = $DIC['objDefinition'];
155 $tree = $DIC->repositoryTree();
156
157 // check if parent takes over control of condition
158 $parent_ref_id = $tree->getParentId($a_target_ref_id);
159 $parent_obj_id = ilObject::_lookupObjId($parent_ref_id);
160 $parent_type = ilObject::_lookupType($parent_obj_id);
161
162 $class = $obj_definition->getClassName($parent_type);
163 $class_name = "il" . $class . "ConditionController";
164 $location = $obj_definition->getLocation($parent_type);
165
166 // if yes, get from parent
167 if ($class !== "" && is_file($location . "/class." . $class_name . ".php")) {
169 $controller = new $class_name();
170 if ($controller->isContainerConditionController($parent_ref_id)) {
171 return (bool) $controller->getConditionSetForRepositoryObject($a_target_ref_id)->getHiddenStatus();
172 }
173 }
174 return self::lookupPersistedHiddenStatusByTarget($a_target_ref_id);
175 }
176
177 public static function lookupPersistedHiddenStatusByTarget(int $a_target_ref_id): bool
178 {
179 global $DIC;
180
181 $ilDB = $DIC->database();
182
183 $query = 'SELECT hidden_status FROM conditions ' .
184 'WHERE target_ref_id = ' . $ilDB->quote($a_target_ref_id, 'integer');
185 $res = $ilDB->query($query);
186 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
187 return (bool) $row->hidden_status;
188 }
189 return false;
190 }
191
198 public static function _adjustMovedObjectConditions(int $a_ref_id): bool
199 {
200 return true;
201 }
202
206 protected static function _getDistinctTargetRefIds(): array
207 {
208 global $DIC;
209
210 $ilDB = $DIC['ilDB'];
211
212 $query = "SELECT DISTINCT target_ref_id ref FROM conditions ";
213 $res = $ilDB->query($query);
214 $ref_ids = [];
215 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
216 $ref_ids[] = (int) $row->ref;
217 }
218 return $ref_ids;
219 }
220
226 protected static function _deleteTargetConditionsByRefId(int $a_target_ref_id): bool
227 {
228 global $DIC;
229
230 $ilDB = $DIC['ilDB'];
231
232 $query = "DELETE FROM conditions " .
233 "WHERE target_ref_id = " . $ilDB->quote($a_target_ref_id, 'integer') . " " .
234 "AND target_type != 'st' ";
235 $res = $ilDB->manipulate($query);
236 return true;
237 }
238
239 public function setReferenceHandlingType(int $a_type): void
240 {
241 $this->condition_reference_type = $a_type;
242 }
243
244 public function getReferenceHandlingType(): int
245 {
247 }
248
249 public function setErrorMessage(string $a_msg): void
250 {
251 $this->error_message = $a_msg;
252 }
253
254 public function getErrorMessage(): string
255 {
257 }
258
259 public function setTargetRefId(int $a_target_ref_id): void
260 {
261 $this->target_ref_id = $a_target_ref_id;
262 }
263
264 public function getTargetRefId(): int
265 {
267 }
268
269 public function setTargetObjId(int $a_target_obj_id): void
270 {
271 $this->target_obj_id = $a_target_obj_id;
272 }
273
274 public function getTargetObjId(): int
275 {
277 }
278
282 public function setTargetType(string $a_target_type): void
283 {
284 $this->target_type = $a_target_type;
285 }
286
290 public function getTargetType(): string
291 {
292 return $this->target_type;
293 }
294
295 public function setTriggerRefId(int $a_trigger_ref_id): void
296 {
297 $this->trigger_ref_id = $a_trigger_ref_id;
298 }
299
300 public function getTriggerRefId(): int
301 {
303 }
304
305 public function setTriggerObjId(int $a_trigger_obj_id): void
306 {
307 $this->trigger_obj_id = $a_trigger_obj_id;
308 }
309
310 public function getTriggerObjId(): int
311 {
313 }
314
318 public function setTriggerType(string $a_trigger_type): void
319 {
320 $this->trigger_type = $a_trigger_type;
321 }
322
326 public function getTriggerType(): string
327 {
328 return $this->trigger_type;
329 }
330
331 public function setOperator(string $a_operator): void
332 {
333 $this->operator = $a_operator;
334 }
335
336 public function getOperator(): string
337 {
338 return $this->operator;
339 }
340
341 public function setValue(string $a_value): void
342 {
343 $this->value = $a_value;
344 }
345
346 public function getValue(): string
347 {
348 return $this->value;
349 }
350
354 public function setObligatory(bool $a_obl): void
355 {
356 $this->obligatory = $a_obl;
357 }
358
362 public function getObligatory(): bool
363 {
364 return $this->obligatory;
365 }
366
367 public function setHiddenStatus(bool $a_status): void
368 {
369 $this->hidden_status = $a_status;
370 }
371
372 public function getHiddenStatus(): bool
373 {
375 }
376
377 public function enableAutomaticValidation(bool $a_validate = true): void
378 {
379 $this->validation = $a_validate;
380 }
381
382 public function getTriggerTypes(): array
383 {
384 $trigger_types = array('crs', 'exc', 'tst', 'sahs', 'svy', 'lm', 'iass', 'prg', 'copa', 'lti', 'cmix');
385
386 // Add operator lp trigger
388 // only if object type has lp
389 foreach ($this->objDefinition->getAllRepositoryTypes() as $t) {
390 if (ilObjectLP::isSupportedObjectType($t) && !in_array($t, $trigger_types, true)) {
391 $trigger_types[] = $t;
392 }
393 }
394 }
395 foreach ($this->objDefinition->getPlugins() as $p_type => $p_info) {
396 try {
397 $name = 'ilObj' . $p_info['class_name'] . 'Access';
398 $reflection = new ReflectionClass($name);
399 if ($reflection->implementsInterface('ilConditionHandling')) {
400 $trigger_types[] = $p_type;
401 }
402 } catch (ReflectionException $e) {
403 $this->logger->warning('Cannot create instance for ' . $name);
404 $this->logger->warning($e->getMessage());
405 }
406 }
407 $active_triggers = array();
408 foreach ($trigger_types as $type) {
409 if (count($this->getOperatorsByTriggerType($type))) {
410 $active_triggers[] = $type;
411 }
412 }
413 return $active_triggers;
414 }
415
419 public function getOperatorsByTriggerType(string $a_type): array
420 {
421 global $DIC;
422
423 $objDefinition = $DIC['objDefinition'];
424
425 if ($a_type === 'crsg') {
426 return ['not_member'];
427 }
428
429 $class = $objDefinition->getClassName($a_type);
431 $full_class = "ilObj" . $class . "Access";
432 $reflection = new ReflectionClass($full_class);
433 if ($reflection->implementsInterface('ilConditionHandling')) {
434 $operators = call_user_func(
435 array($full_class, 'getConditionOperators'),
436 $a_type
437 );
438 } else {
439 $operators = [];
440 }
441
442 // Add operator lp
444 // only if object type has lp
445
447 array_unshift($operators, self::OPERATOR_LP);
448 }
449 }
450 return $operators;
451 }
452
456 public function storeCondition(): bool
457 {
458 // first insert, then validate: it's easier to check for circles if the new condition is in the db table
459 $next_id = $this->db->nextId('conditions');
460 $query = 'INSERT INTO conditions (condition_id,target_ref_id,target_obj_id,target_type,' .
461 'trigger_ref_id,trigger_obj_id,trigger_type,operator,value,ref_handling,obligatory,hidden_status) ' .
462 'VALUES (' .
463 $this->db->quote($next_id, 'integer') . ',' .
464 $this->db->quote($this->getTargetRefId(), 'integer') . "," .
465 $this->db->quote($this->getTargetObjId(), 'integer') . "," .
466 $this->db->quote($this->getTargetType(), 'text') . "," .
467 $this->db->quote($this->getTriggerRefId(), 'integer') . "," .
468 $this->db->quote($this->getTriggerObjId(), 'integer') . "," .
469 $this->db->quote($this->getTriggerType(), 'text') . "," .
470 $this->db->quote($this->getOperator(), 'text') . "," .
471 $this->db->quote($this->getValue(), 'text') . ", " .
472 $this->db->quote($this->getReferenceHandlingType(), 'integer') . ', ' .
473 $this->db->quote($this->getObligatory(), 'integer') . ', ' .
474 $this->db->quote($this->getHiddenStatus(), 'integer') . ' ' .
475 ')';
476
477 $res = $this->db->manipulate($query);
478
479 if ($this->validation && !$this->validate()) {
480 $this->deleteCondition($next_id);
481 return false;
482 }
483 return true;
484 }
485
486 public function checkExists(): bool
487 {
488 $query = "SELECT * FROM conditions " .
489 "WHERE target_ref_id = " . $this->db->quote($this->getTargetRefId(), 'integer') . " " .
490 "AND target_obj_id = " . $this->db->quote($this->getTargetObjId(), 'integer') . " " .
491 "AND trigger_ref_id = " . $this->db->quote($this->getTriggerRefId(), 'integer') . " " .
492 "AND trigger_obj_id = " . $this->db->quote($this->getTriggerObjId(), 'integer') . " " .
493 "AND operator = " . $this->db->quote($this->getOperator(), 'text');
494 $res = $this->db->query($query);
495 return (bool) $res->numRows();
496 }
497
498 public function updateCondition(int $a_id): void
499 {
500 $query = "UPDATE conditions SET " .
501 "target_ref_id = " . $this->db->quote($this->getTargetRefId(), 'integer') . ", " .
502 "operator = " . $this->db->quote($this->getOperator(), 'text') . ", " .
503 "value = " . $this->db->quote($this->getValue(), 'text') . ", " .
504 "ref_handling = " . $this->db->quote($this->getReferenceHandlingType(), 'integer') . ", " .
505 'obligatory = ' . $this->db->quote($this->getObligatory(), 'integer') . ' ' .
506 "WHERE condition_id = " . $this->db->quote($a_id, 'integer');
507 $res = $this->db->manipulate($query);
508 }
509
510 public function updateHiddenStatus(bool $a_status): void
511 {
512 $query = 'UPDATE conditions SET ' .
513 'hidden_status = ' . $this->db->quote($a_status, 'integer') . ' ' .
514 'WHERE target_ref_id = ' . $this->db->quote($this->getTargetRefId(), 'integer');
515 $this->db->manipulate($query);
516 }
517
521 public static function updateObligatory(int $a_id, bool $a_status): void
522 {
523 global $DIC;
524
525 $ilDB = $DIC->database();
526 $query = "UPDATE conditions SET " .
527 'obligatory = ' . $ilDB->quote($a_status, 'integer') . ' ' .
528 "WHERE condition_id = " . $ilDB->quote($a_id, 'integer');
529 $res = $ilDB->manipulate($query);
530 }
531
536 public function delete(int $a_ref_id): void
537 {
538 $query = "DELETE FROM conditions WHERE " .
539 "target_ref_id = " . $this->db->quote($a_ref_id, 'integer') . " " .
540 "OR trigger_ref_id = " . $this->db->quote($a_ref_id, 'integer');
541 $res = $this->db->manipulate($query);
542 }
543
548 public function deleteByObjId(int $a_obj_id): void
549 {
550 $query = "DELETE FROM conditions WHERE " .
551 "target_obj_id = " . $this->db->quote($a_obj_id, 'integer') . " " .
552 "OR trigger_obj_id = " . $this->db->quote($a_obj_id, 'integer');
553 $res = $this->db->manipulate($query);
554 }
555
556 public function deleteCondition(int $a_id): void
557 {
558 $query = "DELETE FROM conditions " .
559 "WHERE condition_id = " . $this->db->quote($a_id, 'integer');
560 $res = $this->db->manipulate($query);
561 }
562
566 public static function getNumberOfConditionsOfTrigger(string $a_trigger_obj_type, int $a_trigger_id): int
567 {
568 global $DIC;
569 $db = $DIC->database();
570
571 $query = 'select count(*) num from conditions ' .
572 'where trigger_obj_id = ' . $db->quote($a_trigger_id, ilDBConstants::T_INTEGER) . ' ' .
573 'and trigger_type = ' . $db->quote($a_trigger_obj_type, ilDBConstants::T_TEXT);
574 $res = $db->query($query);
575 $row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT);
576 return (int) $row->num;
577 }
578
584 public static function _getPersistedConditionsOfTrigger(string $a_trigger_obj_type, int $a_trigger_id): array
585 {
586 global $DIC;
587
588 $ilDB = $DIC['ilDB'];
589
590 $query = "SELECT * FROM conditions " .
591 "WHERE trigger_obj_id = " . $ilDB->quote($a_trigger_id, 'integer') . " " .
592 " AND trigger_type = " . $ilDB->quote($a_trigger_obj_type, 'text');
593
594 $res = $ilDB->query($query);
595 $conditions = [];
596 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
597 $tmp_array = [];
598 $tmp_array['id'] = (int) $row->condition_id;
599 $tmp_array['target_ref_id'] = (int) $row->target_ref_id;
600 $tmp_array['target_obj_id'] = (int) $row->target_obj_id;
601 $tmp_array['target_type'] = (string) $row->target_type;
602 $tmp_array['trigger_ref_id'] = (int) $row->trigger_ref_id;
603 $tmp_array['trigger_obj_id'] = (int) $row->trigger_obj_id;
604 $tmp_array['trigger_type'] = (string) $row->trigger_type;
605 $tmp_array['operator'] = (string) $row->operator;
606 $tmp_array['value'] = (string) $row->value;
607 $tmp_array['ref_handling'] = (int) $row->ref_handling;
608 $tmp_array['obligatory'] = (bool) $row->obligatory;
609 $tmp_array['hidden_status'] = (bool) $row->hidden_status;
610 $conditions[] = $tmp_array;
611 }
612 return $conditions;
613 }
614
620 public static function _getEffectiveConditionsOfTarget(
621 int $a_target_ref_id,
622 int $a_target_obj_id,
623 string $a_target_type = ""
624 ): array {
625 global $DIC;
626
627 if ($a_target_ref_id === 0) {
628 return [];
629 }
630
631 $obj_definition = $DIC["objDefinition"];
632 $tree = $DIC->repositoryTree();
633
634 // get type if no type given
635 if ($a_target_type === "") {
636 $a_target_type = ilObject::_lookupType($a_target_obj_id);
637 }
638
639 // check if parent takes over control of condition
640 $parent_ref_id = $tree->getParentId($a_target_ref_id);
641 $parent_obj_id = ilObject::_lookupObjId($parent_ref_id);
642 $parent_type = ilObject::_lookupType($parent_obj_id);
643
644 $class = $obj_definition->getClassName($parent_type);
645 $class_name = "il" . $class . "ConditionController";
646 $location = $obj_definition->getLocation($parent_type);
647
648 // if yes, get from parent
649 if ($class !== "" && is_file($location . "/class." . $class_name . ".php")
650 && $a_target_type === ilObject::_lookupType($a_target_ref_id, true)) {
652 $controller = new $class_name();
653 if ($controller->isContainerConditionController($parent_ref_id)) {
655 $set = $controller->getConditionSetForRepositoryObject($a_target_ref_id);
656
657 // convert to old structure
658 $cond = [];
659 foreach ($set->getConditions() as $c) {
660 $obligatory = $set->getAllObligatory() || $c->getObligatory();
661 $trigger = $c->getTrigger();
662 $cond[] = array(
663 "target_ref_id" => $a_target_ref_id,
664 "target_obj_id" => $a_target_obj_id,
665 "target_type" => $a_target_type,
666 "trigger_ref_id" => $trigger->getRefId(),
667 "trigger_obj_id" => $trigger->getObjId(),
668 "trigger_type" => $trigger->getType(),
669 "operator" => $c->getOperator(),
670 "value" => $c->getValue(),
671 "ref_handling" => 1,
672 "obligatory" => $obligatory,
673 "num_obligatory" => $set->getNumObligatory(),
674 "hidden_status" => $set->getHiddenStatus()
675 );
676 }
677 return $cond;
678 }
679 }
680
681 return self::_getPersistedConditionsOfTarget($a_target_ref_id, $a_target_obj_id, $a_target_type);
682 }
683
688 public static function _getPersistedConditionsOfTarget(
689 int $a_target_ref_id,
690 int $a_target_obj_id,
691 string $a_target_type = ""
692 ): array {
693 global $DIC;
694
695 $ilDB = $DIC['ilDB'];
696
697 // get type if no type given
698 if ($a_target_type === "") {
699 $a_target_type = ilObject::_lookupType($a_target_obj_id);
700 }
701
702 // check conditions for target cache
703 if (isset(self::$cond_for_target_cache[$a_target_ref_id . ":" . $a_target_obj_id . ":" .
704 $a_target_type])) {
705 return self::$cond_for_target_cache[$a_target_ref_id . ":" . $a_target_obj_id . ":" .
706 $a_target_type];
707 }
708
709 // check rows cache
710 if (isset(self::$cond_target_rows[$a_target_type . ":" . $a_target_obj_id])) {
711 $rows = self::$cond_target_rows[$a_target_type . ":" . $a_target_obj_id];
712 } else {
713 // query data from db
714 $query = "SELECT * FROM conditions " .
715 "WHERE target_obj_id = " . $ilDB->quote($a_target_obj_id, 'integer') . " " .
716 " AND target_type = " . $ilDB->quote($a_target_type, 'text');
717
718 $res = $ilDB->query($query);
719 $rows = array();
720 while ($row = $ilDB->fetchAssoc($res)) {
721 $item = [];
722 $item['condition_id'] = (int) $row['condition_id'];
723 $item['target_ref_id'] = (int) $row['target_ref_id'];
724 $item['target_obj_id'] = (int) $row['target_obj_id'];
725 $item['trigger_ref_id'] = (int) $row['trigger_ref_id'];
726 $item['trigger_obj_id'] = (int) $row['trigger_obj_id'];
727 $item['target_type'] = (string) $row['target_type'];
728 $item['trigger_type'] = (string) $row['trigger_type'];
729 $item['operator'] = (string) $row['operator'];
730 $item['value'] = (string) $row['value'];
731 $item['ref_handling'] = (int) $row['ref_handling'];
732 $item['obligatory'] = (bool) $row['obligatory'];
733 $item['num_obligatory'] = (int) $row['num_obligatory'];
734 $item['hidden_status'] = (bool) $row['hidden_status'];
735
736 $rows[] = $item;
737 }
738 }
739
740 reset($rows);
741 $conditions = [];
742 foreach ($rows as $row) {
743 if (($row["ref_handling"] == self::UNIQUE_CONDITIONS) && $row["target_ref_id"] != $a_target_ref_id) {
744 continue;
745 }
746
747 $row["id"] = $row["condition_id"];
748 $conditions[] = $row;
749 }
750 // write conditions for target cache
751 self::$cond_for_target_cache[$a_target_ref_id . ":" . $a_target_obj_id . ":" .
752 $a_target_type] = $conditions;
753 return $conditions;
754 }
755
759 public static function preloadPersistedConditionsForTargetRecords(string $a_type, array $a_obj_ids): void
760 {
761 global $DIC;
762
763 $ilDB = $DIC['ilDB'];
764
765 if (is_array($a_obj_ids) && count($a_obj_ids) > 0) {
766 $res = $ilDB->query("SELECT * FROM conditions " .
767 "WHERE " . $ilDB->in("target_obj_id", $a_obj_ids, false, "integer") .
768 " AND target_type = " . $ilDB->quote($a_type, 'text'));
769 $rows = array();
770 while ($row = $ilDB->fetchAssoc($res)) {
771 $item = [];
772 $item['condition_id'] = (int) $row['condition_id'];
773 $item['target_ref_id'] = (int) $row['target_ref_id'];
774 $item['target_obj_id'] = (int) $row['target_obj_id'];
775 $item['trigger_ref_id'] = (int) $row['trigger_ref_id'];
776 $item['trigger_obj_id'] = (int) $row['trigger_obj_id'];
777 $item['target_type'] = (string) $row['target_type'];
778 $item['trigger_type'] = (string) $row['trigger_type'];
779 $item['operator'] = (string) $row['operator'];
780 $item['value'] = (string) $row['value'];
781 $item['ref_handling'] = (int) $row['ref_handling'];
782 $item['obligatory'] = (bool) $row['obligatory'];
783 $item['num_obligatory'] = (int) $row['num_obligatory'];
784 $item['hidden_status'] = (bool) $row['hidden_status'];
785 self::$cond_target_rows[$a_type . ":" . $row["target_obj_id"]][] = $item;
786 }
787 // init obj ids without any record
788 foreach ($a_obj_ids as $obj_id) {
789 if (!isset(self::$cond_target_rows[$a_type . ":" . $obj_id])) {
790 self::$cond_target_rows[$a_type . ":" . $obj_id] = array();
791 }
792 }
793 }
794 }
795
796 public static function _getCondition(int $a_id): array
797 {
798 global $DIC;
799
800 $ilDB = $DIC['ilDB'];
801
802 $query = "SELECT * FROM conditions " .
803 "WHERE condition_id = " . $ilDB->quote($a_id, 'integer');
804
805 $res = $ilDB->query($query);
806 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
807 $tmp_array['id'] = (int) $row->condition_id;
808 $tmp_array['target_ref_id'] = (int) $row->target_ref_id;
809 $tmp_array['target_obj_id'] = (int) $row->target_obj_id;
810 $tmp_array['target_type'] = (string) $row->target_type;
811 $tmp_array['trigger_ref_id'] = (int) $row->trigger_ref_id;
812 $tmp_array['trigger_obj_id'] = (int) $row->trigger_obj_id;
813 $tmp_array['trigger_type'] = (string) $row->trigger_type;
814 $tmp_array['operator'] = (string) $row->operator;
815 $tmp_array['value'] = (string) $row->value;
816 $tmp_array['ref_handling'] = (int) $row->ref_handling;
817 $tmp_array['obligatory'] = (bool) $row->obligatory;
818 $tmp_array['hidden_status'] = (bool) $row->hidden_status;
819 $tmp_array['num_obligatory'] = (int) $row->num_obligatory;
820 return $tmp_array;
821 }
822 return [];
823 }
824
830 public static function _checkCondition(array $condition, int $a_usr_id = 0): bool
831 {
832 global $DIC;
833
834 $ilUser = $DIC['ilUser'];
835 $objDefinition = $DIC['objDefinition'];
836 $a_usr_id = $a_usr_id ?: $ilUser->getId();
837
838 // check lp
839 if ($condition['operator'] === self::OPERATOR_LP) {
840 return ilLPStatus::_hasUserCompleted($condition['trigger_obj_id'], $a_usr_id);
841 }
842 switch ($condition['trigger_type']) {
843 case 'crsg':
845 (int) $condition['trigger_obj_id'],
846 (string) $condition['operator'],
847 (string) $condition['value'],
848 (int) $a_usr_id
849 );
850 }
851 $class = $objDefinition->getClassName($condition['trigger_type']);
852 $location = $objDefinition->getLocation($condition['trigger_type']);
853 $full_class = "ilObj" . $class . "Access";
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
1005 $ilDB->manipulate($query);
1006 }
1007
1012 public static function _checkAllConditionsOfTarget(
1013 int $a_target_ref_id,
1014 int $a_target_id,
1015 string $a_target_type = "",
1016 int $a_usr_id = 0
1017 ): bool {
1018 global $DIC;
1019
1020 $ilUser = $DIC['ilUser'];
1021 $tree = $DIC['tree'];
1022 $logger = $DIC->logger()->ac();
1023
1024 $a_usr_id = $a_usr_id ?: $ilUser->getId();
1025 $conditions = self::_getEffectiveConditionsOfTarget(
1026 $a_target_ref_id,
1027 $a_target_id,
1028 $a_target_type
1029 );
1030 if (!count($conditions)) {
1031 return true;
1032 }
1033
1034 if (ilMemberViewSettings::getInstance()->isActive()) {
1035 return true;
1036 }
1037
1038 // First check obligatory conditions
1039 $optional = self::getEffectiveOptionalConditionsOfTarget($a_target_ref_id, $a_target_id, $a_target_type);
1040 $num_required = self::calculateEffectiveRequiredTriggers($a_target_ref_id, $a_target_id, $a_target_type);
1041 $passed = 0;
1042 foreach ($conditions as $condition) {
1043 if ($tree->isDeleted($condition['trigger_ref_id'])) {
1044 continue;
1045 }
1046 $check = self::_checkCondition($condition, $a_usr_id);
1047
1048 if ($check) {
1049 ++$passed;
1050 } else {
1051 // #0027223 if condition is obligatory => return false
1052 if ($condition['obligatory']) {
1053 return false;
1054 }
1055 }
1056 }
1057 return $passed >= $num_required;
1058 }
1059
1060 // PRIVATE
1061 protected function validate(): bool
1062 {
1063 // check if obj_id is already assigned
1064 $trigger_obj = ilObjectFactory::getInstanceByRefId($this->getTriggerRefId());
1065 $target_obj = ilObjectFactory::getInstanceByRefId($this->getTargetRefId());
1066
1067 if ($trigger_obj !== null && $target_obj !== null) {
1068 // check for circle
1069 $this->target_obj_id = $target_obj->getId();
1070
1071 if ($this->checkCircle($this->getTargetRefId(), $target_obj->getId())) {
1072 $this->setErrorMessage($this->lng->txt('condition_circle_created'));
1073
1074 unset($trigger_obj, $target_obj);
1075 return false;
1076 }
1077 return true;
1078 }
1079 return false;
1080 }
1081
1082 protected function checkCircle(int $a_ref_id, int $a_obj_id): bool
1083 {
1084 foreach (self::_getPersistedConditionsOfTarget($a_ref_id, $a_obj_id) as $condition) {
1085 if ($condition['trigger_obj_id'] == $this->target_obj_id) {
1086 $this->circle = true;
1087 break;
1088 }
1089
1090 $this->checkCircle($condition['trigger_ref_id'], $condition['trigger_obj_id']);
1091 }
1092 return $this->circle;
1093 }
1094
1095 public static function cloneDependencies(int $a_src_ref_id, int $a_target_ref_id, int $a_copy_id): void
1096 {
1097 $cwo = ilCopyWizardOptions::_getInstance($a_copy_id);
1098 $mappings = $cwo->getMappings();
1099
1100 $valid = 0;
1101 $conditions = self::_getPersistedConditionsOfTarget(
1102 $a_src_ref_id,
1103 ilObject::_lookupObjId($a_src_ref_id)
1104 );
1105 foreach ($conditions as $con) {
1106 if ($mappings[$con['trigger_ref_id']] ?? false) {
1107 $newCondition = new ilConditionHandler();
1108
1109 $target_obj = ilObject::_lookupObjId($a_target_ref_id);
1110 $target_typ = ilObject::_lookupType($target_obj);
1111
1112 $newCondition->setTargetRefId($a_target_ref_id);
1113 $newCondition->setTargetObjId($target_obj);
1114 $newCondition->setTargetType($target_typ);
1115
1116 $trigger_ref = $mappings[$con['trigger_ref_id']];
1117 $trigger_obj = ilObject::_lookupObjId($trigger_ref);
1118 $trigger_typ = ilObject::_lookupType($trigger_obj);
1119
1120 $newCondition->setTriggerRefId($trigger_ref);
1121 $newCondition->setTriggerObjId($trigger_obj);
1122 $newCondition->setTriggerType($trigger_typ);
1123 $newCondition->setOperator($con['operator']);
1124 $newCondition->setValue($con['value']);
1125 $newCondition->setReferenceHandlingType($con['ref_handling']);
1126 $newCondition->setObligatory($con['obligatory']);
1127
1128 // :TODO: not sure about this
1129 $newCondition->setHiddenStatus(self::lookupPersistedHiddenStatusByTarget($a_src_ref_id));
1130
1131 if ($newCondition->storeCondition()) {
1132 $valid++;
1133
1134 //Copy num_obligatory, to be checked below
1135 self::saveNumberOfRequiredTriggers(
1136 $a_target_ref_id,
1137 $target_obj,
1138 $con['num_obligatory']
1139 );
1140 }
1141 }
1142 }
1143 if ($valid) {
1144 $tgt_obj_id = ilObject::_lookupObjId($a_target_ref_id);
1145
1146 // num_obligatory
1147 self::calculatePersistedRequiredTriggers(
1148 $a_target_ref_id,
1149 $tgt_obj_id,
1150 ilObject::_lookupType($tgt_obj_id),
1151 true
1152 );
1153 }
1154 }
1155}
$check
Definition: buildRTE.php:81
$location
Definition: buildRTE.php:22
INTERNAL CLASS: Please do not use in consumer code.
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...
const string OPERATOR_RESULT_RANGE_PERCENTAGE
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...
const string OPERATOR_ACCREDITED_OR_PASSED
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)
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
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: deliver.php:25
$valid
Interface ilDBInterface.
quote($value, string $type)
query(string $query)
Run a (read-only) Query on the database.
$res
Definition: ltiservices.php:69
global $DIC
Definition: shib_login.php:26