ILIAS  trunk Revision v12.0_alpha-1540-g00f839d5fa1
class.ilObject.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
27use ILIAS\Data\Factory as DataFactory;
28
38{
39 public const TITLE_LENGTH = 255; // title column max length in db
40 public const DESC_LENGTH = 128; // (short) description column max length in db
41 public const LONG_DESC_LENGTH = 4000; // long description column max length in db
42 public const TABLE_OBJECT_DATA = "object_data";
43 private const DATABASE_DATE_FORMAT = 'Y-m-d H:i:s';
44
46
47 protected ilLogger $obj_log;
48 protected ?ILIAS $ilias;
50 protected ilDBInterface $db;
51 protected ?ilLogger $log;
53 protected ilTree $tree;
57 protected ilObjUser $user;
58 protected ilLanguage $lng;
59 protected LOMServices $lom_services;
61 private TranslationsRepository $translations_repository;
62
63 protected bool $call_by_reference;
66 protected bool $add_dots = true;
67 protected ?int $ref_id = null;
68 protected string $type = "";
69 protected string $title = "";
70 protected string $desc = "";
71 protected string $long_desc = "";
72 protected int $owner = 0;
73 protected string $create_date = "";
74 protected string $last_update = "";
75 protected string $import_id = "";
76 protected bool $register = false; // registering required for object? set to true to implement a subscription interface
77
78 private bool $process_auto_reating = false;
79
80
84 public array $objectList;
85
86
87 // BEGIN WebDAV: WebDAV needs to access the untranslated title of an object
88 public string $untranslatedTitle;
89 // END WebDAV: WebDAV needs to access the untranslated title of an object
90
95 public function __construct(
96 protected int $id = 0,
97 protected bool $referenced = true
98 ) {
100 global $DIC;
101
102 $this->ilias = $DIC["ilias"];
103 $this->obj_definition = $DIC["objDefinition"];
104 $this->db = $DIC["ilDB"];
105 $this->log = $DIC["ilLog"];
106 $this->obj_log = ilLoggerFactory::getLogger("obj");
107 $this->error = $DIC["ilErr"];
108 $this->tree = $DIC["tree"];
109 $this->app_event_handler = $DIC["ilAppEventHandler"];
110 $this->lom_services = $DIC->learningObjectMetadata();
111 $object_dic = LocalDIC::dic();
112 $this->properties_aggregator = $object_dic['properties.aggregator'];
113 $this->translations_repository = $object_dic['properties.translations.repository'];
114
115 $this->call_by_reference = $this->referenced;
116
117 if (isset($DIC["lng"])) {
118 $this->lng = $DIC["lng"];
119 }
120
121 if (isset($DIC["ilUser"])) {
122 $this->user = $DIC["ilUser"];
123 }
124
125 if (isset($DIC["rbacadmin"])) {
126 $this->rbac_admin = $DIC["rbacadmin"];
127 }
128
129 if (isset($DIC["rbacreview"])) {
130 $this->rbac_review = $DIC["rbacreview"];
131 }
132
133 if ($id == 0) {
134 $this->referenced = false; // newly created objects are never referenced
135 } // they will get referenced if createReference() is called
136
137 if ($this->referenced) {
138 $this->ref_id = $id;
139 } else {
140 $this->id = $id;
141 }
142 // read object data
143 if ($id != 0) {
144 $this->read();
145 }
146 }
147
149 {
150 if ($this->object_properties === null) {
151 $this->object_properties = $this->properties_aggregator->getFor($this->id, $this->type);
152 }
154 }
155
159 public function flushObjectProperties(): void
160 {
161 $this->object_properties = null;
162 }
163
167 final public function withReferences(): bool
168 {
169 // both vars could differ. this method should always return true if one of them is true without changing their status
170 return ($this->call_by_reference) ? true : $this->referenced;
171 }
172
177 public function processAutoRating(): void
178 {
179 $this->process_auto_reating = true;
180 }
181
182 public function read(): void
183 {
184 global $DIC;
185 try {
186 $ilUser = $DIC["ilUser"];
187 } catch (InvalidArgumentException $e) {
188 }
189
190 if ($this->referenced) {
191 if (!isset($this->ref_id)) {
192 $message = "ilObject::read(): No ref_id given! (" . $this->type . ")";
193 $this->error->raiseError($message, $this->error->WARNING);
194 }
195
196 // read object data
197 $sql =
198 "SELECT od.obj_id, od.type, od.title, od.description, od.owner, od.create_date," . PHP_EOL
199 . "od.last_update, od.import_id, ore.ref_id, ore.obj_id, ore.deleted, ore.deleted_by" . PHP_EOL
200 . "FROM " . self::TABLE_OBJECT_DATA . " od" . PHP_EOL
201 . "JOIN object_reference ore ON od.obj_id = ore.obj_id" . PHP_EOL
202 . "WHERE ore.ref_id = " . $this->db->quote($this->ref_id, "integer") . PHP_EOL
203 ;
204
205 $result = $this->db->query($sql);
206
207 // check number of records
208 if ($this->db->numRows($result) === 0) {
209 $message = sprintf(
210 "ilObject::read(): Object with ref_id %s not found! (%s)",
211 $this->ref_id,
212 $this->type
213 );
214 $this->error->raiseError($message, $this->error->WARNING);
215 }
216 } else {
217 if (!isset($this->id)) {
218 $message = sprintf("ilObject::read(): No obj_id given! (%s)", $this->type);
219 $this->error->raiseError($message, $this->error->WARNING);
220 }
221
222 $sql =
223 "SELECT obj_id, type, title, description, owner, create_date, last_update, import_id, offline" . PHP_EOL
224 . "FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
225 . "WHERE obj_id = " . $this->db->quote($this->id, "integer") . PHP_EOL
226 ;
227 $result = $this->db->query($sql);
228
229 if ($this->db->numRows($result) === 0) {
230 $message = sprintf("ilObject::read(): Object with obj_id: %s (%s) not found!", $this->id, $this->type);
231 throw new ilObjectNotFoundException($message);
232 }
233 }
234 $obj = $this->db->fetchAssoc($result);
235
236 $this->id = (int) $obj["obj_id"];
237
238 // check type match (the "xxx" type is used for the unit test)
239 if ($this->type != $obj["type"] && $obj["type"] != "xxx") {
240 $message = sprintf(
241 "ilObject::read(): Type mismatch. Object with obj_id: %s was instantiated by type '%s'. DB type is: %s",
242 $this->id,
243 $this->type,
244 $obj["type"]
245 );
246
247 $this->log->write($message);
248 throw new ilObjectTypeMismatchException($message);
249 }
250
251 $this->type = (string) $obj["type"];
252 $this->title = (string) $obj["title"];
253 // BEGIN WebDAV: WebDAV needs to access the untranslated title of an object
254 $this->untranslatedTitle = (string) $obj["title"];
255 // END WebDAV: WebDAV needs to access the untranslated title of an object
256
257 $this->desc = (string) $obj["description"];
258 $this->owner = (int) $obj["owner"];
259 $this->create_date = (string) $obj["create_date"];
260 $this->last_update = (string) $obj["last_update"];
261 $this->import_id = (string) $obj["import_id"];
262
263 if ($this->obj_definition->isRBACObject($this->getType())) {
264 $sql =
265 "SELECT obj_id, description" . PHP_EOL
266 . "FROM object_description" . PHP_EOL
267 . "WHERE obj_id = " . $this->db->quote($this->id, 'integer') . PHP_EOL
268 ;
269
270 $res = $this->db->query($sql);
271
272 $this->long_desc = '';
273 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
274 if (($row->description ?? '') !== '') {
275 $this->setDescription($row->description);
276 }
277 }
278 }
279
280 $this->object_properties = null;
281
282 // multilingual support system objects (sys) & categories (db)
283 $translation_type = $this->obj_definition->getTranslationType($this->type);
284
285 if ($translation_type === 'sys') {
286 $this->title = $this->lng->txt("obj_{$this->type}");
287 $this->setDescription($this->lng->txt("obj_{$this->type}_desc"));
288 return;
289 }
290
291 if ($translation_type !== 'db') {
292 return;
293 }
294
295 $translation = $this->translations_repository->getFor($this->id);
296
297 $language = $translation->getLaguageForCode(
298 $ilUser->getCurrentLanguage()
299 ) ?? $translation->getLaguageForCode(
300 $translation->getDefaultLanguage()
301 );
302
303 if ($language === null) {
304 return;
305 }
306
307 $this->title = $language->getTitle();
308 $this->setDescription($language->getDescription());
309 }
310
311 public function getId(): int
312 {
313 return $this->id;
314 }
315
316 public function setId(int $id): void
317 {
318 $this->id = $id;
319 }
320
321 final public function setRefId(int $ref_id): void
322 {
323 $this->ref_id = $ref_id;
324 $this->referenced = true;
325 }
326
327 final public function getRefId(): int
328 {
329 return $this->ref_id ?? 0;
330 }
331
332 public function getType(): string
333 {
334 return $this->type;
335 }
336
337 final public function setType(string $type): void
338 {
339 $this->type = $type;
340 }
341
347 public function getPresentationTitle(): string
348 {
349 return $this->getTitle();
350 }
351
352 public function getTitle(): string
353 {
354 return $this->title;
355 }
356
361 final public function getUntranslatedTitle(): string
362 {
364 }
365
366 final public function setTitle(string $title): void
367 {
368 $property = $this->getObjectProperties()->getPropertyTitleAndDescription()->withTitle(
369 ilStr::shortenTextExtended($title, $this->max_title ?? self::TITLE_LENGTH, $this->add_dots)
370 );
371
372 $this->object_properties = $this->getObjectProperties()->withPropertyTitleAndDescription($property);
373
374 $this->title = $property->getTitle();
375
376 // WebDAV needs to access the untranslated title of an object
377 $this->untranslatedTitle = $this->title;
378 }
379
380 final public function getDescription(): string
381 {
382 return $this->desc;
383 }
384
385 final public function setDescription(string $description): void
386 {
387 $property = $this->getObjectProperties()
388 ->getPropertyTitleAndDescription()->withDescription($description);
389
390 $this->object_properties = $this->getObjectProperties()->withPropertyTitleAndDescription($property);
391
392 // Shortened form is storted in object_data. Long form is stored in object_description
393 $this->desc = $property->getDescription();
394 $this->long_desc = $property->getLongDescription();
395 }
396
400 public function getLongDescription(): string
401 {
402 if ($this->long_desc !== '') {
403 return $this->long_desc;
404 }
405
406 if ($this->desc !== '') {
407 return $this->desc;
408 }
409 return '';
410 }
411
412 final public function getImportId(): string
413 {
414 return $this->import_id;
415 }
416
417 final public function setImportId(string $import_id): void
418 {
419 $this->object_properties = $this->getObjectProperties()->withImportId($import_id);
420 $this->import_id = $import_id;
421 }
422
426 final public static function _lookupObjIdByImportId(string $import_id): int
427 {
428 global $DIC;
429 $db = $DIC->database();
430
431 $sql =
432 "SELECT obj_id" . PHP_EOL
433 . "FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
434 . "WHERE import_id = " . $db->quote($import_id, "text") . PHP_EOL
435 . "ORDER BY create_date DESC" . PHP_EOL
436 ;
437 $result = $db->query($sql);
438
439 if ($db->numRows($result) == 0) {
440 return 0;
441 }
442
443 $row = $db->fetchObject($result);
444
445 return (int) $row->obj_id;
446 }
447
451 public function setOfflineStatus(bool $status): void
452 {
453 $property_is_online = $this->getObjectProperties()->getPropertyIsOnline()->withOnline();
454 if ($status) {
455 $property_is_online = $property_is_online->withOffline();
456 }
457
458 $this->object_properties = $this->getObjectProperties()->withPropertyIsOnline($property_is_online);
459 }
460
461 public function getOfflineStatus(): bool
462 {
463 return !$this->getObjectProperties()->getPropertyIsOnline()->getIsOnline();
464 }
465
466 public function supportsOfflineHandling(): bool
467 {
468 return $this->obj_definition->supportsOfflineHandling($this->getType());
469 }
470
471 public static function _lookupImportId(int $obj_id): string
472 {
473 global $DIC;
474
475 $db = $DIC->database();
476
477 $sql =
478 "SELECT import_id" . PHP_EOL
479 . "FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
480 . "WHERE obj_id = " . $db->quote($obj_id, "integer") . PHP_EOL
481 ;
482
483 $res = $db->query($sql);
484 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
485 return (string) $row->import_id;
486 }
487 return '';
488 }
489
490 final public function getOwner(): int
491 {
492 return $this->owner;
493 }
494
498 final public function getOwnerName(): string
499 {
500 return ilObject::_lookupOwnerName($this->getOwner());
501 }
502
506 final public static function _lookupOwnerName(int $owner_id): string
507 {
508 global $DIC;
509 $lng = $DIC->language();
510
511 $owner = null;
512 if ($owner_id != -1) {
513 if (ilObjUser::userExists([$owner_id])) {
514 $owner = new ilObjUser($owner_id);
515 }
516 }
517
518 $own_name = $lng->txt("unknown");
519 if (is_object($owner)) {
520 $own_name = $owner->getFullname();
521 }
522
523 return $own_name;
524 }
525
526 final public function setOwner(int $usr_id): void
527 {
528 $this->owner = $usr_id;
529 }
530
534 final public function getCreateDate(): string
535 {
536 return $this->create_date;
537 }
538
542 final public function getLastUpdateDate(): string
543 {
544 return $this->last_update;
545 }
546
547
551 public function create(): int
552 {
553 global $DIC;
554 $user = $DIC["ilUser"];
555
556 if (!isset($this->type)) {
557 $message = sprintf("%s::create(): No object type given!", get_class($this));
558 $this->error->raiseError($message, $this->error->WARNING);
559 }
560
561 $this->log->write("ilObject::create(), start");
562
563 // determine owner
564 $owner = 0;
565 if ($this->getOwner() > 0) {
566 $owner = $this->getOwner();
567 } elseif (is_object($user)) {
568 $owner = $user->getId();
569 }
570
571 $now_string = (new DataFactory())->clock()->utc()->now()
572 ->format(self::DATABASE_DATE_FORMAT);
573
574 $this->id = $this->db->nextId(self::TABLE_OBJECT_DATA);
575 $values = [
576 "obj_id" => ["integer", $this->getId()],
577 "type" => ["text", $this->getType()],
578 "title" => ["text", $this->getTitle()],
579 "description" => ["text", $this->getDescription()],
580 "owner" => ["integer", $owner],
581 "create_date" => ["date", $now_string],
582 "last_update" => ["date", $now_string],
583 "import_id" => ["text", $this->getImportId()],
584 ];
585
586 $this->db->insert(self::TABLE_OBJECT_DATA, $values);
587 $this->object_properties = null;
588
589 // Save long form of description if is rbac object
590 if ($this->obj_definition->isRBACObject($this->getType())) {
591 $values = [
592 'obj_id' => ['integer',$this->id],
593 'description' => ['clob', $this->getLongDescription()]
594 ];
595 $this->db->insert('object_description', $values);
596 }
597
598 if ($this->supportsOfflineHandling()) {
599 $property_is_online = $this->getObjectProperties()->getPropertyIsOnline()->withOffline();
600 $this->getObjectProperties()->storePropertyIsOnline($property_is_online);
601 }
602
603 if ($this->obj_definition->isOrgUnitPermissionType($this->type)) {
604 ilOrgUnitGlobalSettings::getInstance()->saveDefaultPositionActivationStatus($this->id);
605 }
606
607 // the line ($this->read();) messes up meta data handling: meta data,
608 // that is not saved at this time, gets lost, so we query for the dates alone
609 $sql =
610 "SELECT last_update, create_date" . PHP_EOL
611 . "FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
612 . "WHERE obj_id = " . $this->db->quote($this->id, "integer") . PHP_EOL
613 ;
614 $obj_set = $this->db->query($sql);
615 $obj_rec = $this->db->fetchAssoc($obj_set);
616 $this->last_update = $obj_rec["last_update"];
617 $this->create_date = $obj_rec["create_date"];
618
619 // set owner for new objects
620 $this->setOwner($owner);
621
622 // write log entry
623 $this->log->write(
624 sprintf(
625 "ilObject::create(), finished, obj_id: %s, type: %s, title: %s",
626 $this->getId(),
627 $this->getType(),
628 $this->getTitle()
629 )
630 );
631
632 $this->app_event_handler->raise(
633 'components/ILIAS/ILIASObject',
634 'create',
635 [
636 'obj_id' => $this->id,
637 'obj_type' => $this->type
638 ]
639 );
640
641 return $this->id;
642 }
643
644 public function update(): bool
645 {
646 $this->getObjectProperties()->storeCoreProperties();
647
648 $this->app_event_handler->raise(
649 'components/ILIAS/ILIASObject',
650 'update',
651 [
652 'obj_id' => $this->getId(),
653 'obj_type' => $this->getType(),
654 'ref_id' => $this->getRefId()
655 ]
656 );
657
658 return true;
659 }
660
670 final public function MDUpdateListener(string $element): void
671 {
672 if ($this->beforeMDUpdateListener($element)) {
673 $this->app_event_handler->raise(
674 'components/ILIAS/ILIASObject',
675 'update',
676 ['obj_id' => $this->getId(),
677 'obj_type' => $this->getType(),
678 'ref_id' => $this->getRefId()
679 ]
680 );
681
682 // Update Title and description
683 if ($element == 'General') {
684 $paths = $this->lom_services->paths();
685 $reader = $this->lom_services->read(
686 $this->getId(),
687 0,
688 $this->getType(),
689 $paths->custom()->withNextStep('general')->get()
690 );
691
692 $this->setTitle($reader->firstData($paths->title())->value());
693 $this->setDescription($reader->firstData($paths->descriptions())->value());
694
695 $this->update();
696 }
697 $this->doMDUpdateListener($element);
698 }
699 }
700
701 protected function doMDUpdateListener(string $a_element): void
702 {
703 }
704
705 protected function beforeMDUpdateListener(string $a_element): bool
706 {
707 return true;
708 }
709
710 final public function createMetaData(): void
711 {
712 if ($this->beforeCreateMetaData()) {
713 global $DIC;
714 $ilUser = $DIC["ilUser"];
715
716 $this->lom_services->derive()->fromBasicProperties(
717 $this->getTitle(),
718 $this->getLongDescription(),
719 $ilUser->getPref('language') ?? ''
720 )->forObject($this->getId(), 0, $this->getType());
721
722 $this->doCreateMetaData();
723 }
724 }
725
726 protected function doCreateMetaData(): void
727 {
728 }
729
730 protected function beforeCreateMetaData(): bool
731 {
732 return true;
733 }
734
735 final public function updateMetaData(): void
736 {
737 if ($this->beforeUpdateMetaData()) {
738 $paths = $this->lom_services->paths();
739
740 $manipulator = $this->lom_services->manipulate($this->getId(), 0, $this->getType())
741 ->prepareCreateOrUpdate($paths->title(), $this->getTitle());
742
743 if ($this->getDescription() !== '') {
744 $manipulator = $manipulator->prepareCreateOrUpdate(
745 $paths->firstDescription(),
746 $this->getLongDescription()
747 );
748 } else {
749 $manipulator = $manipulator->prepareDelete($paths->firstDescription());
750 }
751
752 $manipulator->execute();
753 $this->doUpdateMetaData();
754 }
755 }
756
757 protected function doUpdateMetaData(): void
758 {
759 }
760
761 protected function beforeUpdateMetaData(): bool
762 {
763 return true;
764 }
765
766 final public function deleteMetaData(): void
767 {
768 if ($this->beforeDeleteMetaData()) {
769 $this->lom_services->deleteAll($this->getId(), 0, $this->getType());
770 $this->doDeleteMetaData();
771 }
772 }
773
774 protected function doDeleteMetaData(): void
775 {
776 }
777
778 protected function beforeDeleteMetaData(): bool
779 {
780 return true;
781 }
782
786 final public function updateOwner(): void
787 {
788 $values = [
789 "owner" => ["integer", $this->getOwner()],
790 "last_update" => [
791 "date",
792 (new DateTimeImmutable('@' . time(), new DateTimeZone('UTC')))
793 ->format(self::DATABASE_DATE_FORMAT)
794 ]
795 ];
796
797 $where = [
798 "obj_id" => ["integer", $this->getId()]
799 ];
800
801 $this->db->update(self::TABLE_OBJECT_DATA, $values, $where);
802
803 // get current values from database so last_update is updated as well
804 $this->read();
805 }
806
807 final public static function _getIdForImportId(string $import_id): int
808 {
809 global $DIC;
810 $db = $DIC->database();
811 $db->setLimit(1, 0);
812
813 $sql =
814 "SELECT obj_id" . PHP_EOL
815 . "FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
816 . "WHERE import_id = " . $db->quote($import_id, "text") . PHP_EOL
817 . "ORDER BY create_date DESC" . PHP_EOL
818 ;
819
820 $result = $db->query($sql);
821
822 if ($row = $db->fetchAssoc($result)) {
823 return (int) $row["obj_id"];
824 }
825
826 return 0;
827 }
828
833 final public static function _getAllReferences(int $id): array
834 {
835 global $DIC;
836 $db = $DIC->database();
837
838 $sql =
839 "SELECT ref_id" . PHP_EOL
840 . "FROM object_reference" . PHP_EOL
841 . "WHERE obj_id = " . $db->quote($id, 'integer') . PHP_EOL
842 ;
843
844 $result = $db->query($sql);
845
846 $ref = [];
847 while ($row = $db->fetchAssoc($result)) {
848 $ref[(int) $row["ref_id"]] = (int) $row["ref_id"];
849 }
850
851 return $ref;
852 }
853
854 public static function _lookupTitle(int $obj_id): string
855 {
856 global $DIC;
857 return (string) $DIC["ilObjDataCache"]->lookupTitle($obj_id);
858 }
859
863 public static function lookupOfflineStatus(int $obj_id): bool
864 {
865 global $DIC;
866 return $DIC['ilObjDataCache']->lookupOfflineStatus($obj_id);
867 }
868
872 final public static function _lookupOwner(int $obj_id): int
873 {
874 global $DIC;
875 return (int) $DIC["ilObjDataCache"]->lookupOwner($obj_id);
876 }
877
881 final public static function _getIdsForTitle(string $title, string $type = '', bool $partial_match = false): array
882 {
883 global $DIC;
884 $db = $DIC->database();
885
886 $where = "title = " . $db->quote($title, "text");
887 if ($partial_match) {
888 $where = $db->like("title", "text", '%' . $title . '%');
889 }
890
891 $sql =
892 "SELECT obj_id" . PHP_EOL
893 . "FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
894 . "WHERE " . $where . PHP_EOL
895 ;
896
897 if ($type != '') {
898 $sql .= " AND type = " . $db->quote($type, "text");
899 }
900
901 $result = $db->query($sql);
902
903 $object_ids = [];
904 while ($row = $db->fetchAssoc($result)) {
905 $object_ids[] = (int) $row['obj_id'];
906 }
907
908 return $object_ids;
909 }
910
911 final public static function _lookupDescription(int $obj_id): string
912 {
913 global $DIC;
914 return (string) $DIC["ilObjDataCache"]->lookupDescription($obj_id);
915 }
916
917 final public static function _lookupLastUpdate(int $obj_id, bool $formatted = false): string
918 {
919 global $DIC;
920
921 $last_update = $DIC["ilObjDataCache"]->lookupLastUpdate($obj_id);
922
923 if ($formatted) {
925 }
926
927 return (string) $last_update;
928 }
929
930 final public static function _getLastUpdateOfObjects(array $obj_ids): string
931 {
932 global $DIC;
933 $db = $DIC->database();
934
935 $sql =
936 "SELECT MAX(last_update) as last_update" . PHP_EOL
937 . "FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
938 . "WHERE " . $db->in("obj_id", $obj_ids, false, "integer") . PHP_EOL
939 ;
940
941 $result = $db->query($sql);
942 $row = $db->fetchAssoc($result);
943
944 return (string) $row["last_update"];
945 }
946
947 final public static function _lookupObjId(int $ref_id): int
948 {
949 global $DIC;
950 return $DIC["ilObjDataCache"]->lookupObjId($ref_id);
951 }
952
953 final public static function _setDeletedDate(int $ref_id, int $deleted_by): void
954 {
955 global $DIC;
956 $db = $DIC->database();
957
958 $values = [
959 "deleted" => ["date", $db->now()],
960 "deleted_by" => ["integer", $deleted_by]
961 ];
962
963 $where = [
964 "ref_id" => ["integer", $ref_id]
965 ];
966
967 $db->update("object_reference", $values, $where);
968 }
969
973 public static function setDeletedDates(array $ref_ids, int $user_id): void
974 {
975 global $DIC;
976 $db = $DIC->database();
977
978 $sql =
979 "UPDATE object_reference" . PHP_EOL
980 . "SET deleted = " . $db->now() . ", " . PHP_EOL
981 . "deleted_by = " . $db->quote($user_id, "integer") . PHP_EOL
982 . "WHERE " . $db->in("ref_id", $ref_ids, false, "integer") . PHP_EOL;
983
984 $db->manipulate($sql);
985 }
986
987 final public static function _resetDeletedDate(int $ref_id): void
988 {
989 global $DIC;
990 $db = $DIC->database();
991
992 $values = [
993 "deleted" => ["timestamp", null],
994 "deleted_by" => ["integer", 0]
995 ];
996
997 $where = [
998 "ref_id" => ["integer", $ref_id]
999 ];
1000
1001 $db->update("object_reference", $values, $where);
1002 }
1003
1004 final public static function _lookupDeletedDate(int $ref_id): ?string
1005 {
1006 global $DIC;
1007 $db = $DIC->database();
1008
1009 $sql =
1010 "SELECT deleted" . PHP_EOL
1011 . "FROM object_reference" . PHP_EOL
1012 . "WHERE ref_id = " . $db->quote($ref_id, "integer") . PHP_EOL
1013 ;
1014 $result = $db->query($sql);
1015 $row = $db->fetchAssoc($result);
1016
1017 return $row["deleted"] ?? null;
1018 }
1019
1023 final public static function _writeTitle(int $obj_id, string $title): void
1024 {
1025 global $DIC;
1026 $db = $DIC->database();
1027
1028 $values = [
1029 "title" => ["text", $title],
1030 "last_update" => ["date", $db->now()]
1031 ];
1032
1033 $where = [
1034 "obj_id" => ["integer", $obj_id]
1035 ];
1036
1037 $db->update(self::TABLE_OBJECT_DATA, $values, $where);
1038 }
1039
1043 final public static function _writeDescription(int $obj_id, string $desc): void
1044 {
1045 global $DIC;
1046
1047 $db = $DIC->database();
1048 $obj_definition = $DIC["objDefinition"];
1049
1050 $desc = ilStr::shortenTextExtended($desc, self::DESC_LENGTH, true);
1051
1052 $values = [
1053 "description" => ["text", $desc],
1054 "last_update" => ["date", $db->now()]
1055 ];
1056
1057 $where = [
1058 "obj_id" => ["integer", $obj_id]
1059 ];
1060
1061 $db->update(self::TABLE_OBJECT_DATA, $values, $where);
1062
1063
1065 // Update long description
1066 $sql =
1067 "SELECT obj_id, description" . PHP_EOL
1068 . "FROM object_description" . PHP_EOL
1069 . "WHERE obj_id = " . $db->quote($obj_id, 'integer') . PHP_EOL
1070 ;
1071 $result = $db->query($sql);
1072
1073 if ($result->numRows()) {
1074 $values = [
1075 "description" => ["clob", $desc]
1076 ];
1077 $db->update("object_description", $values, $where);
1078 } else {
1079 $values = [
1080 "description" => ["clob",$desc],
1081 "obj_id" => ["integer",$obj_id]
1082 ];
1083 $db->insert("object_description", $values);
1084 }
1085 }
1086 }
1087
1091 final public static function _writeImportId(int $obj_id, string $import_id): void
1092 {
1093 global $DIC;
1094 $db = $DIC->database();
1095
1096 $values = [
1097 "import_id" => ["text", $import_id],
1098 "last_update" => ["date", $db->now()]
1099 ];
1100
1101 $where = [
1102 "obj_id" => ["integer", $obj_id]
1103 ];
1104
1105 $db->update(self::TABLE_OBJECT_DATA, $values, $where);
1106 }
1107
1108 final public static function _lookupType(int $id, bool $reference = false): string
1109 {
1110 global $DIC;
1111
1112 if ($reference) {
1113 return $DIC["ilObjDataCache"]->lookupType($DIC["ilObjDataCache"]->lookupObjId($id));
1114 }
1115
1116 return $DIC["ilObjDataCache"]->lookupType($id);
1117 }
1118
1119 final public static function _isInTrash(int $ref_id): bool
1120 {
1121 global $DIC;
1122 return $DIC->repositoryTree()->isDeleted($ref_id);
1123 }
1124
1128 final public static function _hasUntrashedReference(int $obj_id): bool
1129 {
1130 $ref_ids = ilObject::_getAllReferences($obj_id);
1131 foreach ($ref_ids as $ref_id) {
1133 return true;
1134 }
1135 }
1136
1137 return false;
1138 }
1139
1140 final public static function _lookupObjectId(int $ref_id): int
1141 {
1142 global $DIC;
1143 return $DIC["ilObjDataCache"]->lookupObjId($ref_id);
1144 }
1145
1153 final public static function _getObjectsDataForType(string $type, bool $omit_trash = false): array
1154 {
1155 global $DIC;
1156 $db = $DIC->database();
1157
1158 $sql =
1159 "SELECT obj_id, type, title, description, owner, create_date, last_update, import_id, offline" . PHP_EOL
1160 . "FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
1161 . "WHERE type = " . $db->quote($type, "text") . PHP_EOL
1162 ;
1163 $result = $db->query($sql);
1164
1165 $objects = [];
1166 while ($row = $db->fetchAssoc($result)) {
1167 if ((!$omit_trash) || ilObject::_hasUntrashedReference((int) $row["obj_id"])) {
1168 $objects[$row["title"] . "." . $row["obj_id"]] = [
1169 "id" => $row["obj_id"],
1170 "type" => $row["type"],
1171 "title" => $row["title"],
1172 "description" => $row["description"]
1173 ];
1174 }
1175 }
1176 ksort($objects);
1177 return $objects;
1178 }
1179
1180
1186 public function putInTree(int $parent_ref_id): void
1187 {
1188 $this->tree->insertNode($this->getRefId(), $parent_ref_id);
1189 $this->handleAutoRating();
1190
1191 $log_entry = sprintf(
1192 "ilObject::putInTree(), parent_ref: %s, ref_id: %s, obj_id: %s, type: %s, title: %s",
1193 $parent_ref_id,
1194 $this->getRefId(),
1195 $this->getId(),
1196 $this->getType(),
1197 $this->getTitle()
1198 );
1199
1200 $this->log->write($log_entry);
1201
1202 $this->app_event_handler->raise(
1203 'components/ILIAS/ILIASObject',
1204 'putObjectInTree',
1205 [
1206 'object' => $this,
1207 'obj_type' => $this->getType(),
1208 'obj_id' => $this->getId(),
1209 'parent_ref_id' => $parent_ref_id
1210 ]
1211 );
1212 }
1213
1214 public function setPermissions(int $parent_ref_id): void
1215 {
1216 $this->setParentRolePermissions($parent_ref_id);
1217 $this->initDefaultRoles();
1218 }
1219
1225 public function setParentRolePermissions(int $parent_ref_id): bool
1226 {
1227 $parent_roles = $this->rbac_review->getParentRoleIds($parent_ref_id);
1228 foreach ($parent_roles as $parent_role) {
1229 if ($parent_role['obj_id'] == SYSTEM_ROLE_ID) {
1230 continue;
1231 }
1232 $operations = $this->rbac_review->getOperationsOfRole(
1233 (int) $parent_role['obj_id'],
1234 $this->getType(),
1235 (int) $parent_role['parent']
1236 );
1237 $this->rbac_admin->grantPermission(
1238 (int) $parent_role['obj_id'],
1239 $operations,
1240 $this->getRefId()
1241 );
1242 }
1243 return true;
1244 }
1245
1249 public function createReference(): int
1250 {
1251 if (!isset($this->id)) {
1252 $message = "ilObject::createNewReference(): No obj_id given!";
1253 $this->error->raiseError($message, $this->error->WARNING);
1254 }
1255
1256 $next_id = $this->db->nextId('object_reference');
1257
1258 $values = [
1259 "ref_id" => ["integer", $next_id],
1260 "obj_id" => ["integer", $this->getId()]
1261 ];
1262
1263 $this->db->insert("object_reference", $values);
1264
1265 $this->ref_id = $next_id;
1266 $this->referenced = true;
1267
1268 return $this->ref_id;
1269 }
1270
1271 final public function countReferences(): int
1272 {
1273 if (!isset($this->id)) {
1274 $message = "ilObject::countReferences(): No obj_id given!";
1275 $this->error->raiseError($message, $this->error->WARNING);
1276 }
1277
1278 $sql =
1279 "SELECT COUNT(ref_id) num" . PHP_EOL
1280 . "FROM object_reference" . PHP_EOL
1281 . "WHERE obj_id = " . $this->db->quote($this->id, 'integer') . PHP_EOL
1282 ;
1283
1284 $res = $this->db->query($sql);
1285 $row = $this->db->fetchObject($res);
1286
1287 return (int) $row->num;
1288 }
1289
1298 public function delete(): bool
1299 {
1300 global $DIC;
1301 $rbac_admin = $DIC["rbacadmin"];
1302
1303 $remove = false;
1304
1305 // delete object_data entry
1306 if ((!$this->referenced) || ($this->countReferences() == 1)) {
1307 $type = ilObject::_lookupType($this->getId());
1308 if ($this->type != $type) {
1309 $log_entry = sprintf(
1310 "ilObject::delete(): Type mismatch. Object with obj_id: %s was instantiated by type '%s'. DB type is: %s",
1311 $this->id,
1312 $this->type,
1313 $type
1314 );
1315
1316 $this->log->write($log_entry);
1317 $this->error->raiseError(
1318 sprintf("ilObject::delete(): Type mismatch. (%s/%s)", $this->type, $this->id),
1319 $this->error->WARNING
1320 );
1321 }
1322
1323 $this->app_event_handler->raise('components/ILIAS/ILIASObject', 'beforeDeletion', ['object' => $this]);
1324
1325 $this->getObjectProperties()->deletePropertyTranslations();
1326
1327 $sql =
1328 "DELETE FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
1329 . "WHERE obj_id = " . $this->db->quote($this->getId(), "integer") . PHP_EOL
1330 ;
1331 $this->db->manipulate($sql);
1332
1333 $sql =
1334 "DELETE FROM object_description" . PHP_EOL
1335 . "WHERE obj_id = " . $this->db->quote($this->getId(), "integer") . PHP_EOL
1336 ;
1337 $this->db->manipulate($sql);
1338
1339 $this->log->write(
1340 sprintf(
1341 "ilObject::delete(), deleted object, obj_id: %s, type: %s, title: %s",
1342 $this->getId(),
1343 $this->getType(),
1344 $this->getTitle()
1345 )
1346 );
1347
1348 // keep log of core object data
1350
1351 // remove news
1352 $news_item = new ilNewsItem();
1353 $news_item->deleteNewsOfContext($this->getId(), $this->getType());
1355
1357
1358 // BEGIN WebDAV: Delete WebDAV properties
1359 $sql =
1360 "DELETE FROM dav_property" . PHP_EOL
1361 . "WHERE obj_id = " . $this->db->quote($this->getId(), 'integer') . PHP_EOL
1362 ;
1363 $this->db->manipulate($sql);
1364 // END WebDAV: Delete WebDAV properties
1365
1366 ilECSImportManager::getInstance()->_deleteByObjId($this->getId());
1369
1370 $remove = true;
1371 } else {
1372 $this->log->write(
1373 sprintf(
1374 "ilObject::delete(), object not deleted, number of references: %s, obj_id: %s, type: %s, title: %s",
1375 $this->countReferences(),
1376 $this->getId(),
1377 $this->getType(),
1378 $this->getTitle()
1379 )
1380 );
1381 }
1382
1383 // delete object_reference entry
1384 if ($this->referenced) {
1386
1387 $this->app_event_handler->raise('components/ILIAS/ILIASObject', 'deleteReference', ['ref_id' => $this->getRefId()]);
1388
1389 $sql =
1390 "DELETE FROM object_reference" . PHP_EOL
1391 . "WHERE ref_id = " . $this->db->quote($this->getRefId(), 'integer') . PHP_EOL
1392 ;
1393 $this->db->manipulate($sql);
1394
1395 $this->log->write(
1396 sprintf(
1397 "ilObject::delete(), reference deleted, ref_id: %s, obj_id: %s, type: %s, title: %s",
1398 $this->getRefId(),
1399 $this->getId(),
1400 $this->getType(),
1401 $this->getTitle()
1402 )
1403 );
1404
1405 // DELETE PERMISSION ENTRIES IN RBAC_PA
1406 // DONE: method overwritten in ilObjRole & ilObjUser.
1407 // this call only applies for objects in rbac (not usr,role,rolt)
1408 // TODO: Do this for role templates too
1409 $rbac_admin->revokePermission($this->getRefId(), 0, false);
1410
1411 ilRbacLog::delete($this->getRefId());
1412
1413 // Remove applied didactic template setting
1415 }
1416
1417 // remove conditions
1418 if ($this->referenced) {
1419 $ch = new ilConditionHandler();
1420 $ch->delete($this->getRefId());
1421 unset($ch);
1422 }
1423
1424 return $remove;
1425 }
1426
1434 public function initDefaultRoles(): void
1435 {
1436 }
1437
1438 public function applyDidacticTemplate(int $tpl_id): void
1439 {
1440 ilLoggerFactory::getLogger('obj')->debug('Applying didactic template with id: ' . $tpl_id);
1441 if ($tpl_id) {
1442 foreach (ilDidacticTemplateActionFactory::getActionsByTemplateId($tpl_id) as $action) {
1443 $action->setRefId($this->getRefId());
1444 $action->apply();
1445 }
1446 }
1447
1449 }
1450
1459 public static function _exists(int $id, bool $reference = false, ?string $type = null): bool
1460 {
1461 global $DIC;
1462 $db = $DIC->database();
1463
1464 if ($reference) {
1465 $sql =
1466 "SELECT object_data.obj_id" . PHP_EOL
1467 . "FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
1468 . "LEFT JOIN object_reference ON object_reference.obj_id = object_data.obj_id " . PHP_EOL
1469 . "WHERE object_reference.ref_id= " . $db->quote($id, "integer") . PHP_EOL
1470 ;
1471 } else {
1472 $sql =
1473 "SELECT object_data.obj_id" . PHP_EOL
1474 . "FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
1475 . "WHERE obj_id = " . $db->quote($id, "integer") . PHP_EOL
1476 ;
1477 }
1478
1479 if ($type) {
1480 $sql .= " AND object_data.type = " . $db->quote($type, "text") . PHP_EOL;
1481 }
1482
1483 $result = $db->query($sql);
1484
1485 return (bool) $db->numRows($result);
1486 }
1487
1488 public function getXMLZip(): string
1489 {
1490 return "";
1491 }
1492 public function getHTMLDirectory(): bool
1493 {
1494 return false;
1495 }
1496
1497 final public static function _getObjectsByType(string $obj_type = "", ?int $owner = null): array
1498 {
1499 global $DIC;
1500 $db = $DIC->database();
1501
1502 $order = " ORDER BY title";
1503
1504 $where = "";
1505 if ($obj_type) {
1506 $where = "WHERE type = " . $db->quote($obj_type, "text");
1507
1508 if (!is_null($owner)) {
1509 $where .= " AND owner = " . $db->quote($owner, "integer");
1510 }
1511 }
1512
1513 $sql =
1514 "SELECT obj_id, type, title, description, owner, create_date, last_update, import_id, offline" . PHP_EOL
1515 . "FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
1516 . $where . PHP_EOL
1517 . $order . PHP_EOL
1518 ;
1519 $result = $db->query($sql);
1520
1521 $arr = [];
1522 if ($db->numRows($result) > 0) {
1523 while ($row = $db->fetchAssoc($result)) {
1524 $row["desc"] = $row["description"];
1525 $arr[$row["obj_id"]] = $row;
1526 }
1527 }
1528
1529 return $arr;
1530 }
1531
1538 final public static function _prepareCloneSelection(
1539 array $ref_ids,
1540 string $new_type,
1541 bool $show_path = true
1542 ): array {
1543 global $DIC;
1544
1545 $db = $DIC->database();
1546 $lng = $DIC->language();
1547 $obj_definition = $DIC["objDefinition"];
1548
1549 $sql =
1550 "SELECT obj_data.title obj_title, path_data.title path_title, child" . PHP_EOL
1551 . "FROM tree " . PHP_EOL
1552 . "JOIN object_reference obj_ref ON child = obj_ref.ref_id " . PHP_EOL
1553 . "JOIN object_data obj_data ON obj_ref.obj_id = obj_data.obj_id " . PHP_EOL
1554 . "JOIN object_reference path_ref ON parent = path_ref.ref_id " . PHP_EOL
1555 . "JOIN object_data path_data ON path_ref.obj_id = path_data.obj_id " . PHP_EOL
1556 . "WHERE " . $db->in("child", $ref_ids, false, "integer") . PHP_EOL
1557 . "ORDER BY obj_data.title" . PHP_EOL
1558 ;
1559 $res = $db->query($sql);
1560
1561 if (!$obj_definition->isPlugin($new_type)) {
1562 $options[0] = $lng->txt('obj_' . $new_type . '_select');
1563 } else {
1564 $options[0] = ilObjectPlugin::lookupTxtById($new_type, "obj_" . $new_type . "_select");
1565 }
1566
1567 while ($row = $db->fetchObject($res)) {
1568 if (mb_strlen($title = $row->obj_title) > 40) {
1569 $title = mb_substr($title, 0, 40) . '...';
1570 }
1571
1572 if ($show_path) {
1573 if (mb_strlen($path = $row->path_title) > 40) {
1574 $path = mb_substr($path, 0, 40) . '...';
1575 }
1576
1577 $title .= ' (' . $lng->txt('path') . ': ' . $path . ')';
1578 }
1579
1580 $options[$row->child] = $title;
1581 }
1582 return $options ?: [];
1583 }
1584
1588 public function cloneObject(int $target_id, int $copy_id = 0, bool $omit_tree = false): ?ilObject
1589 {
1591 global $DIC;
1592
1593 $ilUser = $DIC["ilUser"];
1594 $rbac_admin = $DIC["rbacadmin"];
1595
1596 $class_name = ('ilObj' . $this->obj_definition->getClassName($this->getType()));
1597
1599
1600 $this->obj_log->debug($this->getTitle());
1601 $this->obj_log->debug("isTreeCopyDisabled: " . $options->isTreeCopyDisabled());
1602 $this->obj_log->debug("omit_tree: " . $omit_tree);
1603
1605 $new_obj = new $class_name(0, false);
1606 $new_obj->setOwner($ilUser->getId());
1607 $new_obj->title = $this->getTitle();
1608 $new_obj->long_desc = $this->getLongDescription();
1609 $new_obj->desc = $this->getDescription();
1610 $new_obj->type = $this->getType();
1611
1612 // Choose upload mode to avoid creation of additional settings, db entries ...
1613 $new_obj->create(true);
1614
1615 if (!$options->isTreeCopyDisabled() && !$omit_tree) {
1616 $title_with_suffix = $this->appendCopyInfo($target_id, $copy_id, $new_obj->getId());
1617 $title = mb_strlen($title_with_suffix) < self::TITLE_LENGTH ? $title_with_suffix : $title;
1618 $this->obj_log->debug("title incl. copy info: " . $title);
1619 $new_obj->setTitle($title);
1620 $new_obj->update();
1621 }
1622
1623 if ($this->supportsOfflineHandling()) {
1624 if ($options->isRootNode($this->getRefId())) {
1625 $new_obj->getObjectProperties()->storePropertyIsOnline(
1626 $new_obj->getObjectProperties()->getPropertyIsOnline()->withOffline()
1627 );
1628 } else {
1629 $new_obj->getObjectProperties()->storePropertyIsOnline(
1630 $this->getObjectProperties()->getPropertyIsOnline()
1631 );
1632 }
1633 }
1634
1635 if (!$options->isTreeCopyDisabled() && !$omit_tree) {
1636 ilLoggerFactory::getLogger('obj')->debug('Tree copy is enabled');
1637 $new_obj->createReference();
1638 $new_obj->putInTree($target_id);
1639 $new_obj->setPermissions($target_id);
1640
1641 // when copying from personal workspace we have no current ref id
1642 if ($this->getRefId()) {
1643 // copy local roles
1644 $rbac_admin->copyLocalRoles($this->getRefId(), $new_obj->getRefId());
1645 }
1646 } else {
1647 ilLoggerFactory::getLogger('obj')->debug('Tree copy is disabled');
1648 }
1649
1650 ilAdvancedMDValues::_cloneValues($copy_id, $this->getId(), $new_obj->getId());
1651
1652 // BEGIN WebDAV: Clone WebDAV properties
1653 $sql =
1654 "INSERT INTO dav_property" . PHP_EOL
1655 . "(obj_id, node_id, ns, name, value)" . PHP_EOL
1656 . "SELECT " . $this->db->quote($new_obj->getId(), 'integer') . ", node_id, ns, name, value " . PHP_EOL
1657 . "FROM dav_property" . PHP_EOL
1658 . "WHERE obj_id = " . $this->db->quote($this->getId(), 'integer') . PHP_EOL
1659 ;
1660 $this->db->manipulate($sql);
1661 // END WebDAV: Clone WebDAV properties
1662
1663 $customIconFactory = $DIC['object.customicons.factory'];
1664 $customIcon = $customIconFactory->getByObjId($this->getId(), $this->getType());
1665 $customIcon->copy($new_obj->getId());
1666
1667 $new_obj->getObjectProperties()->storePropertyTileImage(
1668 $new_obj->getObjectProperties()->getPropertyTileImage()->withTileImage(
1669 $this->getObjectProperties()->getPropertyTileImage()
1670 ->getTileImage()->cloneFor($new_obj->getId())
1671 )
1672 );
1673
1674 $this->app_event_handler->raise(
1675 'components/ILIAS/ILIASObject',
1676 'cloneObject',
1677 [
1678 'object' => $new_obj,
1679 'cloned_from_object' => $this,
1680 ]
1681 );
1682
1683 return $new_obj;
1684 }
1685
1689 final public function appendCopyInfo(
1690 int $target_id,
1691 int $copy_id,
1692 int $new_obj_id
1693 ): string {
1694 $cp_options = ilCopyWizardOptions::_getInstance($copy_id);
1695 if (!$cp_options->isRootNode($this->getRefId())) {
1696 return $this->getTitle();
1697 }
1698
1699
1700 $obj_translations = $this->getObjectProperties()->clonePropertyTranslations($new_obj_id);
1701
1702 $other_children_of_same_type = $this->tree->getChildsByType($target_id, $this->type);
1703
1704 if ($obj_translations->getLanguages() === []) {
1705 $existing_titles = array_map(
1706 fn(array $child): string => $child['title'],
1707 $other_children_of_same_type
1708 );
1709
1710 return $this->appendNumberOfCopiesToTitle(
1711 $this->getTitle(),
1712 $existing_titles
1713 );
1714 }
1715
1716 return $this->appendCopyInfoToTranslations($obj_translations, $other_children_of_same_type);
1717 }
1718
1720 Translations $obj_translations,
1721 array $other_children_of_same_type
1722 ): string {
1723 $nodes_translations = array_map(
1724 fn(array $child): Translations =>
1725 $this->translations_repository->getFor($child['obj_id']),
1726 $other_children_of_same_type
1727 );
1728
1729 $title_translations_per_lang = array_reduce(
1730 $nodes_translations,
1731 $this->getCallbackForTitlesPerLanguageTransformation(),
1732 []
1733 );
1734
1735 $installed_langs = $this->lng->getInstalledLanguages();
1736 foreach ($obj_translations->getLanguages() as $language) {
1737 $obj_translations = $obj_translations->withLanguage(
1738 $language->withTitle(
1739 $this->appendNumberOfCopiesToTitle(
1740 $language->getTitle(),
1741 $title_translations_per_lang[$language->getLanguageCode()] ?? []
1742 )
1743 )
1744 );
1745 }
1746
1747 $this->translations_repository->store($obj_translations);
1748
1749 return $obj_translations->getDefaultTitle();
1750 }
1751
1753 {
1754 return function (array $npl, ?Translations $nt): array {
1755 $langs = $nt->getLanguages();
1756 foreach ($langs as $lang) {
1757 if (!array_key_exists($lang->getLanguageCode(), $npl)) {
1758 $npl[$lang->getLanguageCode()] = [];
1759 }
1760 $npl[$lang->getLanguageCode()][] = $lang->getTitle();
1761 }
1762 return $npl;
1763 };
1764 }
1765
1767 string $title,
1768 array $other_titles_for_lang
1769 ): string {
1770 $title_without_suffix = $this->buildTitleWithoutCopySuffix($title);
1771 if ($this->isTitleUnique($title_without_suffix, $other_titles_for_lang)) {
1772 return $title_without_suffix;
1773 }
1774
1775 for ($i = 1; true; $i++) {
1776 $title_with_suffix = "{$title_without_suffix} ({$i})";
1777 if ($this->isTitleUnique($title_with_suffix, $other_titles_for_lang)) {
1778 return $title_with_suffix;
1779 }
1780 }
1781 }
1782
1783 private function isTitleUnique(string $title, array $nodes): bool
1784 {
1785 foreach ($nodes as $node) {
1786 if (($title === $node)) {
1787 return false;
1788 }
1789 }
1790 return true;
1791 }
1792
1793 private function buildTitleWithoutCopySuffix(string $title): string
1794 {
1795 if (preg_match('/ \‍((\d+)\‍)$/', $title, $matches)) {
1796 return mb_substr($title, 0, -strlen($matches[0]));
1797 }
1798
1799 return $title;
1800 }
1801
1809 public function cloneDependencies(int $target_id, int $copy_id): bool
1810 {
1811 ilConditionHandler::cloneDependencies($this->getRefId(), $target_id, $copy_id);
1812
1813 $tpl_id = ilDidacticTemplateObjSettings::lookupTemplateId($this->getRefId());
1814 if ($tpl_id) {
1815 $factory = new ilObjectFactory();
1816 $obj = $factory->getInstanceByRefId($target_id, false);
1817 if ($obj instanceof ilObject) {
1818 $obj->applyDidacticTemplate($tpl_id);
1819 }
1820 }
1821 return true;
1822 }
1823
1827 public function cloneMetaData(ilObject $target_obj): bool
1828 {
1829 $this->lom_services->derive()
1830 ->fromObject($this->getId(), 0, $this->getType())
1831 ->forObject($target_obj->getId(), 0, $target_obj->getType());
1832 return true;
1833 }
1834
1835 public static function getIconForReference(
1836 int $ref_id,
1837 int $obj_id,
1838 string $size,
1839 string $type = "",
1840 bool $offline = false
1841 ): string {
1843 global $DIC;
1844 $icon_factory = $DIC['ui.factory']->symbol()->icon();
1845 $irss = $DIC['resource_storage'];
1846
1847 if ($obj_id == "" && $type == "") {
1848 return "";
1849 }
1850
1851 if ($type === "") {
1852 $type = ilObject::_lookupType($obj_id);
1853 }
1854
1855 if ($size === "") {
1856 $size = "big";
1857 }
1858
1859 if ($obj_id) {
1861 $property_icon = LocalDIC::dic()['properties.additional.repository']->getFor($obj_id)->getPropertyIcon();
1862 $custom_icon = $property_icon->getCustomIcon();
1863 if ($custom_icon?->exists()) {
1864 return $custom_icon->getFullPath() . '?tmp=' . filemtime($custom_icon->getFullPath());
1865 }
1866
1867 $file_type_specific_icon = $property_icon->getObjectTypeSpecificIcon($obj_id, $icon_factory, $irss);
1868 if ($file_type_specific_icon !== null) {
1869 return $file_type_specific_icon->getIconPath();
1870 }
1871
1872 $dtpl_icon_factory = ilDidacticTemplateIconFactory::getInstance();
1873 if ($ref_id) {
1874 $path = $dtpl_icon_factory->getIconPathForReference($ref_id);
1875 } else {
1876 $path = $dtpl_icon_factory->getIconPathForObject($obj_id);
1877 }
1878 if ($path) {
1879 return $path . '?tmp=' . filemtime($path);
1880 }
1881 }
1882
1883 if (!$offline) {
1884 return self::getIconForType($type);
1885 }
1886 return "./images/standard/icon_{$type}.svg";
1887 }
1888
1889 public static function getIconForType(string $type): string
1890 {
1891 global $DIC;
1892 $objDefinition = $DIC['objDefinition'];
1893 if (!$objDefinition->isPluginTypeName($type)) {
1894 return ilUtil::getImagePath("standard/icon_{$type}.svg");
1895 }
1896
1897 if ($objDefinition->getClassName($type) !== '') {
1898 $class_name = "il{$objDefinition->getClassName($type)}Plugin";
1899 $location = $objDefinition->getLocation($type);
1900 if (is_file($location . "/class.{$class_name}.php")) {
1901 return call_user_func([$class_name, '_getIcon'], $type);
1902 }
1903 }
1904 return ilUtil::getImagePath('standard/icon_cmps.svg');
1905 }
1906
1915 final public static function _getIcon(
1916 int $obj_id = 0,
1917 string $size = "big",
1918 string $type = "",
1919 bool $offline = false
1920 ): string {
1921 return self::getIconForReference(0, $obj_id, $size, $type, $offline);
1922 }
1923
1924 protected function handleAutoRating(): void
1925 {
1926 if ($this->process_auto_reating
1927 && $this->hasAutoRating()
1928 && method_exists($this, "setRating")
1929 ) {
1930 $this->setRating(true);
1931 $this->update();
1932 }
1933 }
1934
1935 protected function hasAutoRating(): bool
1936 {
1937 $ref_id = $this->getRefId();
1938 $type = $this->type;
1939
1940 if (!$ref_id || !in_array($type, ["file", "lm", "wiki"])) {
1941 return false;
1942 }
1943
1944 return $this->selfOrParentWithRatingEnabled();
1945 }
1946
1947 public function selfOrParentWithRatingEnabled(): bool
1948 {
1949 $tree = $this->tree;
1950 $ref_id = $this->getRefId();
1951 $parent_ref_id = $tree->checkForParentType($ref_id, "grp");
1952 if (!$parent_ref_id) {
1953 $parent_ref_id = $tree->checkForParentType($ref_id, "crs");
1954 }
1955 if ($parent_ref_id) {
1956 // get auto rate setting
1957 $parent_obj_id = ilObject::_lookupObjId($parent_ref_id);
1959 $parent_obj_id,
1961 );
1962 }
1963 return false;
1964 }
1965
1969 public static function collectDeletionDependencies(
1970 array &$deps,
1971 int $ref_id,
1972 int $obj_id,
1973 string $type,
1974 int $depth = 0
1975 ): void {
1976 global $DIC;
1977
1978 $objDefinition = $DIC["objDefinition"];
1979 $tree = $DIC->repositoryTree();
1980
1981 if ($depth == 0) {
1982 $deps["dep"] = [];
1983 }
1984
1985 $deps["del_ids"][$obj_id] = $obj_id;
1986
1987 if (!$objDefinition->isPluginTypeName($type)) {
1988 $class_name = "ilObj" . $objDefinition->getClassName($type);
1989 $odeps = call_user_func([$class_name, "getDeletionDependencies"], $obj_id);
1990 if (is_array($odeps)) {
1991 foreach ($odeps as $id => $message) {
1992 $deps["dep"][$id][$obj_id][] = $message;
1993 }
1994 }
1995
1996 // get deletion dependency of children
1997 foreach ($tree->getChilds($ref_id) as $c) {
1998 ilObject::collectDeletionDependencies($deps, (int) $c["child"], (int) $c["obj_id"], (string) $c["type"], $depth + 1);
1999 }
2000 }
2001
2002 // delete all dependencies to objects that will be deleted, too
2003 if ($depth == 0) {
2004 foreach ($deps["del_ids"] as $obj_id) {
2005 unset($deps["dep"][$obj_id]);
2006 }
2007 $deps = $deps["dep"];
2008 }
2009 }
2010
2014 public static function getDeletionDependencies(int $obj_id): array
2015 {
2016 return [];
2017 }
2018
2019 public static function getLongDescriptions(array $obj_ids): array
2020 {
2021 global $DIC;
2022 $db = $DIC->database();
2023
2024 $sql =
2025 "SELECT obj_id, description" . PHP_EOL
2026 . "FROM object_description" . PHP_EOL
2027 . "WHERE " . $db->in("obj_id", $obj_ids, false, "integer") . PHP_EOL
2028 ;
2029 $result = $db->query($sql);
2030
2031 $all = [];
2032 while ($row = $db->fetchAssoc($result)) {
2033 $all[$row["obj_id"]] = $row["description"];
2034 }
2035 return $all;
2036 }
2037
2038 public static function getAllOwnedRepositoryObjects(int $user_id): array
2039 {
2040 global $DIC;
2041
2042 $db = $DIC->database();
2043 $obj_definition = $DIC["objDefinition"];
2044
2045 // restrict to repository
2046 $types = array_keys($obj_definition->getSubObjectsRecursively("root"));
2047
2048 $sql =
2049 "SELECT od.obj_id, od.type, od.title" . PHP_EOL
2050 . "FROM object_data od" . PHP_EOL
2051 . "JOIN object_reference oref ON(oref.obj_id = od.obj_id)" . PHP_EOL
2052 . "JOIN tree ON (tree.child = oref.ref_id)" . PHP_EOL
2053 ;
2054
2055 if ($user_id) {
2056 $sql .= "WHERE od.owner = " . $db->quote($user_id, "integer") . PHP_EOL;
2057 } else {
2058 $sql .=
2059 "LEFT JOIN usr_data ud ON (ud.usr_id = od.owner)" . PHP_EOL
2060 . "WHERE (od.owner < " . $db->quote(1, "integer") . PHP_EOL
2061 . "OR od.owner IS NULL OR ud.login IS NULL)" . PHP_EOL
2062 . "AND od.owner <> " . $db->quote(-1, "integer") . PHP_EOL
2063 ;
2064 }
2065
2066 $sql .=
2067 "AND " . $db->in("od.type", $types, false, "text") . PHP_EOL
2068 . "AND tree.tree > " . $db->quote(0, "integer") . PHP_EOL
2069 ;
2070
2071 $res = $db->query($sql);
2072
2073 $all = [];
2074 while ($row = $db->fetchAssoc($res)) {
2075 $all[$row["type"]][$row["obj_id"]] = $row["title"];
2076 }
2077
2078 return $all;
2079 }
2080
2084 public static function fixMissingTitles($type, array &$obj_title_map)
2085 {
2086 global $DIC;
2087 $db = $DIC->database();
2088
2089 if (!in_array($type, ["catr", "crsr", "sess", "grpr", "prgr"])) {
2090 return;
2091 }
2092
2093 // any missing titles?
2094 $missing_obj_ids = [];
2095 foreach ($obj_title_map as $obj_id => $title) {
2096 if (!trim($title)) {
2097 $missing_obj_ids[] = $obj_id;
2098 }
2099 }
2100
2101 if (!sizeof($missing_obj_ids)) {
2102 return;
2103 }
2104
2105 switch ($type) {
2106 case "grpr":
2107 case "catr":
2108 case "crsr":
2109 case "prgr":
2110 $sql =
2111 "SELECT oref.obj_id, od.type, od.title" . PHP_EOL
2112 . "FROM object_data od" . PHP_EOL
2113 . "JOIN container_reference oref ON (od.obj_id = oref.target_obj_id)" . PHP_EOL
2114 . "AND " . $db->in("oref.obj_id", $missing_obj_ids, false, "integer") . PHP_EOL
2115 ;
2116 $result = $db->query($sql);
2117
2118 while ($row = $db->fetchAssoc($result)) {
2119 $obj_title_map[$row["obj_id"]] = $row["title"];
2120 }
2121 break;
2122 case "sess":
2123 foreach ($missing_obj_ids as $obj_id) {
2124 $sess = new ilObjSession($obj_id, false);
2125 $obj_title_map[$obj_id] = $sess->getFirstAppointment()->appointmentToString();
2126 }
2127 break;
2128 }
2129 }
2130
2131 public static function _lookupCreationDate(int $obj_id): string
2132 {
2133 global $DIC;
2134 $db = $DIC->database();
2135
2136 $sql =
2137 "SELECT create_date" . PHP_EOL
2138 . "FROM " . self::TABLE_OBJECT_DATA . PHP_EOL
2139 . "WHERE obj_id = " . $db->quote($obj_id, "integer") . PHP_EOL
2140 ;
2141 $result = $db->query($sql);
2142 $rec = $db->fetchAssoc($result);
2143 return $rec["create_date"];
2144 }
2145
2154 public function getPossibleSubObjects(bool $filter = true): array
2155 {
2156 return $this->obj_definition->getSubObjects($this->type, $filter);
2157 }
2158
2159 public static function _getObjectTypeIdByTitle(string $type, ?\ilDBInterface $ilDB = null): ?int
2160 {
2161 if (!$ilDB) {
2162 global $DIC;
2163 $ilDB = $DIC->database();
2164 }
2165
2166 $sql =
2167 "SELECT obj_id FROM object_data" . PHP_EOL
2168 . "WHERE type = 'typ'" . PHP_EOL
2169 . "AND title = " . $ilDB->quote($type, 'text') . PHP_EOL
2170 ;
2171
2172 $res = $ilDB->query($sql);
2173 if ($ilDB->numRows($res) == 0) {
2174 return null;
2175 }
2176
2177 $row = $ilDB->fetchAssoc($res);
2178 return (int) $row['obj_id'] ?? null;
2179 }
2180}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$location
Definition: buildRTE.php:22
Builds data types.
Definition: Factory.php:36
Class handles translation mode for an object.
const IL_CAL_DATETIME
error(string $a_errmsg)
return true
static _deleteByObjId(int $a_obj_id)
Delete by objekt id.
static _cloneValues(int $copy_id, int $a_source_id, int $a_target_id, ?string $a_sub_type=null, ?int $a_source_sub_id=null, ?int $a_target_sub_id=null)
Clone Advanced Meta Data.
Global event handler.
static _deleteSettingsOfBlock(int $a_block_id, string $a_block_type)
INTERNAL CLASS: Please do not use in consumer code.
static cloneDependencies(int $a_src_ref_id, int $a_target_ref_id, int $a_copy_id)
static _lookupContainerSetting(int $a_id, string $a_keyword, ?string $a_default_value=null)
static _getInstance(int $a_copy_id)
const FETCHMODE_OBJECT
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false, ?ilObjUser $user=null,)
@classDescription Date and time handling
static getActionsByTemplateId(int $a_tpl_id)
Get actions of one template.
static assignTemplate(int $a_ref_id, int $a_obj_id, int $a_tpl_id)
static getInstance()
Get the singleton instance of this ilECSImportManager.
Error Handling & global info handling.
static _deleteByObjId(int $a_obj_id)
language handling
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 getLogger(string $a_component_id)
Get component logger.
Component logger with individual log levels by component id.
A news item can be created by different sources.
User class.
static userExists(array $a_usr_ids=[])
static deleteAllEntries(int $ref_id)
Delete all db entries for ref id.
parses the objects.xml it handles the xml-description of all ilias objects
isPlugin(string $obj_name)
get RBAC status by type returns true if object type is an (activated) plugin type
isRBACObject(string $obj_name)
get RBAC status by type returns true if object type is a RBAC object type
getSubObjectsRecursively(string $obj_type, bool $include_source_obj=true, bool $add_admin_objects=false)
Get all sub objects by type.
Class ilObjectFactory This class offers methods to get instances of the type-specific object classes ...
static lookupTxtById(string $plugin_id, string $lang_var)
Class ilObject Basic functions for all objects.
static _lookupObjectId(int $ref_id)
static _lookupType(int $id, bool $reference=false)
string $desc
setPermissions(int $parent_ref_id)
createReference()
creates reference for object
static _getIcon(int $obj_id=0, string $size="big", string $type="", bool $offline=false)
Get icon for repository item.
string $title
const TITLE_LENGTH
bool $add_dots
static _lookupOwnerName(int $owner_id)
Lookup owner name for owner id.
ilRbacReview $rbac_review
cloneMetaData(ilObject $target_obj)
Copy meta data.
static _writeDescription(int $obj_id, string $desc)
write description to db (static)
putInTree(int $parent_ref_id)
maybe this method should be in tree object!?
static _setDeletedDate(int $ref_id, int $deleted_by)
array $objectList
initDefaultRoles()
init default roles settings Purpose of this function is to create a local role folder and local roles...
static _hasUntrashedReference(int $obj_id)
checks whether an object has at least one reference that is not in trash
static _lookupOwner(int $obj_id)
Lookup owner user ID for object ID.
appendNumberOfCopiesToTitle(string $title, array $other_titles_for_lang)
string $create_date
static _getAllReferences(int $id)
get all reference ids for object ID
updateOwner()
update owner of object in db
const LONG_DESC_LENGTH
appendCopyInfoToTranslations(Translations $obj_translations, array $other_children_of_same_type)
supportsOfflineHandling()
cloneDependencies(int $target_id, int $copy_id)
Clone object dependencies.
ilLanguage $lng
doMDUpdateListener(string $a_element)
static _lookupDeletedDate(int $ref_id)
selfOrParentWithRatingEnabled()
static collectDeletionDependencies(array &$deps, int $ref_id, int $obj_id, string $type, int $depth=0)
Collect deletion dependencies.
ilAppEventHandler $app_event_handler
static _isInTrash(int $ref_id)
getPossibleSubObjects(bool $filter=true)
get all possible sub objects of this type the object can decide which types of sub objects are possib...
buildTitleWithoutCopySuffix(string $title)
static _lookupObjIdByImportId(string $import_id)
Get (latest) object id for an import id.
beforeDeleteMetaData()
static _writeTitle(int $obj_id, string $title)
write title to db (static)
setId(int $id)
ilTree $tree
static _getIdForImportId(string $import_id)
applyDidacticTemplate(int $tpl_id)
bool $call_by_reference
beforeUpdateMetaData()
static _lookupImportId(int $obj_id)
ilObjectDefinition $obj_definition
string $long_desc
static _getIdsForTitle(string $title, string $type='', bool $partial_match=false)
isTitleUnique(string $title, array $nodes)
getLastUpdateDate()
Get last update date in YYYY-MM-DD HH-MM-SS format.
bool $process_auto_reating
setType(string $type)
ilErrorHandling $error
static _prepareCloneSelection(array $ref_ids, string $new_type, bool $show_path=true)
Prepare copy wizard object selection.
appendCopyInfo(int $target_id, int $copy_id, int $new_obj_id)
Prepend Copy info if object with same name exists in that container.
static getDeletionDependencies(int $obj_id)
Get deletion dependencies.
static setDeletedDates(array $ref_ids, int $user_id)
LOMServices $lom_services
Aggregator $properties_aggregator
setTitle(string $title)
setImportId(string $import_id)
ilLogger $log
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
static _getLastUpdateOfObjects(array $obj_ids)
static _lookupLastUpdate(int $obj_id, bool $formatted=false)
getOwnerName()
get full name of object owner
withReferences()
determines whether objects are referenced or not (got ref ids or not)
Properties $object_properties
ilLogger $obj_log
setOwner(int $usr_id)
getLongDescription()
get object long description (stored in object_description)
string $untranslatedTitle
bool $register
ilRbacAdmin $rbac_admin
string $last_update
static _writeImportId(int $obj_id, string $import_id)
write import id to db (static)
static getAllOwnedRepositoryObjects(int $user_id)
const TABLE_OBJECT_DATA
setOfflineStatus(bool $status)
create()
note: title, description and type should be set when this function is called
ilObjUser $user
static _lookupCreationDate(int $obj_id)
static _getObjectTypeIdByTitle(string $type, ?\ilDBInterface $ilDB=null)
getUntranslatedTitle()
Get untranslated object title WebDAV needs to access the untranslated title of an object.
TranslationsRepository $translations_repository
string $type
static getIconForType(string $type)
getCallbackForTitlesPerLanguageTransformation()
static _getObjectsDataForType(string $type, bool $omit_trash=false)
get all objects of a certain type
beforeMDUpdateListener(string $a_element)
static _getObjectsByType(string $obj_type="", ?int $owner=null)
const DATABASE_DATE_FORMAT
const DESC_LENGTH
static _resetDeletedDate(int $ref_id)
static getLongDescriptions(array $obj_ids)
ILIAS $ilias
static _lookupObjId(int $ref_id)
string $import_id
flushObjectProperties()
MDUpdateListener(string $element)
Metadata update listener.
setParentRolePermissions(int $parent_ref_id)
Initialize the permissions of parent roles (local roles of categories, global roles....
setDescription(string $description)
static _lookupTitle(int $obj_id)
static _lookupDescription(int $obj_id)
beforeCreateMetaData()
ilDBInterface $db
getCreateDate()
Get create date in YYYY-MM-DD HH-MM-SS format.
static fixMissingTitles($type, array &$obj_title_map)
Try to fix missing object titles.
getPresentationTitle()
get presentation title Normally same as title Overwritten for sessions
setRefId(int $ref_id)
static lookupOfflineStatus(int $obj_id)
Lookup offline status using objectDataCache.
Class ilRbacAdmin Core functions for role based access control.
copyLocalRoles(int $a_source_id, int $a_target_id)
Copy local roles This method creates a copy of all local role.
revokePermission(int $a_ref_id, int $a_rol_id=0, bool $a_keep_protected=true)
Revokes permissions of an object of one role.
static delete(int $ref_id)
class ilRbacReview Contains Review functions of core Rbac.
static shortenTextExtended(string $a_str, int $a_len, bool $a_dots=false, bool $a_next_blank=false, bool $a_keep_extension=false)
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
getChilds(int $a_node_id, string $a_order="", string $a_direction="ASC")
get child nodes of given node
checkForParentType(int $a_ref_id, string $a_type, bool $a_exclude_source_check=false)
Check for parent type e.g check if a folder (ref_id 3) is in a parent course obj => checkForParentTyp...
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
const SYSTEM_ROLE_ID
Definition: constants.php:29
$c
Definition: deliver.php:25
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Interface ilDBInterface.
update(string $table_name, array $values, array $where)
@description $where MUST contain existing columns only.
insert(string $table_name, array $values)
fetchObject(ilDBStatement $query_result)
setLimit(int $limit, int $offset=0)
like(string $column, string $type, string $value="?", bool $case_insensitive=true)
Generate a like subquery.
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
$path
Definition: ltiservices.php:30
$res
Definition: ltiservices.php:69
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
Class ilObjForumAdministration.
global $DIC
Definition: shib_login.php:26