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