34 $this->questionrepository = TestDIC::dic()[
'general_question_properties_repository'];
44 $ilAccess =
$DIC[
'ilAccess'];
46 $permission_ok =
false;
47 $result =
$ilDB->queryF(
48 "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",
52 $row =
$ilDB->fetchAssoc($result);
54 $obj_id = $row[
'obj_fi'];
56 if ($ilAccess->checkAccess(
"write",
"",
$ref_id)) {
57 $permission_ok =
true;
62 return $permission_ok;
65 public function isAllowedCall(
string $sid,
int $active_id,
bool $saveaction =
true): bool
72 $ilUser =
$DIC[
'ilUser'];
79 $result =
$ilDB->queryF(
80 "SELECT * FROM tst_times WHERE active_fi = %s ORDER BY started DESC",
84 if ($result->numRows()) {
85 $row =
$ilDB->fetchAssoc($result);
86 if (preg_match(
"/(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})/", $row[
"started"], $matches)) {
87 $time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
93 $ilClientIniFile =
$DIC[
'ilClientIniFile'];
94 $expires = $ilClientIniFile->readVariable(
'session',
'expire');
95 return $diff <= $expires;
104 $result =
$ilDB->queryF(
105 "SELECT user_fi FROM tst_active WHERE active_id = %s",
109 $row =
$ilDB->fetchAssoc($result);
111 return (
int) $row[
'user_fi'] === $ilUser->getId();
117 public function saveQuestion(
string $sid,
int $active_id,
int $question_id,
int $pass, array $solution)
126 return $this->
raiseError(
"The required user information is only available for active users.",
"");
132 $ilUser =
$DIC[
'ilUser'];
135 $processLockerFactory->setQuestionId($question_id);
136 $processLockerFactory->setUserId($ilUser->getId());
137 $processLocker = $processLockerFactory->getLocker();
141 $processLocker->executePersistWorkingStateLockOperation(
function () use (
149 $processLocker->executeUserSolutionUpdateLockOperation(
function () use (
157 if (($active_id > 0) && ($question_id > 0) && ($pass > 0)) {
158 $affectedRows =
$ilDB->manipulateF(
159 "DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
160 array(
'integer',
'integer',
'integer'),
161 array($active_id, $question_id, $pass)
164 for ($i = 0, $iMax = count($solution); $i < $iMax; $i += 3) {
165 $next_id =
$ilDB->nextId(
'tst_solutions');
166 $affectedRows =
$ilDB->insert(
"tst_solutions", array(
167 "solution_id" => array(
"integer", $next_id),
168 "active_fi" => array(
"integer", $active_id),
169 "question_fi" => array(
"integer", $question_id),
170 "value1" => array(
"clob", $solution[$i]),
171 "value2" => array(
"clob", $solution[$i + 1]),
172 "points" => array(
"float", $solution[$i + 2]),
173 "pass" => array(
"integer", $pass),
174 "tstamp" => array(
"integer", time())
176 $totalrows += $affectedRows;
180 if ($totalrows !== 0) {
182 $question->setProcessLocker($processLocker);
183 $question->calculateResultsFromSolution($active_id, $pass);
187 if ($totalrows === 0) {
189 "Wrong solution data. ILIAS did not execute any database queries: Solution data: " . print_r(
211 return $this->
raiseError(
"The required user information is only available for active users.",
"");
215 if (preg_match(
"/<values>(.*?)<\/values>/is", $solution, $matches)) {
217 "/<value>(.*?)<\/value><value>(.*?)<\/value><points>(.*?)<\/points>/is",
222 foreach ($matches as $match) {
223 if (count($match) === 4) {
224 for ($i = 1, $iMax = count($match); $i < $iMax; $i++) {
225 $solutions[] = trim($match[$i]);
232 if (count($solutions) === 0) {
234 "Wrong solution data. ILIAS did not find one or more solution triplets: $solution",
240 if (($active_id > 0) && ($question_id > 0) && ($pass > 0)) {
241 $affectedRows =
$ilDB->manipulateF(
242 "DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
243 array(
'integer',
'integer',
'integer'),
244 array($active_id, $question_id, $pass)
248 for ($i = 0, $iMax = count($solutions); $i < $iMax; $i += 3) {
249 $next_id =
$ilDB->nextId(
'tst_solutions');
250 $affectedRows =
$ilDB->insert(
"tst_solutions", array(
251 "solution_id" => array(
"integer", $next_id),
252 "active_fi" => array(
"integer", $active_id),
253 "question_fi" => array(
"integer", $question_id),
254 "value1" => array(
"clob", $solutions[$i]),
255 "value2" => array(
"clob", $solutions[$i + 1]),
256 "points" => array(
"float", $solutions[$i + 2]),
257 "pass" => array(
"integer", $pass),
258 "tstamp" => array(
"integer", time())
260 $totalrows += $affectedRows;
262 if ($totalrows === 0) {
263 return $this->
raiseError(
"Wrong solution data. ILIAS did not execute any database queries",
'');
267 $question->calculateResultsFromSolution($active_id, $pass);
283 return $this->
raiseError(
"The required user information is only available for active users.",
"");
292 $test_obj =
new ilObjTest($test_obj_id,
false);
293 $use_previous_answers = $test_obj->getUsePreviousAnswers();
296 if ($use_previous_answers) {
297 $result =
$ilDB->queryF(
298 "SELECT MAX(pass) maxpass FROM tst_test_result WHERE active_fi = %s AND question_fi = %s",
299 array(
'integer',
'integer'),
300 array($active_id, $question_id)
302 if ($result->numRows() === 1) {
303 $row =
$ilDB->fetchAssoc($result);
304 $lastpass = (
int) $row[
"maxpass"];
310 if (($active_id > 0) && ($question_id > 0) && ($lastpass > 0)) {
311 $result =
$ilDB->queryF(
312 "SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
313 array(
'integer',
'integer',
'integer'),
314 array($active_id, $question_id, $lastpass)
316 if ($result->numRows()) {
317 while ($row =
$ilDB->fetchAssoc($result)) {
318 $solution[] = $row[
"value1"];
319 $solution[] = $row[
"value2"];
320 $solution[] = $row[
"points"];
339 return $this->
raiseError(
"The required user information is only available for active users.",
"");
347 $result =
$ilDB->queryF(
348 "SELECT user_fi, test_fi FROM tst_active WHERE active_id = %s",
352 $row =
$ilDB->fetchAssoc($result);
354 $test_id = $row[
"test_fi"];
357 $test_obj =
new ilObjTest($test_obj_id,
false);
358 $anonymity = $test_obj->getAnonymity();
360 $result =
$ilDB->queryF(
361 "SELECT firstname, lastname, title, login FROM usr_data WHERE usr_id = %s",
367 if ($result->numRows() === 0) {
368 $userdata[
"fullname"] =
$lng->txt(
"deleted_user");
369 $userdata[
"title"] =
"";
370 $userdata[
"firstname"] =
"";
371 $userdata[
"lastname"] =
$lng->txt(
"anonymous");
372 $userdata[
"login"] =
"";
376 $userdata[
"fullname"] =
$lng->txt(
"anonymous");
377 $userdata[
"title"] =
"";
378 $userdata[
"firstname"] =
"";
379 $userdata[
"lastname"] =
$lng->txt(
"anonymous");
380 $userdata[
"login"] =
"";
382 $userdata[
"fullname"] = trim(
$data[
"title"] .
" " .
$data[
"firstname"] .
" " .
$data[
"lastname"]);
383 $userdata[
"title"] =
$data[
"title"];
384 $userdata[
"firstname"] =
$data[
"firstname"];
385 $userdata[
"lastname"] =
$data[
"lastname"];
386 $userdata[
"login"] =
$data[
"login"];
389 return array_values($userdata);
404 return $this->
raiseError(
"The required user information is only available for active users.",
"");
411 return $sequence->getSequenceForQuestion($question_id);
426 return $this->
raiseError(
"The required user information is only available for active users.",
"");
435 $result =
$ilDB->queryF(
436 "SELECT question_fi, points FROM tst_test_result WHERE active_fi = %s AND pass = %s",
437 array(
'integer',
'integer'),
438 array($active_id, $pass)
440 $reachedpoints = array();
441 while ($row =
$ilDB->fetchAssoc($result)) {
442 $reachedpoints[$row[
"question_fi"]] = $row[
"points"];
445 $pointsforposition = array();
446 foreach ($sequence->getUserSequence() as $seq) {
448 $qid = $sequence->getQuestionForSequence($seq);
449 if ($qid == $question_id) {
452 $pointsforposition[] = $reachedpoints[$qid];
456 return $pointsforposition;
471 return $this->
raiseError(
"The required user information is only available for active users.",
"");
480 return $sequence->getUserQuestionCount();
494 if (!($test_ref_id > 0)) {
496 'No test id given. Aborting!',
502 $rbacsystem =
$DIC[
'rbacsystem'];
503 $tree =
$DIC[
'tree'];
504 $ilLog =
$DIC[
'ilLog'];
507 return $this->
raiseError(
'no permission. Aborting!',
'Client');
512 'Test is trashed. Aborting!',
518 return $this->
raiseError(
'No test found for id: ' . $test_ref_id,
'Client');
520 if ($tst->getType() !==
'tst') {
522 'Object with ref_id ' . $test_ref_id .
' is not of type test. Aborting',
528 if (isset($a_user_ids[
'item'])) {
529 $a_user_ids = $a_user_ids[
'item'];
533 $part->setParticipantAccessFilter(
534 ilTestParticipantAccessFilter::getManageParticipantsUserFilter($test_ref_id)
536 $part->setUserIdsFilter((array) $a_user_ids);
537 $part->load($tst->getTestId());
538 $tst->removeTestResults($part);
554 if (!($test_ref_id > 0)) {
556 'No test id given. Aborting!',
562 $rbacsystem =
$DIC[
'rbacsystem'];
563 $tree =
$DIC[
'tree'];
564 $ilLog =
$DIC[
'ilLog'];
568 'Test is trashed. Aborting!',
575 'No test found for id: ' . $test_ref_id,
580 $permission_ok =
false;
582 if ($rbacsystem->checkAccess(
'write',
$ref_id)) {
583 $permission_ok =
true;
591 if (!$permission_ok) {
593 'No permission to edit the object with id: ' . $test_ref_id,
599 $xmlResultSet->addColumn(
"user_id");
600 $xmlResultSet->addColumn(
"login");
601 $xmlResultSet->addColumn(
"firstname");
602 $xmlResultSet->addColumn(
"lastname");
603 $xmlResultSet->addColumn(
"matriculation");
605 $test_obj =
new ilObjTest($obj_id,
false);
606 $participants = $test_obj->getTestParticipants();
608 $accessFilter = ilTestParticipantAccessFilter::getAccessResultsUserFilter($test_ref_id);
610 $participantList->initializeFromDbRows($participants);
611 $participantList = $participantList->getAccessFilteredList($accessFilter);
612 $participantList = $participantList->getScoredParticipantList();
613 foreach ($participants as $activeId => $part) {
614 if ($participantList->isActiveIdInList($activeId)) {
615 $participants[$activeId][
'passed'] = $participantList->getParticipantByActiveId($activeId)->getScoring()->isPassed();
619 unset($participants[$activeId]);
623 $data = $test_obj->getAllTestResults($participants);
625 $xmlResultSet->addColumn(
"maximum_points");
626 $xmlResultSet->addColumn(
"received_points");
627 $xmlResultSet->addColumn(
"passed");
629 $titles = array_shift(
$data);
630 foreach (
$data as $row) {
632 $xmlRow->setValue(0, $row[
"user_id"]);
633 $xmlRow->setValue(1, $row[
"login"]);
634 $xmlRow->setValue(2, $row[
"firstname"]);
635 $xmlRow->setValue(3, $row[
"lastname"]);
636 $xmlRow->setValue(4, $row[
"matriculation"]);
637 $xmlRow->setValue(5, $row[
"max_points"]);
638 $xmlRow->setValue(6, $row[
"reached_points"]);
639 $xmlRow->setValue(7, $row[
"passed"]);
640 $xmlResultSet->addRow($xmlRow);
643 $data = $test_obj->getDetailedTestResults($participants);
645 $xmlResultSet->addColumn(
"question_id");
646 $xmlResultSet->addColumn(
"question_title");
647 $xmlResultSet->addColumn(
"maximum_points");
648 $xmlResultSet->addColumn(
"received_points");
649 $xmlResultSet->addColumn(
"passed");
650 foreach (
$data as $row) {
652 $xmlRow->setValue(0, $row[
"user_id"]);
653 $xmlRow->setValue(1, $row[
"login"]);
654 $xmlRow->setValue(2, $row[
"firstname"]);
655 $xmlRow->setValue(3, $row[
"lastname"]);
656 $xmlRow->setValue(4, $row[
"matriculation"]);
657 $xmlRow->setValue(5, $row[
"question_id"]);
658 $xmlRow->setValue(6, $row[
"question_title"]);
659 $xmlRow->setValue(7, $row[
"max_points"]);
660 $xmlRow->setValue(8, $row[
"reached_points"]);
661 $xmlRow->setValue(9, $row[
"passed"]);
662 $xmlResultSet->addRow($xmlRow);
668 return $xmlWriter->getXML();
673 return $this->
getTestAccess($refId)->checkManageParticipantsAccess();
678 return $this->
getTestAccess($refId)->checkParticipantsResultsAccess();
static instantiateQuestion(int $question_id)
static getLogger(string $a_component_id)
Get component logger.
static _getTestIDFromObjectID(int $object_id)
Returns the ILIAS test id for a given object id.
static _getObjectIDFromTestID($test_id)
Returns the ILIAS test object id for a given test id.
static _lookupTestObjIdForQuestionId(int $q_id)
Get test Object ID for question ID.
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
static _lookupObjectId(int $ref_id)
static _getAllReferences(int $id)
get all reference ids for object ID
static _isInTrash(int $ref_id)
raiseError(string $a_message, $a_code)
checkSession(string $sid)
__construct(bool $use_nusoap=true)
saveQuestionSolution(string $sid, int $active_id, int $question_id, int $pass, int $solution)
getPreviousReachedPoints(string $sid, int $active_id, int $question_id, int $pass)
isAllowedCall(string $sid, int $active_id, bool $saveaction=true)
checkParticipantsResultsAccess(int $refId)
saveQuestion(string $sid, int $active_id, int $question_id, int $pass, array $solution)
getQuestionSolution(string $sid, int $active_id, int $question_id, int $pass)
getPositionOfQuestion(string $sid, int $active_id, int $question_id, int $pass)
getTestAccess(int $refId)
removeTestResults(string $sid, int $test_ref_id, array $a_user_ids)
getTestResults(string $sid, int $test_ref_id, bool $sum_only)
checkManageParticipantsAccess(int $refId)
GeneralQuestionPropertiesRepository $questionrepository
hasWritePermissionForTest(int $active_id)
getTestUserData(string $sid, int $active_id)
getNrOfQuestionsInPass(string $sid, int $active_id, int $pass)
Row Class for XMLResultSet.
XML Writer for XMLResultSet.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc