ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.ilLOTestQuestionAdapter.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 include_once './Modules/Course/classes/Objectives/class.ilLOSettings.php';
5 include_once './Modules/Course/classes/Objectives/class.ilLOTestAssignments.php';
6 
14 {
15  protected $settings = NULL;
16  protected $assignments = null;
17 
18  protected $user_id = 0;
19  protected $container_id = 0;
20 
21  protected $testRefId = null;
22 
28  public function __construct($a_user_id, $a_course_id)
29  {
30  $this->user_id = $a_user_id;
31  $this->container_id = $a_course_id;
32 
33  $this->settings = ilLOSettings::getInstanceByObjId($this->container_id);
34  $this->assignments = ilLOTestAssignments::getInstance($this->container_id);
35  }
36 
40  public function getTestRefId()
41  {
42  return $this->testRefId;
43  }
44 
48  public function setTestRefId($testRefId)
49  {
50  $this->testRefId = $testRefId;
51  }
52 
57  protected function lookupRelevantObjectiveIdsForTest($a_container_id, $a_tst_ref_id, $a_user_id)
58  {
59  include_once './Modules/Course/classes/Objectives/class.ilLOTestAssignments.php';
61 
62  include_once './Modules/Course/classes/class.ilCourseObjective.php';
63  $objective_ids = ilCourseObjective::_getObjectiveIds($a_container_id);
64 
65  $relevant_objective_ids = array();
66  if(!$this->getSettings()->hasSeparateInitialTests())
67  {
68  if($a_tst_ref_id == $this->getSettings()->getInitialTest())
69  {
70  $relevant_objective_ids = $objective_ids;
71  }
72  }
73  elseif(!$this->getSettings()->hasSeparateQualifiedTests())
74  {
75  if($a_tst_ref_id == $this->getSettings()->getQualifiedTest())
76  {
77  $relevant_objective_ids = $objective_ids;
78  }
79  }
80 
81  foreach((array) $objective_ids as $objective_id)
82  {
83  $assigned_itest = $assignments->getTestByObjective($objective_id, ilLOSettings::TYPE_TEST_INITIAL);
84  if($assigned_itest == $a_tst_ref_id)
85  {
86  $relevant_objective_ids[] = $objective_id;
87  }
88  $assigned_qtest = $assignments->getTestByObjective($objective_id, ilLOSettings::TYPE_TEST_QUALIFIED);
89  if($assigned_qtest == $a_tst_ref_id)
90  {
91  $relevant_objective_ids[] = $objective_id;
92  }
93  }
94 
95  $relevant_objective_ids = array_unique($relevant_objective_ids);
96 
97  if(count($relevant_objective_ids) <= 1)
98  {
99  return $relevant_objective_ids;
100  }
101 
102  // filter passed objectives
103  $test_type = $assignments->getTypeByTest($a_tst_ref_id);
104 
105  $passed_objectives = array();
106  include_once './Modules/Course/classes/Objectives/class.ilLOUserResults.php';
107  $results = new ilLOUserResults($a_container_id,$a_user_id);
108 
109  $passed = $results->getCompletedObjectiveIds();
110  $GLOBALS['ilLog']->write(__METHOD__.': Passed objectives are '.print_r($passed,TRUE).' test_type = '.$test_type);
111 
112 
113  // all completed => show all objectives
114  if(count($passed) >= count($relevant_objective_ids))
115  {
116  return $relevant_objective_ids;
117  }
118 
119  $unpassed = array();
120  foreach($relevant_objective_ids as $objective_id)
121  {
122  if(!in_array($objective_id, $passed))
123  {
124  $unpassed[] = $objective_id;
125  }
126  }
127  return $unpassed;
128  }
129 
130 
136  public function notifyTestStart(ilTestSession $a_test_session, $a_test_obj_id)
137  {
138  $relevant_objectives = $this->lookupRelevantObjectiveIdsForTest(
139  $a_test_session->getObjectiveOrientedContainerId(),
140  $a_test_session->getRefId(),
141  $a_test_session->getUserId()
142  );
143  $GLOBALS['ilLog']->write(__METHOD__.': Notify test start ' . print_r($relevant_objectives,TRUE));
144 
145  // delete test runs
146  include_once './Modules/Course/classes/Objectives/class.ilLOTestRun.php';
148  $a_test_session->getObjectiveOrientedContainerId(),
149  $a_test_session->getUserId(),
150  $a_test_obj_id
151  );
152 
153  foreach((array) $relevant_objectives as $oid)
154  {
155  $GLOBALS['ilLog']->write(__METHOD__.': Adding new run for objective with id '.$oid);
156  $run = new ilLOTestRun(
157  $a_test_session->getObjectiveOrientedContainerId(),
158  $a_test_session->getUserId(),
159  $a_test_obj_id,
160  $oid
161  );
162  $run->create();
163  }
164 
165  // finally reinitialize test runs
166  $this->initTestRun($a_test_session);
167  }
168 
174  public function prepareTestPass(ilTestSession $a_test_session, ilTestSequence $a_test_sequence)
175  {
176  $this->updateQuestions($a_test_session, $a_test_sequence);
177 
178  if($this->getSettings()->getPassedObjectiveMode() == ilLOSettings::MARK_PASSED_OBJECTIVE_QST)
179  {
180  $this->setQuestionsOptional($a_test_sequence);
181  }
182  elseif($this->getSettings()->getPassedObjectiveMode() == ilLOSettings::HIDE_PASSED_OBJECTIVE_QST)
183  {
184  $this->hideQuestions($a_test_sequence);
185  }
186 
187  $this->storeTestRun();
188  $this->initUserResult($a_test_session);
189 
190  // Save test sequence
191  $a_test_sequence->saveToDb();
192 
193  return true;
194  }
195 
201  {
202  $testType = $this->assignments->getTypeByTest($this->getTestRefId());
203 
204  if($testType == ilLOSettings::TYPE_TEST_INITIAL && $this->getSettings()->hasSeparateInitialTests())
205  {
206  $this->buildQuestionRelatedObjectiveListByTest($a_test_sequence, $a_objectives_list);
207  }
208  elseif($testType == ilLOSettings::TYPE_TEST_QUALIFIED && $this->getSettings()->hasSeparateQualifiedTests())
209  {
210  $this->buildQuestionRelatedObjectiveListByTest($a_test_sequence, $a_objectives_list);
211  }
212  else
213  {
214  $this->buildQuestionRelatedObjectiveListByQuestions($a_test_sequence, $a_objectives_list);
215  }
216  }
217 
219  {
220  $objectiveIds = array($this->getRelatedObjectivesForSeparatedTest($this->getTestRefId()));
221 
222  foreach( $a_test_sequence->getQuestionIds() as $questionId )
223  {
224  $a_objectives_list->addQuestionRelatedObjectives($questionId, $objectiveIds);
225  }
226  }
227 
229  {
230  foreach( $a_test_sequence->getQuestionIds() as $questionId )
231  {
232  if( $a_test_sequence instanceof ilTestRandomQuestionSequence )
233  {
234  $definitionId = $a_test_sequence->getResponsibleSourcePoolDefinitionId($questionId);
235  $objectiveIds = $this->lookupObjectiveIdByRandomQuestionSelectionDefinitionId($definitionId);
236  }
237  else
238  {
239  $objectiveIds = $this->lookupObjectiveIdByFixedQuestionId($questionId);
240  }
241 
242  if( count($objectiveIds) )
243  {
244  $a_objectives_list->addQuestionRelatedObjectives($questionId, $objectiveIds);
245  }
246  }
247  }
248 
250  {
251  include_once './Modules/Course/classes/Objectives/class.ilLORandomTestQuestionPools.php';
253  }
254 
255  protected function lookupObjectiveIdByFixedQuestionId($a_question_id)
256  {
257  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
259  }
260 
262  {
263  foreach( $this->getAssignments()->getAssignments() as $assignment )
264  {
265  if($assignment->getTestRefId() == $testRefId)
266  {
267  return $assignment->getObjectiveId();
268  }
269  }
270 
271  return null;
272  }
273 
274  protected function getUserId()
275  {
276  return $this->user_id;
277  }
278 
279  protected function getContainerId()
280  {
281  return $this->container_id;
282  }
283 
288  protected function getSettings()
289  {
290  return $this->settings;
291  }
292 
297  protected function getAssignments()
298  {
299  return $this->assignments;
300  }
301 
305  protected function initUserResult(ilTestSession $session)
306  {
307  // check if current test is start object and fullfilled
308  // if yes => do not increase tries.
309  $is_qualified_run = false;
310  if($this->isQualifiedStartRun($session))
311  {
312  $is_qualified_run = true;
313  }
314 
315  foreach($this->run as $run)
316  {
317  include_once './Modules/Course/classes/Objectives/class.ilLOUserResults.php';
318  include_once './Modules/Course/classes/Objectives/class.ilLOUtils.php';
319 
320  $old_result = ilLOUserResults::lookupResult(
321  $this->container_id,
322  $this->user_id,
323  $run->getObjectiveId(),
324  $this->getAssignments()->getTypeByTest($session->getRefId())
325  );
326 
327  include_once './Modules/Course/classes/Objectives/class.ilLOUtils.php';
328 
330  $this->container_id,
331  $run->getObjectiveId(),
332  $session->getRefId(),
333  $run->getMaxPoints()
334  );
335 
336  $max_attempts = ilLOUtils::lookupMaxAttempts($this->container_id, $run->getObjectiveId());
337  if($max_attempts)
338  {
339  // check if current test is start object and fullfilled
340  // if yes => do not increase tries.
341  $GLOBALS['ilLog']->write(__METHOD__.': check for qualified...');
342  if(!$is_qualified_run)
343  {
344  $GLOBALS['ilLog']->write(__METHOD__.': and increase attempts');
345  ++$old_result['tries'];
346  }
347  $old_result['is_final'] = ($old_result['tries'] >= $max_attempts);
348  }
349 
350  $ur = new ilLOUserResults($this->container_id,$this->user_id);
351  $ur->saveObjectiveResult(
352  $run->getObjectiveId(),
353  $this->getAssignments()->getTypeByTest($session->getRefId()),
354  $old_result['status'],
355  $old_result['result_perc'],
356  $limit,
357  $old_result['tries'],
358  $old_result['is_final']
359  );
360  }
361  }
362 
368  protected function isQualifiedStartRun(ilTestSession $session)
369  {
370  if($this->getAssignments()->getTypeByTest($session->getRefId()) == ilLOSettings::TYPE_TEST_INITIAL)
371  {
372  $GLOBALS['ilLog']->write(__METHOD__.': is initial');
373  return false;
374  }
375 
376  if($session->getRefId() != $this->getSettings()->getQualifiedTest())
377  {
378  $GLOBALS['ilLog']->write(__METHOD__.': is not qualified');
379  return false;
380  }
381  include_once './Services/Container/classes/class.ilContainerStartObjects.php';
383  {
384  $GLOBALS['ilLog']->write(__METHOD__.': no start object');
385  return false;
386  }
387  // Check if start object is fullfilled
388 
389  $container_ref_ids = ilObject::_getAllReferences($this->getContainerId());
390  $container_ref_id = end($container_ref_ids);
391 
392  $start = new ilContainerStartObjects(
393  $container_ref_id,
394  $this->getContainerId()
395  );
396  if($start->isFullfilled($this->getUserId(),$session->getRefId()))
397  {
398  $GLOBALS['ilLog']->write(__METHOD__.': is fullfilled');
399 
400  return false;
401  }
402  $GLOBALS['ilLog']->write(__METHOD__.': is not fullfilled');
403  return true;
404  }
405 
411  public function updateQuestionResult(ilTestSession $session, assQuestion $qst)
412  {
413  foreach($this->run as $run)
414  {
415  if($run->questionExists($qst->getId()))
416  {
417  $GLOBALS['ilLog']->write(__METHOD__.': reached points are '.$qst->getReachedPoints($session->getActiveId(),$session->getPass()));
418  $run->setQuestionResult(
419  $qst->getId(),
420  $qst->getReachedPoints($session->getActiveId(),$session->getPass())
421  );
422  $run->update();
423 
424  $res = $run->getResult();
425 
426  include_once './Modules/Course/classes/Objectives/class.ilLOUserResults.php';
427  include_once './Modules/Course/classes/Objectives/class.ilLOUtils.php';
428 
429  $old_result = ilLOUserResults::lookupResult(
430  $this->container_id,
431  $this->user_id,
432  $run->getObjectiveId(),
433  $this->getAssignments()->getTypeByTest($session->getRefId())
434  );
435 
436  $ur = new ilLOUserResults($this->container_id,$this->user_id);
437  $ur->saveObjectiveResult(
438  $run->getObjectiveId(),
439  $this->getAssignments()->getTypeByTest($session->getRefId()),
440  $comp = ilLOUtils::isCompleted(
441  $this->container_id,
442  $session->getRefId(),
443  $run->getObjectiveId(),
444  $res['max'],$res['reached'],$old_result['limit_perc']) ?
447  (int) $res['percentage'],
448  $old_result['limit_perc'],
449  $old_result['tries'],
450  $old_result['is_final']
451  );
452  $GLOBALS['ilLog']->write(__METHOD__.': '.print_r($run->getResult(),true));
453  $GLOBALS['ilLog']->write(__METHOD__.'!!!!!!!!!!!!!!!!!!!!: '.print_r($comp,TRUE));
454 
455  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
456  ilLPStatusWrapper::_updateStatus($this->container_id,$this->user_id);
457  }
458  }
459  return false;
460  }
461 
466  protected function setQuestionsOptional(ilTestSequence $seq)
467  {
468  // first unset optional on all questions
469  $seq->clearOptionalQuestions();
470  foreach($seq->getQuestionIds() as $qid)
471  {
472  if(!$this->isInRun($qid)) // but is assigned to any LO
473  {
474  $seq->setQuestionOptional($qid);
475  }
476  }
477  }
478 
483  protected function hideQuestions(ilTestSequence $seq)
484  {
485  // first unhide all questions
486  $seq->clearHiddenQuestions();
487  foreach($seq->getQuestionIds() as $qid)
488  {
489  if(!$this->isInRun($qid))
490  {
491  $seq->hideQuestion($qid);
492  }
493  }
494  }
495 
496  protected function initTestRun(ilTestSession $session)
497  {
498  include_once './Modules/Course/classes/Objectives/class.ilLOTestRun.php';
499  $this->run = ilLOTestRun::getRun(
500  $this->container_id,
501  $this->user_id,
502  ilObject::_lookupObjId($session->getRefId())
503  );
504  }
505 
509  protected function storeTestRun()
510  {
511  foreach ($this->run as $tst_run)
512  {
513  $tst_run->update();
514  }
515  }
516 
517 
518  protected function updateQuestions(ilTestSession $session, ilTestSequence $seq)
519  {
520  if($this->getAssignments()->isSeparateTest($session->getRefId()))
521  {
522  $GLOBALS['ilLog']->write(__METHOD__.': separate run');
523  return $this->updateSeparateTestQuestions($session, $seq);
524  }
525  if($seq instanceof ilTestSequenceFixedQuestionSet)
526  {
527  $GLOBALS['ilLog']->write(__METHOD__.': fixed run');
528  return $this->updateFixedQuestions($session, $seq);
529  }
530  if($seq instanceof ilTestSequenceRandomQuestionSet)
531  {
532  $GLOBALS['ilLog']->write(__METHOD__.': random run');
533  return $this->updateRandomQuestions($session, $seq);
534  }
535 
536  }
537 
543  protected function updateSeparateTestQuestions(ilTestSession $session, ilTestSequence $seq)
544  {
545  foreach($this->run as $tst_run)
546  {
547  $tst_run->clearQuestions();
548  $points = 0;
549  foreach($seq->getQuestionIds() as $idx => $qst_id)
550  {
551  $tst_run->addQuestion($qst_id);
552  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
554  }
555  $tst_run->setMaxPoints($points);
556  }
557  }
558 
559 
560  protected function updateFixedQuestions(ilTestSession $session, ilTestSequence $seq)
561  {
562  foreach ($this->run as $tst_run)
563  {
564  $tst_run->clearQuestions();
565  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
567  ilObject::_lookupObjId($session->getRefId()),
568  $tst_run->getObjectiveId()
569  );
570  $points = 0;
571  foreach($qst as $id)
572  {
573  $tst_run->addQuestion($id);
575  }
576  $tst_run->setMaxPoints($points);
577  }
578  }
579 
581  {
582  include_once './Modules/Course/classes/Objectives/class.ilLORandomTestQuestionPools.php';
583  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
584 
585  foreach($this->run as $tst_run)
586  {
587  // Clear questions of previous run
588  $tst_run->clearQuestions();
589  $rnd = new ilLORandomTestQuestionPools(
590  $this->container_id,
591  $tst_run->getObjectiveId(),
592  ($this->getSettings()->getQualifiedTest() == $session->getRefId() ?
595  );
596  $stored_sequence_id = $rnd->getQplSequence();
597  $points = 0;
598  foreach($seq->getQuestionIds() as $qst)
599  {
600  if($stored_sequence_id == $seq->getResponsibleSourcePoolDefinitionId($qst))
601  {
602  $tst_run->addQuestion($qst);
604  }
605  }
606  $tst_run->setMaxPoints($points);
607  }
608  }
609 
610  protected function isInRun($a_qid)
611  {
612  foreach($this->run as $run)
613  {
614  if($run->questionExists($a_qid))
615  {
616  return true;
617  }
618  }
619  return false;
620  }
621 
622 
623  private static function getQuestionData($testObjId, $questionIds)
624  {
625  global $ilDB, $lng, $ilPluginAdmin;
626 
627  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionList.php';
628  $questionList = new ilAssQuestionList($ilDB, $lng, $ilPluginAdmin);
629  $questionList->setParentObjId($testObjId);
630 
631  $questionList->setQuestionInstanceTypeFilter(ilAssQuestionList::QUESTION_INSTANCE_TYPE_DUPLICATES);
632  $questionList->setQuestionIdsFilter($questionIds);
633 
634  $questionList->load();
635 
636  return $questionList->getQuestionDataArray();
637  }
638 
639  public static function getInstance(ilTestSession $a_test_session)
640  {
641  $adapter = new self(
642  $a_test_session->getUserId(),
643  $a_test_session->getObjectiveOrientedContainerId()
644  );
645 
646  $adapter->setTestRefId($a_test_session->getRefId());
647  $adapter->initTestRun($a_test_session);
648 
649  return $adapter;
650  }
651 }
652 ?>
static isCompleted($a_cont_oid, $a_test_rid, $a_objective_id, $max_points, $reached, $limit_perc)
Check if objective is completed.
static getInstanceByObjId($a_obj_id)
get singleton instance
updateRandomQuestions(ilTestSession $session, ilTestSequenceRandomQuestionSet $seq)
getId()
Gets the id of the assQuestion object.
static getInstance($a_container_id)
Get instance by container id.
notifyTestStart(ilTestSession $a_test_session, $a_test_obj_id)
Called from learning objective test on actual test start.
static _lookupMaximumPointsOfQuestion($a_question_id)
lookup maximimum point
Abstract basic class which is to be extended by the concrete assessment question type classes...
static lookupResult($a_course_obj_id, $a_user_id, $a_objective_id, $a_tst_type)
Lookup user result.
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
getReachedPoints($active_id, $pass=NULL)
Returns the points, a learner has reached answering the question This is the fast way to get the poin...
static _getObjectiveIds($course_id, $a_activated_only=false)
static getRun($a_container_id, $a_user_id, $a_test_id)
setQuestionsOptional(ilTestSequence $seq)
set questions optional
const HIDE_PASSED_OBJECTIVE_QST
hideQuestion($question_id)
static _getAllReferences($a_id)
get all reference ids of object
Test sequence handler.
updateSeparateTestQuestions(ilTestSession $session, ilTestSequence $seq)
Update questions for separate tests.
hideQuestions(ilTestSequence $seq)
Hide questions.
saveToDb()
Saves the sequence data for a given pass to the database.
static getInstance(ilTestSession $a_test_session)
updateQuestions(ilTestSession $session, ilTestSequence $seq)
buildQuestionRelatedObjectiveListByQuestions(ilTestQuestionSequence $a_test_sequence, ilTestQuestionRelatedObjectivesList $a_objectives_list)
buildQuestionRelatedObjectiveList(ilTestQuestionSequence $a_test_sequence, ilTestQuestionRelatedObjectivesList $a_objectives_list)
updateFixedQuestions(ilTestSession $session, ilTestSequence $seq)
static _lookupObjId($a_id)
const MARK_PASSED_OBJECTIVE_QST
getRefId()
Get Ref id.
Test session handler.
$results
__construct($a_user_id, $a_course_id)
static lookupObjectiveRequiredPercentage($a_container_id, $a_objective_id, $a_test_ref_id, $a_max_points)
static lookupMaxAttempts($a_container_id, $a_objective_id)
updateQuestionResult(ilTestSession $session, assQuestion $qst)
update question result of run
isQualifiedStartRun(ilTestSession $session)
Check if current run is a start object run.
static lookupObjectiveIdsBySequence($a_container_id, $a_seq_id)
Lookup objective id by sequence.
setQuestionOptional($questionId)
buildQuestionRelatedObjectiveListByTest(ilTestQuestionSequence $a_test_sequence, ilTestQuestionRelatedObjectivesList $a_objectives_list)
global $lng
Definition: privfeed.php:40
static deleteRun($a_container_id, $a_user_id, $a_test_id)
global $ilDB
static lookupObjectivesOfQuestion($a_qid)
Lookup objective for test question type $ilDB.
$GLOBALS['PHPCAS_CLIENT']
This global variable is used by the interface class phpCAS.
Definition: CAS.php:276
Stores current objective, questions and max points.
prepareTestPass(ilTestSession $a_test_session, ilTestSequence $a_test_sequence)
Called from learning objective test.
static lookupQuestionsByObjective($a_test_id, $a_objective)
static getQuestionData($testObjId, $questionIds)
lookupRelevantObjectiveIdsForTest($a_container_id, $a_tst_ref_id, $a_user_id)
Lookup all relevant objective ids for a specific test.
initUserResult(ilTestSession $session)
init user result
static isStartObject($a_container_id, $a_item_ref_id)
Check if object is start object type $ilDB.