ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilCourseObjectiveResult.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
5 define('IL_OBJECTIVE_STATUS_EMPTY', 'empty');
6 define('IL_OBJECTIVE_STATUS_PRETEST', 'pretest');
7 define('IL_OBJECTIVE_STATUS_FINAL', 'final');
8 define('IL_OBJECTIVE_STATUS_NONE', 'none');
9 define('IL_OBJECTIVE_STATUS_FINISHED', 'finished');
10 define('IL_OBJECTIVE_STATUS_PRETEST_NON_SUGGEST', 'pretest_non_suggest');
11 
20 {
21  public $db = null;
22  public $user_id = null;
23 
24 
29  public function __construct($a_usr_id)
30  {
31  global $DIC;
32 
33  $ilDB = $DIC['ilDB'];
34 
35  $this->db = $ilDB;
36 
37  $this->user_id = $a_usr_id;
38  }
39  public function getUserId()
40  {
41  return $this->user_id;
42  }
43 
44  public function getAccomplished($a_crs_id)
45  {
46  return ilCourseObjectiveResult::_getAccomplished($this->getUserId(), $a_crs_id);
47  }
48  public static function _getAccomplished($a_user_id, $a_crs_id)
49  {
50  global $DIC;
51 
52  $ilDB = $DIC['ilDB'];
53 
54  include_once 'Modules/Course/classes/class.ilCourseObjective.php';
55  // begin-patch lok
56  $objectives = ilCourseObjective::_getObjectiveIds($a_crs_id, true);
57  // end-patch lok
58 
59  if (!is_array($objectives)) {
60  return array();
61  }
62  $query = "SELECT objective_id FROM crs_objective_status " .
63  "WHERE " . $ilDB->in('objective_id', $objectives, false, 'integer') . ' ' .
64  "AND user_id = " . $ilDB->quote($a_user_id, 'integer') . " ";
65  $res = $ilDB->query($query);
66  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
67  $accomplished[] = $row->objective_id;
68  }
69  return $accomplished ? $accomplished : array();
70  }
71 
72  public function getSuggested($a_crs_id, $a_status = IL_OBJECTIVE_STATUS_FINAL)
73  {
74  return ilCourseObjectiveResult::_getSuggested($this->getUserId(), $a_crs_id, $a_status);
75  }
76 
77  public static function _getSuggested($a_user_id, $a_crs_id, $a_status = IL_OBJECTIVE_STATUS_FINAL)
78  {
79  global $DIC;
80 
81  $ilDB = $DIC['ilDB'];
82 
83  include_once './Modules/Course/classes/class.ilCourseObjective.php';
84  // begin-patch lok
85  $objectives = ilCourseObjective::_getObjectiveIds($a_crs_id, true);
86  // end-patch lok
87 
88  $finished = array();
89  if ($a_status == IL_OBJECTIVE_STATUS_FINAL or
90  $a_status == IL_OBJECTIVE_STATUS_FINISHED) {
91  // check finished
92  $query = "SELECT objective_id FROM crs_objective_status " .
93  "WHERE " . $ilDB->in('objective_id', $objectives, false, 'integer') . " " .
94  "AND user_id = " . $ilDB->quote($a_user_id, 'integer') . " ";
95  $res = $ilDB->query($query);
96  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
97  $finished[] = $row->objective_id;
98  }
99  } else {
100  // Pretest
101  $query = "SELECT objective_id FROM crs_objective_status_p " .
102  "WHERE " . $ilDB->in('objective_id', $objectives, false, 'integer') . ' ' .
103  "AND user_id = " . $ilDB->quote($a_user_id, 'integer');
104  $res = $ilDB->query($query);
105  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
106  $finished[] = $row->objective_id;
107  }
108  }
109  foreach ($objectives as $objective_id) {
110  if (!in_array($objective_id, $finished)) {
111  $suggested[] = $objective_id;
112  }
113  }
114  return $suggested ? $suggested : array();
115  }
116 
123  public static function getSuggestedQuestions($a_usr_id, $a_crs_id)
124  {
125  foreach (self::_getSuggested($a_usr_id, $a_crs_id) as $objective_id) {
126  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
127  $obj = new ilCourseObjectiveQuestion($objective_id);
128  foreach ($obj->getFinalTestQuestions() as $qst) {
129  $qsts[] = $qst['question_id'];
130  }
131  }
132  return $qsts ? $qsts : array();
133  }
134 
135  protected function resetTestForUser(ilObjTest $a_test, $a_user_id)
136  {
137  // this is done in ilTestLP (see below)
138  // $a_test->removeTestResultsForUser($a_user_id);
139 
140  // #15038
141  include_once "Modules/Test/classes/class.ilTestLP.php";
142  $test_lp = ilTestLP::getInstance($a_test->getId());
143  $test_lp->resetLPDataForUserIds(array($a_user_id));
144 
145  // #15205 - see ilObjTestGUI::confirmDeleteSelectedUserDataObject()
146  $active_id = $a_test->getActiveIdOfUser($a_user_id);
147  if ($active_id) {
148  $a_test->removeTestActives(array($active_id));
149  }
150  }
151 
152  public function reset($a_course_id)
153  {
154  global $DIC;
155 
156  $ilDB = $DIC['ilDB'];
157 
158  include_once './Modules/Course/classes/class.ilCourseObjective.php';
159  include_once './Modules/Course/classes/class.ilCourseObjectiveQuestion.php';
160 
161  include_once './Services/Object/classes/class.ilObjectFactory.php';
162  $factory = new ilObjectFactory();
163 
164  include_once './Modules/Course/classes/Objectives/class.ilLOTestAssignments.php';
165  include_once './Modules/Course/classes/Objectives/class.ilLOSettings.php';
166  $assignments = ilLOTestAssignments::getInstance($a_course_id);
167  foreach (array_merge(
168  $assignments->getAssignmentsByType(ilLOSettings::TYPE_TEST_INITIAL),
169  $assignments->getAssignmentsByType(ilLOSettings::TYPE_TEST_QUALIFIED)
170  )
171  as $assignment) {
172  $tst = $factory->getInstanceByRefId($assignment->getTestRefId(), false);
173  if ($tst instanceof ilObjTest) {
174  global $DIC;
175 
176  $lng = $DIC['lng'];
177 
178  require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
179  $participantData = new ilTestParticipantData($ilDB, $lng);
180  $participantData->setUserIdsFilter(array($this->getUserId()));
181  $participantData->load($tst->getTestId());
182  $tst->removeTestResults($participantData);
183  }
184  }
185 
186  $initial = ilLOSettings::getInstanceByObjId($a_course_id)->getInitialTest();
187  $initial_tst = $factory->getInstanceByRefId($initial, false);
188  if ($initial_tst instanceof ilObjTest) {
189  $this->resetTestForUser($initial_tst, $this->getUserId());
190  }
191 
192  $qualified = ilLOSettings::getInstanceByObjId($a_course_id)->getQualifiedTest();
193  $qualified_tst = $factory->getInstanceByRefId($qualified, false);
194  if ($qualified_tst instanceof ilObjTest) {
195  $this->resetTestForUser($qualified_tst, $this->getUserId());
196  }
197 
198  $objectives = ilCourseObjective::_getObjectiveIds($a_course_id, false);
199 
200  if (count($objectives)) {
201  $query = "DELETE FROM crs_objective_status " .
202  "WHERE " . $ilDB->in('objective_id', $objectives, false, 'integer') . ' ' .
203  "AND user_id = " . $ilDB->quote($this->getUserId(), 'integer') . " ";
204  $res = $ilDB->manipulate($query);
205 
206  $query = "DELETE FROM crs_objective_status_p " .
207  "WHERE " . $ilDB->in('objective_id', $objectives, false, 'integer') . ' ' .
208  "AND user_id = " . $ilDB->quote($this->getUserId()) . "";
209  $res = $ilDB->manipulate($query);
210 
211  $query = "DELETE FROM loc_user_results " .
212  "WHERE " . $ilDB->in('objective_id', $objectives, false, 'integer') . ' ' .
213  "AND user_id = " . $ilDB->quote($this->getUserId()) . "";
214  }
215 
216  // update/reset LP for course
217  include_once './Services/Tracking/classes/class.ilLPStatusWrapper.php';
218  ilLPStatusWrapper::_updateStatus($a_course_id, $this->getUserId());
219 
220  return true;
221  }
222 
223  public function getStatus($a_course_id)
224  {
225  include_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
226  include_once 'Modules/Course/classes/class.ilCourseObjective.php';
227  // begin-patch lok
228  $objective_ids = ilCourseObjective::_getObjectiveIds($a_course_id, true);
229  // end-patch lok
230  $objectives = ilCourseObjectiveResult::_readAssignedObjectives($objective_ids);
231  $accomplished = $this->getAccomplished($a_course_id);
232  $suggested = $this->getSuggested($a_course_id);
233 
234  if (!count($objective_ids)) {
236  }
237 
238  if (count($accomplished) == count($objective_ids)) {
240  }
241 
242  $all_pretest_answered = false;
243  $all_final_answered = false;
244  foreach ($objectives as $data) {
245  if (assQuestion::_areAnswered($this->getUserId(), $data['questions'])) {
246  if ($data['tst_status']) {
247  $all_final_answered = true;
248  } else {
249  $all_pretest_answered = true;
250  }
251  }
252  }
253  if ($all_final_answered) {
255  }
256  if ($all_pretest_answered and
257  !count($suggested)) {
259  } elseif ($all_pretest_answered) {
261  }
263  }
264 
265  public function hasAccomplishedObjective($a_objective_id)
266  {
267  global $DIC;
268 
269  $ilDB = $DIC['ilDB'];
270 
271  $query = "SELECT status FROM crs_objective_status " .
272  "WHERE objective_id = " . $ilDB->quote($a_objective_id, 'integer') . " " .
273  "AND user_id = " . $ilDB->quote($this->getUserId(), 'integer') . "";
274 
275  $res = $this->db->query($query);
276  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
277  return true;
278  }
279  return false;
280  }
281 
282  public function readStatus($a_crs_id)
283  {
284  include_once './Modules/Course/classes/class.ilCourseObjective.php';
285 
286  // begin-patch lok
287  $objective_ids = ilCourseObjective::_getObjectiveIds($a_crs_id, true);
288  // end-patch lok
289  $objectives = ilCourseObjectiveResult::_readAssignedObjectives($objective_ids);
291  return true;
292  }
293 
294 
295 
296 
297  // PRIVATE
298  public function __deleteEntries($a_objective_ids)
299  {
300  global $DIC;
301 
302  $ilLog = $DIC['ilLog'];
303 
304  $ilLog->logStack();
305  #$ilLog(__METHOD__.': Call of deprecated method.');
306 
307  return true;
308  }
309 
310  public static function _deleteUser($user_id)
311  {
312  global $DIC;
313 
314  $ilDB = $DIC['ilDB'];
315 
316  $query = "DELETE FROM crs_objective_status " .
317  "WHERE user_id = " . $ilDB->quote($user_id, 'integer') . " ";
318  $res = $ilDB->manipulate($query);
319 
320  $query = "DELETE FROM crs_objective_status_p " .
321  "WHERE user_id = " . $ilDB->quote($user_id, 'integer') . " ";
322  $res = $ilDB->manipulate($query);
323  return true;
324  }
325 
326  public static function _updateObjectiveResult($a_user_id, $a_active_id, $a_question_id)
327  {
328  // find all objectives this question is assigned to
329  if (!$objectives = self::_readAssignedObjectivesOfQuestion($a_question_id)) {
330  // no objectives found. TODO user has passed a test. After that questions of that test are assigned to an objective.
331  // => User has not passed
332  return true;
333  }
334  self::_updateObjectiveStatus($a_user_id, $objectives);
335 
336  return true;
337  }
338 
339  public static function _readAssignedObjectivesOfQuestion($a_question_id)
340  {
341  global $DIC;
342 
343  $ilDB = $DIC['ilDB'];
344 
345  // get all objtives and questions this current question is assigned to
346  $query = "SELECT q2.question_id qid,q2.objective_id ob FROM crs_objective_qst q1, " .
347  "crs_objective_qst q2 " .
348  "WHERE q1.question_id = " . $ilDB->quote($a_question_id, 'integer') . " " .
349  "AND q1.objective_id = q2.objective_id ";
350 
351  $res = $ilDB->query($query);
352  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
353  $objectives['all_objectives'][$row->ob] = $row->ob;
354  $objectives['all_questions'][$row->qid] = $row->qid;
355  }
356  if (!is_array($objectives)) {
357  return false;
358  }
359  $objectives['objectives'] = self::_readAssignedObjectives($objectives['all_objectives']);
360  return $objectives ? $objectives : array();
361  }
362 
363 
364  public static function _readAssignedObjectives($a_all_objectives)
365  {
366  global $DIC;
367 
368  $ilDB = $DIC['ilDB'];
369 
370  // Read necessary points
371  $query = "SELECT t.objective_id obj,t.ref_id ref, question_id,tst_status,tst_limit " .
372  "FROM crs_objective_tst t JOIN crs_objective_qst q " .
373  "ON (t.objective_id = q.objective_id AND t.ref_id = q.ref_id) " .
374  "WHERE " . $ilDB->in('t.objective_id', $a_all_objectives, false, 'integer');
375 
376  $res = $ilDB->query($query);
377  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
378  /*
379  $objectives[$row->obj."_".$row->ref]['questions'][$row->question_id] = $row->question_id;
380  $objectives[$row->obj."_".$row->ref]['tst_status'] = $row->tst_status;
381  $objectives[$row->obj."_".$row->ref]['tst_limit'] = $row->tst_limit;
382  $objectives[$row->obj."_".$row->ref]['objective_id'] = $row->obj;
383  */
384 
385  $objectives[$row->obj . "_" . $row->tst_status]['questions'][$row->question_id] = $row->question_id;
386  $objectives[$row->obj . "_" . $row->tst_status]['tst_status'] = $row->tst_status;
387  $objectives[$row->obj . "_" . $row->tst_status]['tst_limit'] = $row->tst_limit;
388  $objectives[$row->obj . "_" . $row->tst_status]['objective_id'] = $row->obj;
389  }
390  return $objectives ? $objectives : array();
391  }
392 
393  public static function _updateObjectiveStatus($a_user_id, $objectives)
394  {
395  global $DIC;
396 
397  $ilDB = $DIC['ilDB'];
398  $ilUser = $DIC['ilUser'];
399 
400  if (!count($objectives['all_questions']) or
401  !count($objectives['all_objectives'])) {
402  return false;
403  }
404  // Read reachable points
405  $query = "SELECT question_id,points FROM qpl_questions " .
406  "WHERE " . $ilDB->in('question_id', (array) $objectives['all_questions'], false, 'integer');
407  $res = $ilDB->query($query);
408  while ($row = $ilDB->fetchAssoc($res)) {
409  $objectives['all_question_points'][$row['question_id']]['max_points'] = $row['points'];
410  }
411  // Read reached points
412  $query = "SELECT question_fi, MAX(points) as reached FROM tst_test_result " .
413  "JOIN tst_active ON (active_id = active_fi) " .
414  "WHERE user_fi = " . $ilDB->quote($a_user_id, 'integer') . " " .
415  "AND " . $ilDB->in('question_fi', (array) $objectives['all_questions'], false, 'integer') . " " .
416  #"AND question_fi IN (".implode(",",ilUtil::quoteArray($objectives['all_questions'])).") ".
417  "GROUP BY question_fi,user_fi";
418  $res = $ilDB->query($query);
419  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
420  $objectives['all_question_points'][$row->question_fi]['reached_points'] = $row->reached;
421  }
422 
423  // Check accomplished
424  $fullfilled = array();
425  $pretest = array();
426  foreach ($objectives['objectives'] as $kind => $data) {
427  // objective does not allow to change status
428  if (ilCourseObjectiveResult::__isFullfilled($objectives['all_question_points'], $data)) {
429  // Status 0 means pretest fullfilled, status 1 means final test fullfilled
430  if ($data['tst_status']) {
431  $fullfilled[] = array($data['objective_id'],$ilUser->getId(),$data['tst_status']);
432  } else {
433  $pretest[] = array($data['objective_id'],$ilUser->getId());
434  }
435  }
436  }
437  if (count($fullfilled)) {
438  foreach ($fullfilled as $fullfilled_arr) {
439  $ilDB->replace(
440  'crs_objective_status',
441  array(
442  'objective_id' => array('integer',$fullfilled_arr[0]),
443  'user_id' => array('integer',$fullfilled_arr[1])
444  ),
445  array(
446  'status' => array('integer',$fullfilled_arr[2])
447  )
448  );
449  }
450  ilCourseObjectiveResult::__updatePassed($a_user_id, $objectives['all_objectives']);
451  }
452  if (count($pretest)) {
453  foreach ($pretest as $pretest_arr) {
454  $ilDB->replace(
455  'crs_objective_status_p',
456  array(
457  'objective_id' => array('integer',$pretest_arr[0]),
458  'user_id' => array('integer',$pretest_arr[1])
459  ),
460  array()
461  );
462  }
463  }
464  return true;
465  }
466 
467  public static function __isFullfilled($question_points, $objective_data)
468  {
469  if (!is_array($objective_data['questions'])) {
470  return false;
471  }
472  $max_points = 0;
473  $reached_points = 0;
474  foreach ($objective_data['questions'] as $question_id) {
475  $max_points += $question_points[$question_id]['max_points'];
476  $reached_points += $question_points[$question_id]['reached_points'];
477  }
478  if (!$max_points) {
479  return false;
480  }
481 
482  return $reached_points >= $objective_data['tst_limit'] ? true : false;
483 
484  return (($reached_points / $max_points * 100) >= $objective_data['tst_limit']) ? true : false;
485  }
486 
494  public static function __updatePassed($a_user_id, $objective_ids)
495  {
496  global $DIC;
497 
498  $ilDB = $DIC['ilDB'];
499 
500  $passed = array();
501 
502  $query = "SELECT COUNT(t1.crs_id) num,t1.crs_id FROM crs_objectives t1 " .
503  "JOIN crs_objectives t2 WHERE t1.crs_id = t2.crs_id and " .
504  $ilDB->in('t1.objective_id', $objective_ids, false, 'integer') . " " .
505  "GROUP BY t1.crs_id";
506  $res = $ilDB->query($query);
507  $crs_ids = array();
508  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
509  $query = "SELECT COUNT(cs.objective_id) num_passed FROM crs_objective_status cs " .
510  "JOIN crs_objectives co ON cs.objective_id = co.objective_id " .
511  "WHERE crs_id = " . $ilDB->quote($row->crs_id, 'integer') . " " .
512  "AND user_id = " . $ilDB->quote($a_user_id, 'integer') . " ";
513 
514  $user_res = $ilDB->query($query);
515  while ($user_row = $user_res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
516  if ($user_row->num_passed == $row->num) {
517  $passed[] = $row->crs_id;
518  }
519  }
520  $crs_ids[$row->crs_id] = $row->crs_id;
521  }
522  if (count($passed)) {
523  foreach ($passed as $crs_id) {
524  include_once('Modules/Course/classes/class.ilCourseParticipants.php');
525  $members = ilCourseParticipants::_getInstanceByObjId($crs_id);
526  $members->updatePassed($a_user_id, true);
527  }
528  }
529 
530  // update tracking status
531  foreach ($crs_ids as $cid) {
532  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
533  ilLPStatusWrapper::_updateStatus($cid, $a_user_id);
534  }
535  }
536 }
static _readAssignedObjectivesOfQuestion($a_question_id)
static getInstanceByObjId($a_obj_id)
get singleton instance
static getInstance($a_container_id)
Get instance by container id.
static getSuggestedQuestions($a_usr_id, $a_crs_id)
get suggested questions ids
Class ilObjectFactory.
const IL_OBJECTIVE_STATUS_EMPTY
global $DIC
Definition: saml.php:7
const IL_OBJECTIVE_STATUS_FINISHED
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
static _areAnswered($a_user_id, $a_question_ids)
Checks if an array of question ids is answered by an user or not.
static _getInstanceByObjId($a_obj_id)
Get singleton instance.
$factory
Definition: metadata.php:43
static _getObjectiveIds($course_id, $a_activated_only=false)
getSuggested($a_crs_id, $a_status=IL_OBJECTIVE_STATUS_FINAL)
resetTestForUser(ilObjTest $a_test, $a_user_id)
const IL_OBJECTIVE_STATUS_PRETEST_NON_SUGGEST
static _getSuggested($a_user_id, $a_crs_id, $a_status=IL_OBJECTIVE_STATUS_FINAL)
getActiveIdOfUser($user_id="", $anonymous_id="")
Gets the active id of a given user.
foreach($_POST as $key=> $value) $res
getId()
get object id public
$lng
removeTestActives($activeIds)
const IL_OBJECTIVE_STATUS_NONE
$ilUser
Definition: imgupload.php:18
$query
static _updateObjectiveResult($a_user_id, $a_active_id, $a_question_id)
static _getAccomplished($a_user_id, $a_crs_id)
const IL_OBJECTIVE_STATUS_FINAL
$row
static quoteArray($a_array)
Quotes all members of an array for usage in DB query statement.
const IL_OBJECTIVE_STATUS_PRETEST
static _readAssignedObjectives($a_all_objectives)
global $ilDB
static __updatePassed($a_user_id, $objective_ids)
can be protected?
static _updateObjectiveStatus($a_user_id, $objectives)
static getInstance($a_obj_id)
class ilcourseobjectiveQuestion
static __isFullfilled($question_points, $objective_data)
$data
Definition: bench.php:6