ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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  if ($a_tst_ref_id == $this->getSettings()->getInitialTest()) {
75  $relevant_objective_ids = $objective_ids;
76  }
77  } elseif (!$this->getSettings()->hasSeparateQualifiedTests()) {
78  if ($a_tst_ref_id == $this->getSettings()->getQualifiedTest()) {
79  $relevant_objective_ids = $objective_ids;
80  }
81  }
82 
83  foreach ((array) $objective_ids as $objective_id) {
84  $assigned_itest = $assignments->getTestByObjective($objective_id, ilLOSettings::TYPE_TEST_INITIAL);
85  if ($assigned_itest == $a_tst_ref_id) {
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  $relevant_objective_ids[] = $objective_id;
91  }
92  }
93 
94  $relevant_objective_ids = array_unique($relevant_objective_ids);
95 
96  if (count($relevant_objective_ids) <= 1) {
97  return $relevant_objective_ids;
98  }
99 
100  // filter passed objectives
101  $test_type = $assignments->getTypeByTest($a_tst_ref_id);
102 
103  $passed_objectives = array();
104  include_once './Modules/Course/classes/Objectives/class.ilLOUserResults.php';
105  $results = new ilLOUserResults($a_container_id, $a_user_id);
106 
107  $passed = $results->getCompletedObjectiveIds();
108  $this->logger->debug('Passed objectives are ' . print_r($passed, true) . ' for test type: ' . $test_type);
109 
110 
111  // all completed => show all objectives
112  if (count($passed) >= count($relevant_objective_ids)) {
113  return $relevant_objective_ids;
114  }
115 
116  $unpassed = array();
117  foreach ($relevant_objective_ids as $objective_id) {
118  if (!in_array($objective_id, $passed)) {
119  $unpassed[] = $objective_id;
120  }
121  }
122  return $unpassed;
123  }
124 
125 
131  public function notifyTestStart(ilTestSession $a_test_session, $a_test_obj_id)
132  {
133  $relevant_objectives = $this->lookupRelevantObjectiveIdsForTest(
134  $a_test_session->getObjectiveOrientedContainerId(),
135  $a_test_session->getRefId(),
136  $a_test_session->getUserId()
137  );
138  $this->logger->debug('Notify test start: ' . print_r($relevant_objectives, true));
139 
140  // delete test runs
141  include_once './Modules/Course/classes/Objectives/class.ilLOTestRun.php';
143  $a_test_session->getObjectiveOrientedContainerId(),
144  $a_test_session->getUserId(),
145  $a_test_obj_id
146  );
147 
148  foreach ((array) $relevant_objectives as $oid) {
149  $this->logger->debug('Adding new run for objective with id: ' . $oid);
150  $run = new ilLOTestRun(
151  $a_test_session->getObjectiveOrientedContainerId(),
152  $a_test_session->getUserId(),
153  $a_test_obj_id,
154  $oid
155  );
156  $run->create();
157  }
158 
159  // finally reinitialize test runs
160  $this->initTestRun($a_test_session);
161  }
162 
168  public function prepareTestPass(ilTestSession $a_test_session, ilTestSequence $a_test_sequence)
169  {
170  $this->logger->debug('Prepare test pass called');
171 
172  $this->updateQuestions($a_test_session, $a_test_sequence);
173 
174  if ($this->getSettings()->getPassedObjectiveMode() == ilLOSettings::MARK_PASSED_OBJECTIVE_QST) {
175  $this->setQuestionsOptional($a_test_sequence);
176  } elseif ($this->getSettings()->getPassedObjectiveMode() == ilLOSettings::HIDE_PASSED_OBJECTIVE_QST) {
177  $this->hideQuestions($a_test_sequence);
178  }
179 
180  $this->storeTestRun();
181  $this->initUserResult($a_test_session);
182 
183  // Save test sequence
184  $a_test_sequence->saveToDb();
185 
186  return true;
187  }
188 
194  {
195  $testType = $this->assignments->getTypeByTest($this->getTestRefId());
196 
197  if ($testType == ilLOSettings::TYPE_TEST_INITIAL && $this->getSettings()->hasSeparateInitialTests()) {
198  $this->buildQuestionRelatedObjectiveListByTest($a_test_sequence, $a_objectives_list);
199  } elseif ($testType == ilLOSettings::TYPE_TEST_QUALIFIED && $this->getSettings()->hasSeparateQualifiedTests()) {
200  $this->buildQuestionRelatedObjectiveListByTest($a_test_sequence, $a_objectives_list);
201  } else {
202  $this->buildQuestionRelatedObjectiveListByQuestions($a_test_sequence, $a_objectives_list);
203  }
204  }
205 
207  {
208  $objectiveIds = array($this->getRelatedObjectivesForSeparatedTest($this->getTestRefId()));
209 
210  foreach ($a_test_sequence->getQuestionIds() as $questionId) {
211  $a_objectives_list->addQuestionRelatedObjectives($questionId, $objectiveIds);
212  }
213  }
214 
216  {
217  foreach ($a_test_sequence->getQuestionIds() as $questionId) {
218  if ($a_test_sequence instanceof ilTestRandomQuestionSequence) {
219  $definitionId = $a_test_sequence->getResponsibleSourcePoolDefinitionId($questionId);
220  $objectiveIds = $this->lookupObjectiveIdByRandomQuestionSelectionDefinitionId($definitionId);
221  } else {
222  $objectiveIds = $this->lookupObjectiveIdByFixedQuestionId($questionId);
223  }
224 
225  if (count($objectiveIds)) {
226  $a_objectives_list->addQuestionRelatedObjectives($questionId, $objectiveIds);
227  }
228  }
229  }
230 
232  {
233  include_once './Modules/Course/classes/Objectives/class.ilLORandomTestQuestionPools.php';
235  }
236 
237  protected function lookupObjectiveIdByFixedQuestionId($a_question_id)
238  {
239  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
241  }
242 
244  {
245  foreach ($this->getAssignments()->getAssignments() as $assignment) {
246  if ($assignment->getTestRefId() == $testRefId) {
247  return $assignment->getObjectiveId();
248  }
249  }
250 
251  return null;
252  }
253 
254  protected function getUserId()
255  {
256  return $this->user_id;
257  }
258 
259  protected function getContainerId()
260  {
261  return $this->container_id;
262  }
263 
268  protected function getSettings()
269  {
270  return $this->settings;
271  }
272 
277  protected function getAssignments()
278  {
279  return $this->assignments;
280  }
281 
286  {
287  // check if current test is start object and fullfilled
288  // if yes => do not increase tries.
289  $is_qualified_run = false;
290  if ($this->isQualifiedStartRun($session)) {
291  $is_qualified_run = true;
292  }
293 
294  foreach ($this->run as $run) {
295  include_once './Modules/Course/classes/Objectives/class.ilLOUserResults.php';
296  include_once './Modules/Course/classes/Objectives/class.ilLOUtils.php';
297 
298  $old_result = ilLOUserResults::lookupResult(
299  $this->container_id,
300  $this->user_id,
301  $run->getObjectiveId(),
302  $this->getAssignments()->getTypeByTest($session->getRefId())
303  );
304 
305  include_once './Modules/Course/classes/Objectives/class.ilLOUtils.php';
306 
308  $this->container_id,
309  $run->getObjectiveId(),
310  $session->getRefId(),
311  $run->getMaxPoints()
312  );
313 
314  $max_attempts = ilLOUtils::lookupMaxAttempts(
315  $this->container_id,
316  $run->getObjectiveId(),
317  $session->getRefId()
318  );
319 
320  $this->logger->debug('Max attempts = ' . $max_attempts);
321 
322  if ($max_attempts) {
323  // check if current test is start object and fullfilled
324  // if yes => do not increase tries.
325  $this->logger->debug('Checking for qualified test...');
326  if (!$is_qualified_run) {
327  $this->logger->debug(' and increasing attempts.');
328  ++$old_result['tries'];
329  }
330  $old_result['is_final'] = ($old_result['tries'] >= $max_attempts);
331  }
332 
333  $ur = new ilLOUserResults($this->container_id, $this->user_id);
334  $ur->saveObjectiveResult(
335  $run->getObjectiveId(),
336  $this->getAssignments()->getTypeByTest($session->getRefId()),
337  $old_result['status'],
338  $old_result['result_perc'],
339  $limit,
340  $old_result['tries'],
341  $old_result['is_final']
342  );
343  }
344  }
345 
352  {
353  if ($this->getAssignments()->getTypeByTest($session->getRefId()) == ilLOSettings::TYPE_TEST_INITIAL) {
354  $this->logger->debug('Initial test');
355  return false;
356  }
357 
358  if ($session->getRefId() != $this->getSettings()->getQualifiedTest()) {
359  $this->logger->debug('No qualified test run');
360  return false;
361  }
362  include_once './Services/Container/classes/class.ilContainerStartObjects.php';
363  if (!ilContainerStartObjects::isStartObject($this->getContainerId(), $session->getRefId())) {
364  $this->logger->debug('No start object');
365  return false;
366  }
367  // Check if start object is fullfilled
368 
369  $container_ref_ids = ilObject::_getAllReferences($this->getContainerId());
370  $container_ref_id = end($container_ref_ids);
371 
372  $start = new ilContainerStartObjects(
373  $container_ref_id,
374  $this->getContainerId()
375  );
376  if ($start->isFullfilled($this->getUserId(), $session->getRefId())) {
377  $this->logger->debug('Is fullfilled');
378  return false;
379  }
380  $this->logger->debug('Is not fullfilled');
381  return true;
382  }
383 
390  {
391  foreach ($this->run as $run) {
392  if ($run->questionExists($qst->getId())) {
393  $GLOBALS['ilLog']->write(__METHOD__ . ': reached points are ' . $qst->getReachedPoints($session->getActiveId(), $session->getPass()));
394  $run->setQuestionResult(
395  $qst->getId(),
396  $qst->getReachedPoints($session->getActiveId(), $session->getPass())
397  );
398  $run->update();
399 
400  $res = $run->getResult();
401 
402  include_once './Modules/Course/classes/Objectives/class.ilLOUserResults.php';
403  include_once './Modules/Course/classes/Objectives/class.ilLOUtils.php';
404 
405  $old_result = ilLOUserResults::lookupResult(
406  $this->container_id,
407  $this->user_id,
408  $run->getObjectiveId(),
409  $this->getAssignments()->getTypeByTest($session->getRefId())
410  );
411 
412  $ur = new ilLOUserResults($this->container_id, $this->user_id);
413  $ur->saveObjectiveResult(
414  $run->getObjectiveId(),
415  $this->getAssignments()->getTypeByTest($session->getRefId()),
416  $comp = ilLOUtils::isCompleted(
417  $this->container_id,
418  $session->getRefId(),
419  $run->getObjectiveId(),
420  $res['max'],
421  $res['reached'],
422  $old_result['limit_perc']
423  ) ?
426  (int) $res['percentage'],
427  $old_result['limit_perc'],
428  $old_result['tries'],
429  $old_result['is_final']
430  );
431  $GLOBALS['ilLog']->write(__METHOD__ . ': ' . print_r($run->getResult(), true));
432  $GLOBALS['ilLog']->write(__METHOD__ . '!!!!!!!!!!!!!!!!!!!!: ' . print_r($comp, true));
433 
434  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
435  ilLPStatusWrapper::_updateStatus($this->container_id, $this->user_id);
436  }
437  }
438  return false;
439  }
440 
445  protected function setQuestionsOptional(ilTestSequence $seq)
446  {
447  // first unset optional on all questions
448  $seq->clearOptionalQuestions();
449  foreach ($seq->getQuestionIds() as $qid) {
450  if (!$this->isInRun($qid)) { // but is assigned to any LO
451  $seq->setQuestionOptional($qid);
452  }
453  }
454  }
455 
460  protected function hideQuestions(ilTestSequence $seq)
461  {
462  // first unhide all questions
463  $seq->clearHiddenQuestions();
464  foreach ($seq->getQuestionIds() as $qid) {
465  if (!$this->isInRun($qid)) {
466  $seq->hideQuestion($qid);
467  }
468  }
469  }
470 
471  protected function initTestRun(ilTestSession $session)
472  {
473  include_once './Modules/Course/classes/Objectives/class.ilLOTestRun.php';
474  $this->run = ilLOTestRun::getRun(
475  $this->container_id,
476  $this->user_id,
477  ilObject::_lookupObjId($session->getRefId())
478  );
479  }
480 
484  protected function storeTestRun()
485  {
486  foreach ($this->run as $tst_run) {
487  $tst_run->update();
488  }
489  }
490 
491 
493  {
494  if ($this->getAssignments()->isSeparateTest($session->getRefId())) {
495  $GLOBALS['ilLog']->write(__METHOD__ . ': separate run');
496  return $this->updateSeparateTestQuestions($session, $seq);
497  }
498  if ($seq instanceof ilTestSequenceFixedQuestionSet) {
499  $GLOBALS['ilLog']->write(__METHOD__ . ': fixed run');
500  return $this->updateFixedQuestions($session, $seq);
501  }
502  if ($seq instanceof ilTestSequenceRandomQuestionSet) {
503  $GLOBALS['ilLog']->write(__METHOD__ . ': random run');
504  return $this->updateRandomQuestions($session, $seq);
505  }
506  }
507 
514  {
515  foreach ($this->run as $tst_run) {
516  $tst_run->clearQuestions();
517  $points = 0;
518  foreach ($seq->getQuestionIds() as $idx => $qst_id) {
519  $tst_run->addQuestion($qst_id);
520  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
522  }
523  $tst_run->setMaxPoints($points);
524  }
525  }
526 
527 
529  {
530  foreach ($this->run as $tst_run) {
531  $tst_run->clearQuestions();
532  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
534  ilObject::_lookupObjId($session->getRefId()),
535  $tst_run->getObjectiveId()
536  );
537  $points = 0;
538  foreach ($qst as $id) {
539  $tst_run->addQuestion($id);
541  }
542  $tst_run->setMaxPoints($points);
543  }
544  }
545 
552  {
553  include_once './Modules/Course/classes/Objectives/class.ilLORandomTestQuestionPools.php';
554  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
555 
556  foreach ($this->run as $tst_run) {
557  // Clear questions of previous run
558  $tst_run->clearQuestions();
559 
561  $this->container_id,
562  $tst_run->getObjectiveId(),
563  ilObject::_lookupObjId($session->getRefId()),
564  (
565  ($this->getSettings()->getQualifiedTest() == $session->getRefId()) ?
568  )
569  );
570 
571  $points = 0;
572  foreach ($seq->getQuestionIds() as $qst) {
573  if (in_array($seq->getResponsibleSourcePoolDefinitionId($qst), $sequences)) {
574  $tst_run->addQuestion($qst);
576  }
577  }
578  $tst_run->setMaxPoints($points);
579  }
580  }
581 
582  protected function isInRun($a_qid)
583  {
584  foreach ($this->run as $run) {
585  if ($run->questionExists($a_qid)) {
586  return true;
587  }
588  }
589  return false;
590  }
591 
592 
593  private static function getQuestionData($testObjId, $questionIds)
594  {
595  global $ilDB, $lng, $ilPluginAdmin;
596 
597  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionList.php';
598  $questionList = new ilAssQuestionList($ilDB, $lng, $ilPluginAdmin);
599  $questionList->setParentObjId($testObjId);
600 
601  $questionList->setQuestionInstanceTypeFilter(ilAssQuestionList::QUESTION_INSTANCE_TYPE_DUPLICATES);
602  $questionList->setQuestionIdsFilter($questionIds);
603 
604  $questionList->load();
605 
606  return $questionList->getQuestionDataArray();
607  }
608 
609  public static function getInstance(ilTestSession $a_test_session)
610  {
611  $adapter = new self(
612  $a_test_session->getUserId(),
613  $a_test_session->getObjectiveOrientedContainerId()
614  );
615 
616  $adapter->setTestRefId($a_test_session->getRefId());
617  $adapter->initTestRun($a_test_session);
618 
619  return $adapter;
620  }
621 }
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)
update random questions
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.
$session
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
if(!array_key_exists('StateId', $_REQUEST)) $id
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)
foreach($_POST as $key=> $value) $res
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.
__construct($a_user_id, $a_course_id)
static lookupSequencesByType($a_container_id, $a_objective_id, $a_test_id, $a_test_type)
Lookup sequence ids type $ilDB.
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 ids by sequence_id type $ilDB.
setQuestionOptional($questionId)
buildQuestionRelatedObjectiveListByTest(ilTestQuestionSequence $a_test_sequence, ilTestQuestionRelatedObjectivesList $a_objectives_list)
$results
Definition: svg-scanner.php:47
global $lng
Definition: privfeed.php:17
static deleteRun($a_container_id, $a_user_id, $a_test_id)
global $ilDB
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 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.