ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilSoapTestAdministration.php
Go to the documentation of this file.
1 <?php
2  /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 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 
33 include_once './webservice/soap/classes/class.ilSoapAdministration.php';
34 
36 {
38  {
40  }
41 
42  private function hasWritePermissionForTest($active_id)
43  {
44  global $ilDB;
45  global $ilAccess;
46 
47  $permission_ok = false;
48  $result = $ilDB->queryF("SELECT tst_tests.obj_fi FROM tst_active, tst_tests WHERE tst_active.active_id = %s AND tst_active.test_fi = tst_tests.test_id",
49  array('integer'),
50  array($active_id)
51  );
52  $row = $ilDB->fetchAssoc($result);
53  if ($row['obj_fi'])
54  {
55  $obj_id = $row['obj_fi'];
56  foreach($ref_ids = ilObject::_getAllReferences($obj_id) as $ref_id)
57  {
58  if ($ilAccess->checkAccess("write", "", $ref_id))
59  {
60  $permission_ok = true;
61  break;
62  }
63  }
64  }
65  return $permission_ok;
66  }
67 
68  function isAllowedCall($sid, $active_id, $saveaction = true)
69  {
70  global $ilDB;
71  global $ilUser;
72 
73  if ($this->hasWritePermissionForTest($active_id)) return TRUE;
74 
75  if ($saveaction)
76  {
77  $result = $ilDB->queryF("SELECT * FROM tst_times WHERE active_fi = %s ORDER BY started DESC",
78  array('integer'),
79  array($active_id)
80  );
81  if ($result->numRows())
82  {
83  $row = $ilDB->fetchAssoc($result);
84  if (preg_match("/(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})/", $row["started"], $matches))
85  {
86  $time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
87  $now = time();
88  $diff = $now - $time;
89  $client = explode("::", $sid);
90  global $ilClientIniFile;
91  $expires = $ilClientIniFile->readVariable('session','expire');
92  if ($diff <= $expires)
93  {
94  return TRUE;
95  }
96  else
97  {
98  return FALSE;
99  }
100  }
101  else
102  {
103  return FALSE;
104  }
105  }
106  else
107  {
108  return FALSE;
109  }
110  }
111  else
112  {
113  $result = $ilDB->queryF("SELECT user_fi FROM tst_active WHERE active_id = %s",
114  array('integer'),
115  array($active_id)
116  );
117  $row = $ilDB->fetchAssoc($result);
118  if ($row['user_fi'] == $ilUser->getId())
119  {
120  return TRUE;
121  }
122  else
123  {
124  return FALSE;
125  }
126  }
127  }
128 
129  function saveQuestion($sid,$active_id,$question_id,$pass,$solution)
130  {
131  $this->initAuth($sid);
132  $this->initIlias();
133 
134  if(!$this->__checkSession($sid))
135  {
136  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
137  }
138  if (!$this->isAllowedCall($sid, $active_id))
139  {
140  return $this->__raiseError("The required user information is only available for active users.", "");
141  }
142 
143  if (is_array($solution) && (array_key_exists("item", $solution))) $solution = $solution["item"];
144 
145  global $ilDB, $ilUser;
146 
147  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
148  $processLockerFactory = new ilAssQuestionProcessLockerFactory(new ilSetting('assessment'), $ilDB);
149  $processLockerFactory->setQuestionId($question_id);
150  $processLockerFactory->setUserId($ilUser->getId());
151  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
152  $processLockerFactory->setAssessmentLogEnabled(ilObjAssessmentFolder::_enabledAssessmentLogging());
153  $processLocker = $processLockerFactory->getLocker();
154 
155  $processLocker->requestPersistWorkingStateLock();
156  $processLocker->requestUserSolutionUpdateLock();
157 
158  $ilDB = $GLOBALS['ilDB'];
159  if (($active_id > 0) && ($question_id > 0) && (strlen($pass) > 0))
160  {
161  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
162  array('integer', 'integer', 'integer'),
163  array($active_id, $question_id, $pass)
164  );
165  }
166  $totalrows = 0;
167  for($i = 0; $i < count($solution); $i += 3)
168  {
169  $next_id = $ilDB->nextId('tst_solutions');
170  $affectedRows = $ilDB->insert("tst_solutions", array(
171  "solution_id" => array("integer", $next_id),
172  "active_fi" => array("integer", $active_id),
173  "question_fi" => array("integer", $question_id),
174  "value1" => array("clob", $solution[$i]),
175  "value2" => array("clob", $solution[$i+1]),
176  "points" => array("float", $solution[$i+2]),
177  "pass" => array("integer", $pass),
178  "tstamp" => array("integer", time())
179  ));
180  $totalrows += $affectedRows;
181  }
182 
183  $processLocker->releaseUserSolutionUpdateLock();
184 
185  if($totalrows == 0)
186  {
187  $processLocker->releasePersistWorkingStateLock();
188  return $this->__raiseError(
189  "Wrong solution data. ILIAS did not execute any database queries: Solution data: " . print_r($solution, true),
190  'No result'
191  );
192  }
193  else
194  {
195  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
196  $question = assQuestion::_instanciateQuestion($question_id);
197  $question->setProcessLocker($processLocker);
198  $question->calculateResultsFromSolution($active_id, $pass);
199 
200  $processLocker->releasePersistWorkingStateLock();
201  }
202  return true;
203  }
204 
216  function saveQuestionSolution($sid,$active_id,$question_id,$pass,$solution)
217  {
218  $this->initAuth($sid);
219  $this->initIlias();
220 
221  if(!$this->__checkSession($sid))
222  {
223  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
224  }
225  if (!$this->isAllowedCall($sid, $active_id))
226  {
227  return $this->__raiseError("The required user information is only available for active users.", "");
228  }
229 
230  $solutions = array();
231  if (preg_match("/<values>(.*?)<\/values>/is", $solution, $matches))
232  {
233  if (preg_match_all("/<value>(.*?)<\/value><value>(.*?)<\/value><points>(.*?)<\/points>/is", $solution, $matches, PREG_SET_ORDER))
234  {
235  foreach ($matches as $match)
236  {
237  if (count($match) == 4)
238  {
239  for ($i = 1; $i < count($match); $i++)
240  {
241  array_push($solutions, trim($match[$i]));
242  }
243  }
244  }
245  }
246  }
247 
248  if (count($solutions) == 0)
249  {
250  return $this->__raiseError("Wrong solution data. ILIAS did not find one or more solution triplets: $solution", "");
251  }
252 
253  // Include main header
254  $ilDB = $GLOBALS['ilDB'];
255  if (($active_id > 0) && ($question_id > 0) && (strlen($pass) > 0))
256  {
257  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
258  array('integer', 'integer', 'integer'),
259  array($active_id, $question_id, $pass)
260  );
261  }
262  $totalrows = 0;
263  for($i = 0; $i < count($solutions); $i += 3)
264  {
265  $next_id = $ilDB->nextId('tst_solutions');
266  $affectedRows = $ilDB->insert("tst_solutions", array(
267  "solution_id" => array("integer", $next_id),
268  "active_fi" => array("integer", $active_id),
269  "question_fi" => array("integer", $question_id),
270  "value1" => array("clob", $solutions[$i]),
271  "value2" => array("clob", $solutions[$i+1]),
272  "points" => array("float", $solutions[$i+2]),
273  "pass" => array("integer", $pass),
274  "tstamp" => array("integer", time())
275  ));
276  $totalrows += $affectedRows;
277  }
278  if (count($totalrows) == 0)
279  {
280  return $this->__raiseError("Wrong solution data. ILIAS did not execute any database queries");
281  }
282  else
283  {
284  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
285  $question = assQuestion::_instanciateQuestion($question_id);
286  $question->calculateResultsFromSolution($active_id, $pass);
287  }
288  return "TRUE";
289  }
290 
301  function getQuestionSolution($sid,$active_id,$question_id,$pass)
302  {
303  $this->initAuth($sid);
304  $this->initIlias();
305 
306  if(!$this->__checkSession($sid))
307  {
308  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
309  }
310  if (!$this->isAllowedCall($sid, $active_id, false))
311  {
312  return $this->__raiseError("The required user information is only available for active users.", "");
313  }
314  $solution = array();
315  // Include main header
316  global $ilDB;
317 
318  $use_previous_answers = 1;
319 
320  $result = $ilDB->queryF("SELECT tst_tests.use_previous_answers FROM tst_tests, tst_active WHERE tst_tests.test_id = tst_active.test_fi AND tst_active.active_id = %s",
321  array('integer'),
322  array($active_id)
323  );
324  if ($result->numRows())
325  {
326  $row = $ilDB->fetchAssoc($result);
327  $use_previous_answers = $row["use_previous_answers"];
328  }
329  $lastpass = 0;
330  if ($use_previous_answers)
331  {
332  $result = $ilDB->queryF("SELECT MAX(pass) maxpass FROM tst_test_result WHERE active_fi = %s AND question_fi = %s",
333  array('integer', 'integer'),
334  array($active_id, $question_id)
335  );
336  if ($result->numRows() == 1)
337  {
338  $row = $ilDB->fetchAssoc($result);
339  $lastpass = $row["maxpass"];
340  }
341  }
342  else
343  {
344  $lastpass = $pass;
345  }
346 
347  if (($active_id > 0) && ($question_id > 0) && (strlen($lastpass) > 0))
348  {
349  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
350  array('integer', 'integer', 'integer'),
351  array($active_id, $question_id, $lastpass)
352  );
353  if ($result->numRows())
354  {
355  while ($row = $ilDB->fetchAssoc($result))
356  {
357  array_push($solution, $row["value1"]);
358  array_push($solution, $row["value2"]);
359  array_push($solution, $row["points"]);
360  }
361  }
362  }
363  return $solution;
364  }
365 
374  function getTestUserData($sid, $active_id)
375  {
376  $this->initAuth($sid);
377  $this->initIlias();
378 
379  if(!$this->__checkSession($sid))
380  {
381  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
382  }
383  if (!$this->isAllowedCall($sid, $active_id, false))
384  {
385  return $this->__raiseError("The required user information is only available for active users.", "");
386  }
387 
388  global $lng, $ilDB;
389 
390  $result = $ilDB->queryF("SELECT user_fi, test_fi FROM tst_active WHERE active_id = %s",
391  array('integer'),
392  array($active_id)
393  );
394  $row = $ilDB->fetchAssoc($result);
395  $user_id = $row["user_fi"];
396  $test_id = $row["test_fi"];
397 
398  $result = $ilDB->queryF("SELECT anonymity FROM tst_tests WHERE test_id = %s",
399  array('integer'),
400  array($test_id)
401  );
402  $row = $ilDB->fetchAssoc($result);
403  $anonymity = $row["anonymity"];
404 
405  $result = $ilDB->queryF("SELECT firstname, lastname, title, login FROM usr_data WHERE usr_id = %s",
406  array('integer'),
407  array($user_id)
408  );
409 
410  $userdata = array();
411  if ($result->numRows() == 0)
412  {
413  $userdata["fullname"] = $lng->txt("deleted_user");
414  $userdata["title"] = "";
415  $userdata["firstname"] = "";
416  $userdata["lastname"] = $lng->txt("anonymous");
417  $userdata["login"] = "";
418  }
419  else
420  {
421  $data = $ilDB->fetchAssoc($result);
422  if (($user_id == ANONYMOUS_USER_ID) || ($anonymity))
423  {
424  $userdata["fullname"] = $lng->txt("anonymous");
425  $userdata["title"] = "";
426  $userdata["firstname"] = "";
427  $userdata["lastname"] = $lng->txt("anonymous");
428  $userdata["login"] = "";
429  }
430  else
431  {
432  $userdata["fullname"] = trim($data["title"] . " " . $data["firstname"] . " " . $data["lastname"]);
433  $userdata["title"] = $data["title"];
434  $userdata["firstname"] = $data["firstname"];
435  $userdata["lastname"] = $data["lastname"];
436  $userdata["login"] = $data["login"];
437  }
438  }
439  return array_values($userdata);
440  }
441 
452  function getPositionOfQuestion($sid, $active_id, $question_id, $pass)
453  {
454  $this->initAuth($sid);
455  $this->initIlias();
456 
457  if(!$this->__checkSession($sid))
458  {
459  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
460  }
461  if (!$this->isAllowedCall($sid, $active_id, false))
462  {
463  return $this->__raiseError("The required user information is only available for active users.", "");
464  }
465 
466  global $lng, $ilDB;
467 
468  $result = $ilDB->queryF("SELECT tst_tests.random_test FROM tst_active, tst_tests WHERE tst_active.active_id = %s AND tst_tests.test_id = tst_active.test_fi",
469  array('integer'),
470  array($active_id)
471  );
472  if ($result->numRows() != 1) return -1;
473  $row = $ilDB->fetchAssoc($result);
474  $is_random = $row["random_test"];
475 
476  include_once "./Modules/Test/classes/class.ilTestSequence.php";
477  $sequence = new ilTestSequence($active_id, $pass, $is_random);
478  return $sequence->getSequenceForQuestion($question_id);
479  }
480 
491  function getPreviousReachedPoints($sid, $active_id, $question_id, $pass)
492  {
493  $this->initAuth($sid);
494  $this->initIlias();
495 
496  if(!$this->__checkSession($sid))
497  {
498  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
499  }
500  if (!$this->isAllowedCall($sid, $active_id, false))
501  {
502  return $this->__raiseError("The required user information is only available for active users.", "");
503  }
504 
505  global $lng, $ilDB;
506 
507  $result = $ilDB->queryF("SELECT tst_tests.random_test FROM tst_active, tst_tests WHERE tst_active.active_id = %s AND tst_tests.test_id = tst_active.test_fi",
508  array('integer'),
509  array($active_id)
510  );
511  if ($result->numRows() != 1) return -1;
512  $row = $ilDB->fetchAssoc($result);
513  $is_random = $row["random_test"];
514 
515  include_once "./Modules/Test/classes/class.ilTestSequence.php";
516  $sequence = new ilTestSequence($active_id, $pass, $is_random);
517  $result = $ilDB->queryF("SELECT question_fi, points FROM tst_test_result WHERE active_fi = %s AND pass = %s",
518  array('integer', 'integer'),
519  array($active_id, $pass)
520  );
521  $reachedpoints = array();
522  while ($row = $ilDB->fetchAssoc($result))
523  {
524  $reachedpoints[$row["question_fi"]] = $row["points"];
525  }
526  $atposition = FALSE;
527  $pointsforposition = array();
528  foreach ($sequence->getUserSequence() as $seq)
529  {
530  if (!$atposition)
531  {
532  $qid = $sequence->getQuestionForSequence($seq);
533  if ($qid == $question_id)
534  {
535  $atposition = TRUE;
536  }
537  else
538  {
539  array_push($pointsforposition, $reachedpoints[$qid]);
540  }
541  }
542  }
543  return $pointsforposition;
544  }
545 
555  function getNrOfQuestionsInPass($sid, $active_id, $pass)
556  {
557  $this->initAuth($sid);
558  $this->initIlias();
559 
560  if(!$this->__checkSession($sid))
561  {
562  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
563  }
564  if (!$this->isAllowedCall($sid, $active_id, false))
565  {
566  return $this->__raiseError("The required user information is only available for active users.", "");
567  }
568 
569  global $lng, $ilDB;
570 
571  $result = $ilDB->queryF("SELECT tst_tests.random_test FROM tst_active, tst_tests WHERE tst_active.active_id = %s AND tst_tests.test_id = tst_active.test_fi",
572  array('integer'),
573  array($active_id)
574  );
575  if ($result->numRows() != 1) return 0;
576  $row = $ilDB->fetchAssoc($result);
577  $is_random = $row["random_test"];
578 
579  include_once "./Modules/Test/classes/class.ilTestSequence.php";
580  $sequence = new ilTestSequence($active_id, $pass, $is_random);
581  return $sequence->getUserQuestionCount();
582  }
583 
591  public function removeTestResults($sid,$test_ref_id,$a_user_ids)
592  {
593  $this->initAuth($sid);
594  $this->initIlias();
595 
596  if(!$this->__checkSession($sid))
597  {
598  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
599  }
600  if(!strlen($test_ref_id))
601  {
602  return $this->__raiseError('No test id given. Aborting!',
603  'Client');
604  }
605  global $rbacsystem, $tree, $ilLog;
606 
607  if(ilObject::_isInTrash($test_ref_id))
608  {
609  return $this->__raiseError('Test is trashed. Aborting!',
610  'Client');
611  }
612 
613  if(!$tst = ilObjectFactory::getInstanceByRefId($test_ref_id,false))
614  {
615  return $this->__raiseError('No test found for id: '.$test_ref_id,'Client');
616  }
617  if($tst->getType() != 'tst')
618  {
619  return $this->__raiseError('Object with ref_id '.$test_ref_id.' is not of type test. Aborting','Client');
620  }
621 
622  // Dirty hack
623  if(isset($a_user_ids['item']))
624  {
625  $a_user_ids = $a_user_ids['item'];
626  }
627 
628  foreach((array) $a_user_ids as $user_id)
629  {
630  $tst->removeTestResultsForUser($user_id);
631  }
632  return true;
633  }
634 
647  function getTestResults ($sid, $test_ref_id, $sum_only)
648  {
649  $this->initAuth($sid);
650  $this->initIlias();
651 
652  if(!$this->__checkSession($sid))
653  {
654  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
655  }
656  if(!strlen($test_ref_id))
657  {
658  return $this->__raiseError('No test id given. Aborting!',
659  'Client');
660  }
661  global $rbacsystem, $tree, $ilLog;
662 
663  if(ilObject::_isInTrash($test_ref_id))
664  {
665  return $this->__raiseError('Test is trashed. Aborting!',
666  'Client');
667  }
668 
669  // get obj_id
670  if(!$obj_id = ilObject::_lookupObjectId($test_ref_id))
671  {
672  return $this->__raiseError('No test found for id: '.$test_ref_id,
673  'Client');
674  }
675 
676 
677  // Check access
678  $permission_ok = false;
679  foreach($ref_ids = ilObject::_getAllReferences($obj_id) as $ref_id)
680  {
681  if($rbacsystem->checkAccess('write',$ref_id))
682  {
683  $permission_ok = true;
684  break;
685  }
686  }
687  if(!$permission_ok)
688  {
689  return $this->__raiseError('No permission to edit the object with id: '.$test_ref_id,
690  'Server');
691  }
692  // store into xml result set
693  include_once './webservice/soap/classes/class.ilXMLResultSet.php';
694  include_once './webservice/soap/classes/class.ilXMLResultSetWriter.php';
695 
696  $xmlResultSet = new ilXMLResultSet();
697  $xmlResultSet->addColumn("user_id");
698  $xmlResultSet->addColumn("login");
699  $xmlResultSet->addColumn("firstname");
700  $xmlResultSet->addColumn("lastname");
701  $xmlResultSet->addColumn("matriculation");
702 
703  include_once './Modules/Test/classes/class.ilObjTest.php';
704  $test_obj = new ilObjTest($obj_id, false);
705  $participants = $test_obj->getTestParticipants();
706 
707 
708  if ($sum_only)
709  {
710  $data = $test_obj->getAllTestResults($participants, false);
711  // create xml
712  $xmlResultSet->addColumn("maximum_points");
713  $xmlResultSet->addColumn("received_points");
714  // skip titles
715  $titles = array_shift($data);
716  foreach ($data as $row) {
717  $xmlRow = new ilXMLResultSetRow();
718  $xmlRow->setValue(0, $row["user_id"]);
719  $xmlRow->setValue(1, $row["login"]);
720  $xmlRow->setValue(2, $row["firstname"]);
721  $xmlRow->setValue(3, $row["lastname"]);
722  $xmlRow->setValue(4, $row["matriculation"]);
723  $xmlRow->setValue(5, $row["max_points"]);
724  $xmlRow->setValue(6, $row["reached_points"]);
725  $xmlResultSet->addRow($xmlRow);
726  }
727  } else {
728  $data = $test_obj->getDetailedTestResults($participants);
729  // create xml
730  $xmlResultSet->addColumn("question_id");
731  $xmlResultSet->addColumn("question_title");
732  $xmlResultSet->addColumn("maximum_points");
733  $xmlResultSet->addColumn("received_points");
734  foreach ($data as $row) {
735  $xmlRow = new ilXMLResultSetRow();
736  $xmlRow->setValue(0, $row["user_id"]);
737  $xmlRow->setValue(1, $row["login"]);
738  $xmlRow->setValue(2, $row["firstname"]);
739  $xmlRow->setValue(3, $row["lastname"]);
740  $xmlRow->setValue(4, $row["matriculation"]);
741  $xmlRow->setValue(5, $row["question_id"]);
742  $xmlRow->setValue(6, $row["question_title"]);
743  $xmlRow->setValue(7, $row["max_points"]);
744  $xmlRow->setValue(8, $row["reached_points"]);
745  $xmlResultSet->addRow($xmlRow);
746  }
747  }
748  // create writer
749  $xmlWriter = new ilXMLResultSetWriter($xmlResultSet);
750  $xmlWriter->start();
751  return $xmlWriter->getXML();
752  }
753 
754 
755 }
756 ?>