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 $owner_result =
$ilDB->queryF(
80 "SELECT user_fi FROM tst_active WHERE active_id = %s",
84 $owner_row =
$ilDB->fetchAssoc($owner_result);
85 if (!is_array($owner_row) || (
int) $owner_row[
'user_fi'] !== $ilUser->getId()) {
89 $result =
$ilDB->queryF(
90 "SELECT * FROM tst_times WHERE active_fi = %s ORDER BY started DESC",
94 if ($result->numRows()) {
95 $row =
$ilDB->fetchAssoc($result);
96 if (preg_match(
"/(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})/", $row[
"started"], $matches)) {
97 $time = mktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
103 $ilClientIniFile =
$DIC[
'ilClientIniFile'];
104 $expires = $ilClientIniFile->readVariable(
'session',
'expire');
105 return $diff <= $expires;
114 $result =
$ilDB->queryF(
115 "SELECT user_fi FROM tst_active WHERE active_id = %s",
119 $row =
$ilDB->fetchAssoc($result);
121 return (
int) $row[
'user_fi'] === $ilUser->getId();
127 public function saveQuestion(
string $sid,
int $active_id,
int $question_id,
int $pass, array $solution)
136 return $this->
raiseError(
"The required user information is only available for active users.",
"");
142 $ilUser =
$DIC[
'ilUser'];
145 $processLockerFactory->setQuestionId($question_id);
146 $processLockerFactory->setUserId($ilUser->getId());
147 $processLocker = $processLockerFactory->getLocker();
151 $processLocker->executePersistWorkingStateLockOperation(
function () use (
159 $processLocker->executeUserSolutionUpdateLockOperation(
function () use (
167 if (($active_id > 0) && ($question_id > 0) && ($pass > 0)) {
168 $affectedRows =
$ilDB->manipulateF(
169 "DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
170 array(
'integer',
'integer',
'integer'),
171 array($active_id, $question_id, $pass)
174 for ($i = 0, $iMax = count($solution); $i < $iMax; $i += 3) {
175 $next_id =
$ilDB->nextId(
'tst_solutions');
176 $affectedRows =
$ilDB->insert(
"tst_solutions", array(
177 "solution_id" => array(
"integer", $next_id),
178 "active_fi" => array(
"integer", $active_id),
179 "question_fi" => array(
"integer", $question_id),
180 "value1" => array(
"clob", $solution[$i]),
181 "value2" => array(
"clob", $solution[$i + 1]),
182 "points" => array(
"float", $solution[$i + 2]),
183 "pass" => array(
"integer", $pass),
184 "tstamp" => array(
"integer", time())
186 $totalrows += $affectedRows;
190 if ($totalrows !== 0) {
192 $question->setProcessLocker($processLocker);
193 $question->calculateResultsFromSolution($active_id, $pass);
197 if ($totalrows === 0) {
199 "Wrong solution data. ILIAS did not execute any database queries: Solution data: " . print_r(
221 return $this->
raiseError(
"The required user information is only available for active users.",
"");
225 if (preg_match(
"/<values>(.*?)<\/values>/is", $solution, $matches)) {
227 "/<value>(.*?)<\/value><value>(.*?)<\/value><points>(.*?)<\/points>/is",
232 foreach ($matches as $match) {
233 if (count($match) === 4) {
234 for ($i = 1, $iMax = count($match); $i < $iMax; $i++) {
235 $solutions[] = trim($match[$i]);
242 if (count($solutions) === 0) {
244 "Wrong solution data. ILIAS did not find one or more solution triplets: $solution",
250 if (($active_id > 0) && ($question_id > 0) && ($pass > 0)) {
251 $affectedRows =
$ilDB->manipulateF(
252 "DELETE FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
253 array(
'integer',
'integer',
'integer'),
254 array($active_id, $question_id, $pass)
258 for ($i = 0, $iMax = count($solutions); $i < $iMax; $i += 3) {
259 $next_id =
$ilDB->nextId(
'tst_solutions');
260 $affectedRows =
$ilDB->insert(
"tst_solutions", array(
261 "solution_id" => array(
"integer", $next_id),
262 "active_fi" => array(
"integer", $active_id),
263 "question_fi" => array(
"integer", $question_id),
264 "value1" => array(
"clob", $solutions[$i]),
265 "value2" => array(
"clob", $solutions[$i + 1]),
266 "points" => array(
"float", $solutions[$i + 2]),
267 "pass" => array(
"integer", $pass),
268 "tstamp" => array(
"integer", time())
270 $totalrows += $affectedRows;
272 if ($totalrows === 0) {
273 return $this->
raiseError(
"Wrong solution data. ILIAS did not execute any database queries",
'');
277 $question->calculateResultsFromSolution($active_id, $pass);
293 return $this->
raiseError(
"The required user information is only available for active users.",
"");
302 $test_obj =
new ilObjTest($test_obj_id,
false);
303 $use_previous_answers = $test_obj->getUsePreviousAnswers();
306 if ($use_previous_answers) {
307 $result =
$ilDB->queryF(
308 "SELECT MAX(pass) maxpass FROM tst_test_result WHERE active_fi = %s AND question_fi = %s",
309 array(
'integer',
'integer'),
310 array($active_id, $question_id)
312 if ($result->numRows() === 1) {
313 $row =
$ilDB->fetchAssoc($result);
314 $lastpass = (
int) $row[
"maxpass"];
320 if (($active_id > 0) && ($question_id > 0) && ($lastpass > 0)) {
321 $result =
$ilDB->queryF(
322 "SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s",
323 array(
'integer',
'integer',
'integer'),
324 array($active_id, $question_id, $lastpass)
326 if ($result->numRows()) {
327 while ($row =
$ilDB->fetchAssoc($result)) {
328 $solution[] = $row[
"value1"];
329 $solution[] = $row[
"value2"];
330 $solution[] = $row[
"points"];
349 return $this->
raiseError(
"The required user information is only available for active users.",
"");
357 $result =
$ilDB->queryF(
358 "SELECT user_fi, test_fi FROM tst_active WHERE active_id = %s",
362 $row =
$ilDB->fetchAssoc($result);
364 $test_id = $row[
"test_fi"];
367 $test_obj =
new ilObjTest($test_obj_id,
false);
368 $anonymity = $test_obj->getAnonymity();
370 $result =
$ilDB->queryF(
371 "SELECT firstname, lastname, title, login FROM usr_data WHERE usr_id = %s",
377 if ($result->numRows() === 0) {
378 $userdata[
"fullname"] =
$lng->txt(
"deleted_user");
379 $userdata[
"title"] =
"";
380 $userdata[
"firstname"] =
"";
381 $userdata[
"lastname"] =
$lng->txt(
"anonymous");
382 $userdata[
"login"] =
"";
386 $userdata[
"fullname"] =
$lng->txt(
"anonymous");
387 $userdata[
"title"] =
"";
388 $userdata[
"firstname"] =
"";
389 $userdata[
"lastname"] =
$lng->txt(
"anonymous");
390 $userdata[
"login"] =
"";
392 $userdata[
"fullname"] = trim(
$data[
"title"] .
" " .
$data[
"firstname"] .
" " .
$data[
"lastname"]);
393 $userdata[
"title"] =
$data[
"title"];
394 $userdata[
"firstname"] =
$data[
"firstname"];
395 $userdata[
"lastname"] =
$data[
"lastname"];
396 $userdata[
"login"] =
$data[
"login"];
399 return array_values($userdata);
414 return $this->
raiseError(
"The required user information is only available for active users.",
"");
421 return $sequence->getSequenceForQuestion($question_id);
436 return $this->
raiseError(
"The required user information is only available for active users.",
"");
445 $result =
$ilDB->queryF(
446 "SELECT question_fi, points FROM tst_test_result WHERE active_fi = %s AND pass = %s",
447 array(
'integer',
'integer'),
448 array($active_id, $pass)
450 $reachedpoints = array();
451 while ($row =
$ilDB->fetchAssoc($result)) {
452 $reachedpoints[$row[
"question_fi"]] = $row[
"points"];
455 $pointsforposition = array();
456 foreach ($sequence->getUserSequence() as $seq) {
458 $qid = $sequence->getQuestionForSequence($seq);
459 if ($qid == $question_id) {
462 $pointsforposition[] = $reachedpoints[$qid];
466 return $pointsforposition;
481 return $this->
raiseError(
"The required user information is only available for active users.",
"");
490 return $sequence->getUserQuestionCount();
504 if (!($test_ref_id > 0)) {
506 'No test id given. Aborting!',
512 $rbacsystem =
$DIC[
'rbacsystem'];
513 $tree =
$DIC[
'tree'];
514 $ilLog =
$DIC[
'ilLog'];
517 return $this->
raiseError(
'no permission. Aborting!',
'Client');
522 'Test is trashed. Aborting!',
528 return $this->
raiseError(
'No test found for id: ' . $test_ref_id,
'Client');
530 if ($tst->getType() !==
'tst') {
532 'Object with ref_id ' . $test_ref_id .
' is not of type test. Aborting',
538 if (isset($a_user_ids[
'item'])) {
539 $a_user_ids = $a_user_ids[
'item'];
543 $part->setParticipantAccessFilter(
544 ilTestParticipantAccessFilter::getManageParticipantsUserFilter($test_ref_id)
546 $part->setUserIdsFilter((array) $a_user_ids);
547 $part->load($tst->getTestId());
548 $tst->removeTestResults($part);
564 if (!($test_ref_id > 0)) {
566 'No test id given. Aborting!',
572 $rbacsystem =
$DIC[
'rbacsystem'];
573 $tree =
$DIC[
'tree'];
574 $ilLog =
$DIC[
'ilLog'];
578 'Test is trashed. Aborting!',
585 'No test found for id: ' . $test_ref_id,
590 $permission_ok =
false;
592 if ($rbacsystem->checkAccess(
'write',
$ref_id)) {
593 $permission_ok =
true;
601 if (!$permission_ok) {
603 'No permission to edit the object with id: ' . $test_ref_id,
609 $xmlResultSet->addColumn(
"user_id");
610 $xmlResultSet->addColumn(
"login");
611 $xmlResultSet->addColumn(
"firstname");
612 $xmlResultSet->addColumn(
"lastname");
613 $xmlResultSet->addColumn(
"matriculation");
615 $test_obj =
new ilObjTest($obj_id,
false);
616 $participants = $test_obj->getTestParticipants();
618 $accessFilter = ilTestParticipantAccessFilter::getAccessResultsUserFilter($test_ref_id);
620 $participantList->initializeFromDbRows($participants);
621 $participantList = $participantList->getAccessFilteredList($accessFilter);
622 $participantList = $participantList->getScoredParticipantList();
623 foreach ($participants as $activeId => $part) {
624 if ($participantList->isActiveIdInList($activeId)) {
625 $participants[$activeId][
'passed'] = $participantList->getParticipantByActiveId($activeId)->getScoring()->isPassed();
629 unset($participants[$activeId]);
633 $data = $test_obj->getAllTestResults($participants);
635 $xmlResultSet->addColumn(
"maximum_points");
636 $xmlResultSet->addColumn(
"received_points");
637 $xmlResultSet->addColumn(
"passed");
639 $titles = array_shift(
$data);
640 foreach (
$data as $row) {
642 $xmlRow->setValue(0, $row[
"user_id"]);
643 $xmlRow->setValue(1, $row[
"login"]);
644 $xmlRow->setValue(2, $row[
"firstname"]);
645 $xmlRow->setValue(3, $row[
"lastname"]);
646 $xmlRow->setValue(4, $row[
"matriculation"]);
647 $xmlRow->setValue(5, $row[
"max_points"]);
648 $xmlRow->setValue(6, $row[
"reached_points"]);
649 $xmlRow->setValue(7, $row[
"passed"]);
650 $xmlResultSet->addRow($xmlRow);
653 $data = $test_obj->getDetailedTestResults($participants);
655 $xmlResultSet->addColumn(
"question_id");
656 $xmlResultSet->addColumn(
"question_title");
657 $xmlResultSet->addColumn(
"maximum_points");
658 $xmlResultSet->addColumn(
"received_points");
659 $xmlResultSet->addColumn(
"passed");
660 foreach (
$data as $row) {
662 $xmlRow->setValue(0, $row[
"user_id"]);
663 $xmlRow->setValue(1, $row[
"login"]);
664 $xmlRow->setValue(2, $row[
"firstname"]);
665 $xmlRow->setValue(3, $row[
"lastname"]);
666 $xmlRow->setValue(4, $row[
"matriculation"]);
667 $xmlRow->setValue(5, $row[
"question_id"]);
668 $xmlRow->setValue(6, $row[
"question_title"]);
669 $xmlRow->setValue(7, $row[
"max_points"]);
670 $xmlRow->setValue(8, $row[
"reached_points"]);
671 $xmlRow->setValue(9, $row[
"passed"]);
672 $xmlResultSet->addRow($xmlRow);
678 return $xmlWriter->getXML();
683 return $this->
getTestAccess($refId)->checkManageParticipantsAccess();
688 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