ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilObjTestAccess.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 include_once "./Services/Object/classes/class.ilObjectAccess.php";
5 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
6 
20 {
36  function _checkAccess($a_cmd, $a_permission, $a_ref_id, $a_obj_id, $a_user_id = "")
37  {
38  global $ilUser, $lng, $rbacsystem, $ilAccess;
39 
40  if ($a_user_id == "")
41  {
42  $a_user_id = $ilUser->getId();
43  }
44 
45  $is_admin = $rbacsystem->checkAccessOfUser($a_user_id,'write',$a_ref_id);
46 
47  // check "global" online switch
48  if(!self::_isOnline($a_obj_id) && !$is_admin)
49  {
50  $ilAccess->addInfoItem(IL_NO_OBJECT_ACCESS, $lng->txt("offline"));
51  return false;
52  }
53 
54  switch ($a_permission)
55  {
56  case "visible":
57  case "read":
59  !$is_admin)
60  {
61  $ilAccess->addInfoItem(IL_NO_OBJECT_ACCESS, $lng->txt("tst_warning_test_not_complete"));
62  return false;
63  }
64  break;
65  }
66 
67  switch ($a_cmd)
68  {
69  case "eval_a":
70  case "eval_stat":
72  {
73  $ilAccess->addInfoItem(IL_NO_OBJECT_ACCESS, $lng->txt("tst_warning_test_not_complete"));
74  return false;
75  }
76  break;
77 
78  }
79 
80  return true;
81  }
82 
91  function _getMaxPointsForTestPass($random, $user_id, $test_id, $pass)
92  {
93  global $ilDB;
94  $max = 0;
95  if ($random)
96  {
97  $result = $ilDB->queryF("SELECT SUM(qpl_questions.points) maxpoints FROM tst_test_rnd_qst, qpl_questions, tst_active WHERE tst_active.active_id = tst_test_rnd_qst.active_fi AND tst_test_rnd_qst.question_fi = qpl_questions.question_id AND tst_active.test_fi = %s AND tst_test_rnd_qst.pass = %s AND tst_active.user_fi = %s",
98  array('integer','integer','integer'),
99  array($test_id, $pass, $user_id)
100  );
101  if ($result->numRows())
102  {
103  $row = $ilDB->fetchAssoc($result);
104  $max = $row["maxpoints"];
105  }
106  }
107  else
108  {
109  $result = $ilDB->queryF("SELECT SUM(qpl_questions.points) maxpoints FROM tst_test_question, qpl_questions WHERE tst_test_question.question_fi = qpl_questions.question_id AND tst_test_question.test_fi = %s",
110  array('integer'),
111  array($test_id)
112  );
113  if ($result->numRows())
114  {
115  $row = $ilDB->fetchAssoc($result);
116  $max = $row["maxpoints"];
117  }
118  }
119  return $max;
120  }
121 
129  public static function _isPassed($user_id, $a_obj_id)
130  {
131  global $ilDB;
132 
133  $result = $ilDB->queryF("SELECT tst_result_cache.* FROM tst_result_cache, tst_active, tst_tests WHERE tst_active.test_fi = tst_tests.test_id AND tst_active.user_fi = %s AND tst_tests.obj_fi = %s AND tst_result_cache.active_fi = tst_active.active_id",
134  array('integer','integer'),
135  array($user_id, $a_obj_id)
136  );
137  if (!$result->numRows())
138  {
139  $result = $ilDB->queryF("SELECT tst_active.active_id FROM tst_active, tst_tests WHERE tst_active.test_fi = tst_tests.test_id AND tst_active.user_fi = %s AND tst_tests.obj_fi = %s",
140  array('integer','integer'),
141  array($user_id, $a_obj_id)
142  );
143  $row = $ilDB->fetchAssoc($result);
144  if ($row['active_id'] > 0)
145  {
146  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
148  }
149  else
150  {
151  return false;
152  }
153  }
154  $result = $ilDB->queryF("SELECT tst_result_cache.* FROM tst_result_cache, tst_active, tst_tests WHERE tst_active.test_fi = tst_tests.test_id AND tst_active.user_fi = %s AND tst_tests.obj_fi = %s AND tst_result_cache.active_fi = tst_active.active_id",
155  array('integer','integer'),
156  array($user_id, $a_obj_id)
157  );
158  if (!$result->numRows())
159  {
160  $result = $ilDB->queryF("SELECT tst_pass_result.*, tst_tests.pass_scoring, tst_tests.random_test, tst_tests.test_id FROM tst_pass_result, tst_active, tst_tests WHERE tst_active.test_fi = tst_tests.test_id AND tst_active.user_fi = %s AND tst_tests.obj_fi = %s AND tst_pass_result.active_fi = tst_active.active_id ORDER BY tst_pass_result.pass",
161  array('integer','integer'),
162  array($user_id, $a_obj_id)
163  );
164  $points = array();
165  while ($row = $ilDB->fetchAssoc($result))
166  {
167  array_push($points, $row);
168  }
169  $reached = 0;
170  $max = 0;
171  if ($points[0]["pass_scoring"] == 0)
172  {
173  $reached = $points[count($points)-1]["points"];
174  $max = $points[count($points)-1]["maxpoints"];
175  if (!$max)
176  {
177  $active_id = $points[count($points)-1]["active_fi"];
178  $pass = $points[count($points)-1]["pass"];
179  if (strlen($active_id) && strlen($pass))
180  {
181  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
182  $res = assQuestion::_updateTestPassResults($active_id, $pass);
183  $max = $res['maxpoints'];
184  $reached = $res['points'];
185  }
186  }
187  }
188  else
189  {
190  foreach ($points as $row)
191  {
192  if ($row["points"] > $reached)
193  {
194  $reached = $row["points"];
195  $max = $row["maxpoints"];
196  if (!$max)
197  {
198  $active_id = $row["active_fi"];
199  $pass = $row["pass"];
200  if (strlen($active_id) && strlen($pass))
201  {
202  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
203  $res = assQuestion::_updateTestPassResults($active_id, $pass);
204  $max = $res['maxpoints'];
205  $reached = $res['points'];
206  }
207  }
208  }
209  }
210  }
211  include_once "./Modules/Test/classes/class.assMarkSchema.php";
212  $percentage = (!$max) ? 0 : ($reached / $max) * 100.0;
213  $mark = ASS_MarkSchema::_getMatchingMarkFromObjId($a_obj_id, $percentage);
214  return ($mark["passed"]) ? TRUE : FALSE;
215  }
216  else
217  {
218  $row = $ilDB->fetchAssoc($result);
219  return ($row['passed']) ? true : false;
220  }
221  }
222 
228  function _checkCondition($a_obj_id, $a_operator, $a_value, $a_usr_id = 0)
229  {
230  global $ilUser;
231 
232  $a_usr_id = $a_usr_id ? $a_usr_id : $ilUser->getId();
233 
234  switch($a_operator)
235  {
236  case 'passed':
237  return ilObjTestAccess::_isPassed($a_usr_id, $a_obj_id);
238  break;
239 
240  case 'finished':
241  return ilObjTestAccess::hasFinished($a_usr_id,$a_obj_id);
242 
243  case 'not_finished':
244  return !ilObjTestAccess::hasFinished($a_usr_id,$a_obj_id);
245 
246  default:
247  return true;
248  }
249  return true;
250  }
251 
264  function _getCommands()
265  {
266  $commands = array
267  (
268  array("permission" => "write", "cmd" => "questionsTabGateway", "lang_var" => "tst_edit_questions"),
269  array("permission" => "write", "cmd" => "ilObjTestSettingsGeneralGUI::showForm", "lang_var" => "settings"),
270  array("permission" => "read", "cmd" => "infoScreen", "lang_var" => "tst_run",
271  "default" => true),
272  //array("permission" => "write", "cmd" => "", "lang_var" => "edit"),
273  array("permission" => "tst_statistics", "cmd" => "outEvaluation", "lang_var" => "tst_statistical_evaluation"),
274  );
275 
276  return $commands;
277  }
278 
279  //
280  // object specific access related methods
281  //
282 
286  function _lookupCreationComplete($a_obj_id)
287  {
288  global $ilDB;
289 
290  $result = $ilDB->queryF("SELECT complete FROM tst_tests WHERE obj_fi=%s",
291  array('integer'),
292  array($a_obj_id)
293  );
294  if ($result->numRows() == 1)
295  {
296  $row = $ilDB->fetchAssoc($result);
297  }
298 
299  return ($row['complete']) ? true : false;
300  }
301 
307  private static $hasFinishedCache = array();
308 
316  public static function hasFinished($a_user_id, $a_obj_id)
317  {
318  if( !isset(self::$hasFinishedCache["{$a_user_id}:{$a_obj_id}"]) )
319  {
320  require_once 'Modules/Test/classes/class.ilTestParticipantData.php';
321  require_once 'Modules/Test/classes/class.ilTestSessionFactory.php';
322  require_once 'Modules/Test/classes/class.ilTestPassesSelector.php';
323 
324  global $ilDB, $lng;
325 
326  $testOBJ = ilObjectFactory::getInstanceByObjId($a_obj_id);
327 
328  $partData = new ilTestParticipantData($ilDB, $lng);
329  $partData->setUserIds(array($a_user_id));
330  $partData->load($testOBJ->getTestId());
331 
332  $activeId = $partData->getActiveIdByUserId($a_user_id);
333 
334  $testSessionFactory = new ilTestSessionFactory($testOBJ);
335  $testSession = $testSessionFactory->getSession($activeId);
336 
337  $testPassesSelector = new ilTestPassesSelector($ilDB, $testOBJ);
338  $testPassesSelector->setActiveId($activeId);
339  $testPassesSelector->setLastFinishedPass($testSession->getLastFinishedPass());
340 
341  self::$hasFinishedCache["{$a_user_id}:{$a_obj_id}"] = count($testPassesSelector->getClosedPasses());
342  }
343 
344  return self::$hasFinishedCache["{$a_user_id}:{$a_obj_id}"];
345  }
346 
354  function _getTestIDFromObjectID($object_id)
355  {
356  global $ilDB;
357  $test_id = FALSE;
358  $result = $ilDB->queryF("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
359  array('integer'),
360  array($object_id)
361  );
362  if ($result->numRows())
363  {
364  $row = $ilDB->fetchAssoc($result);
365  $test_id = $row["test_id"];
366  }
367  return $test_id;
368  }
369 
370  function &_getTestQuestions($active_id, $pass = NULL)
371  {
372  if (is_null($pass))
373  {
374  $pass = 0;
375  }
376  $questions = array();
377 
378  global $ilDB;
379  $result = $ilDB->queryF("SELECT test_fi FROM tst_active WHERE active_id = %s",
380  array('integer'),
381  array($active_id)
382  );
383  $test_id = "";
384  if ($result->numRows())
385  {
386  $row = $ilDB->fetchAssoc($result);
387  $test_id = $row["test_fi"];
388  }
389  else
390  {
391  return $questions;
392  }
393  $result = $ilDB->queryF("SELECT qpl_questions.question_id, qpl_questions.points FROM qpl_questions, tst_test_question WHERE tst_test_question.question_fi = qpl_questions.question_id AND tst_test_question.test_fi = %s ORDER BY tst_test_question.sequence",
394  array('integer'),
395  array($test_id)
396  );
397  if ($result->numRows())
398  {
399  // standard test
400  while ($row = $ilDB->fetchAssoc($result))
401  {
402  array_push($questions, $row);
403  }
404  }
405  else
406  {
407  // random test
408  $result = $ilDB->queryF("SELECT qpl_questions.question_id, qpl_questions.points FROM qpl_questions, tst_test_rnd_qst WHERE tst_test_rnd_qst.question_fi = qpl_questions.question_id AND tst_test_rnd_qst.active_fi = %s AND tst_test_rnd_qst.pass = %s ORDER BY tst_test_rnd_qst.sequence",
409  array('integer','integer'),
410  array($active_id, $pass)
411  );
412  if ($result->numRows())
413  {
414  while ($row = $ilDB->fetchAssoc($result))
415  {
416  array_push($questions, $row);
417  }
418  }
419  }
420  return $questions;
421  }
422 
429  function _isComplete($a_obj_id)
430  {
431  global $ilDB;
432 
433  $query = "
434  SELECT tst_tests.complete
435  FROM object_data
436  INNER JOIN tst_tests
437  ON tst_tests.obj_fi = object_data.obj_id
438  WHERE object_data.obj_id = %s
439  ";
440 
441  $res = $ilDB->queryF($query, array('integer'), array($a_obj_id));
442 
443  while( $row = $ilDB->fetchAssoc($res) )
444  {
445  return (bool)$row['complete'];
446  }
447 
448  return false;
449  }
450 
458  function &_getTestData($test_id)
459  {
460  global $ilDB;
461  $result = $ilDB->queryF("SELECT * FROM tst_tests WHERE test_id = %s",
462  array('integer'),
463  array($test_id)
464  );
465  if (!$result->numRows())
466  {
467  return 0;
468  }
469  return $ilDB->fetchAssoc($result);
470  }
471 
478  function _lookupObjIdForTestId($a_test_id)
479  {
480  global $ilDB;
481 
482  $result = $ilDB->queryF("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
483  array('integer'),
484  array($a_test_id)
485  );
486 
487  $row = $ilDB->fetchAssoc($result);
488  return $row["obj_fi"];
489  }
490 
499  {
500  global $ilDB;
501 
502  $query = "
503  SELECT DISTINCT t.obj_fi
504  FROM tst_tests t
505  INNER JOIN tst_rnd_quest_set_qpls r
506  ON t.test_id = r.test_fi
507  WHERE r.pool_fi = %s
508  ";
509 
510  $result = $ilDB->queryF($query, array('integer'), array($qpl_id));
511 
512  $tests = array();
513  while ($row = $ilDB->fetchAssoc($result))
514  {
515  $tests[] = $row['obj_fi'];
516  }
517 
518  return $tests;
519  }
520  // fim.
521 
528  function _lookupOnlineTestAccess($a_test_id, $a_user_id)
529  {
530  global $ilDB, $lng;
531 
532  $result = $ilDB->queryF("SELECT tst_tests.* FROM tst_tests WHERE tst_tests.obj_fi = %s",
533  array('integer'),
534  array($a_test_id)
535  );
536  if ($result->numRows())
537  {
538  $row = $ilDB->fetchAssoc($result);
539  if ($row["fixed_participants"])
540  {
541  $result = $ilDB->queryF("SELECT * FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
542  array('integer','integer'),
543  array($row["test_id"], $a_user_id)
544  );
545  if ($result->numRows())
546  {
547  $row = $ilDB->fetchAssoc($result);
548  if (trim($row['clientip']) != "")
549  {
550  $row['clientip'] = preg_replace("/[^0-9.?*,:]+/","",$row['clientip']);
551  $row['clientip'] = str_replace(".","\\.",$row['clientip']);
552  $row['clientip'] = str_replace(Array("?","*",","), Array("[0-9]","[0-9]*","|"), $row['clientip']);
553  if (!preg_match("/^".$row['clientip']."$/", $_SERVER["REMOTE_ADDR"]))
554  {
555  return $lng->txt("tst_user_wrong_clientip");
556  }
557  else
558  {
559  return true;
560  }
561  }
562  else
563  {
564  return true;
565  }
566  }
567  else
568  {
569  return $lng->txt("tst_user_not_invited");
570  }
571  }
572  else
573  {
574  return true;
575  }
576  }
577  else
578  {
579  return true;
580  }
581  }
582 
590  function _getParticipantData($active_id)
591  {
592  global $lng, $ilDB;
593 
594  $result = $ilDB->queryF("SELECT * FROM tst_active WHERE active_id = %s",
595  array("integer"),
596  array($active_id)
597  );
598  $row = $ilDB->fetchAssoc($result);
599  $user_id = $row["user_fi"];
600  $test_id = $row["test_fi"];
601  $importname = $row['importname'];
602 
603  $result = $ilDB->queryF("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
604  array("integer"),
605  array($test_id)
606  );
607  $row = $ilDB->fetchAssoc($result);
608  $obj_id = $row["obj_fi"];
609 
610  include_once "./Modules/Test/classes/class.ilObjTest.php";
611  $is_anonymous = ilObjTest::_lookupAnonymity($obj_id);
612 
613  include_once './Services/User/classes/class.ilObjUser.php';
614  $uname = ilObjUser::_lookupName($user_id);
615 
616  $name = "";
617  if (strlen($importname))
618  {
619  $name = $importname . ' (' . $lng->txt('imported') . ')';
620  }
621  else if (strlen($uname["firstname"].$uname["lastname"]) == 0)
622  {
623  $name = $lng->txt("deleted_user");
624  }
625  else
626  {
627  if ($user_id == ANONYMOUS_USER_ID)
628  {
629  $name = $lastname;
630  }
631  else
632  {
633  $name = trim($uname["lastname"] . ", " . $uname["firstname"] . " " . $uname["title"]);
634  }
635  if ($is_anonymous)
636  {
637  $name = $lng->txt("anonymous");
638  }
639  }
640  return $name;
641  }
642 
649  function _getParticipantId($active_id)
650  {
651  global $lng, $ilDB;
652 
653  $result = $ilDB->queryF("SELECT user_fi FROM tst_active WHERE active_id = %s",
654  array("integer"),
655  array($active_id)
656  );
657  $row = $ilDB->fetchAssoc($result);
658  return $row["user_fi"];
659  }
660 
661 
676  function &_getPassedUsers($a_obj_id)
677  {
678  global $ilDB;
679 
680  $passed_users = array();
681  // Maybe SELECT DISTINCT(tst_active.user_fi)... ?
682  $userresult = $ilDB->queryF("
683  SELECT tst_active.active_id, COUNT(tst_sequence.active_fi) sequences
684  FROM tst_tests
685  INNER JOIN tst_active
686  ON tst_active.test_fi = tst_tests.test_id
687  LEFT JOIN tst_sequence
688  ON tst_sequence.active_fi = tst_active.active_id
689  WHERE tst_tests.obj_fi = %s
690  GROUP BY tst_active.active_id
691  ",
692  array('integer'), array($a_obj_id)
693  );
694  $all_participants = array();
695  $notAttempted = array();
696  while ($row = $ilDB->fetchAssoc($userresult))
697  {
698  if($row['sequences'] == 0)
699  {
700  $notAttempted[$row['active_id']] = $row['active_id'];
701  }
702 
703  $all_participants[$row['active_id']] = $row['active_id'];
704  }
705 
706  $result = $ilDB->query("SELECT tst_result_cache.*, tst_active.user_fi FROM tst_result_cache, tst_active WHERE tst_active.active_id = tst_result_cache.active_fi AND " . $ilDB->in('active_fi', $all_participants, false, 'integer'));
707  $found_all = ($result->numRows() == count($all_participants)) ? true : false;
708  if (!$found_all)
709  {
710  // if the result cache entries do not exist, create them
711  $found_participants = array();
712  while ($data = $ilDB->fetchAssoc($result))
713  {
714  array_push($found_participants, $data['active_fi']);
715  }
716  foreach ($all_participants as $active_id)
717  {
718  if (!in_array($active_id, $found_participants))
719  {
720  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
722  }
723  }
724  $result = $ilDB->query("SELECT tst_result_cache.*, tst_active.user_fi FROM tst_result_cache, tst_active WHERE tst_active.active_id = tst_result_cache.active_fi AND " . $ilDB->in('active_fi', $all_participants, false, 'integer'));
725  }
726  while ($data = $ilDB->fetchAssoc($result))
727  {
728  if( isset($notAttempted[$data['active_fi']]) )
729  {
730  $data['failed'] = 0;
731  $data['passed'] = 0;
732  }
733 
734  $data['user_id'] = $data['user_fi'];
735  array_push($passed_users, $data);
736  }
737  return $passed_users;
738  }
739 
743  function _checkGoto($a_target)
744  {
745  global $ilAccess;
746 
747  $t_arr = explode("_", $a_target);
748 
749  if ($t_arr[0] != "tst" || ((int) $t_arr[1]) <= 0)
750  {
751  return false;
752  }
753 
754  if ($ilAccess->checkAccess("read", "", $t_arr[1]))
755  {
756  return true;
757  }
758  return false;
759  }
760 
769  static function _isOffline($a_obj_id)
770  {
771 // global $ilUser;
772 // return (self::_lookupOnlineTestAccess($a_obj_id, $ilUser->getId()) !== true) ||
773 // (!ilObjTestAccess::_lookupCreationComplete($a_obj_id));
774  return !self::_isOnline($a_obj_id);
775  }
776 
783  public static function _isOnline($a_obj_id)
784  {
785  global $ilDB;
786 
787  $query = "
788  SELECT test_id
789  FROM tst_tests
790  WHERE obj_fi = %s
791  AND online_status = 1
792  ";
793 
794  $result = $ilDB->queryF( $query, array('integer'), array($a_obj_id) );
795 
796  return $result->numRows() == 1;
797  }
798 }
799 
800 ?>