ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
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 {
18  protected $logger = null;
19 
20  protected $settings = NULL;
21  protected $assignments = null;
22 
23  protected $user_id = 0;
24  protected $container_id = 0;
25 
26  protected $testRefId = null;
27 
33  public function __construct($a_user_id, $a_course_id)
34  {
35  $this->logger = $GLOBALS['DIC']->logger()->crs();
36 
37  $this->user_id = $a_user_id;
38  $this->container_id = $a_course_id;
39 
40  $this->settings = ilLOSettings::getInstanceByObjId($this->container_id);
41  $this->assignments = ilLOTestAssignments::getInstance($this->container_id);
42  }
43 
47  public function getTestRefId()
48  {
49  return $this->testRefId;
50  }
51 
55  public function setTestRefId($testRefId)
56  {
57  $this->testRefId = $testRefId;
58  }
59 
64  protected function lookupRelevantObjectiveIdsForTest($a_container_id, $a_tst_ref_id, $a_user_id)
65  {
66  include_once './Modules/Course/classes/Objectives/class.ilLOTestAssignments.php';
68 
69  include_once './Modules/Course/classes/class.ilCourseObjective.php';
70  $objective_ids = ilCourseObjective::_getObjectiveIds($a_container_id);
71 
72  $relevant_objective_ids = array();
73  if(!$this->getSettings()->hasSeparateInitialTests())
74  {
75  if($a_tst_ref_id == $this->getSettings()->getInitialTest())
76  {
77  $relevant_objective_ids = $objective_ids;
78  }
79  }
80  elseif(!$this->getSettings()->hasSeparateQualifiedTests())
81  {
82  if($a_tst_ref_id == $this->getSettings()->getQualifiedTest())
83  {
84  $relevant_objective_ids = $objective_ids;
85  }
86  }
87 
88  foreach((array) $objective_ids as $objective_id)
89  {
90  $assigned_itest = $assignments->getTestByObjective($objective_id, ilLOSettings::TYPE_TEST_INITIAL);
91  if($assigned_itest == $a_tst_ref_id)
92  {
93  $relevant_objective_ids[] = $objective_id;
94  }
95  $assigned_qtest = $assignments->getTestByObjective($objective_id, ilLOSettings::TYPE_TEST_QUALIFIED);
96  if($assigned_qtest == $a_tst_ref_id)
97  {
98  $relevant_objective_ids[] = $objective_id;
99  }
100  }
101 
102  $relevant_objective_ids = array_unique($relevant_objective_ids);
103 
104  if(count($relevant_objective_ids) <= 1)
105  {
106  return $relevant_objective_ids;
107  }
108 
109  // filter passed objectives
110  $test_type = $assignments->getTypeByTest($a_tst_ref_id);
111 
112  $passed_objectives = array();
113  include_once './Modules/Course/classes/Objectives/class.ilLOUserResults.php';
114  $results = new ilLOUserResults($a_container_id,$a_user_id);
115 
116  $passed = $results->getCompletedObjectiveIds();
117  $this->logger->debug('Passed objectives are ' . print_r($passed,true). ' for test type: ' . $test_type);
118 
119 
120  // all completed => show all objectives
121  if(count($passed) >= count($relevant_objective_ids))
122  {
123  return $relevant_objective_ids;
124  }
125 
126  $unpassed = array();
127  foreach($relevant_objective_ids as $objective_id)
128  {
129  if(!in_array($objective_id, $passed))
130  {
131  $unpassed[] = $objective_id;
132  }
133  }
134  return $unpassed;
135  }
136 
137 
143  public function notifyTestStart(ilTestSession $a_test_session, $a_test_obj_id)
144  {
145  $relevant_objectives = $this->lookupRelevantObjectiveIdsForTest(
146  $a_test_session->getObjectiveOrientedContainerId(),
147  $a_test_session->getRefId(),
148  $a_test_session->getUserId()
149  );
150  $this->logger->debug('Notify test start: '. print_r($relevant_objectives,true));
151 
152  // delete test runs
153  include_once './Modules/Course/classes/Objectives/class.ilLOTestRun.php';
155  $a_test_session->getObjectiveOrientedContainerId(),
156  $a_test_session->getUserId(),
157  $a_test_obj_id
158  );
159 
160  foreach((array) $relevant_objectives as $oid)
161  {
162  $this->logger->debug('Adding new run for objective with id: ' . $oid);
163  $run = new ilLOTestRun(
164  $a_test_session->getObjectiveOrientedContainerId(),
165  $a_test_session->getUserId(),
166  $a_test_obj_id,
167  $oid
168  );
169  $run->create();
170  }
171 
172  // finally reinitialize test runs
173  $this->initTestRun($a_test_session);
174  }
175 
181  public function prepareTestPass(ilTestSession $a_test_session, ilTestSequence $a_test_sequence)
182  {
183  $this->logger->debug('Prepare test pass called');
184 
185  $this->updateQuestions($a_test_session, $a_test_sequence);
186 
187  if($this->getSettings()->getPassedObjectiveMode() == ilLOSettings::MARK_PASSED_OBJECTIVE_QST)
188  {
189  $this->setQuestionsOptional($a_test_sequence);
190  }
191  elseif($this->getSettings()->getPassedObjectiveMode() == ilLOSettings::HIDE_PASSED_OBJECTIVE_QST)
192  {
193  $this->hideQuestions($a_test_sequence);
194  }
195 
196  $this->storeTestRun();
197  $this->initUserResult($a_test_session);
198 
199  // Save test sequence
200  $a_test_sequence->saveToDb();
201 
202  return true;
203  }
204 
210  {
211  $testType = $this->assignments->getTypeByTest($this->getTestRefId());
212 
213  if($testType == ilLOSettings::TYPE_TEST_INITIAL && $this->getSettings()->hasSeparateInitialTests())
214  {
215  $this->buildQuestionRelatedObjectiveListByTest($a_test_sequence, $a_objectives_list);
216  }
217  elseif($testType == ilLOSettings::TYPE_TEST_QUALIFIED && $this->getSettings()->hasSeparateQualifiedTests())
218  {
219  $this->buildQuestionRelatedObjectiveListByTest($a_test_sequence, $a_objectives_list);
220  }
221  else
222  {
223  $this->buildQuestionRelatedObjectiveListByQuestions($a_test_sequence, $a_objectives_list);
224  }
225  }
226 
228  {
229  $objectiveIds = array($this->getRelatedObjectivesForSeparatedTest($this->getTestRefId()));
230 
231  foreach( $a_test_sequence->getQuestionIds() as $questionId )
232  {
233  $a_objectives_list->addQuestionRelatedObjectives($questionId, $objectiveIds);
234  }
235  }
236 
238  {
239  foreach( $a_test_sequence->getQuestionIds() as $questionId )
240  {
241  if( $a_test_sequence instanceof ilTestRandomQuestionSequence )
242  {
243  $definitionId = $a_test_sequence->getResponsibleSourcePoolDefinitionId($questionId);
244  $objectiveIds = $this->lookupObjectiveIdByRandomQuestionSelectionDefinitionId($definitionId);
245  }
246  else
247  {
248  $objectiveIds = $this->lookupObjectiveIdByFixedQuestionId($questionId);
249  }
250 
251  if( count($objectiveIds) )
252  {
253  $a_objectives_list->addQuestionRelatedObjectives($questionId, $objectiveIds);
254  }
255  }
256  }
257 
259  {
260  include_once './Modules/Course/classes/Objectives/class.ilLORandomTestQuestionPools.php';
262  }
263 
264  protected function lookupObjectiveIdByFixedQuestionId($a_question_id)
265  {
266  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
268  }
269 
271  {
272  foreach( $this->getAssignments()->getAssignments() as $assignment )
273  {
274  if($assignment->getTestRefId() == $testRefId)
275  {
276  return $assignment->getObjectiveId();
277  }
278  }
279 
280  return null;
281  }
282 
283  protected function getUserId()
284  {
285  return $this->user_id;
286  }
287 
288  protected function getContainerId()
289  {
290  return $this->container_id;
291  }
292 
297  protected function getSettings()
298  {
299  return $this->settings;
300  }
301 
306  protected function getAssignments()
307  {
308  return $this->assignments;
309  }
310 
314  protected function initUserResult(ilTestSession $session)
315  {
316  // check if current test is start object and fullfilled
317  // if yes => do not increase tries.
318  $is_qualified_run = false;
319  if($this->isQualifiedStartRun($session))
320  {
321  $is_qualified_run = true;
322  }
323 
324  foreach($this->run as $run)
325  {
326  include_once './Modules/Course/classes/Objectives/class.ilLOUserResults.php';
327  include_once './Modules/Course/classes/Objectives/class.ilLOUtils.php';
328 
329  $old_result = ilLOUserResults::lookupResult(
330  $this->container_id,
331  $this->user_id,
332  $run->getObjectiveId(),
333  $this->getAssignments()->getTypeByTest($session->getRefId())
334  );
335 
336  include_once './Modules/Course/classes/Objectives/class.ilLOUtils.php';
337 
339  $this->container_id,
340  $run->getObjectiveId(),
341  $session->getRefId(),
342  $run->getMaxPoints()
343  );
344 
345  $max_attempts = ilLOUtils::lookupMaxAttempts(
346  $this->container_id,
347  $run->getObjectiveId(),
348  $session->getRefId()
349  );
350 
351  $this->logger->debug('Max attempts = ' . $max_attempts);
352 
353  if($max_attempts)
354  {
355  // check if current test is start object and fullfilled
356  // if yes => do not increase tries.
357  $this->logger->debug('Checking for qualified test...');
358  if(!$is_qualified_run)
359  {
360  $this->logger->debug(' and increasing attempts.');
361  ++$old_result['tries'];
362  }
363  $old_result['is_final'] = ($old_result['tries'] >= $max_attempts);
364  }
365 
366  $ur = new ilLOUserResults($this->container_id,$this->user_id);
367  $ur->saveObjectiveResult(
368  $run->getObjectiveId(),
369  $this->getAssignments()->getTypeByTest($session->getRefId()),
370  $old_result['status'],
371  $old_result['result_perc'],
372  $limit,
373  $old_result['tries'],
374  $old_result['is_final']
375  );
376  }
377  }
378 
384  protected function isQualifiedStartRun(ilTestSession $session)
385  {
386  if($this->getAssignments()->getTypeByTest($session->getRefId()) == ilLOSettings::TYPE_TEST_INITIAL)
387  {
388  $this->logger->debug('Initial test');
389  return false;
390  }
391 
392  if($session->getRefId() != $this->getSettings()->getQualifiedTest())
393  {
394  $this->logger->debug('No qualified test run');
395  return false;
396  }
397  include_once './Services/Container/classes/class.ilContainerStartObjects.php';
399  {
400  $this->logger->debug('No start object');
401  return false;
402  }
403  // Check if start object is fullfilled
404 
405  $container_ref_ids = ilObject::_getAllReferences($this->getContainerId());
406  $container_ref_id = end($container_ref_ids);
407 
409  $container_ref_id,
410  $this->getContainerId()
411  );
412  if($start->isFullfilled($this->getUserId(),$session->getRefId()))
413  {
414  $this->logger->debug('Is fullfilled');
415  return false;
416  }
417  $this->logger->debug('Is not fullfilled');
418  return true;
419  }
420 
426  public function updateQuestionResult(ilTestSession $session, assQuestion $qst)
427  {
428  foreach($this->run as $run)
429  {
430  if($run->questionExists($qst->getId()))
431  {
432  $GLOBALS['ilLog']->write(__METHOD__.': reached points are '.$qst->getReachedPoints($session->getActiveId(),$session->getPass()));
433  $run->setQuestionResult(
434  $qst->getId(),
435  $qst->getReachedPoints($session->getActiveId(),$session->getPass())
436  );
437  $run->update();
438 
439  $res = $run->getResult();
440 
441  include_once './Modules/Course/classes/Objectives/class.ilLOUserResults.php';
442  include_once './Modules/Course/classes/Objectives/class.ilLOUtils.php';
443 
444  $old_result = ilLOUserResults::lookupResult(
445  $this->container_id,
446  $this->user_id,
447  $run->getObjectiveId(),
448  $this->getAssignments()->getTypeByTest($session->getRefId())
449  );
450 
451  $ur = new ilLOUserResults($this->container_id,$this->user_id);
452  $ur->saveObjectiveResult(
453  $run->getObjectiveId(),
454  $this->getAssignments()->getTypeByTest($session->getRefId()),
455  $comp = ilLOUtils::isCompleted(
456  $this->container_id,
457  $session->getRefId(),
458  $run->getObjectiveId(),
459  $res['max'],$res['reached'],$old_result['limit_perc']) ?
462  (int) $res['percentage'],
463  $old_result['limit_perc'],
464  $old_result['tries'],
465  $old_result['is_final']
466  );
467  $GLOBALS['ilLog']->write(__METHOD__.': '.print_r($run->getResult(),true));
468  $GLOBALS['ilLog']->write(__METHOD__.'!!!!!!!!!!!!!!!!!!!!: '.print_r($comp,TRUE));
469 
470  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
471  ilLPStatusWrapper::_updateStatus($this->container_id,$this->user_id);
472  }
473  }
474  return false;
475  }
476 
481  protected function setQuestionsOptional(ilTestSequence $seq)
482  {
483  // first unset optional on all questions
484  $seq->clearOptionalQuestions();
485  foreach($seq->getQuestionIds() as $qid)
486  {
487  if(!$this->isInRun($qid)) // but is assigned to any LO
488  {
489  $seq->setQuestionOptional($qid);
490  }
491  }
492  }
493 
498  protected function hideQuestions(ilTestSequence $seq)
499  {
500  // first unhide all questions
501  $seq->clearHiddenQuestions();
502  foreach($seq->getQuestionIds() as $qid)
503  {
504  if(!$this->isInRun($qid))
505  {
506  $seq->hideQuestion($qid);
507  }
508  }
509  }
510 
511  protected function initTestRun(ilTestSession $session)
512  {
513  include_once './Modules/Course/classes/Objectives/class.ilLOTestRun.php';
514  $this->run = ilLOTestRun::getRun(
515  $this->container_id,
516  $this->user_id,
517  ilObject::_lookupObjId($session->getRefId())
518  );
519  }
520 
524  protected function storeTestRun()
525  {
526  foreach ($this->run as $tst_run)
527  {
528  $tst_run->update();
529  }
530  }
531 
532 
533  protected function updateQuestions(ilTestSession $session, ilTestSequence $seq)
534  {
535  if($this->getAssignments()->isSeparateTest($session->getRefId()))
536  {
537  $GLOBALS['ilLog']->write(__METHOD__.': separate run');
538  return $this->updateSeparateTestQuestions($session, $seq);
539  }
540  if($seq instanceof ilTestSequenceFixedQuestionSet)
541  {
542  $GLOBALS['ilLog']->write(__METHOD__.': fixed run');
543  return $this->updateFixedQuestions($session, $seq);
544  }
545  if($seq instanceof ilTestSequenceRandomQuestionSet)
546  {
547  $GLOBALS['ilLog']->write(__METHOD__.': random run');
548  return $this->updateRandomQuestions($session, $seq);
549  }
550 
551  }
552 
558  protected function updateSeparateTestQuestions(ilTestSession $session, ilTestSequence $seq)
559  {
560  foreach($this->run as $tst_run)
561  {
562  $tst_run->clearQuestions();
563  $points = 0;
564  foreach($seq->getQuestionIds() as $idx => $qst_id)
565  {
566  $tst_run->addQuestion($qst_id);
567  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
569  }
570  $tst_run->setMaxPoints($points);
571  }
572  }
573 
574 
575  protected function updateFixedQuestions(ilTestSession $session, ilTestSequence $seq)
576  {
577  foreach ($this->run as $tst_run)
578  {
579  $tst_run->clearQuestions();
580  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
582  ilObject::_lookupObjId($session->getRefId()),
583  $tst_run->getObjectiveId()
584  );
585  $points = 0;
586  foreach($qst as $id)
587  {
588  $tst_run->addQuestion($id);
590  }
591  $tst_run->setMaxPoints($points);
592  }
593  }
594 
596  {
597  include_once './Modules/Course/classes/Objectives/class.ilLORandomTestQuestionPools.php';
598  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
599 
600  foreach($this->run as $tst_run)
601  {
602  // Clear questions of previous run
603  $tst_run->clearQuestions();
604  $rnd = new ilLORandomTestQuestionPools(
605  $this->container_id,
606  $tst_run->getObjectiveId(),
607  ($this->getSettings()->getQualifiedTest() == $session->getRefId() ?
610  );
611  $stored_sequence_id = $rnd->getQplSequence();
612  $points = 0;
613  foreach($seq->getQuestionIds() as $qst)
614  {
615  if($stored_sequence_id == $seq->getResponsibleSourcePoolDefinitionId($qst))
616  {
617  $tst_run->addQuestion($qst);
619  }
620  }
621  $tst_run->setMaxPoints($points);
622  }
623  }
624 
625  protected function isInRun($a_qid)
626  {
627  foreach($this->run as $run)
628  {
629  if($run->questionExists($a_qid))
630  {
631  return true;
632  }
633  }
634  return false;
635  }
636 
637 
638  private static function getQuestionData($testObjId, $questionIds)
639  {
640  global $ilDB, $lng, $ilPluginAdmin;
641 
642  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionList.php';
643  $questionList = new ilAssQuestionList($ilDB, $lng, $ilPluginAdmin);
644  $questionList->setParentObjId($testObjId);
645 
646  $questionList->setQuestionInstanceTypeFilter(ilAssQuestionList::QUESTION_INSTANCE_TYPE_DUPLICATES);
647  $questionList->setQuestionIdsFilter($questionIds);
648 
649  $questionList->load();
650 
651  return $questionList->getQuestionDataArray();
652  }
653 
654  public static function getInstance(ilTestSession $a_test_session)
655  {
656  $adapter = new self(
657  $a_test_session->getUserId(),
658  $a_test_session->getObjectiveOrientedContainerId()
659  );
660 
661  $adapter->setTestRefId($a_test_session->getRefId());
662  $adapter->initTestRun($a_test_session);
663 
664  return $adapter;
665  }
666 }
667 ?>
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...
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
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)
Create styles array
The data for the language used.
updateQuestionResult(ilTestSession $session, assQuestion $qst)
update question result of run
settings()
Definition: settings.php:2
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:17
static deleteRun($a_container_id, $a_user_id, $a_test_id)
global $ilDB
static lookupObjectivesOfQuestion($a_qid)
Lookup objective for test question type $ilDB.
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.