ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilObjTestAccess.php
Go to the documentation of this file.
1 <?php
2 /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2006 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +-----------------------------------------------------------------------------+
22 */
23 
24 include_once "./Services/Object/classes/class.ilObjectAccess.php";
25 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
26 
40 {
56  function _checkAccess($a_cmd, $a_permission, $a_ref_id, $a_obj_id, $a_user_id = "")
57  {
58  global $ilUser, $lng, $rbacsystem, $ilAccess;
59 
60  if ($a_user_id == "")
61  {
62  $a_user_id = $ilUser->getId();
63  }
64 
65  $is_admin = $rbacsystem->checkAccessOfUser($a_user_id,'write',$a_ref_id);
66 
67  // check "global" online switch
68  if(!self::_isOnline($a_obj_id) && !$is_admin)
69  {
70  $ilAccess->addInfoItem(IL_NO_OBJECT_ACCESS, $lng->txt("offline"));
71  return false;
72  }
73 
74  switch ($a_permission)
75  {
76  case "visible":
77  case "read":
79  !$is_admin)
80  {
81  $ilAccess->addInfoItem(IL_NO_OBJECT_ACCESS, $lng->txt("tst_warning_test_not_complete"));
82  return false;
83  }
84  break;
85  }
86 
87  switch ($a_cmd)
88  {
89  case "eval_a":
90  case "eval_stat":
92  {
93  $ilAccess->addInfoItem(IL_NO_OBJECT_ACCESS, $lng->txt("tst_warning_test_not_complete"));
94  return false;
95  }
96  break;
97 
98  }
99 
100  return true;
101  }
102 
111  function _getMaxPointsForTestPass($random, $user_id, $test_id, $pass)
112  {
113  global $ilDB;
114  $max = 0;
115  if ($random)
116  {
117  $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",
118  array('integer','integer','integer'),
119  array($test_id, $pass, $user_id)
120  );
121  if ($result->numRows())
122  {
123  $row = $ilDB->fetchAssoc($result);
124  $max = $row["maxpoints"];
125  }
126  }
127  else
128  {
129  $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",
130  array('integer'),
131  array($test_id)
132  );
133  if ($result->numRows())
134  {
135  $row = $ilDB->fetchAssoc($result);
136  $max = $row["maxpoints"];
137  }
138  }
139  return $max;
140  }
141 
149  public static function _isPassed($user_id, $a_obj_id)
150  {
151  global $ilDB;
152 
153  $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",
154  array('integer','integer'),
155  array($user_id, $a_obj_id)
156  );
157  if (!$result->numRows())
158  {
159  $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",
160  array('integer','integer'),
161  array($user_id, $a_obj_id)
162  );
163  $row = $ilDB->fetchAssoc($result);
164  if ($row['active_id'] > 0)
165  {
166  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
168  }
169  else
170  {
171  return false;
172  }
173  }
174  $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",
175  array('integer','integer'),
176  array($user_id, $a_obj_id)
177  );
178  if (!$result->numRows())
179  {
180  $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",
181  array('integer','integer'),
182  array($user_id, $a_obj_id)
183  );
184  $points = array();
185  while ($row = $ilDB->fetchAssoc($result))
186  {
187  array_push($points, $row);
188  }
189  $reached = 0;
190  $max = 0;
191  if ($points[0]["pass_scoring"] == 0)
192  {
193  $reached = $points[count($points)-1]["points"];
194  $max = $points[count($points)-1]["maxpoints"];
195  if (!$max)
196  {
197  $active_id = $points[count($points)-1]["active_fi"];
198  $pass = $points[count($points)-1]["pass"];
199  if (strlen($active_id) && strlen($pass))
200  {
201  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
203  $max = $res['maxpoints'];
204  $reached = $res['points'];
205  }
206  }
207  }
208  else
209  {
210  foreach ($points as $row)
211  {
212  if ($row["points"] > $reached)
213  {
214  $reached = $row["points"];
215  $max = $row["maxpoints"];
216  if (!$max)
217  {
218  $active_id = $row["active_fi"];
219  $pass = $row["pass"];
220  if (strlen($active_id) && strlen($pass))
221  {
222  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
224  $max = $res['maxpoints'];
225  $reached = $res['points'];
226  }
227  }
228  }
229  }
230  }
231  include_once "./Modules/Test/classes/class.assMarkSchema.php";
232  $percentage = (!$max) ? 0 : ($reached / $max) * 100.0;
233  $mark = ASS_MarkSchema::_getMatchingMarkFromObjId($a_obj_id, $percentage);
234  return ($mark["passed"]) ? TRUE : FALSE;
235  }
236  else
237  {
238  $row = $ilDB->fetchAssoc($result);
239  return ($row['passed']) ? true : false;
240  }
241  }
242 
248  function _checkCondition($a_obj_id, $a_operator, $a_value, $a_usr_id = 0)
249  {
250  global $ilUser;
251 
252  $a_usr_id = $a_usr_id ? $a_usr_id : $ilUser->getId();
253 
254  switch($a_operator)
255  {
256  case 'passed':
257  return ilObjTestAccess::_isPassed($a_usr_id, $a_obj_id);
258  break;
259 
260  case 'finished':
261  return ilObjTestAccess::_hasFinished($a_usr_id,$a_obj_id);
262 
263  case 'not_finished':
264  return !ilObjTestAccess::_hasFinished($a_usr_id,$a_obj_id);
265 
266  default:
267  return true;
268  }
269  return true;
270  }
271 
284  function _getCommands()
285  {
286  $commands = array
287  (
288  array("permission" => "write", "cmd" => "showPage", "lang_var" => "tst_edit_questions"),
289  array("permission" => "write", "cmd" => "properties", "lang_var" => "settings"),
290  array("permission" => "read", "cmd" => "infoScreen", "lang_var" => "tst_run",
291  "default" => true),
292  //array("permission" => "write", "cmd" => "", "lang_var" => "edit"),
293  array("permission" => "tst_statistics", "cmd" => "outEvaluation", "lang_var" => "tst_statistical_evaluation"),
294  );
295 
296  return $commands;
297  }
298 
299  //
300  // object specific access related methods
301  //
302 
306  function _lookupCreationComplete($a_obj_id)
307  {
308  global $ilDB;
309 
310  $result = $ilDB->queryF("SELECT complete FROM tst_tests WHERE obj_fi=%s",
311  array('integer'),
312  array($a_obj_id)
313  );
314  if ($result->numRows() == 1)
315  {
316  $row = $ilDB->fetchAssoc($result);
317  }
318 
319  return ($row['complete']) ? true : false;
320  }
321 
331  function _hasFinished($a_user_id,$a_obj_id)
332  {
333  global $ilDB;
334 
335  $res = $ilDB->queryF("SELECT active_id FROM tst_active WHERE user_fi = %s AND test_fi = %s AND tries > '0'",
336  array('integer','integer'),
337  array($a_user_id, ilObjTestAccess::_getTestIDFromObjectID($a_obj_id))
338  );
339  return $res->numRows() ? true : false;
340  }
341 
349  function _getTestIDFromObjectID($object_id)
350  {
351  global $ilDB;
352  $test_id = FALSE;
353  $result = $ilDB->queryF("SELECT test_id FROM tst_tests WHERE obj_fi = %s",
354  array('integer'),
355  array($object_id)
356  );
357  if ($result->numRows())
358  {
359  $row = $ilDB->fetchAssoc($result);
360  $test_id = $row["test_id"];
361  }
362  return $test_id;
363  }
364 
365  function &_getTestQuestions($active_id, $pass = NULL)
366  {
367  if (is_null($pass))
368  {
369  $pass = 0;
370  }
371  $questions = array();
372 
373  global $ilDB;
374  $result = $ilDB->queryF("SELECT test_fi FROM tst_active WHERE active_id = %s",
375  array('integer'),
376  array($active_id)
377  );
378  $test_id = "";
379  if ($result->numRows())
380  {
381  $row = $ilDB->fetchAssoc($result);
382  $test_id = $row["test_fi"];
383  }
384  else
385  {
386  return $questions;
387  }
388  $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",
389  array('integer'),
390  array($test_id)
391  );
392  if ($result->numRows())
393  {
394  // standard test
395  while ($row = $ilDB->fetchAssoc($result))
396  {
397  array_push($questions, $row);
398  }
399  }
400  else
401  {
402  // random test
403  $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",
404  array('integer','integer'),
405  array($active_id, $pass)
406  );
407  if ($result->numRows())
408  {
409  while ($row = $ilDB->fetchAssoc($result))
410  {
411  array_push($questions, $row);
412  }
413  }
414  }
415  return $questions;
416  }
417 
424  function _isComplete($a_obj_id)
425  {
426  global $ilDB;
427 
428  $test_id = ilObjTestAccess::_getTestIDFromObjectID($a_obj_id);
429  $result = $ilDB->queryF("SELECT tst_mark.*, tst_tests.* FROM tst_tests, tst_mark WHERE tst_mark.test_fi = tst_tests.test_id AND tst_tests.test_id = %s",
430  array('integer'),
431  array($test_id)
432  );
433  $found = $result->numRows();
434  if ($found)
435  {
436  $row = $ilDB->fetchAssoc($result);
437  // check for at least: title, author and minimum of 1 mark step
438  if ((strlen($row["title"])) &&
439  (strlen($row["author"])) &&
440  ($found))
441  {
442  // check also for minmum of 1 question
443  if (ilObjTestAccess::_getQuestionCount($test_id) > 0)
444  {
445  return true;
446  }
447  else
448  {
449  return false;
450  }
451  }
452  else
453  {
454  return false;
455  }
456  }
457  else
458  {
459  return false;
460  }
461  $test = new ilObjTest($obj_id, false);
462  $test->loadFromDb();
463  if (($test->getTitle()) and ($test->author) and (count($test->mark_schema->mark_steps)) and (count($test->questions)))
464  {
465  return true;
466  }
467  else
468  {
469  return false;
470  }
471  }
472 
480  function &_getTestData($test_id)
481  {
482  global $ilDB;
483  $result = $ilDB->queryF("SELECT * FROM tst_tests WHERE test_id = %s",
484  array('integer'),
485  array($test_id)
486  );
487  if (!$result->numRows())
488  {
489  return 0;
490  }
491  return $ilDB->fetchAssoc($result);
492  }
493 
500  function _lookupObjIdForTestId($a_test_id)
501  {
502  global $ilDB;
503 
504  $result = $ilDB->queryF("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
505  array('integer'),
506  array($a_test_id)
507  );
508 
509  $row = $ilDB->fetchAssoc($result);
510  return $row["obj_fi"];
511  }
512 
519 function _getQuestionCount($test_id)
520 {
521  global $ilDB;
522 
523  $num = 0;
524 
526 
527  if ($test["random_test"] == 1)
528  {
529  if ($test["random_question_count"] > 0)
530  {
531  $num = $test["random_question_count"];
532  }
533  else
534  {
535  $result = $ilDB->queryF("SELECT SUM(num_of_q) questioncount FROM tst_test_random WHERE test_fi = %s ORDER BY test_random_id",
536  array('integer'),
537  array($test_id)
538  );
539  if ($result->numRows())
540  {
541  $row = $ilDB->fetchAssoc($result);
542  $num = $row["questioncount"];
543  }
544  }
545  }
546  else
547  {
548  $result = $ilDB->queryF("SELECT test_question_id FROM tst_test_question WHERE test_fi = %s",
549  array('integer'),
550  array($test_id)
551  );
552  $num = $result->numRows();
553  }
554  return $num;
555 }
556 
565  {
566  global $ilDB;
567 
568  $query = 'SELECT DISTINCT t.obj_fi '
569  .'FROM tst_tests t '
570  .'INNER JOIN tst_test_random r '
571  .'ON t.test_id = r.test_fi '
572  .'WHERE r.questionpool_fi = '
573  . $ilDB->quote($qpl_id, 'integer');
574 
575  $result = $ilDB->query($query);
576 
577  $tests = array();
578  while ($row = $ilDB->fetchAssoc($result))
579  {
580  $tests[] = $row['obj_fi'];
581  }
582 
583  return $tests;
584  }
585  // fim.
586 
593  function _lookupOnlineTestAccess($a_test_id, $a_user_id)
594  {
595  global $ilDB, $lng;
596 
597  $result = $ilDB->queryF("SELECT tst_tests.* FROM tst_tests WHERE tst_tests.obj_fi = %s",
598  array('integer'),
599  array($a_test_id)
600  );
601  if ($result->numRows())
602  {
603  $row = $ilDB->fetchAssoc($result);
604  if ($row["fixed_participants"])
605  {
606  $result = $ilDB->queryF("SELECT * FROM tst_invited_user WHERE test_fi = %s AND user_fi = %s",
607  array('integer','integer'),
608  array($row["test_id"], $a_user_id)
609  );
610  if ($result->numRows())
611  {
612  $row = $ilDB->fetchAssoc($result);
613  if (trim($row['clientip']) != "")
614  {
615  $row['clientip'] = preg_replace("/[^0-9.?*,:]+/","",$row['clientip']);
616  $row['clientip'] = str_replace(".","\\.",$row['clientip']);
617  $row['clientip'] = str_replace(Array("?","*",","), Array("[0-9]","[0-9]*","|"), $row['clientip']);
618  if (!preg_match("/^".$row['clientip']."$/", $_SERVER["REMOTE_ADDR"]))
619  {
620  return $lng->txt("tst_user_wrong_clientip");
621  }
622  else
623  {
624  return true;
625  }
626  }
627  else
628  {
629  return true;
630  }
631  }
632  else
633  {
634  return $lng->txt("tst_user_not_invited");
635  }
636  }
637  else
638  {
639  return true;
640  }
641  }
642  else
643  {
644  return true;
645  }
646  }
647 
655  function _getParticipantData($active_id)
656  {
657  global $lng, $ilDB;
658 
659  $result = $ilDB->queryF("SELECT * FROM tst_active WHERE active_id = %s",
660  array("integer"),
661  array($active_id)
662  );
663  $row = $ilDB->fetchAssoc($result);
664  $user_id = $row["user_fi"];
665  $test_id = $row["test_fi"];
666  $importname = $row['importname'];
667 
668  $result = $ilDB->queryF("SELECT obj_fi FROM tst_tests WHERE test_id = %s",
669  array("integer"),
670  array($test_id)
671  );
672  $row = $ilDB->fetchAssoc($result);
673  $obj_id = $row["obj_fi"];
674 
675  include_once "./Modules/Test/classes/class.ilObjTest.php";
676  $is_anonymous = ilObjTest::_lookupAnonymity($obj_id);
677 
678  include_once './Services/User/classes/class.ilObjUser.php';
679  $uname = ilObjUser::_lookupName($user_id);
680 
681  $name = "";
682  if (strlen($importname))
683  {
684  $name = $importname . ' (' . $lng->txt('imported') . ')';
685  }
686  else if (strlen($uname["firstname"].$uname["lastname"]) == 0)
687  {
688  $name = $lng->txt("deleted_user");
689  }
690  else
691  {
692  if ($user_id == ANONYMOUS_USER_ID)
693  {
694  $name = $lastname;
695  }
696  else
697  {
698  $name = trim($uname["lastname"] . ", " . $uname["firstname"] . " " . $uname["title"]);
699  }
700  if ($is_anonymous)
701  {
702  $name = $lng->txt("anonymous");
703  }
704  }
705  return $name;
706  }
707 
714  function _getParticipantId($active_id)
715  {
716  global $lng, $ilDB;
717 
718  $result = $ilDB->queryF("SELECT user_fi FROM tst_active WHERE active_id = %s",
719  array("integer"),
720  array($active_id)
721  );
722  $row = $ilDB->fetchAssoc($result);
723  return $row["user_fi"];
724  }
725 
726 
741  function &_getPassedUsers($a_obj_id)
742  {
743  global $ilDB;
744 
745  $passed_users = array();
746  // Maybe SELECT DISTINCT(tst_active.user_fi)... ?
747  $userresult = $ilDB->queryF("
748  SELECT tst_active.active_id, COUNT(tst_sequence.active_fi) sequences
749  FROM tst_tests
750  INNER JOIN tst_active
751  ON tst_active.test_fi = tst_tests.test_id
752  LEFT JOIN tst_sequence
753  ON tst_sequence.active_fi = tst_active.active_id
754  WHERE tst_tests.obj_fi = %s
755  GROUP BY tst_active.active_id
756  ",
757  array('integer'), array($a_obj_id)
758  );
759  $all_participants = array();
760  $notAttempted = array();
761  while ($row = $ilDB->fetchAssoc($userresult))
762  {
763  if($row['sequences'] == 0)
764  {
765  $notAttempted[$row['active_id']] = $row['active_id'];
766  }
767 
768  $all_participants[$row['active_id']] = $row['active_id'];
769  }
770 
771  $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'));
772  $found_all = ($result->numRows() == count($all_participants)) ? true : false;
773  if (!$found_all)
774  {
775  // if the result cache entries do not exist, create them
776  $found_participants = array();
777  while ($data = $ilDB->fetchAssoc($result))
778  {
779  array_push($found_participants, $data['active_fi']);
780  }
781  foreach ($all_participants as $active_id)
782  {
783  if (!in_array($active_id, $found_participants))
784  {
785  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
787  }
788  }
789  $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'));
790  }
791  while ($data = $ilDB->fetchAssoc($result))
792  {
793  if( isset($notAttempted[$data['active_fi']]) )
794  {
795  $data['failed'] = 0;
796  $data['passed'] = 0;
797  }
798 
799  $data['user_id'] = $data['user_fi'];
800  array_push($passed_users, $data);
801  }
802  return $passed_users;
803  }
804 
808  function _checkGoto($a_target)
809  {
810  global $ilAccess;
811 
812  $t_arr = explode("_", $a_target);
813 
814  if ($t_arr[0] != "tst" || ((int) $t_arr[1]) <= 0)
815  {
816  return false;
817  }
818 
819  if ($ilAccess->checkAccess("visible", "", $t_arr[1]))
820  {
821  return true;
822  }
823  return false;
824  }
825 
834  static function _isOffline($a_obj_id)
835  {
836 // global $ilUser;
837 // return (self::_lookupOnlineTestAccess($a_obj_id, $ilUser->getId()) !== true) ||
838 // (!ilObjTestAccess::_lookupCreationComplete($a_obj_id));
839  return !self::_isOnline($a_obj_id);
840  }
841 
848  public static function _isOnline($a_obj_id)
849  {
850  global $ilDB;
851 
852  $query = "
853  SELECT test_id
854  FROM tst_tests
855  WHERE obj_fi = %s
856  AND online_status = 1
857  ";
858 
859  $result = $ilDB->queryF( $query, array('integer'), array($a_obj_id) );
860 
861  return $result->numRows() == 1;
862  }
863 }
864 
865 ?>