1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssQuestionType.php';
5
6/**
7 * Handles a list of questions
8 *
9 * @author		Björn Heyser <bheyser@databay.de>
10 * @version		$Id$
11 *
12 * @package		Modules/TestQuestionPool
13 *
14 */
15class ilTestRandomQuestionSetStagingPoolQuestionList implements Iterator
16{
17    /**
18     * @var ilDBInterface
19     */
20    private $db = null;
21
22    /**
23     * @var ilPluginAdmin
24     */
25    private $pluginAdmin = null;
26
27    /**
28     * @var integer
29     */
30    private $testObjId = -1;
31
32    /**
33     * @var integer
34     */
35    private $testId = -1;
36
37    /**
38     * @var integer
39     */
40    private $poolId = -1;
41
42    /**
43     * @var array
44     */
45    private $taxFilters = array();
46
47    // fau: taxFilter/typeFilter - private variable
48    // TODO-RND2017: rename to typesFilter (multiple types allowed)
49    /**
50     * @var array
51     */
52    private $typeFilter = array();
53    // fau.
54
55    /**
56     * @var array
57     */
58    private $lifecycleFilter = array();
59
60    /**
61     * @var array
62     */
63    private $questions = array();
64
65    /**
66     * @param ilDB $db
67     * @param ilPluginAdmin $pluginAdmin
68     */
69    public function __construct(ilDBInterface $db, ilPluginAdmin $pluginAdmin)
70    {
71        $this->db = $db;
72        $this->pluginAdmin = $pluginAdmin;
73    }
74
75    public function setTestObjId($testObjId)
76    {
77        $this->testObjId = $testObjId;
78    }
79
80    public function getTestObjId()
81    {
82        return $this->testObjId;
83    }
84
85    public function setTestId($testId)
86    {
87        $this->testId = $testId;
88    }
89
90    public function getTestId()
91    {
92        return $this->testId;
93    }
94
95    public function setPoolId($poolId)
96    {
97        $this->poolId = $poolId;
98    }
99
100    public function getPoolId()
101    {
102        return $this->poolId;
103    }
104
105    public function addTaxonomyFilter($taxId, $taxNodes)
106    {
107        $this->taxFilters[$taxId] = $taxNodes;
108    }
109
110    public function getTaxonomyFilters()
111    {
112        return $this->taxFilters;
113    }
114
115    // fau: taxFilter/typeFilter - getter/setter
116    public function getTypeFilter()
117    {
118        return $this->typeFilter;
119    }
120
121    public function setTypeFilter($typeFilter)
122    {
123        $this->typeFilter = $typeFilter;
124    }
125    // fau.
126
127    /**
128     * @return array
129     */
130    public function getLifecycleFilter() : array
131    {
132        return $this->lifecycleFilter;
133    }
134
135    /**
136     * @param array $lifecycleFilter
137     */
138    public function setLifecycleFilter(array $lifecycleFilter)
139    {
140        $this->lifecycleFilter = $lifecycleFilter;
141    }
142
143    public function loadQuestions()
144    {
145        $query = "
146			SELECT		qpl_questions.question_id,
147						qpl_qst_type.type_tag,
148						qpl_qst_type.plugin,
149						qpl_qst_type.plugin_name
150
151			FROM		tst_rnd_cpy
152
153			INNER JOIN	qpl_questions
154			ON			qpl_questions.question_id = tst_rnd_cpy.qst_fi
155
156			INNER JOIN	qpl_qst_type
157			ON			qpl_qst_type.question_type_id = qpl_questions.question_type_fi
158
159			WHERE		tst_rnd_cpy.tst_fi = %s
160			AND			tst_rnd_cpy.qpl_fi = %s
161
162			{$this->getConditionalExpression()}
163		";
164
165        $res = $this->db->queryF(
166            $query,
167            array('integer', 'integer'),
168            array($this->getTestId(), $this->getPoolId())
169        );
170
171        //echo sprintf($query, $this->getTestId(), $this->getPoolId());exit;
172
173        while ($row = $this->db->fetchAssoc($res)) {
174            $row = ilAssQuestionType::completeMissingPluginName($row);
175
176            if (!$this->isActiveQuestionType($row)) {
177                continue;
178            }
179
180            $this->questions[] = $row['question_id'];
181        }
182    }
183
184    private function getConditionalExpression()
185    {
186        $CONDITIONS = $this->getTaxonomyFilterExpressions();
187
188        // fau: taxFilter/typeFilter - add the type filter expression to conditions
189        $CONDITIONS = array_merge($CONDITIONS, $this->getTypeFilterExpressions());
190        // fau.
191
192        $CONDITIONS = array_merge($CONDITIONS, $this->getLifecycleFilterExpressions());
193
194        $CONDITIONS = implode(' AND ', $CONDITIONS);
195
196        return strlen($CONDITIONS) ? 'AND ' . $CONDITIONS : '';
197    }
198
199    private function getTaxonomyFilterExpressions()
200    {
201        $expressions = array();
202
203        require_once 'Services/Taxonomy/classes/class.ilTaxonomyTree.php';
204        require_once 'Services/Taxonomy/classes/class.ilTaxNodeAssignment.php';
205
206        foreach ($this->getTaxonomyFilters() as $taxId => $taxNodes) {
207            $questionIds = array();
208
209            $forceBypass = true;
210
211            foreach ($taxNodes as $taxNode) {
212                $forceBypass = false;
213
214                $taxTree = new ilTaxonomyTree($taxId);
215
216                $taxNodeAssignment = new ilTaxNodeAssignment('tst', $this->getTestObjId(), 'quest', $taxId);
217
218                $subNodes = $taxTree->getSubTreeIds($taxNode);
219                $subNodes[] = $taxNode;
220
221                $taxItems = $taxNodeAssignment->getAssignmentsOfNode($subNodes);
222
223                foreach ($taxItems as $taxItem) {
224                    $questionIds[$taxItem['item_id']] = $taxItem['item_id'];
225                }
226            }
227
228            if (!$forceBypass) {
229                $expressions[] = $this->db->in('question_id', $questionIds, false, 'integer');
230            }
231        }
232
233        return $expressions;
234    }
235
236    private function getLifecycleFilterExpressions()
237    {
238        if (count($this->lifecycleFilter)) {
239            return array(
240                $this->db->in('lifecycle', $this->lifecycleFilter, false, 'text')
241            );
242        }
243
244        return array();
245    }
246
247    // fau: taxFilter/typeFilter - get the expressions for a type filter
248    private function getTypeFilterExpressions()
249    {
250        if (count($this->typeFilter)) {
251            return array(
252                $this->db->in('question_type_fi', $this->typeFilter, false, 'integer')
253            );
254        }
255
256        return array();
257    }
258    // fau;
259
260    private function isActiveQuestionType($questionData)
261    {
262        if (!isset($questionData['plugin'])) {
263            return false;
264        }
265
266        if (!$questionData['plugin']) {
267            return true;
268        }
269
270        return $this->pluginAdmin->isActive(IL_COMP_MODULE, 'TestQuestionPool', 'qst', $questionData['plugin_name']);
271    }
272
273    public function resetQuestionList()
274    {
275        $this->questions = array();
276        $this->taxFilters = array();
277
278        $this->testObjId = -1;
279        $this->testId = -1;
280        $this->poolId = -1;
281    }
282
283    public function getQuestions()
284    {
285        return array_values($this->questions);
286    }
287
288    // =================================================================================================================
289
290    /**
291     * @return ilTestRandomQuestionSetSourcePoolDefinition
292     */
293    public function rewind()
294    {
295        return reset($this->questions);
296    }
297
298    /**
299     * @return ilTestRandomQuestionSetSourcePoolDefinition
300     */
301    public function current()
302    {
303        return current($this->questions);
304    }
305
306    /**
307     * @return integer
308     */
309    public function key()
310    {
311        return key($this->questions);
312    }
313
314    /**
315     * @return ilTestRandomQuestionSetSourcePoolDefinition
316     */
317    public function next()
318    {
319        return next($this->questions);
320    }
321
322    /**
323     * @return boolean
324     */
325    public function valid()
326    {
327        return key($this->questions) !== null;
328    }
329
330    public static function updateSourceQuestionPoolId($testId, $oldPoolId, $newPoolId)
331    {
332        $db = $GLOBALS['DIC']['ilDB'];
333
334        $query = "UPDATE tst_rnd_cpy SET qpl_fi = %s WHERE tst_fi = %s AND qpl_fi = %s";
335
336        $db->manipulateF(
337            $query,
338            array('integer', 'integer', 'integer'),
339            array($newPoolId, $testId, $oldPoolId)
340        );
341    }
342}
343