ILIAS  trunk Revision v11.0_alpha-1723-g8e69f309bab
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
class.ilLMObject.php
Go to the documentation of this file.
1 <?php
2 
24 
33 {
34  public const CHAPTER_TITLE = "st_title";
35  public const PAGE_TITLE = "pg_title";
36  public const NO_HEADER = "none";
37  protected string $layout = "";
38  protected string $import_id = "";
39 
40  protected ilObjUser $user;
41  public int $lm_id = 0;
42  public string $type = "";
43  public int $id = 0;
44  public ?array $data_record; // assoc array of lm_data record
46  public string $title = "";
47  public string $short_title = "";
48  public string $description = "";
49  public bool $active = true;
50  protected static $data_records = array();
51  protected ilDBInterface $db;
53 
54  public function __construct(
55  ilObjLearningModule $a_content_obj,
56  int $a_id = 0
57  ) {
58  global $DIC;
59  $this->user = $DIC->user();
60 
61  $this->db = $DIC->database();
62  $this->lom_services = $DIC->learningObjectMetadata();
63 
64  $this->id = $a_id;
65  $this->setContentObject($a_content_obj);
66  $this->setLMId($a_content_obj->getId());
67  if ($a_id != 0) {
68  $this->read();
69  }
70  }
71 
81  public function MDUpdateListener(string $a_element): void
82  {
83  switch ($a_element) {
84  case 'General':
85 
86  // Update Title and description
87  $paths = $this->lom_services->paths();
88  $reader = $this->lom_services->read(
89  $this->getLMId(),
90  $this->getId(),
91  $this->getType(),
92  $paths->custom()->withNextStep('general')->get()
93  );
94  $title = $reader->firstData($paths->title())->value();
95 
96  ilLMObject::_writeTitle($this->getId(), $title);
97  break;
98 
99  case 'Educational':
100  $obj_lp = ilObjectLP::getInstance($this->getLMId());
101  if (in_array(
102  $obj_lp->getCurrentMode(),
104  )) {
106  }
107  break;
108 
109  default:
110  }
111  }
112 
113 
117  public function createMetaData(): void
118  {
119  $ilUser = $this->user;
120 
121  $this->lom_services->derive()
122  ->fromBasicProperties(
123  $this->getTitle(),
124  $this->getDescription(),
125  $ilUser->getPref('language')
126  )->forObject($this->getLMId(), $this->getId(), $this->getType());
127  }
128 
132  public function updateMetaData(): void
133  {
134  $this->lom_services->manipulate($this->getLMId(), $this->getId(), $this->getType())
135  ->prepareCreateOrUpdate(
136  $this->lom_services->paths()->title(),
137  $this->getTitle()
138  )->execute();
139  }
140 
141 
145  public function deleteMetaData(): void
146  {
147  $this->lom_services->deleteAll($this->getLMId(), $this->getId(), $this->getType());
148  }
149 
150 
151 
155  public function setDataRecord(array $a_record): void
156  {
157  $this->data_record = $a_record;
158  }
159 
160  public function read(): void
161  {
162  $ilDB = $this->db;
163 
164  if (!isset($this->data_record)) {
165  $query = "SELECT * FROM lm_data WHERE obj_id = " .
166  $ilDB->quote($this->id, "integer");
167  $obj_set = $ilDB->query($query);
168  $this->data_record = $ilDB->fetchAssoc($obj_set);
169  }
170 
171  $this->type = $this->data_record["type"];
172  $this->setImportId((string) $this->data_record["import_id"]);
173  $this->setTitle((string) $this->data_record["title"]);
174  $this->setShortTitle((string) $this->data_record["short_title"]);
175  $this->setLayout((string) $this->data_record["layout"]);
176  }
177 
178 
183  public static function preloadDataByLM(int $a_lm_id): int
184  {
185  global $DIC;
186 
187  $ilDB = $DIC->database();
188 
189  $set = $ilDB->query(
190  "SELECT * FROM lm_data " .
191  " WHERE lm_id = " . $ilDB->quote($a_lm_id, "integer")
192  );
193  while ($rec = $ilDB->fetchAssoc($set)) {
194  self::$data_records[$rec["obj_id"]] = $rec;
195  }
196  return count(self::$data_records);
197  }
198 
199  public function setTitle(string $a_title): void
200  {
201  $this->title = $a_title;
202  }
203 
204  public function getTitle(): string
205  {
206  return $this->title;
207  }
208 
209  public function setShortTitle(string $a_title): void
210  {
211  $this->short_title = $a_title;
212  }
213 
214  public function getShortTitle(): string
215  {
216  return $this->short_title;
217  }
218 
219  protected static function _lookup(int $a_obj_id, string $a_field): string
220  {
221  global $DIC;
222 
223  $ilDB = $DIC->database();
224 
225  if (isset(self::$data_records[$a_obj_id])) {
226  return self::$data_records[$a_obj_id][$a_field] ?? "";
227  }
228 
229  $query = "SELECT " . $a_field . " FROM lm_data WHERE obj_id = " .
230  $ilDB->quote($a_obj_id, "integer");
231  $obj_set = $ilDB->query($query);
232  $obj_rec = $ilDB->fetchAssoc($obj_set);
233 
234  return $obj_rec[$a_field] ?? "";
235  }
236 
237  public static function _lookupTitle(int $a_obj_id): string
238  {
239  return self::_lookup($a_obj_id, "title");
240  }
241 
242  public static function _lookupShortTitle(int $a_obj_id): string
243  {
244  return self::_lookup($a_obj_id, "short_title");
245  }
246 
247  public static function _lookupType(int $a_obj_id, int $a_lm_id = 0): string
248  {
249  global $DIC;
250 
251  $ilDB = $DIC->database();
252 
253  if (isset(self::$data_records[$a_obj_id])) {
254  if ($a_lm_id == 0 || self::$data_records[$a_obj_id]["lm_id"] == $a_lm_id) {
255  return self::$data_records[$a_obj_id]["type"];
256  }
257  }
258 
259  $and = "";
260  if ($a_lm_id) {
261  $and = ' AND lm_id = ' . $ilDB->quote($a_lm_id, 'integer');
262  }
263 
264  $query = "SELECT type FROM lm_data WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") . $and;
265  $obj_set = $ilDB->query($query);
266  $obj_rec = $ilDB->fetchAssoc($obj_set);
267 
268  return $obj_rec["type"] ?? "";
269  }
270 
271 
272  public static function _writeTitle(int $a_obj_id, string $a_title): void
273  {
274  global $DIC;
275 
276  $ilDB = $DIC->database();
277 
278  $query = "UPDATE lm_data SET " .
279  " title = " . $ilDB->quote($a_title, "text") .
280  " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer");
281  $ilDB->manipulate($query);
282  }
283 
284 
285  public function setDescription(string $a_description): void
286  {
287  $this->description = $a_description;
288  }
289 
290  public function getDescription(): string
291  {
292  return $this->description;
293  }
294 
295  public function setType(string $a_type): void
296  {
297  $this->type = $a_type;
298  }
299 
300  public function getType(): string
301  {
302  return $this->type;
303  }
304 
305  public function setLMId(int $a_lm_id): void
306  {
307  $this->lm_id = $a_lm_id;
308  }
309 
310  public function getLMId(): int
311  {
312  return $this->lm_id;
313  }
314 
315  public function setContentObject(ilObjLearningModule $a_content_obj): void
316  {
317  $this->content_object = $a_content_obj;
318  }
319 
321  {
322  return $this->content_object;
323  }
324 
325  public function setId(int $a_id): void
326  {
327  $this->id = $a_id;
328  }
329 
330  public function getId(): int
331  {
332  return $this->id;
333  }
334 
335  public function getImportId(): string
336  {
337  return $this->import_id;
338  }
339 
340  public function setImportId(string $a_id): void
341  {
342  $this->import_id = $a_id;
343  }
344 
345  public function setLayout(string $a_val): void
346  {
347  $this->layout = $a_val;
348  }
349 
350  public function getLayout(): string
351  {
352  return $this->layout;
353  }
354 
355  public static function _writeImportId(int $a_id, string $a_import_id): void
356  {
357  global $DIC;
358 
359  $ilDB = $DIC->database();
360 
361  $q = "UPDATE lm_data " .
362  "SET " .
363  "import_id = " . $ilDB->quote($a_import_id, "text") . "," .
364  "last_update = " . $ilDB->now() . " " .
365  "WHERE obj_id = " . $ilDB->quote($a_id, "integer");
366 
367  $ilDB->manipulate($q);
368  }
369 
370  public function create(bool $a_upload = false): void
371  {
372  $ilDB = $this->db;
373 
374  // insert object data
375  $this->setId($ilDB->nextId("lm_data"));
376  $query = "INSERT INTO lm_data (obj_id, title, type, layout, lm_id, import_id, short_title, create_date) " .
377  "VALUES (" .
378  $ilDB->quote($this->getId(), "integer") . "," .
379  $ilDB->quote($this->getTitle(), "text") . "," .
380  $ilDB->quote($this->getType(), "text") . ", " .
381  $ilDB->quote($this->getLayout(), "text") . ", " .
382  $ilDB->quote($this->getLMId(), "integer") . "," .
383  $ilDB->quote($this->getImportId(), "text") . "," .
384  $ilDB->quote($this->getShortTitle(), "text") .
385  ", " . $ilDB->now() . ")";
386  $ilDB->manipulate($query);
387 
388  if (!$a_upload) {
389  $this->createMetaData();
390  }
391  }
392 
393  public function update(): void
394  {
395  $ilDB = $this->db;
396 
397  $this->updateMetaData();
398 
399  $query = "UPDATE lm_data SET " .
400  " lm_id = " . $ilDB->quote($this->getLMId(), "integer") .
401  " ,title = " . $ilDB->quote($this->getTitle(), "text") .
402  " ,short_title = " . $ilDB->quote($this->getShortTitle(), "text") .
403  " ,layout = " . $ilDB->quote($this->getLayout(), "text") .
404  " WHERE obj_id = " . $ilDB->quote($this->getId(), "integer");
405 
406  $ilDB->manipulate($query);
407  }
408 
409  public function delete(bool $a_delete_meta_data = true): void
410  {
411  $ilDB = $this->db;
412 
413  $query = "DELETE FROM lm_data WHERE obj_id = " .
414  $ilDB->quote($this->getId(), "integer");
415  $ilDB->manipulate($query);
416 
417  $this->deleteMetaData();
418  }
419 
427  public static function _getIdForImportId(string $a_import_id): int
428  {
429  global $DIC;
430 
431  $ilDB = $DIC->database();
432  $help_module = $DIC->help()->internal()->domain()->module();
433 
434  $q = "SELECT obj_id FROM lm_data WHERE import_id = " .
435  $ilDB->quote($a_import_id, "text") . " " .
436  " ORDER BY create_date DESC";
437  $obj_set = $ilDB->query($q);
438  while ($obj_rec = $ilDB->fetchAssoc($obj_set)) {
439  $lm_id = ilLMObject::_lookupContObjID($obj_rec["obj_id"]);
440 
441  // link only in learning module, that is not trashed
442  $ref_ids = ilObject::_getAllReferences($lm_id); // will be 0 if import of lm is in progress (new import)
443  if (count($ref_ids) == 0 || ilObject::_hasUntrashedReference($lm_id) ||
444  $help_module->isHelpLM($lm_id)) {
445  return $obj_rec["obj_id"];
446  }
447  }
448 
449  return 0;
450  }
451 
457  public static function _getAllObjectsForImportId(
458  string $a_import_id,
459  int $a_in_lm = 0
460  ): array {
461  global $DIC;
462 
463  $ilDB = $DIC->database();
464 
465  $where = ($a_in_lm > 0)
466  ? " AND lm_id = " . $ilDB->quote($a_in_lm, "integer") . " "
467  : "";
468 
469  $q = "SELECT * FROM lm_data WHERE import_id = " .
470  $ilDB->quote($a_import_id, "text") . " " .
471  $where .
472  " ORDER BY create_date DESC";
473  $obj_set = $ilDB->query($q);
474 
475  $items = array();
476  while ($obj_rec = $ilDB->fetchAssoc($obj_set)) {
477  // check, whether lm is not trashed
478  if (ilObject::_hasUntrashedReference($obj_rec["lm_id"])) {
479  $items[] = $obj_rec;
480  }
481  }
482 
483  return $items;
484  }
485 
489  public static function _exists(int $a_id): bool
490  {
491  global $DIC;
492 
493  $ilDB = $DIC->database();
494 
495  if (is_int(strpos($a_id, "_"))) {
497  }
498 
499  $q = "SELECT * FROM lm_data WHERE obj_id = " .
500  $ilDB->quote($a_id, "integer");
501  $obj_set = $ilDB->query($q);
502  if ($obj_rec = $ilDB->fetchAssoc($obj_set)) {
503  return true;
504  } else {
505  return false;
506  }
507  }
508 
509  public static function getObjectList(
510  int $lm_id,
511  string $type = ""
512  ): array {
513  global $DIC;
514 
515  $ilDB = $DIC->database();
516 
517  $type_str = ($type != "")
518  ? "AND type = " . $ilDB->quote($type, "text") . " "
519  : "";
520 
521  $query = "SELECT * FROM lm_data " .
522  "WHERE lm_id= " . $ilDB->quote($lm_id, "integer") . " " .
523  $type_str . " " .
524  "ORDER BY title";
525  $obj_set = $ilDB->query($query);
526  $obj_list = array();
527  while ($obj_rec = $ilDB->fetchAssoc($obj_set)) {
528  $obj_list[] = array("obj_id" => $obj_rec["obj_id"],
529  "title" => $obj_rec["title"],
530  "import_id" => $obj_rec["import_id"],
531  "type" => $obj_rec["type"]);
532  }
533  return $obj_list;
534  }
535 
536 
540  public static function _deleteAllObjectData(
541  ilObjLearningModule $a_cobj
542  ): void {
543  global $DIC;
544 
545  $ilDB = $DIC->database();
546 
547  $query = "SELECT * FROM lm_data " .
548  "WHERE lm_id= " . $ilDB->quote($a_cobj->getId(), "integer");
549  $obj_set = $ilDB->query($query);
550 
551  while ($obj_rec = $ilDB->fetchAssoc($obj_set)) {
552  $lm_obj = ilLMObjectFactory::getInstance($a_cobj, $obj_rec["obj_id"], false);
553 
554  if (is_object($lm_obj)) {
555  $lm_obj->delete(true);
556  }
557  }
558  }
559 
563  public static function _lookupContObjID(int $a_id): int
564  {
565  global $DIC;
566 
567  $ilDB = $DIC->database();
568 
569  if (isset(self::$data_records[$a_id])) {
570  return self::$data_records[$a_id]["lm_id"];
571  }
572 
573  $query = "SELECT lm_id FROM lm_data WHERE obj_id = " .
574  $ilDB->quote($a_id, "integer");
575  $obj_set = $ilDB->query($query);
576  $obj_rec = $ilDB->fetchAssoc($obj_set);
577 
578  return (int) ($obj_rec["lm_id"] ?? 0);
579  }
580 
584  public static function putInTree(
585  ilLMObject $a_obj,
586  int $a_parent_id = 0,
587  int $a_target_node_id = 0
588  ): void {
589  global $DIC;
590 
591  $ilLog = $DIC["ilLog"];
592 
593  $tree = new ilLMTree($a_obj->getContentObject()->getId());
594 
595  // determine parent
596  $parent_id = ($a_parent_id != 0)
597  ? $a_parent_id
598  : $tree->getRootId();
599 
600  // determine target
601  if ($a_target_node_id != 0) {
602  $target = $a_target_node_id;
603  } else {
604  // determine last child that serves as predecessor
605  if ($a_obj->getType() == "st") {
606  $s_types = array("st", "pg");
607  $childs = $tree->getChildsByTypeFilter($parent_id, $s_types);
608  } else {
609  $s_types = "pg";
610  $childs = $tree->getChildsByType($parent_id, $s_types);
611  }
612 
613  if (count($childs) == 0) {
614  $target = ilTree::POS_FIRST_NODE;
615  } else {
616  $target = $childs[count($childs) - 1]["obj_id"];
617  }
618  }
619 
620  if ($tree->isInTree($parent_id) && !$tree->isInTree($a_obj->getId())) {
621  $ilLog->write("LMObject::putInTree: insertNode, ID: " . $a_obj->getId() .
622  "Parent ID: " . $parent_id . ", Target: " . $target);
623 
624  $tree->insertNode($a_obj->getId(), $parent_id, $target);
625  }
626  }
627 
631  public static function getTree(
632  int $a_cont_obj_id
633  ): ilLMTree {
634  $tree = new ilLMTree($a_cont_obj_id);
635  $tree->readRootId();
636 
637  return $tree;
638  }
639 
643  public static function clipboardCut(
644  int $a_cont_obj_id,
645  array $a_ids
646  ): void {
647  $tree = ilLMObject::getTree($a_cont_obj_id);
648  $cut_ids = [];
649 
650  if (!is_array($a_ids)) {
651  return;
652  } else {
653  // get all "top" ids, i.e. remove ids, that have a selected parent
654  foreach ($a_ids as $id) {
655  $path = $tree->getPathId($id);
656  $take = true;
657  foreach ($path as $path_id) {
658  if ($path_id != $id && in_array($path_id, $a_ids)) {
659  $take = false;
660  }
661  }
662  if ($take) {
663  $cut_ids[] = $id;
664  }
665  }
666  }
667 
668  ilLMObject::clipboardCopy($a_cont_obj_id, $cut_ids);
669 
670  // remove the objects from the tree
671  // note: we are getting chapters which are *not* in the tree
672  // we do not delete any pages/chapters here
673  foreach ($cut_ids as $id) {
674  $curnode = $tree->getNodeData($id);
675  if ($tree->isInTree($id)) {
676  $tree->deleteTree($curnode);
677  }
678  }
679  }
680 
684  public static function clipboardCopy(
685  int $a_cont_obj_id,
686  array $a_ids
687  ): void {
688  global $DIC;
689 
690  $ilUser = $DIC->user();
691 
692  $tree = ilLMObject::getTree($a_cont_obj_id);
693 
694  $ilUser->clipboardDeleteObjectsOfType("pg");
695  $ilUser->clipboardDeleteObjectsOfType("st");
696 
697  // put them into the clipboard
698  $time = date("Y-m-d H:i:s", time());
699  $order = 0;
700  foreach ($a_ids as $id) {
701  $curnode = array();
702  if ($tree->isInTree($id)) {
703  $curnode = $tree->getNodeData($id);
704  $subnodes = $tree->getSubTree($curnode);
705  foreach ($subnodes as $subnode) {
706  if ($subnode["child"] != $id) {
707  $ilUser->addObjectToClipboard(
708  $subnode["child"],
709  $subnode["type"],
710  ilStr::subStr($subnode["title"], 0, 70),
711  $subnode["parent"],
712  $time,
713  $subnode["lft"]
714  );
715  }
716  }
717  }
718  $order = (($curnode["lft"] ?? 0) > 0)
719  ? $curnode["lft"]
720  : (int) ($order + 1);
721  $ilUser->addObjectToClipboard(
722  $id,
723  self::_lookupType($id),
724  ilStr::subStr(self::_lookupTitle($id), 0, 70),
725  0,
726  $time,
727  $order
728  );
729  }
730  }
731 
735  public static function pasteTree(
736  ilObjLearningModule $a_target_lm,
737  int $a_item_id,
738  int $a_parent_id,
739  int $a_target,
740  string $a_insert_time,
741  array &$a_copied_nodes,
742  bool $a_as_copy = false,
743  ?ilObjLearningModule $a_source_lm = null
744  ): int {
745  global $DIC;
746 
747  $item = null;
748  $ilUser = $DIC->user();
749  $ilLog = $DIC["ilLog"];
750  $lom_services = $DIC->learningObjectMetadata();
751 
752  $item_lm_id = ilLMObject::_lookupContObjID($a_item_id);
753  $item_type = ilLMObject::_lookupType($a_item_id);
755  $lm_obj = ilObjectFactory::getInstanceByObjId($item_lm_id);
756  if ($item_type == "st") {
757  $item = new ilStructureObject($lm_obj, $a_item_id);
758  } elseif ($item_type == "pg") {
759  $item = new ilLMPageObject($lm_obj, $a_item_id);
760  }
761 
762  $ilLog->write("Getting from clipboard type " . $item_type . ", " .
763  "Item ID: " . $a_item_id . ", of original LM: " . $item_lm_id);
764 
765  if ($item_lm_id != $a_target_lm->getId() && !$a_as_copy) {
766  // @todo: check whether st is NOT in tree
767 
768  // "move" metadata to new lm
769  $lom_services->derive()
770  ->fromObject($item_lm_id, $item->getId(), $item->getType())
771  ->forObject($a_target_lm->getId(), $item->getId(), $item->getType());
772 
773  // delete old meta data set
774  $lom_services->deleteAll($item_lm_id, $item->getId(), $item->getType());
775 
776  if ($item_type == "pg") {
777  $page = $item->getPageObject();
778  $page->buildDom();
779  $page->setParentId($a_target_lm->getId());
780  $page->update();
781  }
782  }
783 
784  if ($a_as_copy) {
785  $target_item = $item->copy($a_target_lm);
786  $a_copied_nodes[$item->getId()] = $target_item->getId();
787  } else {
788  $target_item = $item;
789  }
790 
791  $ilLog->write("Putting into tree type " . $target_item->getType() .
792  "Item ID: " . $target_item->getId() . ", Parent: " . $a_parent_id . ", " .
793  "Target: " . $a_target . ", Item LM:" . $target_item->getContentObject()->getId());
794 
795  ilLMObject::putInTree($target_item, $a_parent_id, $a_target);
796 
797  if ($a_source_lm == null) {
798  $childs = $ilUser->getClipboardChilds($item->getId(), $a_insert_time);
799  } else {
800  $childs = $a_source_lm->lm_tree->getChilds($item->getId());
801  foreach ($childs as $k => $child) {
802  $childs[$k]["id"] = $child["child"];
803  }
804  }
805 
806  foreach ($childs as $child) {
807  ilLMObject::pasteTree(
808  $a_target_lm,
809  $child["id"],
810  $target_item->getId(),
812  $a_insert_time,
813  $a_copied_nodes,
814  $a_as_copy,
815  $a_source_lm
816  );
817  }
818 
819  return $target_item->getId();
820  // @todo: write history (see pastePage)
821  }
822 
826  public static function saveTitles(
827  ilObjLearningModule $a_lm,
828  array $a_titles,
829  string $a_lang = "-"
830  ): void {
831  global $DIC;
832 
833  $lom_services = $DIC->learningObjectMetadata();
834 
835  if ($a_lang == "") {
836  $a_lang = "-";
837  }
838  if (is_array($a_titles)) {
839  foreach ($a_titles as $id => $title) {
840  self::saveTitle($id, $title, $a_lang);
841  }
842  }
843  }
844 
845  public static function saveTitle(int $id, string $title, string $lang = "-"): void
846  {
847  global $DIC;
848 
849  $lom_services = $DIC->learningObjectMetadata();
851  if (in_array($lang, ["-", ""])) {
852  $lm_id = self::_lookupContObjID($id);
853  $type = self::_lookupType($id);
854  if ($type !== "" && $lm_id > 0) {
855  $lom_services->manipulate($lm_id, $id, $type)
856  ->prepareCreateOrUpdate(
857  $lom_services->paths()->title(),
858  $title
859  )->execute();
860  self::_writeTitle($id, $title);
861  }
862  } else {
863  $lmobjtrans = new ilLMObjTranslation($id, $lang);
864  $lmobjtrans->setTitle($title);
865  $lmobjtrans->save();
866  }
867  }
868 
872  public static function updateInternalLinks(
873  array $a_copied_nodes,
874  string $a_parent_type = "lm"
875  ): void {
876  $all_fixes = array();
877  foreach ($a_copied_nodes as $original_id => $copied_id) {
878  $copied_type = ilLMObject::_lookupType($copied_id);
879  $copy_lm = ilLMObject::_lookupContObjID($copied_id);
880 
881  if ($copied_type == "pg") {
882  foreach (ilPageObject::lookupTranslations($a_parent_type, $copied_id) as $l) {
883  //
884  // 1. Outgoing links from the copied page.
885  //
886  //$targets = ilInternalLink::_getTargetsOfSource($a_parent_type.":pg", $copied_id);
887  $tpg = new ilLMPage($copied_id, 0, $l);
888  $tpg->buildDom();
889  $il = $tpg->getInternalLinks();
890  $targets = array();
891  foreach ($il as $l2) {
892  $targets[] = array("type" => ilInternalLink::_extractTypeOfTarget($l2["Target"]),
893  "id" => (int) ilInternalLink::_extractObjIdOfTarget($l2["Target"]),
894  "inst" => (int) ilInternalLink::_extractInstOfTarget($l2["Target"]));
895  }
896  $fix = array();
897  foreach ($targets as $target) {
898  if (($target["inst"] == 0 || $target["inst"] = IL_INST_ID) &&
899  ($target["type"] == "pg" || $target["type"] == "st")) {
900  // first check, whether target is also within the copied set
901  if (($a_copied_nodes[$target["id"]] ?? 0) > 0) {
902  $fix[$target["id"]] = $a_copied_nodes[$target["id"]];
903  } else {
904  // now check, if a copy if the target is already in the same lm
905 
906  // only if target is not already in the same lm!
907  $trg_lm = ilLMObject::_lookupContObjID($target["id"]);
908  if ($trg_lm != $copy_lm) {
909  $lm_data = ilLMObject::_getAllObjectsForImportId("il__" . $target["type"] . "_" . $target["id"]);
910  $found = false;
911 
912  foreach ($lm_data as $item) {
913  if (!$found && ($item["lm_id"] == $copy_lm)) {
914  $fix[$target["id"]] = $item["obj_id"];
915  $found = true;
916  }
917  }
918  }
919  }
920  }
921  }
922 
923  // outgoing links to be fixed
924  if (count($fix) > 0) {
925  //echo "<br>--".$copied_id;
926  //var_dump($fix);
927  $t = ilObject::_lookupType($copy_lm);
928  if (isset($all_fixes[$t . ":" . $copied_id])) {
929  $all_fixes[$t . ":" . $copied_id] += $fix;
930  } else {
931  $all_fixes[$t . ":" . $copied_id] = $fix;
932  }
933  }
934  }
935  }
936 
937  if ($copied_type == "pg" ||
938  $copied_type == "st") {
939  //
940  // 2. Incoming links to the original pages
941  //
942  // A->B A2 (A+B currently copied)
943  // A->C B2
944  // B->A
945  // C->A C2->A (C already copied)
946  $original_lm = ilLMObject::_lookupContObjID($original_id);
947  $original_type = ilObject::_lookupType($original_lm);
948 
949  if ($original_lm != $copy_lm) {
950  // This gets sources that link to A+B (so we have C here)
951  // (this also does already the trick when instance map areas are given in C)
952  // int_link, where target_type, target_id, target_inst -> ok
954  $copied_type,
955  $original_id,
956  0
957  );
958 
959  // mobs linking to $original_id
960  // map_area, where link_type, target -> ok
961  $mobs = ilMapArea::_getMobsForTarget("int", "il__" . $copied_type .
962  "_" . $original_id);
963 
964  // pages using these mobs
965  foreach ($mobs as $mob) {
966  // mob_usage, where id -> ok
967  // mep_item, where foreign_id, type -> ok
968  // mep_tree, where child -> already existed
969  // il_news_item, where mob_id -> ok
970  // map_area, where link_type, target -> aready existed
971  // media_item, where id -> already existed
972  // personal_clipboard, where item_id, type -> ok
973  $usages = ilObjMediaObject::lookupUsages($mob);
974  foreach ($usages as $usage) {
975  if ($usage["type"] == "lm:pg" | $usage["type"] == "lm:st") {
976  $sources[] = $usage;
977  }
978  }
979  }
980  $fix = array();
981  foreach ($sources as $source) {
982  $stype = explode(":", $source["type"]);
983  $source_type = $stype[1] ?? "";
984 
985  if ($source_type == "pg" || $source_type == "st") {
986  // first of all: source must be in original lm
987  $src_lm = ilLMObject::_lookupContObjID($source["id"]);
988 
989  if ($src_lm == $original_lm) {
990  // check, if a copy if the source is already in the same lm
991  // now we look for the latest copy of C in LM2
993  "il__" . $source_type . "_" . $source["id"],
994  $copy_lm
995  );
996  $found = false;
997  foreach ($lm_data as $item) {
998  if (!$found) {
999  $fix[$item["obj_id"]][$original_id] = $copied_id;
1000  $found = true;
1001  }
1002  }
1003  }
1004  }
1005  }
1006  // outgoing links to be fixed
1007  if (count($fix) > 0) {
1008  foreach ($fix as $page_id => $fix_array) {
1009  $t = ilObject::_lookupType($copy_lm);
1010  if (isset($all_fixes[$t . ":" . $page_id])) {
1011  $all_fixes[$t . ":" . $page_id] += $fix_array;
1012  } else {
1013  $all_fixes[$t . ":" . $page_id] = $fix_array;
1014  }
1015  }
1016  }
1017  }
1018  }
1019  }
1020 
1021  foreach ($all_fixes as $pg => $fixes) {
1022  $pg = explode(":", $pg);
1023  foreach (ilPageObject::lookupTranslations($pg[0], $pg[1]) as $l) {
1024  $page = ilPageObjectFactory::getInstance($pg[0], $pg[1], 0, $l);
1025  if ($page->moveIntLinks($fixes)) {
1026  $page->update(true, true);
1027  }
1028  }
1029  }
1030  }
1031 
1035  public static function uniqueTypesCheck(array $a_items): bool
1036  {
1037  $types = array();
1038  if (is_array($a_items)) {
1039  foreach ($a_items as $item) {
1040  $type = ilLMObject::_lookupType($item);
1041  $types[$type] = $type;
1042  }
1043  }
1044 
1045  if (count($types) > 1) {
1046  return false;
1047  }
1048  return true;
1049  }
1050 
1054  public static function writeLayout(
1055  int $a_obj_id,
1056  string $a_layout,
1057  ?ilObjLearningModule $a_lm = null
1058  ): void {
1059  global $DIC;
1060 
1061  $ilDB = $DIC->database();
1062 
1063  $t = ilLMObject::_lookupType($a_obj_id);
1064 
1065  if ($t == "pg") {
1066  $query = "UPDATE lm_data SET " .
1067  " layout = " . $ilDB->quote($a_layout, "text") .
1068  " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer");
1069  $ilDB->manipulate($query);
1070  } elseif ($t == "st" && is_object($a_lm)) {
1071  $node = $a_lm->getLMTree()->getNodeData($a_obj_id);
1072  $child_nodes = $a_lm->getLMTree()->getSubTree($node);
1073  if (is_array($child_nodes) && count($child_nodes) > 0) {
1074  foreach ($child_nodes as $c) {
1075  if ($c["type"] == "pg") {
1076  $query = "UPDATE lm_data SET " .
1077  " layout = " . $ilDB->quote($a_layout, "text") .
1078  " WHERE obj_id = " . $ilDB->quote($c["child"], "integer");
1079  $ilDB->manipulate($query);
1080  }
1081  }
1082  }
1083  }
1084  }
1085 
1089  public static function lookupLayout(int $a_obj_id): string
1090  {
1091  global $DIC;
1092 
1093  $ilDB = $DIC->database();
1094 
1095  $query = "SELECT layout FROM lm_data WHERE obj_id = " .
1096  $ilDB->quote($a_obj_id, "integer");
1097  $obj_set = $ilDB->query($query);
1098  $obj_rec = $ilDB->fetchAssoc($obj_set);
1099 
1100  return $obj_rec["layout"];
1101  }
1102 
1106  public static function getPagesOfChapter(
1107  int $a_lm_id,
1108  int $a_chap_id
1109  ): array {
1110  // update structure entries: if at least one page of a chapter is public set chapter to public too
1111  $lm_tree = new ilTree($a_lm_id);
1112  $lm_tree->setTableNames('lm_tree', 'lm_data');
1113  $lm_tree->setTreeTablePK("lm_id");
1114  $lm_tree->readRootId();
1115 
1116  $childs = $lm_tree->getChildsByType($a_chap_id, "pg");
1117 
1118  return $childs;
1119  }
1120 
1124  public static function _getAllLMObjectsOfLM(
1125  int $a_lm_id,
1126  string $a_type = ""
1127  ): array {
1128  global $DIC;
1129 
1130  $ilDB = $DIC->database();
1131 
1132  $and = ($a_type != "")
1133  ? " AND type = " . $ilDB->quote($a_type, "text")
1134  : "";
1135 
1136  $set = $ilDB->query("SELECT obj_id FROM lm_data " .
1137  " WHERE lm_id = " . $ilDB->quote($a_lm_id, "integer") . $and);
1138  $obj_ids = array();
1139  while ($rec = $ilDB->fetchAssoc($set)) {
1140  $obj_ids[] = $rec["obj_id"];
1141  }
1142 
1143  return $obj_ids;
1144  }
1145 
1146 
1150 
1151  public static function saveExportId(
1152  int $a_lm_id,
1153  int $a_lmobj_id,
1154  string $a_exp_id,
1155  string $a_type = "pg"
1156  ): void {
1157  global $DIC;
1158 
1159  $manipulator = $DIC->learningObjectMetadata()->manipulate($a_lm_id, $a_lmobj_id, $a_type);
1160  if (trim($a_exp_id) == "") {
1161  $manipulator = $manipulator->prepareDelete(self::getPathToExportIDInLOM());
1162  } else {
1163  $manipulator = $manipulator->prepareCreateOrUpdate(self::getPathToExportIDInLOM(), $a_exp_id);
1164  }
1165  $manipulator->execute();
1166  }
1167 
1168  protected static function getPathToExportIDInLOM(): LOMPath
1169  {
1170  global $DIC;
1171 
1172  return $DIC->learningObjectMetadata()
1173  ->paths()
1174  ->custom()
1175  ->withNextStep('general')
1176  ->withNextStep('identifier')
1177  ->withNextStep('catalog')
1178  ->withAdditionalFilterAtCurrentStep(FilterType::DATA, 'ILIAS_NID')
1179  ->withNextStepToSuperElement()
1180  ->withNextStep('entry')
1181  ->get();
1182  }
1183 
1184  public static function getExportId(
1185  int $a_lm_id,
1186  int $a_lmobj_id,
1187  string $a_type = "pg"
1188  ): string {
1189  global $DIC;
1190 
1191  // look for export id
1192  $export_id_path = self::getPathToExportIDInLOM();
1193  return $DIC->learningObjectMetadata()->read(
1194  $a_lm_id,
1195  $a_lmobj_id,
1196  $a_type,
1197  $export_id_path
1198  )->firstData($export_id_path)->value();
1199  }
1200 
1204  public function existsExportID(
1205  int $a_lm_id,
1206  int $a_exp_id,
1207  string $a_type = "pg"
1208  ): bool {
1209  $searcher = $this->lom_services->search();
1210 
1211  $search_clause = $searcher->getClauseFactory()->getBasicClause(
1212  self::getPathToExportIDInLOM(),
1213  Mode::EQUALS,
1214  $a_exp_id
1215  );
1216  $results = $searcher->execute(
1217  $search_clause,
1218  1,
1219  null,
1220  $searcher->getFilter($a_lm_id, Placeholder::ANY, $a_type)
1221  );
1222  return count(iterator_to_array($results)) > 0;
1223  }
1224 
1228  public static function getDuplicateExportIDs(
1229  int $a_lm_id,
1230  string $a_type = "pg"
1231  ): array {
1232  global $DIC;
1233 
1234  $lom_services = $DIC->learningObjectMetadata();
1235  $export_id_path = self::getPathToExportIDInLOM();
1236 
1237  $searcher = $lom_services->search();
1238  $search_clause = $searcher->getClauseFactory()->getBasicClause(
1239  $export_id_path,
1240  Mode::EQUALS,
1241  '',
1242  true
1243  );
1244  $search_results = $searcher->execute(
1245  $search_clause,
1246  1,
1247  null,
1248  $searcher->getFilter($a_lm_id, Placeholder::ANY, $a_type)
1249  );
1250 
1251  $res = [];
1252  foreach ($search_results as $search_result) {
1253  if (!ilLMObject::_exists($search_result->subID())) {
1254  continue;
1255  }
1256  $reader = $lom_services->read(
1257  $search_result->objID(),
1258  $search_result->subID(),
1259  $search_result->type(),
1260  $export_id_path
1261  );
1262  foreach ($reader->allData($export_id_path) as $export_id_datum) {
1263  $export_id = trim($export_id_datum->value());
1264  $res[$export_id] = ($res[$export_id] ?? 0) + 1;
1265  }
1266  }
1267  return $res;
1268  }
1269 
1270  // Get effective title
1271  public static function _getNodePresentationTitle(
1272  array $a_node,
1273  string $a_mode = self::PAGE_TITLE,
1274  bool $a_include_numbers = false,
1275  bool $a_time_scheduled_activation = false,
1276  bool $a_force_content = false,
1277  int $a_lm_id = 0,
1278  string $a_lang = "-"
1279  ): string {
1280  if ($a_lang == "") {
1281  $a_lang = "-";
1282  }
1283 
1284  if ($a_node["type"] == "st") {
1286  $a_node["child"],
1287  self::CHAPTER_TITLE,
1288  $a_include_numbers,
1289  $a_time_scheduled_activation,
1290  $a_force_content,
1291  $a_lm_id,
1292  $a_lang
1293  );
1294  } else {
1296  $a_node["child"],
1297  $a_mode,
1298  $a_include_numbers,
1299  $a_time_scheduled_activation,
1300  $a_force_content,
1301  $a_lm_id,
1302  $a_lang
1303  );
1304  }
1305  }
1306 
1307  public static function getShortTitles(
1308  int $a_lm_id,
1309  string $a_lang = "-"
1310  ): array {
1311  global $DIC;
1312 
1313  $db = $DIC->database();
1314 
1315  $title_data = array();
1316  if ($a_lang == "-") {
1317  $set = $db->query("SELECT t.child, d.obj_id, d.title, d.short_title FROM lm_data d LEFT JOIN lm_tree t ON (d.obj_id = t.child) WHERE d.lm_id = " .
1318  $db->quote($a_lm_id, "integer") . " ORDER BY t.lft, d.title");
1319  } else {
1320  $set = $db->query("SELECT t.child, d.obj_id, tr.title, tr.short_title, d.title default_title, d.short_title default_short_title FROM lm_data d " .
1321  " LEFT JOIN lm_tree t ON (d.obj_id = t.child) " .
1322  " LEFT JOIN lm_data_transl tr ON (tr.id = d.obj_id AND tr.lang=" . $db->quote($a_lang, "text") . ") WHERE d.lm_id = " .
1323  $db->quote($a_lm_id, "integer") . " ORDER BY t.lft, d.title");
1324  }
1325  while ($rec = $db->fetchAssoc($set)) {
1326  $title_data[] = $rec;
1327  }
1328  return $title_data;
1329  }
1330 
1331  public static function writeShortTitle(
1332  int $a_id,
1333  string $a_short_title,
1334  string $a_lang = "-"
1335  ): void {
1336  global $DIC;
1337 
1338  $db = $DIC->database();
1339 
1340  if ($a_lang != "-" && $a_lang != "") {
1341  $trans = new ilLMObjTranslation($a_id, $a_lang);
1342  $trans->setShortTitle($a_short_title);
1343  $trans->save();
1344  } else {
1345  $db->manipulate(
1346  "UPDATE lm_data SET " .
1347  " short_title = " . $db->quote($a_short_title, "text") .
1348  " WHERE obj_id = " . $db->quote($a_id, "integer")
1349  );
1350  }
1351  }
1352 }
static updateInternalLinks(array $a_copied_nodes, string $a_parent_type="lm")
Update internal links, after multiple pages have been copied.
static _getPresentationTitle(int $a_st_id, string $a_mode=self::CHAPTER_TITLE, bool $a_include_numbers=false, bool $a_time_scheduled_activation=false, bool $a_force_content=false, int $a_lm_id=0, string $a_lang="-", bool $a_include_short=false)
$res
Definition: ltiservices.php:66
static _getMobsForTarget(string $a_type, string $a_target)
Get areas for a certain target.
setDescription(string $a_description)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static $data_records
const IL_INST_ID
Definition: constants.php:40
static getExportId(int $a_lm_id, int $a_lmobj_id, string $a_type="pg")
static _getAllObjectsForImportId(string $a_import_id, int $a_in_lm=0)
Get all items for an import ID.
static saveTitles(ilObjLearningModule $a_lm, array $a_titles, string $a_lang="-")
Save titles for lm objects.
fetchAssoc(ilDBStatement $statement)
static lookupUsages(int $a_id, bool $a_include_history=true)
Lookup usages of media object.
FilterType
Values should always be all lowercase.
Definition: FilterType.php:26
static _getAllReferences(int $id)
get all reference ids for object ID
static _deleteAllObjectData(ilObjLearningModule $a_cobj)
delete all objects of content object (digi book / learning module)
string $description
static uniqueTypesCheck(array $a_items)
Check for unique types (all pages or all chapters)
static getInstance(ilObjLearningModule $a_content_obj, int $a_id=0, bool $a_halt=true)
MDUpdateListener(string $a_element)
Meta data update listener Important note: Do never call create() or update() method of ilObject here...
setType(string $a_type)
create(bool $a_upload=false)
static _hasUntrashedReference(int $obj_id)
checks whether an object has at least one reference that is not in trash
static _lookupShortTitle(int $a_obj_id)
static getObjectList(int $lm_id, string $type="")
quote($value, string $type)
static preloadDataByLM(int $a_lm_id)
Preload data records by lm.
static clipboardCut(int $a_cont_obj_id, array $a_ids)
Copy a set of chapters/pages into the clipboard.
static subStr(string $a_str, int $a_start, ?int $a_length=null)
Definition: class.ilStr.php:24
static getTree(int $a_cont_obj_id)
Get learning module tree.
static lookupTranslations(string $a_parent_type, int $a_id)
Lookup translations.
$c
Definition: deliver.php:25
string $short_title
static putInTree(ilLMObject $a_obj, int $a_parent_id=0, int $a_target_node_id=0)
put this object into content object tree
$path
Definition: ltiservices.php:29
static writeShortTitle(int $a_id, string $a_short_title, string $a_lang="-")
static _lookupTitle(int $a_obj_id)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
__construct(ilObjLearningModule $a_content_obj, int $a_id=0)
const POS_FIRST_NODE
setId(int $a_id)
setLayout(string $a_val)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static writeLayout(int $a_obj_id, string $a_layout, ?ilObjLearningModule $a_lm=null)
Write layout setting.
LOMServices $lom_services
static getPathToExportIDInLOM()
static _getIdForImportId(string $a_import_id)
get current object id for import id (static)
static getPagesOfChapter(int $a_lm_id, int $a_chap_id)
Get pages of chapter.
setLMId(int $a_lm_id)
global $DIC
Definition: shib_login.php:22
ilObjUser $user
static _refreshStatus(int $a_obj_id, ?array $a_users=null)
ilDBInterface $db
query(string $query)
Run a (read-only) Query on the database.
static saveTitle(int $id, string $title, string $lang="-")
setTitle(string $a_title)
updateMetaData()
update meta data entry
$results
setImportId(string $a_id)
static _getAllLMObjectsOfLM(int $a_lm_id, string $a_type="")
Get all objects of learning module.
existsExportID(int $a_lm_id, int $a_exp_id, string $a_type="pg")
Does export ID exist in lm?
static _writeImportId(int $a_id, string $a_import_id)
static _writeTitle(int $a_obj_id, string $a_title)
setShortTitle(string $a_title)
$lang
Definition: xapiexit.php:25
static getInstanceByObjId(?int $obj_id, bool $stop_on_error=true)
get an instance of an Ilias object by object id
const POS_LAST_NODE
static _exists(int $a_id)
checks wether a lm content object with specified id exists or not
static saveExportId(int $a_lm_id, int $a_lmobj_id, string $a_exp_id, string $a_type="pg")
static getShortTitles(int $a_lm_id, string $a_lang="-")
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
createMetaData()
create meta data entry
static _getPresentationTitle(int $a_pg_id, string $a_mode=self::CHAPTER_TITLE, bool $a_include_numbers=false, bool $a_time_scheduled_activation=false, bool $a_force_content=false, int $a_lm_id=0, string $a_lang="-", bool $a_include_short=false)
presentation title doesn&#39;t have to be page title, it may be chapter title + page title or chapter tit...
static removeProhibitedCharacters(string $a_text)
Remove prohibited characters see #19159.
static getDuplicateExportIDs(int $a_lm_id, string $a_type="pg")
Get duplicate export IDs (count export ID usages)
static _lookupType(int $a_obj_id, int $a_lm_id=0)
$q
Definition: shib_logout.php:21
static _lookupContObjID(int $a_id)
get learning module id for lm object
deleteMetaData()
delete meta data entry
ilObjLearningModule $content_object
static lookupLayout(int $a_obj_id)
Lookup type.
manipulate(string $query)
Run a (write) Query on the database.
static _lookupType(int $id, bool $reference=false)
setContentObject(ilObjLearningModule $a_content_obj)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getInstance(int $obj_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getInstance(string $a_parent_type, int $a_id=0, int $a_old_nr=0, string $a_lang="-")
Get page object instance.
static _lookup(int $a_obj_id, string $a_field)
static clipboardCopy(int $a_cont_obj_id, array $a_ids)
Copy a set of chapters/pages into the clipboard.
setDataRecord(array $a_record)
this method should only be called by class ilLMObjectFactory
static _getNodePresentationTitle(array $a_node, string $a_mode=self::PAGE_TITLE, bool $a_include_numbers=false, bool $a_time_scheduled_activation=false, bool $a_force_content=false, int $a_lm_id=0, string $a_lang="-")