1<?php
2/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4/**
5 * Settings for LO courses
6 *
7 * @author Stefan Meyer <smeyer.ilias@gmx.de>
8 * @version $Id$
9 */
10class ilLOSettings
11{
12    // new settings 5.1
13    const QST_PASSED_FLAG = 1;
14    const QST_PASSED_HIDE = 2;
15
16    const TYPE_INITIAL_PLACEMENT_ALL = 1;
17    const TYPE_INITIAL_PLACEMENT_SELECTED = 2;
18    const TYPE_INITIAL_QUALIFYING_ALL = 3;
19    const TYPE_INITIAL_QUALIFYING_SELECTED = 4;
20    const TYPE_INITIAL_NONE = 5;
21
22    const TYPE_QUALIFYING_ALL = 1;
23    const TYPE_QUALIFYING_SELECTED = 2;
24
25    // end new settings
26
27    const TYPE_TEST_UNDEFINED = 0;
28    const TYPE_TEST_INITIAL = 1;
29    const TYPE_TEST_QUALIFIED = 2;
30
31    const QT_VISIBLE_ALL = 0;
32    const QT_VISIBLE_OBJECTIVE = 1;
33
34
35    const LOC_INITIAL_ALL = 1;
36    const LOC_INITIAL_SEL = 2;
37    const LOC_QUALIFIED = 3;
38    const LOC_PRACTISE = 4;
39
40    const HIDE_PASSED_OBJECTIVE_QST = 1;
41    const MARK_PASSED_OBJECTIVE_QST = 2;
42
43
44    private static $instances = array();
45
46    /**
47     * @var ilLogger
48     */
49    private $logger = null;
50
51
52    // settings 5.1
53    private $it_type = self::TYPE_INITIAL_PLACEMENT_ALL;
54    private $qt_type = self::TYPE_QUALIFYING_ALL;
55
56    private $it_start = false;
57    private $qt_start = false;
58
59    // end settings 5.1
60
61    private $container_id = 0;
62    private $type = 0;
63    private $initial_test = 0;
64    private $qualified_test = 0;
65    private $reset_results = true;
66    private $passed_obj_mode = self::HIDE_PASSED_OBJECTIVE_QST;
67
68
69    private $entry_exists = false;
70
71
72    /**
73     * Constructor
74     * @param int $a_cont_id
75     */
76    protected function __construct($a_cont_id)
77    {
78        $this->logger = $GLOBALS['DIC']->logger()->crs();
79
80        $this->container_id = $a_cont_id;
81        $this->read();
82    }
83
84    /**
85     * get singleton instance
86     * @param int $a_obj_id
87     * @return ilLOSettings
88     */
89    public static function getInstanceByObjId($a_obj_id)
90    {
91        if (self::$instances[$a_obj_id]) {
92            return self::$instances[$a_obj_id];
93        }
94        return self::$instances[$a_obj_id] = new ilLOSettings($a_obj_id);
95    }
96
97    /**
98     * Set Initial test type
99     * @param type $a_type
100     */
101    public function setInitialTestType($a_type)
102    {
103        $this->it_type = $a_type;
104    }
105
106    /**
107     * Get initial test type
108     * @return type
109     */
110    public function getInitialTestType()
111    {
112        return $this->it_type;
113    }
114
115    /**
116     * Get qualifying test type
117     */
118    public function getQualifyingTestType()
119    {
120        return $this->qt_type;
121    }
122
123    /**
124     * Set qualifying test type
125     * @param type $a_type
126     */
127    public function setQualifyingTestType($a_type)
128    {
129        $this->qt_type = $a_type;
130    }
131
132    /**
133     *
134     * @param type $a_type
135     */
136    public function setInitialTestAsStart($a_type)
137    {
138        $this->it_start = $a_type;
139    }
140
141    /**
142     * Get initial test start
143     * @return type
144     */
145    public function isInitialTestStart()
146    {
147        return $this->it_start;
148    }
149
150    /**
151     * Set qt as start object
152     * @param type $a_type
153     */
154    public function setQualifyingTestAsStart($a_type)
155    {
156        $this->qt_start = $a_type;
157    }
158
159    /**
160     * Is qt start object
161     * @return type
162     */
163    public function isQualifyingTestStart()
164    {
165        return $this->qt_start;
166    }
167
168    /**
169     * Check if separate initial test are configured
170     */
171    public function hasSeparateInitialTests()
172    {
173        return $this->getInitialTestType() == self::TYPE_INITIAL_PLACEMENT_SELECTED || $this->getInitialTestType() == self::TYPE_INITIAL_QUALIFYING_SELECTED;
174    }
175
176    /**
177     * Check if separate qualified tests are configured
178     */
179    public function hasSeparateQualifiedTests()
180    {
181        return $this->getQualifyingTestType() == self::TYPE_QUALIFYING_SELECTED;
182    }
183
184    /**
185     *  Check if initial test is qualifying*
186     */
187    public function isInitialTestQualifying()
188    {
189        return $this->getInitialTestType() == self::TYPE_INITIAL_QUALIFYING_ALL || $this->getInitialTestType() == self::TYPE_INITIAL_QUALIFYING_SELECTED;
190    }
191
192    /**
193     * Check if test ref_id is used in an objective course
194     * @param int ref_id
195     */
196    public static function isObjectiveTest($a_trst_ref_id)
197    {
198        global $DIC;
199
200        $ilDB = $DIC['ilDB'];
201
202
203        // Check for direct assignment
204        $query = 'SELECT obj_id FROM loc_settings ' .
205                'WHERE itest = ' . $ilDB->quote($a_trst_ref_id, 'integer') . ' ' .
206                'OR qtest = ' . $ilDB->quote($a_trst_ref_id, 'integer');
207        $res = $ilDB->query($query);
208        while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
209            return $row->obj_id;
210        }
211
212        include_once './Modules/Course/classes/Objectives/class.ilLOTestAssignments.php';
213        return ilLOTestAssignments::lookupContainerForTest($a_trst_ref_id);
214    }
215
216    /**
217     * Clone settings
218     * @param type $a_copy_id
219     * @param type $a_container_id
220     * @param type $a_new_container_id
221     */
222    public static function cloneSettings($a_copy_id, $a_container_id, $a_new_container_id)
223    {
224        include_once './Services/CopyWizard/classes/class.ilCopyWizardOptions.php';
225        $options = ilCopyWizardOptions::_getInstance($a_copy_id);
226        $mappings = $options->getMappings();
227
228        $settings = self::getInstanceByObjId($a_container_id);
229        $new_settings = self::getInstanceByObjId($a_new_container_id);
230
231        $new_settings->setType($settings->getType());
232        $new_settings->setInitialTestType($settings->getInitialTestType());
233        $new_settings->setQualifyingTestType($settings->getQualifyingTestType());
234        $new_settings->resetResults($settings->isResetResultsEnabled());
235        $new_settings->setPassedObjectiveMode($settings->getPassedObjectiveMode());
236
237        if ($settings->getInitialTest() and array_key_exists($settings->getInitialTest(), $mappings)) {
238            $new_settings->setInitialTest($mappings[$settings->getInitialTest()]);
239            $new_settings->setInitialTestAsStart($new_settings->isInitialTestStart());
240        }
241
242        if ($settings->getQualifiedTest() and array_key_exists($settings->getQualifiedTest(), $mappings)) {
243            $new_settings->setQualifiedTest($mappings[$settings->getQualifiedTest()]);
244            $new_settings->setQualifyingTestAsStart($settings->isQualifyingTestStart());
245        }
246
247        // update calls create in case of no entry exists.
248        $new_settings->update();
249    }
250
251    /**
252     * Check if start objects are enabled
253     */
254    public function worksWithStartObjects()
255    {
256        return $this->isInitialTestStart() or $this->isQualifyingTestStart();
257    }
258
259
260    /**
261     * Check if the loc is configured for initial tests
262     */
263    public function worksWithInitialTest()
264    {
265        return $this->getInitialTestType() != self::TYPE_INITIAL_NONE;
266    }
267
268    /**
269     * Check if qualified test for all objectives is visible
270     * @return type
271     */
272    public function isGeneralQualifiedTestVisible()
273    {
274        return $this->getQualifyingTestType() == self::TYPE_QUALIFYING_ALL;
275    }
276
277    /**
278     * @return type
279     */
280    public function setGeneralQualifiedTestVisibility($a_stat)
281    {
282        $this->qt_visible_all = $a_stat;
283        return true;
284    }
285
286    public function isQualifiedTestPerObjectiveVisible()
287    {
288        return $this->getQualifyingTestType() == self::TYPE_QUALIFYING_SELECTED;
289    }
290
291    public function setQualifiedTestPerObjectiveVisibility($a_stat)
292    {
293        $this->qt_visible_lo = $a_stat;
294    }
295
296    public function getPassedObjectiveMode()
297    {
298        return $this->passed_objective_mode;
299    }
300
301    public function setPassedObjectiveMode($a_mode)
302    {
303        $this->passed_objective_mode = $a_mode;
304    }
305
306    /**
307     * Check if initial test for all objectives is visible
308     * @return bool
309     */
310    public function isGeneralInitialTestVisible()
311    {
312        return $this->getInitialTestType() == self::TYPE_INITIAL_PLACEMENT_ALL || $this->getInitialTestType() == self::TYPE_INITIAL_QUALIFYING_ALL;
313    }
314
315    /**
316     *
317     * @return type
318     */
319    public function settingsExist()
320    {
321        return $this->entry_exists;
322    }
323
324    public function getObjId()
325    {
326        return $this->container_id;
327    }
328
329    public function setType($a_type)
330    {
331        $this->type = $a_type;
332    }
333
334    public function getType()
335    {
336        return $this->type;
337    }
338
339    /**
340     *
341     * @param type $a_type
342     * @return type
343     * @todo refactor
344     */
345    public function getTestByType($a_type)
346    {
347        switch ($a_type) {
348            case self::TYPE_TEST_INITIAL:
349                return $this->getInitialTest();
350
351            case self::TYPE_TEST_QUALIFIED:
352                return $this->getQualifiedTest();
353        }
354    }
355
356    /**
357     * Get assigned tests
358     * @return type
359     * @todo refactor
360     */
361    public function getTests()
362    {
363        $tests = array();
364        if ($this->getInitialTest()) {
365            $tests[] = $this->getInitialTest();
366        }
367        if ($this->getQualifiedTest()) {
368            $tests[] = $this->getQualifiedTest();
369        }
370        return $tests;
371    }
372
373    /**
374     * Check if test is of type random test
375     * @param type $a_type
376     * @return type
377     * @todo refactor
378     */
379    public function isRandomTestType($a_type)
380    {
381        $tst = $this->getTestByType($a_type);
382        include_once './Modules/Test/classes/class.ilObjTest.php';
383        return ilObjTest::_lookupRandomTest(ilObject::_lookupObjId($tst));
384    }
385
386    /**
387     * set initial test id
388     * @param type $a_id
389     * @todo refactor
390     */
391    public function setInitialTest($a_id)
392    {
393        $this->initial_test = $a_id;
394    }
395
396    /**
397     * get initial test
398     * @return type
399     * @todo refactor
400     */
401    public function getInitialTest()
402    {
403        return $this->initial_test;
404    }
405
406    /**
407     * set qualified test
408     * @param type $a_id
409     * @todo refactor
410     */
411    public function setQualifiedTest($a_id)
412    {
413        $this->qualified_test = $a_id;
414    }
415
416    /**
417     * get qualified test
418     * @return type
419     * @todo refactor
420     */
421    public function getQualifiedTest()
422    {
423        return $this->qualified_test;
424    }
425
426    /**
427     * reset results
428     * @param type $a_status
429     */
430    public function resetResults($a_status)
431    {
432        $this->reset_results = $a_status;
433    }
434
435    /**
436     * check if reset result is enabled
437     * @return type
438     */
439    public function isResetResultsEnabled()
440    {
441        return (bool) $this->reset_results;
442    }
443
444    /**
445     * Create new entry
446     */
447    public function create()
448    {
449        global $DIC;
450
451        $ilDB = $DIC['ilDB'];
452
453        $query = 'INSERT INTO loc_settings ' .
454                '(obj_id, it_type,itest,qtest,it_start,qt_type,qt_start,reset_results,passed_obj_mode) VALUES ( ' .
455                $ilDB->quote($this->getObjId(), 'integer') . ', ' .
456                $ilDB->quote($this->getInitialTestType(), 'integer') . ', ' .
457                $ilDB->quote($this->getInitialTest(), 'integer') . ', ' .
458                $ilDB->quote($this->getQualifiedTest(), 'integer') . ', ' .
459                $ilDB->quote($this->isInitialTestStart(), 'integer') . ', ' .
460                $ilDB->quote($this->getQualifyingTestType(), 'integer') . ', ' .
461                $ilDB->quote($this->isQualifyingTestStart(), 'integer') . ', ' .
462                $ilDB->quote($this->isResetResultsEnabled(), 'integer') . ', ' .
463                $ilDB->quote($this->getPassedObjectiveMode(), 'integer') . ' ' .
464                ') ';
465        $ilDB->manipulate($query);
466
467        $this->entry_exists = true;
468    }
469
470
471    /**
472     * update settings
473     * @global type $ilDB
474     */
475    public function update()
476    {
477        global $DIC;
478
479        $ilDB = $DIC['ilDB'];
480
481        if (!$this->entry_exists) {
482            return $this->create();
483        }
484
485        $query = 'UPDATE loc_settings ' . ' ' .
486                'SET it_type = ' . $ilDB->quote($this->getInitialTestType(), 'integer') . ', ' .
487                'itest = ' . $ilDB->quote($this->getInitialTest(), 'integer') . ', ' .
488                'qtest = ' . $ilDB->quote($this->getQualifiedTest(), 'integer') . ', ' .
489                'it_start = ' . $ilDB->quote($this->isInitialTestStart(), 'integer') . ', ' .
490                'qt_type = ' . $ilDB->quote($this->getQualifyingTestType(), 'integer') . ', ' .
491                'qt_start = ' . $ilDB->quote($this->isQualifyingTestStart(), 'integer') . ', ' .
492                'reset_results = ' . $ilDB->quote($this->isResetResultsEnabled(), 'integer') . ', ' .
493                'passed_obj_mode = ' . $ilDB->quote($this->getPassedObjectiveMode(), 'integer') . ' ' .
494                'WHERE obj_id = ' . $ilDB->quote($this->getObjId(), 'integer');
495
496        $ilDB->manipulate($query);
497    }
498
499    /**
500     * Update start objects
501     * Depends on course objective settings
502     *
503     * @param ilContainerStartObjects
504     */
505    public function updateStartObjects(ilContainerStartObjects $start)
506    {
507        if ($this->getInitialTestType() != self::TYPE_INITIAL_NONE) {
508            if ($start->exists($this->getQualifiedTest())) {
509                $start->deleteItem($this->getQualifiedTest());
510            }
511        }
512
513        switch ($this->getInitialTestType()) {
514            case self::TYPE_INITIAL_PLACEMENT_ALL:
515            case self::TYPE_INITIAL_QUALIFYING_ALL:
516
517                if ($this->isInitialTestStart()) {
518                    if (!$start->exists($this->getInitialTest())) {
519                        $start->add($this->getInitialTest());
520                    }
521                } else {
522                    if ($start->exists($this->getInitialTest())) {
523                        $start->deleteItem($this->getInitialTest());
524                    }
525                }
526                break;
527
528            case self::TYPE_INITIAL_NONE:
529
530                if ($start->exists($this->getInitialTest())) {
531                    $start->deleteItem($this->getInitialTest());
532                }
533                break;
534
535            default:
536
537                $this->logger->debug('Type initial default');
538                if ($start->exists($this->getInitialTest())) {
539                    $this->logger->debug('Old start object exists. Trying to delete');
540                    $start->deleteItem($this->getInitialTest());
541                }
542                break;
543        }
544
545        switch ($this->getQualifyingTestType()) {
546            case self::TYPE_QUALIFYING_ALL:
547
548                if ($this->isQualifyingTestStart()) {
549                    if (!$start->exists($this->getQualifiedTest())) {
550                        $start->add($this->getQualifiedTest());
551                    }
552                }
553                break;
554
555            default:
556                if ($start->exists($this->getQualifiedTest())) {
557                    $start->deleteItem($this->getQualifiedTest());
558                }
559                break;
560        }
561        return true;
562    }
563
564
565    /**
566     * Read
567     */
568    protected function read()
569    {
570        global $DIC;
571
572        $ilDB = $DIC['ilDB'];
573
574        $query = 'SELECT * FROM loc_settings ' .
575                'WHERE obj_id = ' . $ilDB->quote($this->getObjId(), 'integer');
576        $res = $ilDB->query($query);
577        while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
578            $this->entry_exists = true;
579
580            $this->setInitialTestType($row->it_type);
581            $this->setInitialTestAsStart((bool) $row->it_start);
582            $this->setQualifyingTestType($row->qt_type);
583            $this->setQualifyingTestAsStart($row->qt_start);
584
585            #$this->setType($row->type);
586            $this->setInitialTest($row->itest);
587            $this->setQualifiedTest($row->qtest);
588            #$this->setGeneralQualifiedTestVisibility($row->qt_vis_all);
589            #$this->setQualifiedTestPerObjectiveVisibility($row->qt_vis_obj);
590            $this->resetResults($row->reset_results);
591            $this->setPassedObjectiveMode($row->passed_obj_mode);
592        }
593
594        if ($GLOBALS['DIC']['tree']->isDeleted($this->getInitialTest())) {
595            $this->setInitialTest(0);
596        }
597        if ($GLOBALS['DIC']['tree']->isDeleted($this->getQualifiedTest())) {
598            $this->setQualifiedTest(0);
599        }
600    }
601
602    /**
603     * export to xml
604     * @param ilXmlWriter $writer
605     */
606    public function toXml(ilXmlWriter $writer)
607    {
608        $writer->xmlElement(
609            'Settings',
610            array(
611                'initialTestType' => (int) $this->getInitialTestType(),
612                'initialTestStart' => (int) $this->isInitialTestStart(),
613                'qualifyingTestType' => (int) $this->getQualifyingTestType(),
614                'qualifyingTestStart' => (int) $this->isQualifyingTestStart(),
615                'resetResults' => (int) $this->isResetResultsEnabled(),
616                'passedObjectivesMode' => (int) $this->getPassedObjectiveMode(),
617                'iTest' => (int) $this->getInitialTest(),
618                'qTest' => (int) $this->getQualifiedTest()
619            )
620        );
621    }
622}
623