1<?php
2
3/* Copyright (c) 1998-2011 ILIAS open source, Extended GPL, see docs/LICENSE */
4
5require_once("Services/MetaData/classes/class.ilMDLanguageItem.php");
6
7/**
8* Class ilLMObject
9*
10* Base class for ilStructureObjects and ilPageObjects (see ILIAS DTD)
11*
12* @author Alex Killing <alex.killing@gmx.de>
13* @version $Id$
14*
15* @ingroup ModulesIliasLearningModule
16*/
17class ilLMObject
18{
19    /**
20     * @var ilObjUser
21     */
22    protected $user;
23
24    public $lm_id;
25    public $type;
26    public $id;
27    public $meta_data;
28    public $data_record;		// assoc array of lm_data record
29    public $content_object;
30    public $title;
31    public $short_title;
32    public $description;
33    public $active = true;
34    protected static $data_records = array();
35
36    /**
37     * @var ilDB
38     */
39    protected $db;
40
41    /**
42    * @param	object		$a_content_obj		content object (digi book or learning module)
43    */
44    public function __construct($a_content_obj, $a_id = 0)
45    {
46        global $DIC;
47        $this->user = $DIC->user();
48
49        $this->db = $DIC->database();
50
51        $this->id = $a_id;
52        $this->setContentObject($a_content_obj);
53        $this->setLMId($a_content_obj->getId());
54        if ($a_id != 0) {
55            $this->read();
56        }
57    }
58
59    /**
60     * Meta data update listener
61     *
62     * Important note: Do never call create() or update()
63     * method of ilObject here. It would result in an
64     * endless loop: update object -> update meta -> update
65     * object -> ...
66     * Use static _writeTitle() ... methods instead.
67     *
68     * @param string $a_element md element
69     * @return boolean success
70     */
71    public function MDUpdateListener($a_element)
72    {
73        include_once 'Services/MetaData/classes/class.ilMD.php';
74
75        switch ($a_element) {
76            case 'General':
77
78                // Update Title and description
79                $md = new ilMD($this->getLMId(), $this->getId(), $this->getType());
80                $md_gen = $md->getGeneral();
81
82                ilLMObject::_writeTitle($this->getId(), $md_gen->getTitle());
83
84                foreach ($md_gen->getDescriptionIds() as $id) {
85                    $md_des = $md_gen->getDescription($id);
86                    //					ilLMObject::_writeDescription($this->getId(),$md_des->getDescription());
87                    break;
88                }
89                break;
90
91            case 'Educational':
92                include_once("./Services/Object/classes/class.ilObjectLP.php");
93                $obj_lp = ilObjectLP::getInstance($this->getLMId());
94                if (in_array(
95                    $obj_lp->getCurrentMode(),
96                    array(ilLPObjSettings::LP_MODE_TLT, ilLPObjSettings::LP_MODE_COLLECTION_TLT)
97                )) {
98                    include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
99                    ilLPStatusWrapper::_refreshStatus($this->getLMId());
100                }
101                break;
102
103            default:
104        }
105        return true;
106    }
107
108
109    /**
110    * lookup named identifier (ILIAS_NID)
111    */
112    public static function _lookupNID($a_lm_id, $a_lm_obj_id, $a_type)
113    {
114        include_once 'Services/MetaData/classes/class.ilMD.php';
115        //echo "-".$a_lm_id."-".$a_lm_obj_id."-".$a_type."-";
116        $md = new ilMD($a_lm_id, $a_lm_obj_id, $a_type);
117        $md_gen = $md->getGeneral();
118        if (is_object($md_gen)) {
119            foreach ($md_gen->getIdentifierIds() as $id) {
120                $md_id = $md_gen->getIdentifier($id);
121                if ($md_id->getCatalog() == "ILIAS_NID") {
122                    return $md_id->getEntry();
123                }
124            }
125        }
126
127        return false;
128    }
129
130
131    /**
132    * create meta data entry
133    */
134    public function createMetaData()
135    {
136        include_once 'Services/MetaData/classes/class.ilMDCreator.php';
137
138        $ilUser = $this->user;
139
140        $md_creator = new ilMDCreator($this->getLMId(), $this->getId(), $this->getType());
141        $md_creator->setTitle($this->getTitle());
142        $md_creator->setTitleLanguage($ilUser->getPref('language'));
143        $md_creator->setDescription($this->getDescription());
144        $md_creator->setDescriptionLanguage($ilUser->getPref('language'));
145        $md_creator->setKeywordLanguage($ilUser->getPref('language'));
146        $md_creator->setLanguage($ilUser->getPref('language'));
147        $md_creator->create();
148
149        return true;
150    }
151
152    /**
153    * update meta data entry
154    */
155    public function updateMetaData()
156    {
157        include_once("Services/MetaData/classes/class.ilMD.php");
158        include_once("Services/MetaData/classes/class.ilMDGeneral.php");
159        include_once("Services/MetaData/classes/class.ilMDDescription.php");
160
161        $md = new ilMD($this->getLMId(), $this->getId(), $this->getType());
162        $md_gen = $md->getGeneral();
163        $md_gen->setTitle($this->getTitle());
164
165        // sets first description (maybe not appropriate)
166        $md_des_ids = $md_gen->getDescriptionIds();
167        if (count($md_des_ids) > 0) {
168            $md_des = $md_gen->getDescription($md_des_ids[0]);
169            //			$md_des->setDescription($this->getDescription());
170            $md_des->update();
171        }
172        $md_gen->update();
173    }
174
175
176    /**
177    * delete meta data entry
178    */
179    public function deleteMetaData()
180    {
181        // Delete meta data
182        include_once('Services/MetaData/classes/class.ilMD.php');
183        $md = new ilMD($this->getLMId(), $this->getId(), $this->getType());
184        $md->deleteAll();
185    }
186
187
188
189    /**
190    * this method should only be called by class ilLMObjectFactory
191    */
192    public function setDataRecord($a_record)
193    {
194        $this->data_record = $a_record;
195    }
196
197    public function read()
198    {
199        $ilDB = $this->db;
200
201        if (!isset($this->data_record)) {
202            $query = "SELECT * FROM lm_data WHERE obj_id = " .
203                $ilDB->quote($this->id, "integer");
204            $obj_set = $ilDB->query($query);
205            $this->data_record = $ilDB->fetchAssoc($obj_set);
206        }
207
208        $this->type = $this->data_record["type"];
209        $this->setImportId($this->data_record["import_id"]);
210        $this->setTitle($this->data_record["title"]);
211        $this->setShortTitle($this->data_record["short_title"]);
212        $this->setLayout($this->data_record["layout"]);
213    }
214
215
216    /**
217     * Preload data records by lm
218     *
219     * @param integer $a_lm_id lm id
220     * @return int number of preloaded records
221     */
222    public static function preloadDataByLM($a_lm_id)
223    {
224        global $DIC;
225
226        $ilDB = $DIC->database();
227
228        $set = $ilDB->query(
229            "SELECT * FROM lm_data " .
230            " WHERE lm_id = " . $ilDB->quote($a_lm_id, "integer")
231        );
232        while ($rec = $ilDB->fetchAssoc($set)) {
233            self::$data_records[$rec["obj_id"]] = $rec;
234        }
235        return count(self::$data_records);
236    }
237
238
239    /**
240     * set title of lm object
241     *
242     * @param	string		$a_title	title of chapter or page
243     */
244    public function setTitle($a_title)
245    {
246        $this->title = $a_title;
247    }
248
249    /**
250     * get title of lm object
251     *
252     * @return	string		title of chapter or page
253     */
254    public function getTitle()
255    {
256        return $this->title;
257    }
258
259    /**
260     * set short title of lm object
261     *
262     * @param	string		$a_title	short title of chapter or page
263     */
264    public function setShortTitle($a_title)
265    {
266        $this->short_title = $a_title;
267    }
268
269    /**
270     * get short title of lm object
271     *
272     * @return	string		short title of chapter or page
273     */
274    public function getShortTitle()
275    {
276        return $this->short_title;
277    }
278
279
280    /**
281     * Lookup title
282     *
283     * @param	int		lm object id
284     */
285    protected static function _lookup($a_obj_id, $a_field)
286    {
287        global $DIC;
288
289        $ilDB = $DIC->database();
290
291        if (isset(self::$data_records[$a_obj_id])) {
292            return self::$data_records[$a_obj_id][$a_field];
293        }
294
295        $query = "SELECT " . $a_field . " FROM lm_data WHERE obj_id = " .
296            $ilDB->quote($a_obj_id, "integer");
297        $obj_set = $ilDB->query($query);
298        $obj_rec = $ilDB->fetchAssoc($obj_set);
299
300        return $obj_rec[$a_field];
301    }
302
303    /**
304     * Lookup title
305     *
306     * @param int $a_obj_id object id
307     * @return string
308     */
309    public static function _lookupTitle($a_obj_id)
310    {
311        return self::_lookup($a_obj_id, "title");
312    }
313
314    /**
315     * Lookup short title
316     *
317     * @param int $a_obj_id object id
318     * @return string
319     */
320    public static function _lookupShortTitle($a_obj_id)
321    {
322        return self::_lookup($a_obj_id, "short_title");
323    }
324
325    /**
326    * Lookup type
327    *
328    * @param	int		id of pg st
329    * @param	int		id of lm object [optional]
330    */
331    public static function _lookupType($a_obj_id, $a_lm_id = 0)
332    {
333        global $DIC;
334
335        $ilDB = $DIC->database();
336
337        if (isset(self::$data_records[$a_obj_id])) {
338            if ($a_lm_id == 0 || self::$data_records[$a_obj_id]["lm_id"] == $a_lm_id) {
339                return self::$data_records[$a_obj_id]["type"];
340            }
341        }
342
343        if ($a_lm_id) {
344            $and = ' AND lm_id = ' . $ilDB->quote($a_lm_id, 'integer');
345        }
346
347        $query = "SELECT type FROM lm_data WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer") . $and;
348        $obj_set = $ilDB->query($query);
349        $obj_rec = $ilDB->fetchAssoc($obj_set);
350
351        return $obj_rec["type"];
352    }
353
354
355    public static function _writeTitle($a_obj_id, $a_title)
356    {
357        global $DIC;
358
359        $ilDB = $DIC->database();
360
361        $query = "UPDATE lm_data SET " .
362            " title = " . $ilDB->quote($a_title, "text") .
363            " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer");
364        $ilDB->manipulate($query);
365    }
366
367
368    public function setDescription($a_description)
369    {
370        $this->description = $a_description;
371    }
372
373    public function getDescription()
374    {
375        return $this->description;
376    }
377
378    public function setType($a_type)
379    {
380        $this->type = $a_type;
381    }
382
383    public function getType()
384    {
385        return $this->type;
386    }
387
388    public function setLMId($a_lm_id)
389    {
390        $this->lm_id = $a_lm_id;
391    }
392
393    public function getLMId()
394    {
395        return $this->lm_id;
396    }
397
398    public function setContentObject(&$a_content_obj)
399    {
400        $this->content_object = $a_content_obj;
401    }
402
403    public function &getContentObject()
404    {
405        return $this->content_object;
406    }
407
408    public function setId($a_id)
409    {
410        $this->id = $a_id;
411    }
412
413    public function getId()
414    {
415        return $this->id;
416    }
417
418    public function getImportId()
419    {
420        return $this->import_id;
421    }
422
423    public function setImportId($a_id)
424    {
425        $this->import_id = $a_id;
426    }
427
428    /**
429    * Set layout
430    *
431    * @param	string	layout
432    */
433    public function setLayout($a_val)
434    {
435        $this->layout = $a_val;
436    }
437
438    /**
439    * Get layout
440    *
441    * @return	string	layout
442    */
443    public function getLayout()
444    {
445        return $this->layout;
446    }
447
448    /**
449    * write import id to db (static)
450    *
451    * @param	int		$a_id				lm object id
452    * @param	string	$a_import_id		import id
453    * @access	public
454    */
455    public static function _writeImportId($a_id, $a_import_id)
456    {
457        global $DIC;
458
459        $ilDB = $DIC->database();
460
461        $q = "UPDATE lm_data " .
462            "SET " .
463            "import_id = " . $ilDB->quote($a_import_id, "text") . "," .
464            "last_update = " . $ilDB->now() . " " .
465            "WHERE obj_id = " . $ilDB->quote($a_id, "integer");
466
467        $ilDB->manipulate($q);
468    }
469
470    public function create($a_upload = false)
471    {
472        $ilDB = $this->db;
473
474        // insert object data
475        $this->setId($ilDB->nextId("lm_data"));
476        $query = "INSERT INTO lm_data (obj_id, title, type, layout, lm_id, import_id, short_title, create_date) " .
477            "VALUES (" .
478            $ilDB->quote($this->getId(), "integer") . "," .
479            $ilDB->quote($this->getTitle(), "text") . "," .
480            $ilDB->quote($this->getType(), "text") . ", " .
481            $ilDB->quote($this->getLayout(), "text") . ", " .
482            $ilDB->quote($this->getLMId(), "integer") . "," .
483            $ilDB->quote($this->getImportId(), "text") . "," .
484            $ilDB->quote($this->getShortTitle(), "text") .
485            ", " . $ilDB->now() . ")";
486        $ilDB->manipulate($query);
487
488        // create history entry
489        include_once("./Services/History/classes/class.ilHistory.php");
490        ilHistory::_createEntry(
491            $this->getId(),
492            "create",
493            "",
494            $this->content_object->getType() . ":" . $this->getType()
495        );
496
497        if (!$a_upload) {
498            $this->createMetaData();
499        }
500    }
501
502    /**
503    * update complete object
504    */
505    public function update()
506    {
507        $ilDB = $this->db;
508
509        $this->updateMetaData();
510
511        $query = "UPDATE lm_data SET " .
512            " lm_id = " . $ilDB->quote($this->getLMId(), "integer") .
513            " ,title = " . $ilDB->quote($this->getTitle(), "text") .
514            " ,short_title = " . $ilDB->quote($this->getShortTitle(), "text") .
515            " ,layout = " . $ilDB->quote($this->getLayout(), "text") .
516            " WHERE obj_id = " . $ilDB->quote($this->getId(), "integer");
517
518        $ilDB->manipulate($query);
519    }
520
521
522    /**
523    * update public access flags in lm_data for all pages of a content object
524    * @static
525    * @access	public
526    * @param	array	page ids
527    * @param	integer	content object id
528    * @return	of the jedi
529    */
530    public static function _writePublicAccessStatus($a_pages, $a_cont_obj_id)
531    {
532        global $DIC;
533
534        $ilDB = $DIC->database();
535        $ilLog = $DIC["ilLog"];
536        $ilErr = $DIC["ilErr"];
537
538        if (!is_array($a_pages)) {
539            $a_pages = array(0);
540            /*$message = sprintf('ilLMObject::_writePublicAccessStatus(): Invalid parameter! $a_pages must be an array');
541            $ilLog->write($message,$ilLog->WARNING);
542            $ilErr->raiseError($message,$ilErr->MESSAGE);
543            return false;*/
544        }
545
546        if (empty($a_cont_obj_id)) {
547            $message = sprintf('ilLMObject::_writePublicAccessStatus(): Invalid parameter! $a_cont_obj_id is empty');
548            $ilLog->write($message, $ilLog->WARNING);
549            $ilErr->raiseError($message, $ilErr->MESSAGE);
550            return false;
551        }
552
553        // update structure entries: if at least one page of a chapter is public set chapter to public too
554        $lm_tree = new ilTree($a_cont_obj_id);
555        $lm_tree->setTableNames('lm_tree', 'lm_data');
556        $lm_tree->setTreeTablePK("lm_id");
557        $lm_tree->readRootId();
558
559        // get all st entries of cont_obj
560        $q = "SELECT obj_id FROM lm_data " .
561             "WHERE lm_id = " . $ilDB->quote($a_cont_obj_id, "integer") . " " .
562             "AND type = 'st'";
563        $r = $ilDB->query($q);
564
565        // add chapters with a public page to a_pages
566        while ($row = $ilDB->fetchAssoc($r)) {
567            $childs = $lm_tree->getChilds($row["obj_id"]);
568
569            foreach ($childs as $page) {
570                if ($page["type"] == "pg" and in_array($page["obj_id"], $a_pages)) {
571                    array_push($a_pages, $row["obj_id"]);
572                    break;
573                }
574            }
575        }
576
577        // update public access status of all pages of cont_obj
578        $q = "UPDATE lm_data SET " .
579             "public_access = CASE " .
580             "WHEN " . $ilDB->in("obj_id", $a_pages, false, "integer") . " " .
581             "THEN " . $ilDB->quote("y", "text") .
582             "ELSE " . $ilDB->quote("n", "text") .
583             "END " .
584             "WHERE lm_id = " . $ilDB->quote($a_cont_obj_id, "integer") . " " .
585             "AND " . $ilDB->in("type", array("pg", "st"), false, "text");
586        $ilDB->manipulate($q);
587
588        return true;
589    }
590
591    public static function _isPagePublic($a_node_id, $a_check_public_mode = false)
592    {
593        global $DIC;
594
595        $ilDB = $DIC->database();
596        $ilLog = $DIC["ilLog"];
597
598        if (empty($a_node_id)) {
599            $message = sprintf('ilLMObject::_isPagePublic(): Invalid parameter! $a_node_id is empty');
600            $ilLog->write($message, $ilLog->WARNING);
601            return false;
602        }
603
604        if ($a_check_public_mode === true) {
605            $lm_id = ilLMObject::_lookupContObjId($a_node_id);
606
607            $q = "SELECT public_access_mode FROM content_object WHERE id = " .
608                $ilDB->quote($lm_id, "integer");
609            $r = $ilDB->query($q);
610            $row = $ilDB->fetchAssoc($r);
611
612            if ($row["public_access_mode"] == "complete") {
613                return true;
614            }
615        }
616
617        $q = "SELECT public_access FROM lm_data WHERE obj_id=" .
618            $ilDB->quote($a_node_id, "integer");
619        $r = $ilDB->query($q);
620        $row = $ilDB->fetchAssoc($r);
621
622        return ilUtil::yn2tf($row["public_access"]);
623    }
624
625    /**
626    * delete lm object data
627    */
628    public function delete($a_delete_meta_data = true)
629    {
630        $ilDB = $this->db;
631
632        $query = "DELETE FROM lm_data WHERE obj_id = " .
633            $ilDB->quote($this->getId(), "integer");
634        $ilDB->manipulate($query);
635
636        $this->deleteMetaData();
637    }
638
639    /**
640    * get current object id for import id (static)
641    *
642    * import ids can exist multiple times (if the same learning module
643    * has been imported multiple times). we get the object id of
644    * the last imported object, that is not in trash
645    *
646    * @param	int		$a_import_id		import id
647    *
648    * @return	int		id
649    */
650    public static function _getIdForImportId($a_import_id)
651    {
652        global $DIC;
653
654        $ilDB = $DIC->database();
655
656        $q = "SELECT obj_id FROM lm_data WHERE import_id = " .
657            $ilDB->quote($a_import_id, "text") . " " .
658            " ORDER BY create_date DESC";
659        $obj_set = $ilDB->query($q);
660        while ($obj_rec = $ilDB->fetchAssoc($obj_set)) {
661            $lm_id = ilLMObject::_lookupContObjID($obj_rec["obj_id"]);
662
663            // link only in learning module, that is not trashed
664            include_once("./Services/Help/classes/class.ilObjHelpSettings.php");
665            $ref_ids = ilObject::_getAllReferences($lm_id);	// will be 0 if import of lm is in progress (new import)
666            if (count($ref_ids) == 0 || ilObject::_hasUntrashedReference($lm_id) ||
667                ilObjHelpSettings::isHelpLM($lm_id)) {
668                return $obj_rec["obj_id"];
669            }
670        }
671
672        return 0;
673    }
674
675    /**
676    * Get all items for an import ID
677    *
678    * (only for items notnot in trash)
679    *
680    * @param	int		$a_import_id		import id
681    *
682    * @return	int		id
683    */
684    public static function _getAllObjectsForImportId($a_import_id, $a_in_lm = 0)
685    {
686        global $DIC;
687
688        $ilDB = $DIC->database();
689
690        $where = ($a_in_lm > 0)
691            ? " AND lm_id = " . $ilDB->quote($a_in_lm, "integer") . " "
692            : "";
693
694        $q = "SELECT * FROM lm_data WHERE import_id = " .
695            $ilDB->quote($a_import_id, "text") . " " .
696            $where .
697            " ORDER BY create_date DESC";
698        $obj_set = $ilDB->query($q);
699
700        $items = array();
701        while ($obj_rec = $ilDB->fetchAssoc($obj_set)) {
702            // check, whether lm is not trashed
703            if (ilObject::_hasUntrashedReference($obj_rec["lm_id"])) {
704                $items[] = $obj_rec;
705            }
706        }
707
708        return $items;
709    }
710
711    /**
712    * checks wether a lm content object with specified id exists or not
713    *
714    * @param	int		$id		id
715    *
716    * @return	boolean		true, if lm content object exists
717    */
718    public static function _exists($a_id)
719    {
720        global $DIC;
721
722        $ilDB = $DIC->database();
723
724        include_once("./Services/Link/classes/class.ilInternalLink.php");
725        if (is_int(strpos($a_id, "_"))) {
726            $a_id = ilInternalLink::_extractObjIdOfTarget($a_id);
727        }
728
729        $q = "SELECT * FROM lm_data WHERE obj_id = " .
730            $ilDB->quote($a_id, "integer");
731        $obj_set = $ilDB->query($q);
732        if ($obj_rec = $ilDB->fetchAssoc($obj_set)) {
733            return true;
734        } else {
735            return false;
736        }
737    }
738
739    /**
740    * static
741    */
742    public static function getObjectList($lm_id, $type = "")
743    {
744        global $DIC;
745
746        $ilDB = $DIC->database();
747
748        $type_str = ($type != "")
749            ? "AND type = " . $ilDB->quote($type, "text") . " "
750            : "";
751
752        $query = "SELECT * FROM lm_data " .
753            "WHERE lm_id= " . $ilDB->quote($lm_id, "integer") . " " .
754            $type_str . " " .
755            "ORDER BY title";
756        $obj_set = $ilDB->query($query);
757        $obj_list = array();
758        while ($obj_rec = $ilDB->fetchAssoc($obj_set)) {
759            $obj_list[] = array("obj_id" => $obj_rec["obj_id"],
760                                "title" => $obj_rec["title"],
761                                "import_id" => $obj_rec["import_id"],
762                                "type" => $obj_rec["type"]);
763        }
764        return $obj_list;
765    }
766
767
768    /**
769    * delete all objects of content object (digi book / learning module)
770    */
771    public static function _deleteAllObjectData(&$a_cobj)
772    {
773        global $DIC;
774
775        $ilDB = $DIC->database();
776
777        $query = "SELECT * FROM lm_data " .
778            "WHERE lm_id= " . $ilDB->quote($a_cobj->getId(), "integer");
779        $obj_set = $ilDB->query($query);
780
781        require_once("./Modules/LearningModule/classes/class.ilLMObjectFactory.php");
782        while ($obj_rec = $ilDB->fetchAssoc($obj_set)) {
783            $lm_obj = ilLMObjectFactory::getInstance($a_cobj, $obj_rec["obj_id"], false);
784
785            if (is_object($lm_obj)) {
786                $lm_obj->delete(true);
787            }
788        }
789
790        return true;
791    }
792
793    /**
794    * get learning module / digibook id for lm object
795    */
796    public static function _lookupContObjID($a_id)
797    {
798        global $DIC;
799
800        $ilDB = $DIC->database();
801
802        if (isset(self::$data_records[$a_id])) {
803            return self::$data_records[$a_id]["lm_id"];
804        }
805
806        $query = "SELECT lm_id FROM lm_data WHERE obj_id = " .
807            $ilDB->quote($a_id, "integer");
808        $obj_set = $ilDB->query($query);
809        $obj_rec = $ilDB->fetchAssoc($obj_set);
810
811        return $obj_rec["lm_id"];
812    }
813
814    /**
815    * put this object into content object tree
816    */
817    public static function putInTree($a_obj, $a_parent_id = "", $a_target_node_id = "")
818    {
819        global $DIC;
820
821        $ilLog = $DIC["ilLog"];
822
823        $tree = new ilTree($a_obj->getContentObject()->getId());
824        $tree->setTableNames('lm_tree', 'lm_data');
825        $tree->setTreeTablePK("lm_id");
826
827        // determine parent
828        $parent_id = ($a_parent_id != "")
829            ? $a_parent_id
830            : $tree->getRootId();
831
832        // determine target
833        if ($a_target_node_id != "") {
834            $target = $a_target_node_id;
835        } else {
836            // determine last child that serves as predecessor
837            if ($a_obj->getType() == "st") {
838                $s_types = array("st", "pg");
839                $childs = $tree->getChildsByTypeFilter($parent_id, $s_types);
840            } else {
841                $s_types = "pg";
842                $childs = $tree->getChildsByType($parent_id, $s_types);
843            }
844
845            if (count($childs) == 0) {
846                $target = IL_FIRST_NODE;
847            } else {
848                $target = $childs[count($childs) - 1]["obj_id"];
849            }
850        }
851
852        if ($tree->isInTree($parent_id) && !$tree->isInTree($a_obj->getId())) {
853            $ilLog->write("LMObject::putInTree: insertNode, ID: " . $a_obj->getId() .
854                "Parent ID: " . $parent_id . ", Target: " . $target);
855
856            $tree->insertNode($a_obj->getId(), $parent_id, $target);
857        }
858    }
859
860    /**
861    * Get learningmodule tree
862    *
863    * @param	int		learning module object id
864    *
865    * @return	object		tree object
866    */
867    public static function getTree($a_cont_obj_id)
868    {
869        $tree = new ilTree($a_cont_obj_id);
870        $tree->setTableNames('lm_tree', 'lm_data');
871        $tree->setTreeTablePK("lm_id");
872        $tree->readRootId();
873
874        return $tree;
875    }
876
877    /**
878    * Copy a set of chapters/pages into the clipboard
879    */
880    public static function clipboardCut($a_cont_obj_id, $a_ids)
881    {
882        $tree = ilLMObject::getTree($a_cont_obj_id);
883
884        if (!is_array($a_ids)) {
885            return false;
886        } else {
887            // get all "top" ids, i.e. remove ids, that have a selected parent
888            foreach ($a_ids as $id) {
889                $path = $tree->getPathId($id);
890                $take = true;
891                foreach ($path as $path_id) {
892                    if ($path_id != $id && in_array($path_id, $a_ids)) {
893                        $take = false;
894                    }
895                }
896                if ($take) {
897                    $cut_ids[] = $id;
898                }
899            }
900        }
901
902        ilLMObject::clipboardCopy($a_cont_obj_id, $cut_ids);
903
904        // remove the objects from the tree
905        // note: we are getting chapters which are *not* in the tree
906        // we do not delete any pages/chapters here
907        foreach ($cut_ids as $id) {
908            $curnode = $tree->getNodeData($id);
909            if ($tree->isInTree($id)) {
910                $tree->deleteTree($curnode);
911            }
912        }
913    }
914
915    /**
916    * Copy a set of chapters/pages into the clipboard
917    */
918    public static function clipboardCopy($a_cont_obj_id, $a_ids)
919    {
920        global $DIC;
921
922        $ilUser = $DIC->user();
923
924        $tree = ilLMObject::getTree($a_cont_obj_id);
925
926        $ilUser->clipboardDeleteObjectsOfType("pg");
927        $ilUser->clipboardDeleteObjectsOfType("st");
928
929        // put them into the clipboard
930        $time = date("Y-m-d H:i:s", time());
931        $order = 0;
932        foreach ($a_ids as $id) {
933            $curnode = array();
934            if ($tree->isInTree($id)) {
935                $curnode = $tree->getNodeData($id);
936                $subnodes = $tree->getSubTree($curnode);
937                foreach ($subnodes as $subnode) {
938                    if ($subnode["child"] != $id) {
939                        $ilUser->addObjectToClipboard(
940                            $subnode["child"],
941                            $subnode["type"],
942                            $subnode["title"],
943                            $subnode["parent"],
944                            $time,
945                            $subnode["lft"]
946                        );
947                    }
948                }
949            }
950            $order = ($curnode["lft"] > 0)
951                ? $curnode["lft"]
952                : (int) ($order + 1);
953            $ilUser->addObjectToClipboard(
954                $id,
955                ilLMObject::_lookupType($id),
956                ilLMObject::_lookupTitle($id),
957                0,
958                $time,
959                $order
960            );
961        }
962    }
963
964    /**
965    * Paste item (tree) from clipboard to current lm
966    */
967    public static function pasteTree(
968        $a_target_lm,
969        $a_item_id,
970        $a_parent_id,
971        $a_target,
972        $a_insert_time,
973        &$a_copied_nodes,
974        $a_as_copy = false,
975        $a_source_lm = null
976    ) {
977        global $DIC;
978
979        $ilUser = $DIC->user();
980        $ilLog = $DIC["ilLog"];
981
982        include_once("./Modules/LearningModule/classes/class.ilStructureObject.php");
983        include_once("./Modules/LearningModule/classes/class.ilLMPageObject.php");
984
985        $item_lm_id = ilLMObject::_lookupContObjID($a_item_id);
986        $item_type = ilLMObject::_lookupType($a_item_id);
987        $lm_obj = ilObjectFactory::getInstanceByObjId($item_lm_id);
988        if ($item_type == "st") {
989            $item = new ilStructureObject($lm_obj, $a_item_id);
990        } elseif ($item_type == "pg") {
991            $item = new ilLMPageObject($lm_obj, $a_item_id);
992        }
993
994        $ilLog->write("Getting from clipboard type " . $item_type . ", " .
995            "Item ID: " . $a_item_id . ", of original LM: " . $item_lm_id);
996
997        if ($item_lm_id != $a_target_lm->getId() && !$a_as_copy) {
998            // @todo: check whether st is NOT in tree
999
1000            // "move" metadata to new lm
1001            include_once("Services/MetaData/classes/class.ilMD.php");
1002            $md = new ilMD($item_lm_id, $item->getId(), $item->getType());
1003            $new_md = $md->cloneMD($a_target_lm->getId(), $item->getId(), $item->getType());
1004
1005            // update lm object
1006            $item->setLMId($a_target_lm->getId());
1007            $item->setContentObject($a_target_lm);
1008            $item->update();
1009
1010            // delete old meta data set
1011            $md->deleteAll();
1012
1013            if ($item_type == "pg") {
1014                $page = $item->getPageObject();
1015                $page->buildDom();
1016                $page->setParentId($a_target_lm->getId());
1017                $page->update();
1018            }
1019        }
1020
1021        if ($a_as_copy) {
1022            $target_item = $item->copy($a_target_lm);
1023            $a_copied_nodes[$item->getId()] = $target_item->getId();
1024        } else {
1025            $target_item = $item;
1026        }
1027
1028        $ilLog->write("Putting into tree type " . $target_item->getType() .
1029            "Item ID: " . $target_item->getId() . ", Parent: " . $a_parent_id . ", " .
1030            "Target: " . $a_target . ", Item LM:" . $target_item->getContentObject()->getId());
1031
1032        ilLMObject::putInTree($target_item, $a_parent_id, $a_target);
1033
1034        if ($a_source_lm == null) {
1035            $childs = $ilUser->getClipboardChilds($item->getId(), $a_insert_time);
1036        } else {
1037            $childs = $a_source_lm->lm_tree->getChilds($item->getId());
1038            foreach ($childs as $k => $child) {
1039                $childs[$k]["id"] = $childs[$k]["child"];
1040            }
1041        }
1042
1043        foreach ($childs as $child) {
1044            ilLMObject::pasteTree(
1045                $a_target_lm,
1046                $child["id"],
1047                $target_item->getId(),
1048                IL_LAST_NODE,
1049                $a_insert_time,
1050                $a_copied_nodes,
1051                $a_as_copy,
1052                $a_source_lm
1053            );
1054        }
1055
1056        return $target_item->getId();
1057        // @todo: write history (see pastePage)
1058    }
1059
1060    /**
1061    * Save titles for lm objects
1062    *
1063    * @param	array		titles (key is ID, value is title)
1064    */
1065    public static function saveTitles($a_lm, $a_titles, $a_lang = "-")
1066    {
1067        include_once("./Modules/LearningModule/classes/class.ilLMObjTranslation.php");
1068
1069        if ($a_lang == "") {
1070            $a_lang = "-";
1071        }
1072        if (is_array($a_titles)) {
1073            include_once("./Services/Form/classes/class.ilFormPropertyGUI.php");
1074            include_once("./Services/MetaData/classes/class.ilMD.php");
1075            foreach ($a_titles as $id => $title) {
1076                // see #20375
1077                $title = ilFormPropertyGUI::removeProhibitedCharacters($title);
1078                if ($a_lang == "-") {
1079                    $lmobj = ilLMObjectFactory::getInstance($a_lm, $id, false);
1080                    if (is_object($lmobj)) {
1081                        // Update Title and description
1082                        $md = new ilMD($a_lm->getId(), $id, $lmobj->getType());
1083                        $md_gen = $md->getGeneral();
1084                        if (is_object($md_gen)) {			// see bug #0015843
1085                            $md_gen->setTitle($title);
1086                            $md_gen->update();
1087                            $md->update();
1088                        }
1089                        ilLMObject::_writeTitle($id, $title);
1090                    }
1091                } else {
1092                    $lmobjtrans = new ilLMObjTranslation($id, $a_lang);
1093                    $lmobjtrans->setTitle($title);
1094                    $lmobjtrans->save();
1095                }
1096            }
1097        }
1098    }
1099
1100    /**
1101    * Update internal links, after multiple pages have been copied
1102    */
1103    public static function updateInternalLinks($a_copied_nodes, $a_parent_type = "lm")
1104    {
1105        $all_fixes = array();
1106        foreach ($a_copied_nodes as $original_id => $copied_id) {
1107            $copied_type = ilLMObject::_lookupType($copied_id);
1108            $copy_lm = ilLMObject::_lookupContObjID($copied_id);
1109
1110            if ($copied_type == "pg") {
1111                foreach (ilPageObject::lookupTranslations($a_parent_type, $copied_id) as $l) {
1112                    //
1113                    // 1. Outgoing links from the copied page.
1114                    //
1115                    //$targets = ilInternalLink::_getTargetsOfSource($a_parent_type.":pg", $copied_id);
1116                    include_once("./Modules/LearningModule/classes/class.ilLMPage.php");
1117                    $tpg = new ilLMPage($copied_id, 0, $l);
1118                    $tpg->buildDom();
1119                    $il = $tpg->getInternalLinks();
1120                    $targets = array();
1121                    foreach ($il as $l) {
1122                        $targets[] = array("type" => ilInternalLink::_extractTypeOfTarget($l["Target"]),
1123                            "id" => (int) ilInternalLink::_extractObjIdOfTarget($l["Target"]),
1124                            "inst" => (int) ilInternalLink::_extractInstOfTarget($l["Target"]));
1125                    }
1126                    $fix = array();
1127                    foreach ($targets as $target) {
1128                        if (($target["inst"] == 0 || $target["inst"] = IL_INST_ID) &&
1129                            ($target["type"] == "pg" || $target["type"] == "st")) {
1130                            // first check, whether target is also within the copied set
1131                            if ($a_copied_nodes[$target["id"]] > 0) {
1132                                $fix[$target["id"]] = $a_copied_nodes[$target["id"]];
1133                            } else {
1134                                // now check, if a copy if the target is already in the same lm
1135
1136                                // only if target is not already in the same lm!
1137                                $trg_lm = ilLMObject::_lookupContObjID($target["id"]);
1138                                if ($trg_lm != $copy_lm) {
1139                                    $lm_data = ilLMObject::_getAllObjectsForImportId("il__" . $target["type"] . "_" . $target["id"]);
1140                                    $found = false;
1141
1142                                    foreach ($lm_data as $item) {
1143                                        if (!$found && ($item["lm_id"] == $copy_lm)) {
1144                                            $fix[$target["id"]] = $item["obj_id"];
1145                                            $found = true;
1146                                        }
1147                                    }
1148                                }
1149                            }
1150                        }
1151                    }
1152
1153                    // outgoing links to be fixed
1154                    if (count($fix) > 0) {
1155                        //echo "<br>--".$copied_id;
1156                        //var_dump($fix);
1157                        $t = ilObject::_lookupType($copy_lm);
1158                        if (is_array($all_fixes[$t . ":" . $copied_id])) {
1159                            $all_fixes[$t . ":" . $copied_id] += $fix;
1160                        } else {
1161                            $all_fixes[$t . ":" . $copied_id] = $fix;
1162                        }
1163                    }
1164                }
1165            }
1166
1167            if ($copied_type == "pg" ||
1168                $copied_type == "st") {
1169
1170                //
1171                // 2. Incoming links to the original pages
1172                //
1173                // A->B			A2			(A+B currently copied)
1174                // A->C			B2
1175                // B->A
1176                // C->A			C2->A		(C already copied)
1177                $original_lm = ilLMObject::_lookupContObjID($original_id);
1178                $original_type = ilObject::_lookupType($original_lm);
1179
1180                if ($original_lm != $copy_lm) {
1181
1182                    // This gets sources that link to A+B (so we have C here)
1183                    // (this also does already the trick when instance map areas are given in C)
1184                    // int_link, where target_type, target_id, target_inst -> ok
1185                    $sources = ilInternalLink::_getSourcesOfTarget(
1186                        $copied_type,
1187                        $original_id,
1188                        0
1189                    );
1190
1191                    // mobs linking to $original_id
1192                    // map_area, where link_type, target -> ok
1193                    $mobs = ilMapArea::_getMobsForTarget("int", "il__" . $copied_type .
1194                        "_" . $original_id);
1195
1196                    // pages using these mobs
1197                    include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1198                    foreach ($mobs as $mob) {
1199                        // mob_usage, where id -> ok
1200                        // mep_item, where foreign_id, type -> ok
1201                        // mep_tree, where child -> already existed
1202                        // il_news_item, where mob_id -> ok
1203                        // map_area, where link_type, target -> aready existed
1204                        // media_item, where id -> already existed
1205                        // personal_clipboard, where item_id, type -> ok
1206                        $usages = ilObjMediaObject::lookupUsages($mob);
1207                        foreach ($usages as $usage) {
1208                            if ($usage["type"] == "lm:pg" | $usage["type"] == "lm:st") {
1209                                $sources[] = $usage;
1210                            }
1211                        }
1212                    }
1213                    $fix = array();
1214                    foreach ($sources as $source) {
1215                        $stype = explode(":", $source["type"]);
1216                        $source_type = $stype[1];
1217
1218                        if ($source_type == "pg" || $source_type == "st") {
1219                            // first of all: source must be in original lm
1220                            $src_lm = ilLMObject::_lookupContObjID($source["id"]);
1221
1222                            if ($src_lm == $original_lm) {
1223                                // check, if a copy if the source is already in the same lm
1224                                // now we look for the latest copy of C in LM2
1225                                $lm_data = ilLMObject::_getAllObjectsForImportId(
1226                                    "il__" . $source_type . "_" . $source["id"],
1227                                    $copy_lm
1228                                );
1229                                $found = false;
1230                                foreach ($lm_data as $item) {
1231                                    if (!$found) {
1232                                        $fix[$item["obj_id"]][$original_id] = $copied_id;
1233                                        $found = true;
1234                                    }
1235                                }
1236                            }
1237                        }
1238                    }
1239                    // outgoing links to be fixed
1240                    if (count($fix) > 0) {
1241                        foreach ($fix as $page_id => $fix_array) {
1242                            $t = ilObject::_lookupType($copy_lm);
1243                            if (is_array($all_fixes[$t . ":" . $page_id])) {
1244                                $all_fixes[$t . ":" . $page_id] += $fix_array;
1245                            } else {
1246                                $all_fixes[$t . ":" . $page_id] = $fix_array;
1247                            }
1248                        }
1249                    }
1250                }
1251            }
1252        }
1253
1254        foreach ($all_fixes as $pg => $fixes) {
1255            $pg = explode(":", $pg);
1256            include_once("./Services/COPage/classes/class.ilPageObjectFactory.php");
1257            foreach (ilPageObject::lookupTranslations($pg[0], $pg[1]) as $l) {
1258                $page = ilPageObjectFactory::getInstance($pg[0], $pg[1], 0, $l);
1259                if ($page->moveIntLinks($fixes)) {
1260                    $page->update(true, true);
1261                }
1262            }
1263        }
1264    }
1265
1266    /**
1267    * Check for unique types (all pages or all chapters)
1268    */
1269    public static function uniqueTypesCheck($a_items)
1270    {
1271        $types = array();
1272        if (is_array($a_items)) {
1273            foreach ($a_items as $item) {
1274                $type = ilLMObject::_lookupType($item);
1275                $types[$type] = $type;
1276            }
1277        }
1278
1279        if (count($types) > 1) {
1280            return false;
1281        }
1282        return true;
1283    }
1284
1285    /**
1286    * Write layout setting
1287    *
1288    * @param	int		lm object id
1289    * @param	string	layout
1290    */
1291    public static function writeLayout($a_obj_id, $a_layout, $a_lm = null)
1292    {
1293        global $DIC;
1294
1295        $ilDB = $DIC->database();
1296
1297        $t = ilLMObject::_lookupType($a_obj_id);
1298
1299        if ($t == "pg") {
1300            $query = "UPDATE lm_data SET " .
1301                " layout = " . $ilDB->quote($a_layout, "text") .
1302                " WHERE obj_id = " . $ilDB->quote($a_obj_id, "integer");
1303            $ilDB->manipulate($query);
1304        } elseif ($t == "st" && is_object($a_lm)) {
1305            $node = $a_lm->getLMTree()->getNodeData($a_obj_id);
1306            $child_nodes = $a_lm->getLMTree()->getSubTree($node);
1307            if (is_array($child_nodes) && count($child_nodes) > 0) {
1308                foreach ($child_nodes as $c) {
1309                    if ($c["type"] == "pg") {
1310                        $query = "UPDATE lm_data SET " .
1311                            " layout = " . $ilDB->quote($a_layout, "text") .
1312                            " WHERE obj_id = " . $ilDB->quote($c["child"], "integer");
1313                        $ilDB->manipulate($query);
1314                    }
1315                }
1316            }
1317        }
1318    }
1319
1320    /**
1321    * Lookup type
1322    *
1323    * @param	int		lm object id
1324    */
1325    public static function lookupLayout($a_obj_id)
1326    {
1327        global $DIC;
1328
1329        $ilDB = $DIC->database();
1330
1331        $query = "SELECT layout FROM lm_data WHERE obj_id = " .
1332            $ilDB->quote($a_obj_id, "integer");
1333        $obj_set = $ilDB->query($query);
1334        $obj_rec = $ilDB->fetchAssoc($obj_set);
1335
1336        return $obj_rec["layout"];
1337    }
1338
1339    /**
1340     * Get pages of chapter
1341     *
1342     * @param
1343     * @return
1344     */
1345    public static function getPagesOfChapter($a_lm_id, $a_chap_id)
1346    {
1347        // update structure entries: if at least one page of a chapter is public set chapter to public too
1348        $lm_tree = new ilTree($a_lm_id);
1349        $lm_tree->setTableNames('lm_tree', 'lm_data');
1350        $lm_tree->setTreeTablePK("lm_id");
1351        $lm_tree->readRootId();
1352
1353        $childs = $lm_tree->getChildsByType($a_chap_id, "pg");
1354
1355        return $childs;
1356    }
1357
1358    /**
1359     * Get all objects of learning module
1360     *
1361     * @param
1362     * @return
1363     */
1364    public static function _getAllLMObjectsOfLM($a_lm_id, $a_type = "")
1365    {
1366        global $DIC;
1367
1368        $ilDB = $DIC->database();
1369
1370        $and = ($a_type != "")
1371            ? " AND type = " . $ilDB->quote($a_type, "text")
1372            : "";
1373
1374        $set = $ilDB->query("SELECT obj_id FROM lm_data " .
1375            " WHERE lm_id = " . $ilDB->quote($a_lm_id, "integer") . $and);
1376        $obj_ids = array();
1377        while ($rec = $ilDB->fetchAssoc($set)) {
1378            $obj_ids[] = $rec["obj_id"];
1379        }
1380
1381        return $obj_ids;
1382    }
1383
1384
1385    ////
1386    //// Export ID handling
1387    ////
1388
1389    /**
1390     * Save export id
1391     *
1392     * @param
1393     * @return
1394     */
1395    public static function saveExportId($a_lm_id, $a_lmobj_id, $a_exp_id, $a_type = "pg")
1396    {
1397        global $DIC;
1398
1399        $ilDB = $DIC->database();
1400
1401        include_once("Services/MetaData/classes/class.ilMDIdentifier.php");
1402
1403        if (trim($a_exp_id) == "") {
1404            // delete export ids, if existing
1405            $entries = ilMDIdentifier::_getEntriesForObj(
1406                $a_lm_id,
1407                $a_lmobj_id,
1408                $a_type
1409            );
1410
1411            foreach ($entries as $id => $e) {
1412                if ($e["catalog"] == "ILIAS_NID") {
1413                    $identifier = new ilMDIdentifier();
1414                    $identifier->setMetaId($id);
1415                    $identifier->delete();
1416                }
1417            }
1418        } else {
1419            // update existing entry
1420            $entries = ilMDIdentifier::_getEntriesForObj(
1421                $a_lm_id,
1422                $a_lmobj_id,
1423                $a_type
1424            );
1425
1426            $updated = false;
1427            foreach ($entries as $id => $e) {
1428                if ($e["catalog"] == "ILIAS_NID") {
1429                    $identifier = new ilMDIdentifier();
1430                    $identifier->setMetaId($id);
1431                    $identifier->read();
1432                    $identifier->setEntry($a_exp_id);
1433                    $identifier->update();
1434                    $updated = true;
1435                }
1436            }
1437
1438            // nothing updated? create a new one
1439            if (!$updated) {
1440                include_once("./Services/MetaData/classes/class.ilMD.php");
1441                $md = new ilMD($a_lm_id, $a_lmobj_id, $a_type);
1442                $md_gen = $md->getGeneral();
1443                $identifier = $md_gen->addIdentifier();
1444                $identifier->setEntry($a_exp_id);
1445                $identifier->setCatalog("ILIAS_NID");
1446                $identifier->save();
1447            }
1448        }
1449    }
1450
1451    /**
1452     * Get export ID
1453     *
1454     * @param
1455     * @return
1456     */
1457    public static function getExportId($a_lm_id, $a_lmobj_id, $a_type = "pg")
1458    {
1459        // look for export id
1460        include_once("./Services/MetaData/classes/class.ilMDIdentifier.php");
1461        $entries = ilMDIdentifier::_getEntriesForObj(
1462            $a_lm_id,
1463            $a_lmobj_id,
1464            $a_type
1465        );
1466
1467        foreach ($entries as $e) {
1468            if ($e["catalog"] == "ILIAS_NID") {
1469                return $e["entry"];
1470            }
1471        }
1472    }
1473
1474    /**
1475     * Does export ID exist in lm?
1476     *
1477     * @param
1478     * @return
1479     */
1480    public function existsExportID($a_lm_id, $a_exp_id, $a_type = "pg")
1481    {
1482        include_once("./Services/MetaData/classes/class.ilMDIdentifier.php");
1483        return ilMDIdentifier::existsIdInRbacObject($a_lm_id, $a_type, "ILIAS_NID", $a_exp_id);
1484    }
1485
1486    /**
1487     * Get duplicate export IDs (count export ID usages)
1488     */
1489    public static function getDuplicateExportIDs($a_lm_id, $a_type = "pg")
1490    {
1491        include_once("./Services/MetaData/classes/class.ilMDIdentifier.php");
1492        $entries = ilMDIdentifier::_getEntriesForRbacObj($a_lm_id, $a_type);
1493        $res = array();
1494        foreach ($entries as $e) {
1495            if ($e["catalog"] == "ILIAS_NID") {
1496                if (ilLMObject::_exists($e["obj_id"])) {
1497                    $res[trim($e["entry"])]++;
1498                }
1499            }
1500        }
1501        return $res;
1502    }
1503
1504    /**
1505     * Does export ID exist in lm?
1506     *
1507     * @param
1508     * @return
1509     */
1510    public function getExportIDInfo($a_lm_id, $a_exp_id, $a_type = "pg")
1511    {
1512        include_once("./Services/MetaData/classes/class.ilMDIdentifier.php");
1513        $data = ilMDIdentifier::readIdData($a_lm_id, $a_type, "ILIAS_NID", $a_exp_id);
1514        return $data;
1515    }
1516
1517    /**
1518     * Get affective title
1519     *
1520     * @param
1521     * @return
1522     */
1523    public static function _getPresentationTitle(
1524        $a_node,
1525        $a_mode = IL_PAGE_TITLE,
1526        $a_include_numbers = false,
1527        $a_time_scheduled_activation = false,
1528        $a_force_content = false,
1529        $a_lm_id = 0,
1530        $a_lang = "-"
1531    ) {
1532        if ($a_lang == "") {
1533            $a_lang = "-";
1534        }
1535
1536        if ($a_node["type"] == "st") {
1537            include_once './Modules/LearningModule/classes/class.ilStructureObject.php';
1538            return ilStructureObject::_getPresentationTitle(
1539                $a_node["child"],
1540                IL_CHAPTER_TITLE,
1541                $a_include_numbers,
1542                $a_time_scheduled_activation,
1543                $a_force_content,
1544                $a_lm_id,
1545                $a_lang
1546            );
1547        } else {
1548            include_once './Modules/LearningModule/classes/class.ilLMPageObject.php';
1549            return ilLMPageObject::_getPresentationTitle(
1550                $a_node["child"],
1551                $a_mode,
1552                $a_include_numbers,
1553                $a_time_scheduled_activation,
1554                $a_force_content,
1555                $a_lm_id,
1556                $a_lang
1557            );
1558        }
1559    }
1560
1561    /**
1562     * Get short titles
1563     *
1564     * @param
1565     * @return array
1566     */
1567    public static function getShortTitles($a_lm_id, $a_lang = "-")
1568    {
1569        global $DIC;
1570
1571        $db = $DIC->database();
1572
1573        $title_data = array();
1574        if ($a_lang == "-") {
1575            $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 = " .
1576                $db->quote($a_lm_id, "integer") . " ORDER BY t.lft, d.title");
1577        } else {
1578            $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 " .
1579                " LEFT JOIN lm_tree t ON (d.obj_id = t.child) " .
1580                " LEFT JOIN lm_data_transl tr ON (tr.id = d.obj_id AND tr.lang=" . $db->quote($a_lang, "text") . ") WHERE d.lm_id = " .
1581                $db->quote($a_lm_id, "integer") . " ORDER BY t.lft, d.title");
1582        }
1583        while ($rec = $db->fetchAssoc($set)) {
1584            $title_data[] = $rec;
1585        }
1586        return $title_data;
1587    }
1588
1589    /**
1590     * Write short title
1591     *
1592     * @param integer $a_id object id
1593     * @param string $a_short_title short title
1594     */
1595    public static function writeShortTitle($a_id, $a_short_title, $a_lang = "-")
1596    {
1597        global $DIC;
1598
1599        $db = $DIC->database();
1600
1601        if ($a_lang != "-" && $a_lang != "") {
1602            $trans = new ilLMObjTranslation($a_id, $a_lang);
1603            $trans->setShortTitle($a_short_title);
1604            $trans->save();
1605        } else {
1606            $db->manipulate(
1607                "UPDATE lm_data SET " .
1608                " short_title = " . $db->quote($a_short_title, "text") .
1609                " WHERE obj_id = " . $db->quote($a_id, "integer")
1610            );
1611        }
1612    }
1613}
1614