1<?php
2
3/* Copyright (c) 1998-2011 ILIAS open source, Extended GPL, see docs/LICENSE */
4
5require_once "./Services/Object/classes/class.ilObject.php";
6require_once "./Modules/ScormAicc/classes/class.ilObjSCORMValidator.php";
7//require_once "Services/MetaData/classes/class.ilMDLanguageItem.php";
8
9/** @defgroup ModulesScormAicc Modules/ScormAicc
10 */
11
12/**
13* Class ilObjSCORMLearningModule
14*
15* @author Alex Killing <alex.killing@gmx.de>
16* $Id$
17*
18* @ingroup ModulesScormAicc
19*/
20class ilObjSAHSLearningModule extends ilObject
21{
22    public $validator;
23    //	var $meta_data;
24
25    /**
26    * Constructor
27    * @access	public
28    * @param	integer	reference_id or object_id
29    * @param	boolean	treat the id as reference_id (true) or object_id (false)
30    */
31    public function __construct($a_id = 0, $a_call_by_reference = true)
32    {
33        $this->type = "sahs";
34        parent::__construct($a_id, $a_call_by_reference);
35    }
36
37    /**
38    * create file based lm
39    */
40    public function create($upload = false)
41    {
42        global $DIC;
43        $ilDB = $DIC['ilDB'];
44
45        parent::create();
46        if (!$upload) {
47            $this->createMetaData();
48        }
49
50        $this->createDataDirectory();
51        $ilDB->manipulateF(
52            '
53			INSERT INTO sahs_lm (id, api_adapter, c_type, editable, seq_exp_mode,localization)
54			VALUES (%s,%s,%s,%s,%s,%s)',
55            array('integer', 'text', 'text', 'integer','integer','text'),
56            array($this->getId(),'API', $this->getSubType(),(int) $this->getEditable(),
57                (int) $this->getSequencingExpertMode(), $this->getLocalization()
58                )
59        );
60    }
61
62    /**
63    * read object
64    */
65    public function read()
66    {
67        global $DIC;
68        $ilDB = $DIC['ilDB'];
69
70        parent::read();
71
72        $lm_set = $ilDB->queryF(
73            'SELECT * FROM sahs_lm WHERE id = %s',
74            array('integer'),
75            array($this->getId())
76        );
77
78        while ($lm_rec = $ilDB->fetchAssoc($lm_set)) {
79            $this->setAutoReviewChar($lm_rec["auto_review"]);
80            $this->setAPIAdapterName($lm_rec["api_adapter"]);
81            $this->setDefaultLessonMode($lm_rec["default_lesson_mode"]);
82            $this->setAPIFunctionsPrefix($lm_rec["api_func_prefix"]);
83            $this->setCreditMode($lm_rec["credit"]);
84            $this->setSubType($lm_rec["c_type"]);
85            $this->setEditable($lm_rec["editable"]);
86            $this->setStyleSheetId($lm_rec["stylesheet"]);
87            $this->setMaxAttempt($lm_rec["max_attempt"]);
88            $this->setModuleVersion($lm_rec["module_version"]);
89            $this->setAssignedGlossary($lm_rec["glossary"]);
90            $this->setTries($lm_rec["question_tries"]);
91            $this->setLocalization($lm_rec["localization"]);
92            $this->setSession(ilUtil::yn2tf($lm_rec["unlimited_session"]));
93            $this->setNoMenu(ilUtil::yn2tf($lm_rec["no_menu"]));
94            $this->setHideNavig(ilUtil::yn2tf($lm_rec["hide_navig"]));
95            $this->setFourth_edition(ilUtil::yn2tf($lm_rec["fourth_edition"]));
96            $this->setSequencing(ilUtil::yn2tf($lm_rec["sequencing"]));
97            $this->setInteractions(ilUtil::yn2tf($lm_rec["interactions"]));
98            $this->setObjectives(ilUtil::yn2tf($lm_rec["objectives"]));
99            $this->setComments(ilUtil::yn2tf($lm_rec["comments"]));
100            $this->setTime_from_lms(ilUtil::yn2tf($lm_rec["time_from_lms"]));
101            $this->setDebug(ilUtil::yn2tf($lm_rec["debug"]));
102            $this->setDebugPw($lm_rec["debugpw"]);
103            $this->setSequencingExpertMode($lm_rec["seq_exp_mode"]);
104            $this->setOpenMode($lm_rec["open_mode"]);
105            $this->setWidth($lm_rec["width"]);
106            $this->setHeight($lm_rec["height"]);
107            $this->setAutoContinue(ilUtil::yn2tf($lm_rec["auto_continue"]));
108            $this->setAuto_last_visited(ilUtil::yn2tf($lm_rec["auto_last_visited"]));
109            $this->setCheck_values(ilUtil::yn2tf($lm_rec["check_values"]));
110            $this->setOfflineMode(ilUtil::yn2tf($lm_rec["offline_mode"]));
111            $this->setAutoSuspend(ilUtil::yn2tf($lm_rec["auto_suspend"]));
112            $this->setIe_force_render(ilUtil::yn2tf($lm_rec["ie_force_render"]));
113            $this->setMasteryScore($lm_rec["mastery_score"]);
114            $this->setIdSetting($lm_rec["id_setting"]);
115            $this->setNameSetting($lm_rec["name_setting"]);
116
117            include_once("./Services/Style/Content/classes/class.ilObjStyleSheet.php");
118            if (ilObject::_lookupType($this->getStyleSheetId()) != "sty") {
119                $this->setStyleSheetId(0);
120            }
121        }
122    }
123
124
125    /**
126     * Get affective localization
127     *
128     * @param int $a_id scorm lm id
129     */
130    public static function getAffectiveLocalization($a_id)
131    {
132        global $DIC;
133        $ilDB = $DIC['ilDB'];
134        $lng = $DIC['lng'];
135
136        $lm_set = $ilDB->queryF(
137            'SELECT localization FROM sahs_lm WHERE id = %s',
138            array('integer'),
139            array($a_id)
140        );
141        $lm_rec = $ilDB->fetchAssoc($lm_set);
142        $inst_lang = $lng->getInstalledLanguages();
143        if ($lm_rec["localization"] != "" && in_array($lm_rec["localization"], $inst_lang)) {
144            return $lm_rec["localization"];
145        }
146        return $lng->getLangKey();
147    }
148
149    /**
150    * lookup subtype id (scorm, )
151    *
152    * @param	int		$a_id		object id
153    */
154    public static function _lookupSubType($a_obj_id)
155    {
156        global $DIC;
157        $ilDB = $DIC['ilDB'];
158
159        $obj_set = $ilDB->queryF(
160            'SELECT c_type FROM sahs_lm WHERE id = %s',
161            array('integer'),
162            array($a_obj_id)
163        );
164        $obj_rec = $ilDB->fetchAssoc($obj_set);
165
166        return $obj_rec["c_type"];
167    }
168
169    /**
170    * Set Editable.
171    *
172    * @param	boolean	$a_editable	Editable
173    */
174    public function setEditable($a_editable)
175    {
176        $this->editable = $a_editable;
177    }
178
179    /**
180    * Get Editable.
181    *
182    * @return	boolean	Editable
183    */
184    public function getEditable()
185    {
186        return $this->editable;
187    }
188
189
190    /**
191    * Set default tries for questions
192    *
193    * @param	boolean	$a_tres	tries
194    */
195    public function setTries($a_tries)
196    {
197        $this->tries = $a_tries;
198    }
199
200    /**
201    * Get Tries.
202    *
203    * @return	boolean	tries
204    */
205    public function getTries()
206    {
207        return $this->tries;
208    }
209
210    /**
211     * Set localization
212     *
213     * @param string $a_val localization
214     */
215    public function setLocalization($a_val)
216    {
217        $this->localization = $a_val;
218    }
219
220    /**
221     * Get localization
222     *
223     * @return string localization
224     */
225    public function getLocalization()
226    {
227        return $this->localization;
228    }
229
230    public static function _getTries($a_id)
231    {
232        global $DIC;
233        $ilDB = $DIC['ilDB'];
234
235        $lm_set = $ilDB->queryF(
236            'SELECT question_tries FROM sahs_lm WHERE id = %s',
237            array('integer'),
238            array($a_id)
239        );
240        $lm_rec = $ilDB->fetchAssoc($lm_set);
241
242        return $lm_rec['question_tries'];
243    }
244    /**
245    * Gets the disk usage of the object in bytes.
246    *
247    * @access	public
248    * @return	integer		the disk usage in bytes
249    */
250    public function getDiskUsage()
251    {
252        require_once("./Modules/ScormAicc/classes/class.ilObjSAHSLearningModuleAccess.php");
253        return ilObjSAHSLearningModuleAccess::_lookupDiskUsage($this->id);
254    }
255
256
257    /**
258    * creates data directory for package files
259    * ("./data/lm_data/lm_<id>")
260    */
261    public function createDataDirectory()
262    {
263        $lm_data_dir = ilUtil::getWebspaceDir() . "/lm_data";
264        ilUtil::makeDir($lm_data_dir);
265        ilUtil::makeDir($this->getDataDirectory());
266    }
267
268    /**
269    * get data directory of lm
270    */
271    public function getDataDirectory($mode = "filesystem")
272    {
273        $lm_data_dir = ilUtil::getWebspaceDir($mode) . "/lm_data";
274        $lm_dir = $lm_data_dir . "/lm_" . $this->getId();
275
276        return $lm_dir;
277    }
278
279    /**
280    * get api adapter name
281    */
282    public function getAPIAdapterName()
283    {
284        return $this->api_adapter;
285    }
286
287    /**
288    * set api adapter name
289    */
290    public function setAPIAdapterName($a_api)
291    {
292        $this->api_adapter = $a_api;
293    }
294
295    /**
296    * get api functions prefix
297    */
298    public function getAPIFunctionsPrefix()
299    {
300        return $this->api_func_prefix;
301    }
302
303    /**
304    * set api functions prefix
305    */
306    public function setAPIFunctionsPrefix($a_prefix)
307    {
308        $this->api_func_prefix = $a_prefix;
309    }
310
311    /**
312    * get credit mode
313    */
314    public function getCreditMode()
315    {
316        return $this->credit_mode;
317    }
318
319    /**
320    * set credit mode
321    */
322    public function setCreditMode($a_credit_mode)
323    {
324        $this->credit_mode = $a_credit_mode;
325    }
326
327    /**
328    * set default lesson mode
329    */
330    public function setDefaultLessonMode($a_lesson_mode)
331    {
332        $this->lesson_mode = $a_lesson_mode;
333    }
334
335    /**
336    * get default lesson mode
337    */
338    public function getDefaultLessonMode()
339    {
340        global $DIC;
341        if ($DIC['ilUser']->getId() == 13) {
342            return "browse";
343        }
344        return $this->lesson_mode;
345    }
346    /**
347    * get ID of assigned style sheet object
348    */
349    public function getStyleSheetId()
350    {
351        return $this->style_id;
352    }
353
354    /**
355    * set ID of assigned style sheet object
356    */
357    public function setStyleSheetId($a_style_id)
358    {
359        $this->style_id = $a_style_id;
360    }
361
362
363    /**
364    * set auto review as true/false for SCORM 1.2
365    */
366    public function setAutoReview($a_auto_review)
367    {
368        $this->auto_review = ilUtil::tf2yn($a_auto_review);
369    }
370    /**
371    * get auto review as true/false for SCORM 1.2
372    */
373    public function getAutoReview()
374    {
375        return ilUtil::yn2tf($this->auto_review);
376    }
377
378    /**
379    * set auto review as Char for SCORM 2004
380    */
381    public function setAutoReviewChar($a_auto_review)
382    {
383        $this->auto_review = $a_auto_review;
384    }
385    /**
386    * get auto review as Char for SCORM 2004
387    */
388    public function getAutoReviewChar()
389    {
390        return $this->auto_review;
391    }
392
393    /**
394    * get max attempt
395    */
396    public function getMaxAttempt()
397    {
398        return $this->max_attempt;
399    }
400
401
402    /**
403    * set max attempt
404    */
405    public function setMaxAttempt($a_max_attempt)
406    {
407        $this->max_attempt = $a_max_attempt;
408    }
409
410    /**
411    * get module version
412    */
413    public function getModuleVersion()
414    {
415        return $this->module_version;
416    }
417
418    /**
419    * get assigned glossary
420    */
421    public function getAssignedGlossary()
422    {
423        return $this->assigned_glossary;
424    }
425
426    /**
427    * set assigned glossary
428    */
429    public function setAssignedGlossary($a_assigned_glossary)
430    {
431        $this->assigned_glossary = $a_assigned_glossary;
432    }
433    /**
434    * set max attempt
435    */
436    public function setModuleVersion($a_module_version)
437    {
438        $this->module_version = $a_module_version;
439    }
440
441    /**
442    * get session setting
443    */
444    public function getSession()
445    {
446        return $this->session;
447    }
448
449    /**
450    * set session setting
451    */
452    public function setSession($a_session)
453    {
454        $this->session = $a_session;
455    }
456
457    /**
458    * disable menu
459    */
460    public function getNoMenu()
461    {
462        return $this->no_menu;
463    }
464
465    /**
466    * disable menu
467    */
468    public function setNoMenu($a_no_menu)
469    {
470        $this->no_menu = $a_no_menu;
471    }
472
473    /**
474    * hide navigation tree
475    */
476    public function getHideNavig()
477    {
478        return $this->hide_navig;
479    }
480
481    /**
482    * disable menu
483    */
484    public function setHideNavig($a_hide_navig)
485    {
486        $this->hide_navig = $a_hide_navig;
487    }
488
489    /**
490    * BrowserCacheDisabled for SCORM 2004 / ENABLE_JS_DEBUG
491    */
492    public function getCacheDeactivated()
493    {
494        global $DIC;
495        $ilSetting = $DIC['ilSetting'];
496        $lm_set = new ilSetting("lm");
497        if ($lm_set->get("scormdebug_disable_cache") == "1") {
498            return true;
499        }
500        return false;
501    }
502
503    /**
504    * sessionDisabled for SCORM 2004
505    */
506    public function getSessionDeactivated()
507    {
508        global $DIC;
509        $ilSetting = $DIC['ilSetting'];
510        $lm_set = new ilSetting("lm");
511        if ($lm_set->get("scorm_without_session") == "1") {
512            return true;
513        }
514        return false;
515    }
516
517    /**
518    * debugActivated
519    */
520    public function getDebugActivated()
521    {
522        global $DIC;
523        $ilSetting = $DIC['ilSetting'];
524        $lm_set = new ilSetting("lm");
525        if ($lm_set->get("scormdebug_global_activate") == "1") {
526            return true;
527        }
528        return false;
529    }
530
531    /**
532    * force Internet Explorer to render again after some Milliseconds - useful for learning Modules with a lot of iframesor frames and IE >=10
533    */
534    public function getIe_force_render()
535    {
536        return $this->ie_force_render;
537    }
538
539    public function setIe_force_render($a_ie_force_render)
540    {
541        $this->ie_force_render = $a_ie_force_render;
542    }
543
544    /**
545    * SCORM 2004 4th edition features
546    */
547    public function getFourth_Edition()
548    {
549        return $this->fourth_edition;
550    }
551
552    public function setFourth_edition($a_fourth_edition)
553    {
554        $this->fourth_edition = $a_fourth_edition;
555    }
556
557    /**
558    * sequencing
559    */
560    public function getSequencing()
561    {
562        return $this->sequencing;
563    }
564
565    public function setSequencing($a_sequencing)
566    {
567        $this->sequencing = $a_sequencing;
568    }
569
570    /**
571    * interactions
572    */
573    public function getInteractions()
574    {
575        return $this->interactions;
576    }
577
578    public function setInteractions($a_interactions)
579    {
580        $this->interactions = $a_interactions;
581    }
582
583    /**
584    * objectives
585    */
586    public function getObjectives()
587    {
588        return $this->objectives;
589    }
590
591    public function setObjectives($a_objectives)
592    {
593        $this->objectives = $a_objectives;
594    }
595
596    /**
597    * comments
598    */
599    public function getComments()
600    {
601        return $this->comments;
602    }
603
604    public function setComments($a_comments)
605    {
606        $this->comments = $a_comments;
607    }
608
609    /**
610    * time_from_lms
611    */
612    public function getTime_from_lms()
613    {
614        return $this->time_from_lms;
615    }
616
617    public function setTime_from_lms($a_time_from_lms)
618    {
619        $this->time_from_lms = $a_time_from_lms;
620    }
621
622    /**
623    * check_values
624    */
625    public function getCheck_values()
626    {
627        return $this->check_values;
628    }
629
630    public function setCheck_values($a_check_values)
631    {
632        $this->check_values = $a_check_values;
633    }
634
635    /**
636    * offlineMode
637    */
638    public function getOfflineMode()
639    {
640        return $this->offline_mode;
641    }
642
643    public function setOfflineMode($a_offline_mode)
644    {
645        $this->offline_mode = $a_offline_mode;
646    }
647
648
649    /**
650    * debug
651    */
652    public function getDebug()
653    {
654        return $this->debug;
655    }
656
657    /**
658    * debug
659    */
660    public function setDebug($a_debug)
661    {
662        $this->debug = $a_debug;
663    }
664
665    /**
666    * debug pw
667    */
668    public function getDebugPw()
669    {
670        return $this->debug_pw;
671    }
672
673    /**
674    * debug pw
675    */
676    public function setDebugPw($a_debug_pw)
677    {
678        $this->debug_pw = $a_debug_pw;
679    }
680
681    /**
682    * get auto continue
683    */
684    public function setAutoContinue($a_auto_continue)
685    {
686        $this->auto_continue = $a_auto_continue;
687    }
688    /**
689    * set auto continue
690    */
691    public function getAutoContinue()
692    {
693        return $this->auto_continue;
694    }
695
696    /**
697    * auto_last_visited
698    */
699    public function getAuto_last_visited()
700    {
701        return $this->auto_last_visited;
702    }
703
704    public function setAuto_last_visited($a_auto_last_visited)
705    {
706        $this->auto_last_visited = $a_auto_last_visited;
707    }
708
709
710    /**
711     * Set sequencing expert mode
712     *
713     * @param boolean $a_val sequencing expert mode
714     */
715    public function setSequencingExpertMode($a_val)
716    {
717        $this->seq_exp_mode = $a_val;
718    }
719
720    /**
721     * Get sequencing expert mode
722     *
723     * @return boolean sequencing expert mode
724     */
725    public function getSequencingExpertMode()
726    {
727        return $this->seq_exp_mode;
728    }
729
730    /**
731    * get auto continue
732    */
733    public function setAutoSuspend($a_auto_suspend)
734    {
735        $this->auto_suspend = $a_auto_suspend;
736    }
737    /**
738    * set auto continue
739    */
740    public function getAutoSuspend()
741    {
742        return $this->auto_suspend;
743    }
744
745
746    /**
747    * open_mode
748    * 0: in Tab/new Window like in previous versions
749    * 1: in iFrame with width=100% and heigth=100%
750    * 2: in iFrame with specified width and height
751    * 3:
752    * 4:
753    * 5: in new Window without specified width and height
754    * 6: in new Window with specified width and height
755    */
756    public function getOpenMode()
757    {
758        return $this->open_mode;
759    }
760    public function setOpenMode($a_open_mode)
761    {
762        $this->open_mode = $a_open_mode;
763    }
764
765    /**
766    * width
767    */
768    public function getWidth()
769    {
770        return $this->width;
771    }
772    public function setWidth($a_width)
773    {
774        $this->width = $a_width;
775    }
776
777    /**
778    * height
779    */
780    public function getHeight()
781    {
782        return $this->height;
783    }
784    public function setHeight($a_height)
785    {
786        $this->height = $a_height;
787    }
788
789
790    /**
791    * get mastery_score
792    */
793    public function getMasteryScore()
794    {
795        return $this->mastery_score;
796    }
797
798    /**
799    * set mastery_score
800    */
801    public function setMasteryScore($a_mastery_score)
802    {
803        $this->mastery_score = $a_mastery_score;
804    }
805
806    /**
807    * check mastery_score / min_normalized_measure of SCOs (SCORM 1.2) / objectives (SCORM 2004)
808    */
809    public function checkMasteryScoreValues()
810    {
811        global $DIC;
812        $ilDB = $DIC['ilDB'];
813        $s_result = "";
814        $a_result = array();
815        $type = $this->_lookupSubType($this->getID());
816
817        if ($type == "scorm2004") {
818            $set = $ilDB->query("SELECT minnormalmeasure FROM cp_objective, cp_node" .
819                " WHERE satisfiedbymeasure=1 AND minnormalmeasure is not null AND cp_objective.cp_node_id=cp_node.cp_node_id AND" .
820                " slm_id = " . $ilDB->quote($this->getID(), "integer"));
821            while ($rec = $ilDB->fetchAssoc($set)) {
822                $tmpval = $rec["minnormalmeasure"] * 100;
823                if (!in_array($tmpval, $a_result)) {
824                    $a_result[] = $tmpval;
825                }
826            }
827        } else {
828            $set = $ilDB->query("SELECT masteryscore FROM sc_item,scorm_object" .
829                " WHERE sc_item.masteryscore is not null AND sc_item.obj_id=scorm_object.obj_id AND" .
830                " slm_id = " . $ilDB->quote($this->getID(), "integer"));
831            while ($rec = $ilDB->fetchAssoc($set)) {
832                if (!in_array($rec["masteryscore"], $a_result)) {
833                    $a_result[] = $rec["masteryscore"];
834                }
835            }
836        }
837        $s_result = implode(", ", $a_result);
838        $this->mastery_score_values = $s_result;
839    }
840
841    /**
842    * get mastery_score_values
843    */
844    public function getMasteryScoreValues()
845    {
846        return $this->mastery_score_values;
847    }
848
849    /**
850    * update values for mastery_score / min_normalized_measure in database - not requested
851    */
852    /*
853    function updateMasteryScoreValues()
854    {
855        global $DIC;
856        $ilDB = $DIC['ilDB'];
857        $s_mastery_score = $this->getMasteryScore();
858        if ($s_mastery_score != "" && is_numeric($s_mastery_score)) {
859            $i_mastery_score = round(intval($s_mastery_score,10));
860            $type = $this->_lookupSubType( $this->getID() );
861
862            if ($type == "scorm2004") {
863                if ($i_mastery_score > 100) $i_mastery_score = 100;
864                $i_mastery_score = $i_mastery_score/100;
865                $statement = $ilDB->manipulateF(
866                    'UPDATE cp_objective,cp_node SET minnormalmeasure = %s
867                    WHERE satisfiedbymeasure=1 AND minnormalmeasure is not null AND cp_objective.cp_node_id=cp_node.cp_node_id AND slm_id = %s',
868                    array('text','integer'),
869                    array($i_mastery_score,$this->getID())
870                );
871            } else {
872                if ($i_mastery_score > 127) $i_mastery_score = 127;
873                $statement = $ilDB->manipulateF(
874                    'UPDATE sc_item,scorm_object SET sc_item.masteryscore = %s
875                    WHERE sc_item.masteryscore is not null AND sc_item.obj_id=scorm_object.obj_id AND slm_id = %s',
876                    array('integer','integer'),
877                    array($i_mastery_score,$this->getID())
878                );
879            }
880        }
881    }
882    */
883
884    /**
885    * update meta data only
886    */
887    /*
888        function updateMetaData()
889        {
890            $this->meta_data->update();
891            if ($this->meta_data->section != "General")
892            {
893                $meta = $this->meta_data->getElement("Title", "General");
894                $this->meta_data->setTitle($meta[0]["value"]);
895                $meta = $this->meta_data->getElement("Description", "General");
896                $this->meta_data->setDescription($meta[0]["value"]);
897            }
898            else
899            {
900                $this->setTitle($this->meta_data->getTitle());
901                $this->setDescription($this->meta_data->getDescription());
902            }
903            parent::update();
904
905        }
906    */
907
908    /**
909    * get id_setting
910    */
911    public function getIdSetting()
912    {
913        return $this->id_setting;
914    }
915
916    /**
917    * set id_setting
918    */
919    public function setIdSetting($a_id_setting)
920    {
921        $this->id_setting = $a_id_setting;
922    }
923
924    /**
925    * get name_setting
926    */
927    public function getNameSetting()
928    {
929        return $this->name_setting;
930    }
931
932    /**
933    * set name_setting
934    */
935    public function setNameSetting($a_name_setting)
936    {
937        $this->name_setting = $a_name_setting;
938    }
939
940
941
942
943    /**
944    * update object data
945    *
946    * @access	public
947    * @return	boolean
948    */
949    public function update()
950    {
951        global $DIC;
952        $ilDB = $DIC['ilDB'];
953
954        $this->updateMetaData();
955        parent::update();
956
957        $s_mastery_score = $this->getMasteryScore();
958        if ($s_mastery_score == "") {
959            $s_mastery_score = null;
960        }
961
962        $statement = $ilDB->manipulateF(
963            '
964			UPDATE sahs_lm
965			SET api_adapter = %s,
966				api_func_prefix = %s,
967				auto_review = %s,
968				default_lesson_mode = %s,
969				c_type = %s,
970				stylesheet = %s,
971				editable = %s,
972				max_attempt = %s,
973				module_version = %s,
974				credit = %s,
975				glossary = %s,
976				question_tries = %s,
977				unlimited_session = %s,
978				no_menu = %s,
979				hide_navig = %s,
980				fourth_edition =%s,
981				sequencing = %s,
982				interactions = %s,
983				objectives = %s,
984				comments = %s,
985				time_from_lms = %s,
986				debug = %s,
987				localization = %s,
988				seq_exp_mode = %s,
989				debugpw = %s,
990				open_mode = %s,
991				width = %s,
992				height = %s,
993				auto_continue = %s,
994				auto_last_visited = %s,
995				check_values = %s,
996				offline_mode = %s,
997				auto_suspend = %s,
998				ie_force_render = %s,
999				mastery_score = %s,
1000				id_setting = %s,
1001				name_setting = %s
1002			WHERE id = %s',
1003            array(	'text',
1004                'text',
1005                'text',
1006                'text',
1007                'text',
1008                'integer',
1009                'integer',
1010                'integer',
1011                'integer',
1012                'text',
1013                'integer',
1014                'integer',
1015                'text',
1016                'text',
1017                'text',
1018                'text',
1019                'text',
1020                'text',
1021                'text',
1022                'text',
1023                'text',
1024                'text',
1025                'text',
1026                'integer',
1027                'text',
1028                'integer',
1029                'integer',
1030                'integer',
1031                'text',
1032                'text',
1033                'text',
1034                'text',
1035                'text',
1036                'text',
1037                'integer',
1038                'integer',
1039                'integer',
1040                'integer'
1041                ),
1042            array(	$this->getAPIAdapterName(),
1043                $this->getAPIFunctionsPrefix(),
1044                $this->getAutoReviewChar(),
1045                $this->getDefaultLessonMode(),
1046                $this->getSubType(),
1047                $this->getStyleSheetId(),
1048                $this->getEditable(),
1049                $this->getMaxAttempt(),
1050                $this->getModuleVersion(),
1051                $this->getCreditMode(),
1052                $this->getAssignedGlossary(),
1053                $this->getTries(),
1054                ilUtil::tf2yn($this->getSession()),
1055                ilUtil::tf2yn($this->getNoMenu()),
1056                ilUtil::tf2yn($this->getHideNavig()),
1057                ilUtil::tf2yn($this->getFourth_edition()),
1058                ilUtil::tf2yn($this->getSequencing()),
1059                ilUtil::tf2yn($this->getInteractions()),
1060                ilUtil::tf2yn($this->getObjectives()),
1061                ilUtil::tf2yn($this->getComments()),
1062                ilUtil::tf2yn($this->getTime_from_lms()),
1063                ilUtil::tf2yn($this->getDebug()),
1064                $this->getLocalization(),
1065                $this->getSequencingExpertMode(),
1066                $this->getDebugPw(),
1067                $this->getOpenMode(),
1068                $this->getWidth(),
1069                $this->getHeight(),
1070                ilUtil::tf2yn($this->getAutoContinue()),
1071                ilUtil::tf2yn($this->getAuto_last_visited()),
1072                ilUtil::tf2yn($this->getCheck_values()),
1073                ilUtil::tf2yn($this->getOfflineMode()),
1074                ilUtil::tf2yn($this->getAutoSuspend()),
1075                ilUtil::tf2yn($this->getIe_force_render()),
1076                $s_mastery_score,
1077                $this->getIdSetting(),
1078                $this->getNameSetting(),
1079                $this->getId())
1080        );
1081
1082        return true;
1083    }
1084
1085    /**
1086     * Get SCORM modules that assign a certain glossary
1087     *
1088     * @param
1089     * @return
1090     */
1091    public static function getScormModulesForGlossary($a_glo_id)
1092    {
1093        global $DIC;
1094        $ilDB = $DIC['ilDB'];
1095
1096        $set = $ilDB->query("SELECT DISTINCT id FROM sahs_lm WHERE " .
1097            " glossary = " . $ilDB->quote($a_glo_id, "integer"));
1098        $sms = array();
1099        while ($rec = $ilDB->fetchAssoc($set)) {
1100            if (ilObject::_hasUntrashedReference($rec["id"])) {
1101                $sms[] = $rec["id"];
1102            }
1103        }
1104        return $sms;
1105    }
1106
1107    /**
1108     * Get SCORM modules that assign a certain glossary
1109     *
1110     * @param
1111     * @return
1112     */
1113    public static function lookupAssignedGlossary($a_slm_id)
1114    {
1115        global $DIC;
1116        $ilDB = $DIC['ilDB'];
1117
1118        $set = $ilDB->query("SELECT DISTINCT glossary FROM sahs_lm WHERE " .
1119            " id = " . $ilDB->quote($a_slm_id, "integer"));
1120        $rec = $ilDB->fetchAssoc($set);
1121        $glo_id = $rec["glossary"];
1122        if (ilObject::_lookupType($glo_id) == "glo") {
1123            return $glo_id;
1124        }
1125        return 0;
1126    }
1127
1128
1129    /**
1130    * get sub type
1131    */
1132    public function setSubType($a_sub_type)
1133    {
1134        $this->sub_type = $a_sub_type;
1135    }
1136
1137    /**
1138    * set sub type
1139    */
1140    public function getSubType()
1141    {
1142        return $this->sub_type;
1143    }
1144
1145    /**
1146    * delete SCORM learning module and all related data
1147    *
1148    * this method has been tested on may 9th 2004
1149    * meta data, scorm lm data, scorm tree, scorm objects (organization(s),
1150    * manifest, resources and items), tracking data and data directory
1151    * have been deleted correctly as desired
1152    *
1153    * @access	public
1154    * @return	boolean	true if all object data were removed; false if only a references were removed
1155    */
1156    public function delete()
1157    {
1158        global $DIC;
1159        $ilDB = $DIC['ilDB'];
1160        $ilLog = $DIC['ilLog'];
1161
1162        // always call parent delete function first!!
1163        if (!parent::delete()) {
1164            return false;
1165        }
1166
1167        // delete meta data of scorm content object
1168        $this->deleteMetaData();
1169
1170        // delete data directory
1171        ilUtil::delDir($this->getDataDirectory());
1172
1173        // delete scorm learning module record
1174        $ilDB->manipulateF(
1175            'DELETE FROM sahs_lm WHERE id = %s',
1176            array('integer'),
1177            array($this->getId())
1178        );
1179
1180        $ilLog->write("SAHS Delete(SAHSLM), Subtype: " . $this->getSubType());
1181
1182        if ($this->getSubType() == "scorm") {
1183            // remove all scorm objects and scorm tree
1184            include_once("./Modules/ScormAicc/classes/SCORM/class.ilSCORMTree.php");
1185            include_once("./Modules/ScormAicc/classes/SCORM/class.ilSCORMObject.php");
1186            $sc_tree = new ilSCORMTree($this->getId());
1187            $r_id = $sc_tree->readRootId();
1188            if ($r_id > 0) {
1189                $items = $sc_tree->getSubTree($sc_tree->getNodeData($r_id));
1190                foreach ($items as $item) {
1191                    $sc_object = ilSCORMObject::_getInstance($item["obj_id"], $this->getId());
1192                    if (is_object($sc_object)) {
1193                        $sc_object->delete();
1194                    }
1195                }
1196                $sc_tree->removeTree($sc_tree->getTreeId());
1197            }
1198        }
1199
1200        if ($this->getSubType() != "scorm") {
1201            // delete aicc data
1202            $res = $ilDB->queryF(
1203                '
1204				SELECT aicc_object.obj_id FROM aicc_object, aicc_units
1205				WHERE aicc_object.obj_id = aicc_units.obj_id
1206				AND aicc_object.slm_id = %s',
1207                array('integer'),
1208                array($this->getId())
1209            );
1210
1211            while ($row = $ilDB->fetchAssoc($res)) {
1212                $obj_id = $row['obj_id'];
1213                $ilDB->manipulateF(
1214                    '
1215					DELETE FROM aicc_units WHERE obj_id = %s',
1216                    array('integer'),
1217                    array($obj_id)
1218                    );
1219            }
1220
1221            $res = $ilDB->queryF(
1222                '
1223				SELECT aicc_object.obj_id FROM aicc_object, aicc_course
1224				WHERE aicc_object.obj_id = aicc_course.obj_id
1225				AND aicc_object.slm_id = %s',
1226                array('integer'),
1227                array($this->getId())
1228            );
1229
1230            while ($row = $ilDB->fetchAssoc($res)) {
1231                $obj_id = $row['obj_id'];
1232                $ilDB->manipulateF(
1233                    '
1234					DELETE FROM aicc_course WHERE obj_id = %s',
1235                    array('integer'),
1236                    array($obj_id)
1237                    );
1238            }
1239
1240            $ilDB->manipulateF(
1241                '
1242				DELETE FROM aicc_object WHERE slm_id = %s',
1243                array('integer'),
1244                array($this->getId())
1245            );
1246        }
1247
1248        $q_log = "DELETE FROM scorm_tracking WHERE obj_id = " . $ilDB->quote($this->getId());
1249        $ilLog->write("SAHS Delete(SAHSLM): " . $q_log);
1250
1251        $ilDB->manipulateF(
1252            'DELETE FROM scorm_tracking WHERE obj_id = %s',
1253            array('integer'),
1254            array($this->getId())
1255        );
1256
1257        $q_log = "DELETE FROM sahs_user WHERE obj_id = " . $ilDB->quote($this->getId());
1258        $ilLog->write("SAHS Delete(SAHSLM): " . $q_log);
1259
1260        $ilDB->manipulateF(
1261            'DELETE FROM sahs_user WHERE obj_id = %s',
1262            array('integer'),
1263            array($this->getId())
1264        );
1265
1266        // always call parent delete function at the end!!
1267        return true;
1268    }
1269
1270    /**
1271    * Returns the points in percent for the learning module
1272    * This is called by the certificate generator if [SCORM_POINTS] is
1273    * inserted.
1274    */
1275    public function getPointsInPercent()
1276    {
1277        global $DIC;
1278        $ilUser = $DIC['ilUser'];
1279        if (strcmp($this->getSubType(), "scorm2004") == 0) {
1280            $res = ilObjSCORM2004LearningModule::_getUniqueScaledScoreForUser($this->getId(), $ilUser->getId());
1281            if (!is_null($res)) {
1282                return $res * 100.0;
1283            } else {
1284                return $res;
1285            }
1286        } else {
1287            return null;
1288        }
1289    }
1290
1291    /**
1292     *
1293     * Returns score.max for the learning module, refered to the last sco where score.max is set.
1294     * This is called by the certificate generator if [SCORM_POINTS_MAX] is
1295     * inserted.
1296     *
1297     * @access	public
1298     * @return	float
1299     *
1300     */
1301    public function getMaxPoints()
1302    {
1303        global $DIC;
1304        $ilUser = $DIC['ilUser'];
1305
1306        if (strcmp($this->getSubType(), 'scorm2004') == 0) {
1307            $res = ilObjSCORM2004LearningModule::_getMaxScoreForUser($this->getId(), $ilUser->getId());
1308            return $res;
1309        } else {
1310            return null;
1311        }
1312    }
1313
1314    /**
1315     * Populate by directory. Add a filename to do a special check for
1316     * ILIAS SCORM export files. If the corresponding directory is found
1317     * within the passed directory path (i.e. "htlm_<id>") this
1318     * subdirectory is used instead.
1319     *
1320     * @param
1321     * @return
1322     */
1323    public function populateByDirectoy($a_dir, $a_filename = "")
1324    {
1325        /*preg_match("/.*sahs_([0-9]*)\.zip/", $a_filename, $match);
1326        if (is_dir($a_dir."/sahs_".$match[1]))
1327        {
1328            $a_dir = $a_dir."/sahs_".$match[1];
1329        }*/
1330        ilUtil::rCopy($a_dir, $this->getDataDirectory());
1331        ilUtil::renameExecutables($this->getDataDirectory());
1332    }
1333
1334
1335    /**
1336     * Clone scorm object
1337     *
1338     * @param int target ref_id
1339     * @param int copy id
1340     */
1341    public function cloneObject($a_target_id, $a_copy_id = 0, $a_omit_tree = false)
1342    {
1343        global $DIC;
1344        $ilDB = $DIC['ilDB'];
1345        $ilUser = $DIC['ilUser'];
1346        $ilias = $DIC['ilias'];
1347        $lng = $DIC['lng'];
1348
1349        $new_obj = parent::cloneObject($a_target_id, $a_copy_id, $a_omit_tree);
1350        $this->cloneMetaData($new_obj);
1351
1352        $new_obj->setOfflineStatus($this->getOfflineStatus());
1353        //copy online status if object is not the root copy object
1354        $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
1355        if ($cp_options->isRootNode($this->getRefId())) {
1356            $new_obj->setOfflineStatus(true);
1357        }
1358
1359        // copy properties
1360        // $new_obj->setTitle($this->getTitle() . ' ' . $lng->txt('copy_of_suffix'));
1361        $new_obj->setDescription($this->getDescription());
1362        $new_obj->setSubType($this->getSubType());
1363        $new_obj->setAPIAdapterName($this->getAPIAdapterName());
1364        $new_obj->setAPIFunctionsPrefix($this->getAPIFunctionsPrefix());
1365        $new_obj->setAutoReviewChar($this->getAutoReviewChar());
1366        $new_obj->setDefaultLessonMode($this->getDefaultLessonMode());
1367        $new_obj->setEditable($this->getEditable());
1368        $new_obj->setMaxAttempt($this->getMaxAttempt());
1369        $new_obj->setModuleVersion($this->getModuleVersion());
1370        $new_obj->setModuleVersion(1);
1371        $new_obj->setCreditMode($this->getCreditMode());
1372        $new_obj->setAssignedGlossary($this->getAssignedGlossary());
1373        $new_obj->setTries($this->getTries());
1374        $new_obj->setSession($this->getSession());
1375        $new_obj->setNoMenu($this->getNoMenu());
1376        $new_obj->setHideNavig($this->getHideNavig());
1377        $new_obj->setFourth_edition($this->getFourth_edition());
1378        $new_obj->setSequencing($this->getSequencing());
1379        $new_obj->setInteractions($this->getInteractions());
1380        $new_obj->setObjectives($this->getObjectives());
1381        $new_obj->setComments($this->getComments());
1382        $new_obj->setTime_from_lms($this->getTime_from_lms());
1383        $new_obj->setDebug($this->getDebug());
1384        $new_obj->setLocalization($this->getLocalization());
1385        $new_obj->setSequencingExpertMode($this->getSequencingExpertMode());
1386        $new_obj->setDebugPw($this->getDebugPw());
1387        $new_obj->setOpenMode($this->getOpenMode());
1388        $new_obj->setWidth($this->getWidth());
1389        $new_obj->setHeight($this->getHeight());
1390        $new_obj->setAutoContinue($this->getAutoContinue());
1391        $new_obj->setAuto_last_visited($this->getAuto_last_visited());
1392        $new_obj->setCheck_values($this->getCheck_values());
1393        $new_obj->setOfflineMode($this->getOfflineMode());
1394        $new_obj->setAutoSuspend($this->getAutoSuspend());
1395        $new_obj->setIe_force_render($this->getIe_force_render());
1396        $new_obj->setStyleSheetId($this->getStyleSheetId());
1397        $new_obj->update();
1398
1399
1400        // set/copy stylesheet
1401        /*		include_once("./Services/Style/Content/classes/class.ilObjStyleSheet.php");
1402                $style_id = $this->getStyleSheetId();
1403                if ($style_id > 0 && !ilObjStyleSheet::_lookupStandard($style_id))
1404                {
1405                    $style_obj = $ilias->obj_factory->getInstanceByObjId($style_id);
1406                    $new_id = $style_obj->ilClone();
1407                    $new_obj->setStyleSheetId($new_id);
1408                    $new_obj->update();
1409                }*/
1410
1411        // up to this point $new_obj is of type ilobjsahslearning module
1412
1413        // create instance of correct subtype and call forward it to
1414        // cloneIntoNewObject method
1415        switch ($this->getSubType()) {
1416            case "scorm":
1417                include_once("./Modules/ScormAicc/classes/class.ilObjSCORMLearningModule.php");
1418                $source_obj = new ilObjSCORMLearningModule($this->getRefId());
1419                $new_obj = new ilObjSCORMLearningModule($new_obj->getRefId());
1420                break;
1421
1422            case "scorm2004":
1423                include_once("./Modules/Scorm2004/classes/class.ilObjSCORM2004LearningModule.php");
1424                $source_obj = new ilObjSCORM2004LearningModule($this->getRefId());
1425                $new_obj = new ilObjSCORM2004LearningModule($new_obj->getRefId());
1426                break;
1427        }
1428
1429        // copy data directory
1430        $new_obj->populateByDirectoy($source_obj->getDataDirectory());
1431
1432        // copy authored content ...
1433        if ($new_obj->getEditable()) {
1434            $source_obj->copyAuthoredContent($new_obj);
1435        } else {
1436            // ... or read manifest file
1437            $new_obj->readObject();
1438        }
1439
1440        // Copy learning progress settings (Mantis #0022964)
1441        include_once('Services/Tracking/classes/class.ilLPObjSettings.php');
1442        $obj_settings = new ilLPObjSettings($this->getId());
1443        $obj_settings->cloneSettings($new_obj->getId());
1444
1445        include_once('Services/Object/classes/class.ilObjectLP.php');
1446        /** @var ilScormLP $olp */
1447        $olp = ilObjectLP::getInstance($this->getId());
1448        $collection = $olp->getCollectionInstance();
1449        if ($collection) {
1450            $collection->cloneCollection($new_obj->getRefId(), $cp_options->getCopyId());
1451        }
1452        return $new_obj;
1453    }
1454
1455    public function zipLmForOfflineMode()
1456    {
1457        $lmDir = ilUtil::getWebspaceDir("filesystem") . "/lm_data/lm_" . $this->getId();
1458        $zipFile = ilUtil::getDataDir() . "/lm_data/lm_" . $this->getId();
1459        return ilUtil::zip($lmDir, $zipFile, true);
1460    }
1461
1462    /**
1463    * Get cmi.core.student_id / cmi.learner_id for API
1464    */
1465    public function getApiStudentId()
1466    {
1467        global $DIC;
1468        $ilias = $DIC['ilias'];
1469        $idSetting = $this->getIdSetting();
1470        $studentId = $ilias->account->getId();
1471        if ($idSetting % 2 == 1) {
1472            $studentId = $ilias->account->getLogin();
1473        }
1474        if ($idSetting > 3) {
1475            $studentId .= '_o_' . $this->getId();
1476        } elseif ($idSetting > 1) {
1477            $studentId .= '_r_' . $_GET["ref_id"];
1478        }
1479        return $studentId;
1480    }
1481
1482    /**
1483    * Get cmi.core.student_name / cmi.learner_name for API
1484    * note: 'lastname, firstname' is required for SCORM 1.2; 9 = no name to hide student_name for external content
1485    */
1486    public function getApiStudentName()
1487    {
1488        global $DIC;
1489        $ilias = $DIC['ilias'];
1490        $lng = $DIC['lng'];
1491        $studentName = " ";
1492        switch ($this->getNameSetting()) {
1493            case 0:
1494                $studentName = $ilias->account->getLastname() . ', ' . $ilias->account->getFirstname();
1495                break;
1496            case 1:
1497                $studentName = $ilias->account->getFirstname() . ' ' . $ilias->account->getLastname();
1498                break;
1499            case 2:
1500                $studentName = $ilias->account->getFullname();
1501                break;
1502            case 3:
1503                switch ($ilias->account->getGender()) {
1504                    case 'f':
1505                        $studentName = $lng->txt('salutation_f') . ' ';
1506                        break;
1507
1508                    case 'm':
1509                        $studentName = $lng->txt('salutation_m') . ' ';
1510                        break;
1511
1512                    case 'n':
1513                        $studentName = '';//$lng->txt('salutation_n');
1514                        break;
1515
1516                    default:
1517                        $studentName = $lng->txt('salutation') . ' ';
1518                }
1519                $studentName .= $ilias->account->getLastname();
1520                break;
1521            case 4:
1522                $studentName = $ilias->account->getFirstname();
1523                break;
1524        }
1525        return $studentName;
1526    }
1527
1528    /**
1529    * get button for view
1530    */
1531    public function getViewButton()
1532    {
1533        $setUrl = "ilias.php?baseClass=ilSAHSPresentationGUI&amp;ref_id=" . $this->getRefID();
1534        // $setUrl = $this->getLinkTargetByClass("ilsahspresentationgui", "")."&amp;ref_id=".$this->getRefID();
1535        $setTarget = "ilContObj" . $this->getId();
1536        $om = $this->getOpenMode();
1537        $width = $this->getWidth();
1538        $height = $this->getHeight();
1539        if (($om == 5 || $om == 1) && $width > 0 && $height > 0) {
1540            $om++;
1541        }
1542        if ($om != 0) {
1543            $setUrl = "javascript:void(0); onclick=startSAHS('" . $setUrl . "','ilContObj" . $this->getId() . "'," . $om . "," . $width . "," . $height . ");";
1544            $setTarget = "";
1545        }
1546        include_once "Services/UIComponent/Button/classes/class.ilLinkButton.php";
1547        $button = ilLinkButton::getInstance();
1548        $button->setCaption("view");
1549        $button->setPrimary(true);
1550        $button->setUrl($setUrl);
1551        $button->setTarget($setTarget);
1552        return $button;
1553    }
1554}
1555