1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetQuestionCollection.php';
5require_once 'Modules/Test/interfaces/interface.ilTestRandomSourcePoolDefinitionQuestionCollectionProvider.php';
6/**
7 * @author		Björn Heyser <bheyser@databay.de>
8 * @version		$Id$
9 *
10 * @package		Modules/Test
11 */
12abstract class ilTestRandomQuestionSetBuilder implements ilTestRandomSourcePoolDefinitionQuestionCollectionProvider
13{
14    /**
15     * @var ilDBInterface
16     */
17    protected $db = null;
18
19    /**
20     * @var ilObjTest
21     */
22    protected $testOBJ = null;
23
24    /**
25     * @var ilTestRandomQuestionSetConfig
26     */
27    protected $questionSetConfig = null;
28
29    /**
30     * @var ilTestRandomQuestionSetSourcePoolDefinitionList
31     */
32    protected $sourcePoolDefinitionList = null;
33
34    /**
35     * @var ilTestRandomQuestionSetStagingPoolQuestionList
36     */
37    protected $stagingPoolQuestionList = null;
38
39    //fau: fixRandomTestBuildable - variable for messages
40    protected $checkMessages = array();
41    // fau.
42
43    /**
44     * @param ilDBInterface $db
45     * @param ilObjTest $testOBJ
46     * @param ilTestRandomQuestionSetConfig $questionSetConfig
47     * @param ilTestRandomQuestionSetSourcePoolDefinitionList $sourcePoolDefinitionList
48     * @param ilTestRandomQuestionSetStagingPoolQuestionList $stagingPoolQuestionList
49     */
50    protected function __construct(
51        ilDBInterface $db,
52        ilObjTest $testOBJ,
53        ilTestRandomQuestionSetConfig $questionSetConfig,
54        ilTestRandomQuestionSetSourcePoolDefinitionList $sourcePoolDefinitionList,
55        ilTestRandomQuestionSetStagingPoolQuestionList $stagingPoolQuestionList
56    ) {
57        $this->db = $db;
58        $this->testOBJ = $testOBJ;
59        $this->questionSetConfig = $questionSetConfig;
60        $this->sourcePoolDefinitionList = $sourcePoolDefinitionList;
61        $this->stagingPoolQuestionList = $stagingPoolQuestionList;
62    }
63
64    abstract public function checkBuildable();
65
66    abstract public function performBuild(ilTestSession $testSession);
67
68
69    // hey: fixRandomTestBuildable - rename/public-access to be aware for building interface
70    public function getSrcPoolDefListRelatedQuestCombinationCollection(ilTestRandomQuestionSetSourcePoolDefinitionList $sourcePoolDefinitionList)
71    // hey.
72    {
73        $questionStage = new ilTestRandomQuestionSetQuestionCollection();
74
75        foreach ($sourcePoolDefinitionList as $definition) {
76            /** @var ilTestRandomQuestionSetSourcePoolDefinition $definition */
77
78            // hey: fixRandomTestBuildable - rename/public-access to be aware for building interface
79            $questions = $this->getSrcPoolDefRelatedQuestCollection($definition);
80            // hey.
81            $questionStage->mergeQuestionCollection($questions);
82        }
83
84        return $questionStage;
85    }
86
87    // hey: fixRandomTestBuildable - rename/public-access to be aware for building interface
88    /**
89     * @param ilTestRandomQuestionSetSourcePoolDefinition $definition
90     * @return ilTestRandomQuestionSetQuestionCollection
91     */
92    public function getSrcPoolDefRelatedQuestCollection(ilTestRandomQuestionSetSourcePoolDefinition $definition)
93    // hey.
94    {
95        $questionIds = $this->getQuestionIdsForSourcePoolDefinitionIds($definition);
96        $questionStage = $this->buildSetQuestionCollection($definition, $questionIds);
97
98        return $questionStage;
99    }
100
101    // hey: fixRandomTestBuildable - rename/public-access to be aware for building interface
102    /**
103     * @param ilTestRandomQuestionSetSourcePoolDefinitionList $sourcePoolDefinitionList
104     * @return ilTestRandomQuestionSetQuestionCollection
105     */
106    public function getSrcPoolDefListRelatedQuestUniqueCollection(ilTestRandomQuestionSetSourcePoolDefinitionList $sourcePoolDefinitionList)
107    {
108        $combinationCollection = $this->getSrcPoolDefListRelatedQuestCombinationCollection($sourcePoolDefinitionList);
109        return $combinationCollection->getUniqueQuestionCollection();
110    }
111    // hey.
112
113    private function getQuestionIdsForSourcePoolDefinitionIds(ilTestRandomQuestionSetSourcePoolDefinition $definition)
114    {
115        $this->stagingPoolQuestionList->resetQuestionList();
116
117        $this->stagingPoolQuestionList->setTestObjId($this->testOBJ->getId());
118        $this->stagingPoolQuestionList->setTestId($this->testOBJ->getTestId());
119        $this->stagingPoolQuestionList->setPoolId($definition->getPoolId());
120
121        if ($this->hasTaxonomyFilter($definition)) {
122            // fau: taxFilter/typeFilter - use new taxonomy filter
123            foreach ($definition->getMappedTaxonomyFilter() as $taxId => $nodeIds) {
124                $this->stagingPoolQuestionList->addTaxonomyFilter($taxId, $nodeIds);
125            }
126            #$this->stagingPoolQuestionList->addTaxonomyFilter(
127            #	$definition->getMappedFilterTaxId(), array($definition->getMappedFilterTaxNodeId())
128            #);
129            // fau.
130        }
131
132        if (count($definition->getLifecycleFilter())) {
133            $this->stagingPoolQuestionList->setLifecycleFilter($definition->getLifecycleFilter());
134        }
135
136        // fau: taxFilter/typeFilter - use type filter
137        if ($this->hasTypeFilter($definition)) {
138            $this->stagingPoolQuestionList->setTypeFilter($definition->getTypeFilter());
139        }
140        // fau.
141
142        $this->stagingPoolQuestionList->loadQuestions();
143
144        return $this->stagingPoolQuestionList->getQuestions();
145    }
146
147    private function buildSetQuestionCollection(ilTestRandomQuestionSetSourcePoolDefinition $definition, $questionIds)
148    {
149        $setQuestionCollection = new ilTestRandomQuestionSetQuestionCollection();
150
151        foreach ($questionIds as $questionId) {
152            $setQuestion = new ilTestRandomQuestionSetQuestion();
153
154            $setQuestion->setQuestionId($questionId);
155            $setQuestion->setSourcePoolDefinitionId($definition->getId());
156
157            $setQuestionCollection->addQuestion($setQuestion);
158        }
159
160        return $setQuestionCollection;
161    }
162
163    private function hasTaxonomyFilter(ilTestRandomQuestionSetSourcePoolDefinition $definition)
164    {
165        // fau: taxFilter - check for existing taxonomy filter
166        if (!count($definition->getMappedTaxonomyFilter())) {
167            return false;
168        }
169        #if( !(int)$definition->getMappedFilterTaxId() )
170        #{
171        #	return false;
172        #}
173        #
174        #if( !(int)$definition->getMappedFilterTaxNodeId() )
175        #{
176        #	return false;
177        #}
178        // fau.
179        return true;
180    }
181
182    //	fau: typeFilter - check for existing type filter
183    private function hasTypeFilter(ilTestRandomQuestionSetSourcePoolDefinition $definition)
184    {
185        if (count($definition->getTypeFilter())) {
186            return true;
187        }
188
189        return false;
190    }
191    //	fau.
192
193    protected function storeQuestionSet(ilTestSession $testSession, $questionSet)
194    {
195        $position = 0;
196
197        foreach ($questionSet->getQuestions() as $setQuestion) {
198            /* @var ilTestRandomQuestionSetQuestion $setQuestion */
199
200            $setQuestion->setSequencePosition($position++);
201
202            $this->storeQuestion($testSession, $setQuestion);
203        }
204    }
205
206    private function storeQuestion(ilTestSession $testSession, ilTestRandomQuestionSetQuestion $setQuestion)
207    {
208        $nextId = $this->db->nextId('tst_test_rnd_qst');
209
210        $this->db->insert('tst_test_rnd_qst', array(
211            'test_random_question_id' => array('integer', $nextId),
212            'active_fi' => array('integer', $testSession->getActiveId()),
213            'question_fi' => array('integer', $setQuestion->getQuestionId()),
214            'sequence' => array('integer', $setQuestion->getSequencePosition()),
215            'pass' => array('integer', $testSession->getPass()),
216            'tstamp' => array('integer', time()),
217            'src_pool_def_fi' => array('integer', $setQuestion->getSourcePoolDefinitionId())
218        ));
219    }
220
221    protected function fetchQuestionsFromStageRandomly(ilTestRandomQuestionSetQuestionCollection $questionStage, $requiredQuestionAmount)
222    {
223        $questionSet = $questionStage->getRandomQuestionCollection($requiredQuestionAmount);
224
225        return $questionSet;
226    }
227
228    protected function handleQuestionOrdering(ilTestRandomQuestionSetQuestionCollection $questionSet)
229    {
230        if ($this->testOBJ->getShuffleQuestions()) {
231            $questionSet->shuffleQuestions();
232        }
233    }
234
235    // =================================================================================================================
236
237    final public static function getInstance(
238        ilDBInterface $db,
239        ilObjTest $testOBJ,
240        ilTestRandomQuestionSetConfig $questionSetConfig,
241        ilTestRandomQuestionSetSourcePoolDefinitionList $sourcePoolDefinitionList,
242        ilTestRandomQuestionSetStagingPoolQuestionList $stagingPoolQuestionList
243    ) {
244        if ($questionSetConfig->isQuestionAmountConfigurationModePerPool()) {
245            require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetBuilderWithAmountPerPool.php';
246
247            return new ilTestRandomQuestionSetBuilderWithAmountPerPool(
248                $db,
249                $testOBJ,
250                $questionSetConfig,
251                $sourcePoolDefinitionList,
252                $stagingPoolQuestionList
253            );
254        }
255
256        require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetBuilderWithAmountPerTest.php';
257
258        return new ilTestRandomQuestionSetBuilderWithAmountPerTest(
259            $db,
260            $testOBJ,
261            $questionSetConfig,
262            $sourcePoolDefinitionList,
263            $stagingPoolQuestionList
264        );
265    }
266
267    //fau: fixRandomTestBuildable - function to get messages
268    /**
269     * @return array
270     */
271    public function getCheckMessages()
272    {
273        return $this->checkMessages;
274    }
275    // fau.
276}
277