ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilObjectActivation.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
28{
29 public const ERR_SUG_START_END = 1;
30
31 public const TIMINGS_ACTIVATION = 0;
32 public const TIMINGS_DEACTIVATED = 1;
33 public const TIMINGS_PRESETTING = 2;
34 public const TIMINGS_FIXED = 3; // session only => obsolete?
35
36 protected static array $preloaded_data = [];
37
39 protected ilLanguage $lng;
40 protected ilDBInterface $db;
41
42 protected int $timing_type = 0;
43 protected ?int $timing_start = null;
44 protected ?int $timing_end = null;
45 protected ?int $suggestion_start = null;
46 protected ?int $suggestion_end = null;
47 protected bool $visible = false;
48 protected int $changeable = 0;
49
50 protected ?int $suggestion_start_rel = null;
51 protected ?int $suggestion_end_rel = null;
52
53 public function __construct()
54 {
55 global $DIC;
56
57 $this->error = $DIC["ilErr"];
58 $this->lng = $DIC->language();
59 $this->db = $DIC->database();
60 }
61
62 public function setTimingType(int $type): void
63 {
64 $this->timing_type = $type;
65 }
66
67 public function getTimingType(): int
68 {
69 return $this->timing_type;
70 }
71
72 public function setTimingStart(?int $start): void
73 {
74 $this->timing_start = $start;
75 }
76
77 public function getTimingStart(): ?int
78 {
80 }
81
82 public function setTimingEnd(?int $end): void
83 {
84 $this->timing_end = $end;
85 }
86
87 public function getTimingEnd(): ?int
88 {
89 return $this->timing_end;
90 }
91
92 public function setSuggestionStart(?int $start): void
93 {
94 if ($start === 0) {
95 $start = null;
96 }
97 $this->suggestion_start = $start;
98 }
99
100 public function setSuggestionStartRelative(?int $start): void
101 {
102 if ($start === 0) {
103 $start = null;
104 }
105 $this->suggestion_start_rel = $start;
106 }
107
108 public function setSuggestionEndRelative(?int $end): void
109 {
110 if ($end === 0) {
111 $end = null;
112 }
113 $this->suggestion_end_rel = $end;
114 }
115
116 public function setSuggestionEnd(int $end): void
117 {
118 if ($end === 0) {
119 $end = null;
120 }
121 $this->suggestion_end = $end;
122 }
123
124 public function toggleVisible(bool $status): void
125 {
126 $this->visible = $status;
127 }
128
129 public function enabledVisible(): bool
130 {
131 return $this->visible;
132 }
133
134 public function toggleChangeable(bool $status): void
135 {
136 $this->changeable = (int) $status;
137 }
138
139 public function enabledChangeable(): bool
140 {
141 return (bool) $this->changeable;
142 }
143
144 public function update(int $ref_id, ?int $parent_id = null): bool
145 {
146 // #10110
147 $values = [
148 "timing_type" => ["integer", $this->getTimingType()],
149 "timing_start" => ["integer", $this->getTimingStart() ?? 0],
150 "timing_end" => ["integer", $this->getTimingEnd() ?? 0],
151 "suggestion_start" => ["integer", $this->suggestion_start ?? 0],
152 "suggestion_end" => ["integer", $this->suggestion_end ?? 0],
153 "changeable" => ["integer", (int) $this->enabledChangeable()],
154 "suggestion_start_rel" => ["integer", $this->suggestion_start_rel ?? 0],
155 "suggestion_end_rel" => ["integer", $this->suggestion_end_rel ?? 0],
156 "visible" => ["integer", $this->enabledVisible()]
157 ];
158
159 if (!is_null($parent_id)) {
160 $values["parent_id"] = ["integer", $parent_id];
161 }
162
163 $where = [
164 "obj_id" => ["integer", $ref_id]
165 ];
166
167 $this->db->update("crs_items", $values, $where);
168
169 unset(self::$preloaded_data[$ref_id]);
170
171 return true;
172 }
173
177 public static function preloadData(array $ref_ids): void
178 {
179 global $DIC;
180 $db = $DIC->database();
181
182 $sql =
183 "SELECT parent_id, obj_id, timing_type, timing_start, timing_end, suggestion_start," . PHP_EOL
184 . "suggestion_end, changeable, visible, position, suggestion_start_rel, suggestion_end_rel" . PHP_EOL
185 . "FROM crs_items" . PHP_EOL
186 . "WHERE " . $db->in("obj_id", $ref_ids, false, "integer") . PHP_EOL
187 ;
188 $set = $db->query($sql);
189 while ($row = $db->fetchAssoc($set)) {
190 self::$preloaded_data[$row["obj_id"]] = $row;
191 }
192 }
193
194 public static function getItem(int $ref_id): array
195 {
196 global $DIC;
197
198 $db = $DIC->database();
199
200 if (isset(self::$preloaded_data[$ref_id])) {
201 return self::$preloaded_data[$ref_id];
202 }
203
204 $sql =
205 "SELECT parent_id, obj_id, timing_type, timing_start, timing_end, suggestion_start," . PHP_EOL
206 . "suggestion_end, changeable, visible, position, suggestion_start_rel, suggestion_end_rel" . PHP_EOL
207 . "FROM crs_items" . PHP_EOL
208 . "WHERE obj_id = " . $db->quote($ref_id, "integer") . PHP_EOL
209 ;
210 $set = $db->query($sql);
211 $row = $db->fetchAssoc($set);
212
213 if (!isset($row["obj_id"])) {
215 } else {
216 self::$preloaded_data[$row["obj_id"]] = $row;
217 }
218 return $row;
219 }
220
224 public static function addAdditionalSubItemInformation(array &$item): void
225 {
226 global $DIC;
227 $ilUser = $DIC->user();
228
229 $item_array = self::getItem((int) $item['ref_id']);
230
231 $item['obj_id'] = ($item['obj_id'] > 0)
232 ? $item['obj_id']
233 : ilObject::_lookupObjId((int) $item['ref_id']);
234 $item['type'] = ($item['type'] != '')
235 ? $item['type']
236 : ilObject::_lookupType((int) $item['obj_id']);
237
238 $item['timing_type'] = $item_array['timing_type'] ?? 0;
239
240 if ($item['timing_type'] == self::TIMINGS_PRESETTING &&
241 (
242 ($item_array['changeable'] ?? false) ||
244 )
245 ) {
246 // cognos-blu-patch: begin
247 $user_data = new ilTimingUser((int) $item['ref_id'], $ilUser->getId());
248 if ($user_data->isScheduled()) {
249 $item['start'] = $user_data->getStart()->get(IL_CAL_UNIX);
250 $item['end'] = $user_data->getEnd()->get(IL_CAL_UNIX);
251 $item['activation_info'] = 'crs_timings_planed_info';
252 } else {
253 $item['start'] = $item_array['suggestion_start'] ?? "";
254 $item['end'] = $item_array['suggestion_end'] ?? "";
255 $item['activation_info'] = 'crs_timings_suggested_info';
256 }
257 // cognos-blu-patch: end
258 } elseif (($item_array['timing_type'] ?? 0) == self::TIMINGS_PRESETTING) {
259 $item['start'] = $item_array['suggestion_start'] ?? "";
260 $item['end'] = $item_array['suggestion_end'] ?? "";
261 $item['activation_info'] = 'crs_timings_suggested_info';
262 } elseif (($item_array['timing_type'] ?? 0) == self::TIMINGS_ACTIVATION) {
263 $item['start'] = $item_array['timing_start'] ?? "";
264 $item['end'] = $item_array['timing_end'] ?? "";
265 $item['activation_info'] = 'obj_activation_list_gui';
266 }
267
268 // #7359 - session sorting should always base on appointment date
269 if ($item['type'] == 'sess') {
270 $info = ilSessionAppointment::_lookupAppointment((int) $item['obj_id']);
271 // #11987
272 $item['masked_start'] = $item['start'] ?? '';
273 $item['masked_end'] = $item['end'] ?? '';
274 $item['start'] = $info['start'] ?? '';
275 $item['end'] = $info['end'] ?? '';
276 }
277 }
278
282 public static function addListGUIActivationProperty(ilObjectListGUI $list_gui, array &$item): void
283 {
285 if (isset($item['timing_type'])) {
286 if (!isset($item['masked_start'])) {
287 $start = $item['start'] ?? 0;
288 $end = $item['end'] ?? 0;
289 } else {
290 $start = $item['masked_start'];
291 $end = $item['masked_end'];
292 }
293 $activation = '';
294 switch ($item['timing_type']) {
297 new ilDateTime($start, IL_CAL_UNIX),
298 new ilDateTime($end, IL_CAL_UNIX)
299 );
300 break;
301
304 new ilDate($start, IL_CAL_UNIX),
305 new ilDate($end, IL_CAL_UNIX)
306 );
307 break;
308 }
309 if ($activation != "") {
310 global $DIC;
311
312 $lng = $DIC->language();
313 $lng->loadLanguageModule('crs');
314
315 $list_gui->addCustomProperty(
316 $lng->txt($item['activation_info']),
317 $activation,
318 false,
319 true
320 );
321 }
322 }
323 }
324
328 protected static function createDefaultEntry(int $ref_id): array
329 {
330 global $DIC;
331
332 $db = $DIC->database();
333 $tree = $DIC->repositoryTree();
334
335 $parent_id = $tree->getParentId($ref_id);
336 if (!$parent_id) {
337 return [];
338 }
339
340 $ilAtomQuery = $db->buildAtomQuery();
341 $ilAtomQuery->addTableLock("crs_items");
342
343 $ilAtomQuery->addQueryCallable(function (ilDBInterface $db) use ($ref_id, $parent_id, &$item): void {
344 $sql =
345 "SELECT parent_id, obj_id, timing_type, timing_start, timing_end, suggestion_start," . PHP_EOL
346 . "suggestion_end, changeable, visible, position, suggestion_start_rel, suggestion_end_rel" . PHP_EOL
347 . "FROM crs_items" . PHP_EOL
348 . "WHERE obj_id = " . $db->quote($ref_id, "integer") . PHP_EOL
349 ;
350 $set = $db->query($sql);
351 if (!$db->numRows($set)) {
352 $now = time();
353
354 $item = [];
355 $item["timing_type"] = self::TIMINGS_DEACTIVATED;
356 $item["timing_start"] = $now;
357 $item["timing_end"] = $now;
358 $item["suggestion_start"] = $now;
359 $item["suggestion_end"] = $now;
360 $item['visible'] = 0;
361 $item['changeable'] = 0;
362
363 $values = [
364 "parent_id" => ["integer", $parent_id],
365 "obj_id" => ["integer", $ref_id],
366 "timing_type" => ["integer", $item["timing_type"]],
367 "timing_start" => ["integer", $item["timing_start"]],
368 "timing_end" => ["integer", $item["timing_end"]],
369 "suggestion_start" => ["integer", $item["suggestion_start"]],
370 "suggestion_end" => ["integer", $item["suggestion_end"]],
371 "changeable" => ["integer", $item["changeable"]],
372 "visible" => ["integer", $item["visible"]],
373 "suggestion_start_rel" => ["integer", $item["suggestion_start_rel"] ?? 0],
374 "suggestion_end_rel" => ["integer", $item["suggestion_end_rel"] ?? 0],
375 "position" => ["integer", 0]
376 ];
377 $db->insert("crs_items", $values);
378 }
379 });
380
381 $ilAtomQuery->run();
382
383 // #9982 - to make getItem()-cache work
384 $item["obj_id"] = $ref_id;
385 $item["parent_id"] = $parent_id;
386
387 return $item;
388 }
389
393 public static function deleteAllEntries(int $ref_id): bool
394 {
395 global $DIC;
396
397 $db = $DIC->database();
398
399 if (!$ref_id) {
400 return false;
401 }
402
403 $sql =
404 "DELETE FROM crs_items " . PHP_EOL
405 . "WHERE obj_id = " . $db->quote($ref_id, 'integer') . PHP_EOL
406 ;
407 $db->manipulate($sql);
408
409 $sql =
410 "DELETE FROM crs_items " . PHP_EOL
411 . "WHERE parent_id = " . $db->quote($ref_id, 'integer') . PHP_EOL
412 ;
413 $db->manipulate($sql);
414
415 return true;
416 }
417
418 public static function cloneDependencies(int $ref_id, int $target_id, int $copy_id): void
419 {
420 global $DIC;
421
422 $ilLog = $DIC["ilLog"];
423
424 $ilLog->write(__METHOD__ . ': Begin course items...' . $ref_id);
425
426 $items = self::getItems($ref_id, false);
427 if (!$items) {
428 $ilLog->write(__METHOD__ . ': No course items found.');
429 return;
430 }
431
432 // new course item object
433 if (!is_object(ilObjectFactory::getInstanceByRefId($target_id, false))) {
434 $ilLog->write(__METHOD__ . ': Cannot create target object.');
435 return;
436 }
437
438 $cp_options = ilCopyWizardOptions::_getInstance($copy_id);
439 $mappings = $cp_options->getMappings();
440
441 foreach ($items as $item) {
442 if (!isset($mappings[$item['parent_id']]) or !$mappings[$item['parent_id']]) {
443 $ilLog->write(__METHOD__ . ': No mapping for parent nr. ' . $item['parent_id']);
444 continue;
445 }
446 if (!isset($mappings[$item['obj_id']]) or !$mappings[$item['obj_id']]) {
447 $ilLog->write(__METHOD__ . ': No mapping for item nr. ' . $item['obj_id']);
448 continue;
449 }
450 $new_item_id = $mappings[$item['obj_id']];
451 $new_parent = $mappings[$item['parent_id']];
452
453 $new_item = new self();
454 $new_item->setTimingType((int) $item['timing_type']);
455 $new_item->setTimingStart((int) $item['timing_start']);
456 $new_item->setTimingEnd((int) $item['timing_end']);
457 $new_item->setSuggestionStart((int) $item['suggestion_start']);
458 $new_item->setSuggestionEnd((int) $item['suggestion_end']);
459 $new_item->toggleChangeable((bool) $item['changeable']);
460 $new_item->toggleVisible((bool) $item['visible']);
461 $new_item->update($new_item_id, $new_parent);
462 $new_item->setSuggestionStartRelative((int) ($item['suggestion_start_rel'] ?? 0));
463 $new_item->setSuggestionEndRelative((int) ($item['suggestion_end_rel'] ?? 0));
464 $new_item->createDefaultEntry($new_item_id);
465 $new_item->update($new_item_id);
466 }
467 }
468
469
470 //
471 // TIMINGS VIEW RELATED (COURSE ONLY)
472 //
473
477 public static function hasTimings(int $ref_id): bool
478 {
479 global $DIC;
480
481 $tree = $DIC->repositoryTree();
482 $db = $DIC->database();
483
484 $subtree = $tree->getSubTree($tree->getNodeData($ref_id));
485 $ref_ids = [];
486 foreach ($subtree as $node) {
487 $ref_ids[] = $node['ref_id'];
488 }
489
490 $sql =
491 "SELECT parent_id" . PHP_EOL
492 . "FROM crs_items" . PHP_EOL
493 . "WHERE timing_type = " . $db->quote(self::TIMINGS_PRESETTING, 'integer') . PHP_EOL
494 . "AND " . $db->in('obj_id', $ref_ids, false, 'integer') . PHP_EOL
495 ;
496 $res = $db->query($sql);
497 return (bool) $res->numRows();
498 }
499
503 public static function hasChangeableTimings(int $ref_id): bool
504 {
505 global $DIC;
506
507 $tree = $DIC->repositoryTree();
508 $db = $DIC->database();
509
510 $subtree = $tree->getSubTree($tree->getNodeData($ref_id));
511 $ref_ids = [];
512 foreach ($subtree as $node) {
513 $ref_ids[] = $node['ref_id'];
514 }
515
516 $sql =
517 "SELECT parent_id" . PHP_EOL
518 . "FROM crs_items" . PHP_EOL
519 . "WHERE timing_type = " . $db->quote(self::TIMINGS_PRESETTING, 'integer') . PHP_EOL
520 . "AND changeable = " . $db->quote(1, 'integer') . PHP_EOL
521 . "AND " . $db->in('obj_id', $ref_ids, false, 'integer') . PHP_EOL
522 ;
523 $res = $db->query($sql);
524 return (bool) $res->numRows();
525 }
526
530 protected static function processListItems(array $ref_ids): array
531 {
532 global $DIC;
533
534 $tree = $DIC->repositoryTree();
535
536 $res = [];
537
538 foreach (array_map('intval', $ref_ids) as $item_ref_id) {
539 if ($tree->isDeleted($item_ref_id)) {
540 continue;
541 }
542 // #7571: when node is removed from system, e.g. inactive trashcan, an empty array is returned
543 $node = $tree->getNodeData($item_ref_id);
544 if (!isset($node["ref_id"]) || (int) $node["ref_id"] !== $item_ref_id) {
545 continue;
546 }
547 $res[$item_ref_id] = $node;
548 }
549
550 if (count($res)) {
551 self::preloadData(array_keys($res));
552 foreach ($res as $idx => $item) {
554 $res[$idx] = $item;
555 }
556 }
557
558 return array_values($res);
559 }
560
564 public static function getItemsByEvent(int $event_id): array
565 {
566 $event_items = new ilEventItems($event_id);
567 return self::processListItems($event_items->getItems());
568 }
569
573 public static function getItemsByItemGroup(int $item_group_ref_id): array
574 {
575 $ig_items = new ilItemGroupItems($item_group_ref_id);
576 $items = $ig_items->getValidItems();
577 return self::processListItems($items);
578 }
579
583 public static function getItemsByObjective(int $objective_id): array
584 {
585 $item_ids = ilCourseObjectiveMaterials::_getAssignedMaterials($objective_id);
586 return self::processListItems($item_ids);
587 }
588
592 public static function getItems(int $parent_id, bool $with_list_data = true): array
593 {
594 global $DIC;
595
596 $tree = $DIC->repositoryTree();
597
598 $items = [];
599
600 $ref_ids = [];
601 foreach ($tree->getChilds($parent_id) as $item) {
602 if ($item['type'] !== 'rolf') {
603 $items[] = $item;
604 $ref_ids[] = (int) $item['ref_id'];
605 }
606 }
607
608 if ($ref_ids) {
609 self::preloadData($ref_ids);
610
611 foreach ($items as $idx => $item) {
612 if (!$with_list_data) {
613 $items[$idx] = array_merge($item, self::getItem((int) $item['ref_id']));
614 } else {
616 $items[$idx] = $item;
617 }
618 }
619 }
620 return $items;
621 }
622
626 public static function getTimingsAdministrationItems(int $parent_id): array
627 {
628 $items = self::getItems($parent_id, false);
629 $active = $availability = $inactive = [];
630 foreach ($items as $item) {
631 if ($item['timing_type'] == self::TIMINGS_DEACTIVATED) {
632 $inactive[] = $item;
633 } elseif ($item['timing_type'] == self::TIMINGS_ACTIVATION) {
634 $availability[] = $item;
635 } else {
636 $active[] = $item;
637 }
638 }
639 $active = ilArrayUtil::sortArray($active, 'suggestion_start');
640 $availability = ilArrayUtil::sortArray($availability, 'timing_start');
641 $inactive = ilArrayUtil::sortArray($inactive, 'title');
642
643 $items = array_merge($active, $availability, $inactive);
644 return $items;
645 }
646
650 public static function getTimingsItems(int $container_ref_id): array
651 {
652 global $DIC;
653
654 $objDefinition = $DIC["objDefinition"];
655
656 $filtered = [];
657
658 $event_items = ilEventItems::_getItemsOfContainer($container_ref_id);
659 foreach (self::getTimingsAdministrationItems($container_ref_id) as $item) {
660 if (!in_array($item['ref_id'], $event_items) &&
661 !$objDefinition->isSideBlock($item['type'])) {
662 $filtered[] = $item;
663 }
664 }
665
666 return $filtered;
667 }
668
669 public function read(int $ref_id, int $parent_id = 0): void
670 {
671 global $DIC;
672 $db = $DIC->database();
673
674 $sql =
675 "SELECT parent_id, obj_id, timing_type, timing_start, timing_end, suggestion_start," . PHP_EOL
676 . "suggestion_end, changeable, visible, position, suggestion_start_rel, suggestion_end_rel" . PHP_EOL
677 . "FROM crs_items" . PHP_EOL
678 . "WHERE obj_id = " . $db->quote($ref_id, 'integer') . PHP_EOL
679 ;
680
681 if ($parent_id) {
682 $sql .= "AND parent_id = " . $db->quote($parent_id, "integer") . PHP_EOL;
683 }
684
685 $res = $db->query($sql);
686 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
687 $this->setSuggestionStart((int) $row->suggestion_start);
688 $this->setSuggestionEnd((int) $row->suggestion_end);
689 $this->setSuggestionStartRelative((int) $row->suggestion_start_rel);
690 $this->setSuggestionEndRelative((int) $row->suggestion_end_rel);
691 $this->toggleVisible((bool) $row->visible);
692 $this->toggleChangeable((bool) $row->changeable);
693 $this->setTimingType((int) $row->timing_type);
694 $this->setTimingStart((int) $row->timing_start);
695 $this->setTimingEnd((int) $row->timing_end);
696 }
697 }
698}
const IL_CAL_UNIX
error(string $a_errmsg)
static sortArray(array $array, string $a_array_sortby_key, string $a_array_sortorder="asc", bool $a_numeric=false, bool $a_keep_keys=false)
static _getInstance(int $a_copy_id)
static _getAssignedMaterials(int $a_objective_id)
static formatPeriod(ilDateTime $start, ilDateTime $end, bool $a_skip_starting_day=false, ?ilObjUser $user=null)
Format a period of two dates Shows: 14.
@classDescription Date and time handling
Class for single dates.
Error Handling & global info handling.
class ilEventItems
static _getItemsOfContainer(int $a_ref_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
language handling
loadLanguageModule(string $a_module)
Load language module.
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
static lookupTimingMode(int $a_obj_id)
Class ilObjectActivation.
static cloneDependencies(int $ref_id, int $target_id, int $copy_id)
static processListItems(array $ref_ids)
Validate ref ids and add list data.
static hasChangeableTimings(int $ref_id)
Check if there is any active changeable timing (in subtree)
update(int $ref_id, ?int $parent_id=null)
static getItemsByEvent(int $event_id)
Get session material / event items.
static getTimingsItems(int $container_ref_id)
Get (sub) item data for timings view (no session material, no side blocks)
static getTimingsAdministrationItems(int $parent_id)
Get (sub) item data for timings administration view (active/inactive)
static getItems(int $parent_id, bool $with_list_data=true)
Get sub item data.
static getItem(int $ref_id)
static getItemsByObjective(int $objective_id)
Get objective items.
static getItemsByItemGroup(int $item_group_ref_id)
Get materials of item group.
read(int $ref_id, int $parent_id=0)
static preloadData(array $ref_ids)
Preload data to internal cache.
static createDefaultEntry(int $ref_id)
Create db entry with default values.
static addAdditionalSubItemInformation(array &$item)
Parse item data for list entries.
static hasTimings(int $ref_id)
Check if there is any active timing (in subtree)
static addListGUIActivationProperty(ilObjectListGUI $list_gui, array &$item)
Get timing details for list gui.
static deleteAllEntries(int $ref_id)
Delete all db entries for ref id.
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
addCustomProperty(string $property='', string $value='', bool $alert=false, bool $newline=false)
static _lookupType(int $id, bool $reference=false)
static _lookupObjId(int $ref_id)
static _lookupAppointment(int $a_obj_id)
TableGUI class for timings administration.
$info
Definition: entry_point.php:21
Interface ilDBInterface.
numRows(ilDBStatement $statement)
quote($value, string $type)
manipulate(string $query)
Run a (write) Query on the database.
query(string $query)
Run a (read-only) Query on the database.
fetchAssoc(ilDBStatement $statement)
in(string $field, array $values, bool $negate=false, string $type="")
$ref_id
Definition: ltiauth.php:66
$res
Definition: ltiservices.php:69
global $DIC
Definition: shib_login.php:26