ILIAS  release_4-3 Revision
 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  $ilDB = $GLOBALS['ilDB'];
146  if (($active_id > 0) && ($question_id > 0) && (strlen($pass) > 0))
147  {
148  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
149  array('integer', 'integer', 'integer'),
150  array($active_id, $question_id, $pass)
151  );
152  }
153  $totalrows = 0;
154  for($i = 0; $i < count($solution); $i += 3)
155  {
156  $next_id = $ilDB->nextId('tst_solutions');
157  $affectedRows = $ilDB->insert("tst_solutions", array(
158  "solution_id" => array("integer", $next_id),
159  "active_fi" => array("integer", $active_id),
160  "question_fi" => array("integer", $question_id),
161  "value1" => array("clob", $solution[$i]),
162  "value2" => array("clob", $solution[$i+1]),
163  "points" => array("float", $solution[$i+2]),
164  "pass" => array("integer", $pass),
165  "tstamp" => array("integer", time())
166  ));
167  $totalrows += $affectedRows;
168  }
169  if ($totalrows == 0)
170  {
171  return $this->__raiseError("Wrong solution data. ILIAS did not execute any database queries: Solution data: " . print_r($solution, true));
172  }
173  else
174  {
175  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
176  $question = assQuestion::_instanciateQuestion($question_id);
177  $question->calculateResultsFromSolution($active_id, $pass);
178  }
179  return true;
180  }
181 
193  function saveQuestionSolution($sid,$active_id,$question_id,$pass,$solution)
194  {
195  $this->initAuth($sid);
196  $this->initIlias();
197 
198  if(!$this->__checkSession($sid))
199  {
200  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
201  }
202  if (!$this->isAllowedCall($sid, $active_id))
203  {
204  return $this->__raiseError("The required user information is only available for active users.", "");
205  }
206 
207  $solutions = array();
208  if (preg_match("/<values>(.*?)<\/values>/is", $solution, $matches))
209  {
210  if (preg_match_all("/<value>(.*?)<\/value><value>(.*?)<\/value><points>(.*?)<\/points>/is", $solution, $matches, PREG_SET_ORDER))
211  {
212  foreach ($matches as $match)
213  {
214  if (count($match) == 4)
215  {
216  for ($i = 1; $i < count($match); $i++)
217  {
218  array_push($solutions, trim($match[$i]));
219  }
220  }
221  }
222  }
223  }
224 
225  if (count($solutions) == 0)
226  {
227  return $this->__raiseError("Wrong solution data. ILIAS did not find one or more solution triplets: $solution", "");
228  }
229 
230  // Include main header
231  $ilDB = $GLOBALS['ilDB'];
232  if (($active_id > 0) && ($question_id > 0) && (strlen($pass) > 0))
233  {
234  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
235  array('integer', 'integer', 'integer'),
236  array($active_id, $question_id, $pass)
237  );
238  }
239  $totalrows = 0;
240  for($i = 0; $i < count($solutions); $i += 3)
241  {
242  $next_id = $ilDB->nextId('tst_solutions');
243  $affectedRows = $ilDB->insert("tst_solutions", array(
244  "solution_id" => array("integer", $next_id),
245  "active_fi" => array("integer", $active_id),
246  "question_fi" => array("integer", $question_id),
247  "value1" => array("clob", $solutions[$i]),
248  "value2" => array("clob", $solutions[$i+1]),
249  "points" => array("float", $solutions[$i+2]),
250  "pass" => array("integer", $pass),
251  "tstamp" => array("integer", time())
252  ));
253  $totalrows += $affectedRows;
254  }
255  if (count($totalrows) == 0)
256  {
257  return $this->__raiseError("Wrong solution data. ILIAS did not execute any database queries");
258  }
259  else
260  {
261  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
262  $question = assQuestion::_instanciateQuestion($question_id);
263  $question->calculateResultsFromSolution($active_id, $pass);
264  }
265  return "TRUE";
266  }
267 
278  function getQuestionSolution($sid,$active_id,$question_id,$pass)
279  {
280  $this->initAuth($sid);
281  $this->initIlias();
282 
283  if(!$this->__checkSession($sid))
284  {
285  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
286  }
287  if (!$this->isAllowedCall($sid, $active_id, false))
288  {
289  return $this->__raiseError("The required user information is only available for active users.", "");
290  }
291  $solution = array();
292  // Include main header
293  global $ilDB;
294 
295  $use_previous_answers = 1;
296 
297  $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",
298  array('integer'),
299  array($active_id)
300  );
301  if ($result->numRows())
302  {
303  $row = $ilDB->fetchAssoc($result);
304  $use_previous_answers = $row["use_previous_answers"];
305  }
306  $lastpass = 0;
307  if ($use_previous_answers)
308  {
309  $result = $ilDB->queryF("SELECT MAX(pass) maxpass FROM tst_test_result WHERE active_fi = %s AND question_fi = %s",
310  array('integer', 'integer'),
311  array($active_id, $question_id)
312  );
313  if ($result->numRows() == 1)
314  {
315  $row = $ilDB->fetchAssoc($result);
316  $lastpass = $row["maxpass"];
317  }
318  }
319  else
320  {
321  $lastpass = $pass;
322  }
323 
324  if (($active_id > 0) && ($question_id > 0) && (strlen($lastpass) > 0))
325  {
326  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
327  array('integer', 'integer', 'integer'),
328  array($active_id, $question_id, $lastpass)
329  );
330  if ($result->numRows())
331  {
332  while ($row = $ilDB->fetchAssoc($result))
333  {
334  array_push($solution, $row["value1"]);
335  array_push($solution, $row["value2"]);
336  array_push($solution, $row["points"]);
337  }
338  }
339  }
340  return $solution;
341  }
342 
351  function getTestUserData($sid, $active_id)
352  {
353  $this->initAuth($sid);
354  $this->initIlias();
355 
356  if(!$this->__checkSession($sid))
357  {
358  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
359  }
360  if (!$this->isAllowedCall($sid, $active_id, false))
361  {
362  return $this->__raiseError("The required user information is only available for active users.", "");
363  }
364 
365  global $lng, $ilDB;
366 
367  $result = $ilDB->queryF("SELECT user_fi, test_fi FROM tst_active WHERE active_id = %s",
368  array('integer'),
369  array($active_id)
370  );
371  $row = $ilDB->fetchAssoc($result);
372  $user_id = $row["user_fi"];
373  $test_id = $row["test_fi"];
374 
375  $result = $ilDB->queryF("SELECT anonymity FROM tst_tests WHERE test_id = %s",
376  array('integer'),
377  array($test_id)
378  );
379  $row = $ilDB->fetchAssoc($result);
380  $anonymity = $row["anonymity"];
381 
382  $result = $ilDB->queryF("SELECT firstname, lastname, title, login FROM usr_data WHERE usr_id = %s",
383  array('integer'),
384  array($user_id)
385  );
386 
387  $userdata = array();
388  if ($result->numRows() == 0)
389  {
390  $userdata["fullname"] = $lng->txt("deleted_user");
391  $userdata["title"] = "";
392  $userdata["firstname"] = "";
393  $userdata["lastname"] = $lng->txt("anonymous");
394  $userdata["login"] = "";
395  }
396  else
397  {
398  $data = $ilDB->fetchAssoc($result);
399  if (($user_id == ANONYMOUS_USER_ID) || ($anonymity))
400  {
401  $userdata["fullname"] = $lng->txt("anonymous");
402  $userdata["title"] = "";
403  $userdata["firstname"] = "";
404  $userdata["lastname"] = $lng->txt("anonymous");
405  $userdata["login"] = "";
406  }
407  else
408  {
409  $userdata["fullname"] = trim($data["title"] . " " . $data["firstname"] . " " . $data["lastname"]);
410  $userdata["title"] = $data["title"];
411  $userdata["firstname"] = $data["firstname"];
412  $userdata["lastname"] = $data["lastname"];
413  $userdata["login"] = $data["login"];
414  }
415  }
416  return array_values($userdata);
417  }
418 
429  function getPositionOfQuestion($sid, $active_id, $question_id, $pass)
430  {
431  $this->initAuth($sid);
432  $this->initIlias();
433 
434  if(!$this->__checkSession($sid))
435  {
436  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
437  }
438  if (!$this->isAllowedCall($sid, $active_id, false))
439  {
440  return $this->__raiseError("The required user information is only available for active users.", "");
441  }
442 
443  global $lng, $ilDB;
444 
445  $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",
446  array('integer'),
447  array($active_id)
448  );
449  if ($result->numRows() != 1) return -1;
450  $row = $ilDB->fetchAssoc($result);
451  $is_random = $row["random_test"];
452 
453  include_once "./Modules/Test/classes/class.ilTestSequence.php";
454  $sequence = new ilTestSequence($active_id, $pass, $is_random);
455  return $sequence->getSequenceForQuestion($question_id);
456  }
457 
468  function getPreviousReachedPoints($sid, $active_id, $question_id, $pass)
469  {
470  $this->initAuth($sid);
471  $this->initIlias();
472 
473  if(!$this->__checkSession($sid))
474  {
475  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
476  }
477  if (!$this->isAllowedCall($sid, $active_id, false))
478  {
479  return $this->__raiseError("The required user information is only available for active users.", "");
480  }
481 
482  global $lng, $ilDB;
483 
484  $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",
485  array('integer'),
486  array($active_id)
487  );
488  if ($result->numRows() != 1) return -1;
489  $row = $ilDB->fetchAssoc($result);
490  $is_random = $row["random_test"];
491 
492  include_once "./Modules/Test/classes/class.ilTestSequence.php";
493  $sequence = new ilTestSequence($active_id, $pass, $is_random);
494  $result = $ilDB->queryF("SELECT question_fi, points FROM tst_test_result WHERE active_fi = %s AND pass = %s",
495  array('integer', 'integer'),
496  array($active_id, $pass)
497  );
498  $reachedpoints = array();
499  while ($row = $ilDB->fetchAssoc($result))
500  {
501  $reachedpoints[$row["question_fi"]] = $row["points"];
502  }
503  $atposition = FALSE;
504  $pointsforposition = array();
505  foreach ($sequence->getUserSequence() as $seq)
506  {
507  if (!$atposition)
508  {
509  $qid = $sequence->getQuestionForSequence($seq);
510  if ($qid == $question_id)
511  {
512  $atposition = TRUE;
513  }
514  else
515  {
516  array_push($pointsforposition, $reachedpoints[$qid]);
517  }
518  }
519  }
520  return $pointsforposition;
521  }
522 
532  function getNrOfQuestionsInPass($sid, $active_id, $pass)
533  {
534  $this->initAuth($sid);
535  $this->initIlias();
536 
537  if(!$this->__checkSession($sid))
538  {
539  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
540  }
541  if (!$this->isAllowedCall($sid, $active_id, false))
542  {
543  return $this->__raiseError("The required user information is only available for active users.", "");
544  }
545 
546  global $lng, $ilDB;
547 
548  $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",
549  array('integer'),
550  array($active_id)
551  );
552  if ($result->numRows() != 1) return 0;
553  $row = $ilDB->fetchAssoc($result);
554  $is_random = $row["random_test"];
555 
556  include_once "./Modules/Test/classes/class.ilTestSequence.php";
557  $sequence = new ilTestSequence($active_id, $pass, $is_random);
558  return $sequence->getUserQuestionCount();
559  }
560 
568  public function removeTestResults($sid,$test_ref_id,$a_user_ids)
569  {
570  $this->initAuth($sid);
571  $this->initIlias();
572 
573  if(!$this->__checkSession($sid))
574  {
575  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
576  }
577  if(!strlen($test_ref_id))
578  {
579  return $this->__raiseError('No test id given. Aborting!',
580  'Client');
581  }
582  global $rbacsystem, $tree, $ilLog;
583 
584  if(ilObject::_isInTrash($test_ref_id))
585  {
586  return $this->__raiseError('Test is trashed. Aborting!',
587  'Client');
588  }
589 
590  if(!$tst = ilObjectFactory::getInstanceByRefId($test_ref_id,false))
591  {
592  return $this->__raiseError('No test found for id: '.$test_ref_id,'Client');
593  }
594  if($tst->getType() != 'tst')
595  {
596  return $this->__raiseError('Object with ref_id '.$test_ref_id.' is not of type test. Aborting','Client');
597  }
598 
599  // Dirty hack
600  if(isset($a_user_ids['item']))
601  {
602  $a_user_ids = $a_user_ids['item'];
603  }
604 
605  foreach((array) $a_user_ids as $user_id)
606  {
607  $tst->removeTestResultsForUser($user_id);
608  }
609  return true;
610  }
611 
624  function getTestResults ($sid, $test_ref_id, $sum_only)
625  {
626  $this->initAuth($sid);
627  $this->initIlias();
628 
629  if(!$this->__checkSession($sid))
630  {
631  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
632  }
633  if(!strlen($test_ref_id))
634  {
635  return $this->__raiseError('No test id given. Aborting!',
636  'Client');
637  }
638  global $rbacsystem, $tree, $ilLog;
639 
640  if(ilObject::_isInTrash($test_ref_id))
641  {
642  return $this->__raiseError('Test is trashed. Aborting!',
643  'Client');
644  }
645 
646  // get obj_id
647  if(!$obj_id = ilObject::_lookupObjectId($test_ref_id))
648  {
649  return $this->__raiseError('No test found for id: '.$test_ref_id,
650  'Client');
651  }
652 
653 
654  // Check access
655  $permission_ok = false;
656  foreach($ref_ids = ilObject::_getAllReferences($obj_id) as $ref_id)
657  {
658  if($rbacsystem->checkAccess('write',$ref_id))
659  {
660  $permission_ok = true;
661  break;
662  }
663  }
664  if(!$permission_ok)
665  {
666  return $this->__raiseError('No permission to edit the object with id: '.$test_ref_id,
667  'Server');
668  }
669  // store into xml result set
670  include_once './webservice/soap/classes/class.ilXMLResultSet.php';
671  include_once './webservice/soap/classes/class.ilXMLResultSetWriter.php';
672 
673  $xmlResultSet = new ilXMLResultSet();
674  $xmlResultSet->addColumn("user_id");
675  $xmlResultSet->addColumn("login");
676  $xmlResultSet->addColumn("firstname");
677  $xmlResultSet->addColumn("lastname");
678  $xmlResultSet->addColumn("matriculation");
679 
680  include_once './Modules/Test/classes/class.ilObjTest.php';
681  $test_obj = new ilObjTest($obj_id, false);
682  $participants = $test_obj->getTestParticipants();
683 
684 
685  if ($sum_only)
686  {
687  $data = $test_obj->getAllTestResults($participants, false);
688  // create xml
689  $xmlResultSet->addColumn("maximum_points");
690  $xmlResultSet->addColumn("received_points");
691  // skip titles
692  $titles = array_shift($data);
693  foreach ($data as $row) {
694  $xmlRow = new ilXMLResultSetRow();
695  $xmlRow->setValue(0, $row["user_id"]);
696  $xmlRow->setValue(1, $row["login"]);
697  $xmlRow->setValue(2, $row["firstname"]);
698  $xmlRow->setValue(3, $row["lastname"]);
699  $xmlRow->setValue(4, $row["matriculation"]);
700  $xmlRow->setValue(5, $row["max_points"]);
701  $xmlRow->setValue(6, $row["reached_points"]);
702  $xmlResultSet->addRow($xmlRow);
703  }
704  } else {
705  $data = $test_obj->getDetailedTestResults($participants);
706  // create xml
707  $xmlResultSet->addColumn("question_id");
708  $xmlResultSet->addColumn("question_title");
709  $xmlResultSet->addColumn("maximum_points");
710  $xmlResultSet->addColumn("received_points");
711  foreach ($data as $row) {
712  $xmlRow = new ilXMLResultSetRow();
713  $xmlRow->setValue(0, $row["user_id"]);
714  $xmlRow->setValue(1, $row["login"]);
715  $xmlRow->setValue(2, $row["firstname"]);
716  $xmlRow->setValue(3, $row["lastname"]);
717  $xmlRow->setValue(4, $row["matriculation"]);
718  $xmlRow->setValue(5, $row["question_id"]);
719  $xmlRow->setValue(6, $row["question_title"]);
720  $xmlRow->setValue(7, $row["max_points"]);
721  $xmlRow->setValue(8, $row["reached_points"]);
722  $xmlResultSet->addRow($xmlRow);
723  }
724  }
725  // create writer
726  $xmlWriter = new ilXMLResultSetWriter($xmlResultSet);
727  $xmlWriter->start();
728  return $xmlWriter->getXML();
729  }
730 
731 
732 }
733 ?>