19 require_once
'./Modules/TestQuestionPool/classes/class.assQuestion.php';
20 require_once
'./Modules/Test/classes/inc.AssessmentConstants.php';
21 require_once
'./Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
22 require_once
'./Modules/TestQuestionPool/interfaces/interface.ilObjFileHandlingQuestionType.php';
103 $ilDB = $DIC[
'ilDB'];
107 array( $this->
getId() )
111 ) .
" (question_fi, maxsize, allowedextensions, compl_by_submission) VALUES (%s, %s, %s, %s)",
112 array(
"integer",
"float",
"text",
"integer" ),
130 $ilDB = $DIC[
'ilDB'];
138 $this->
setId($question_id);
149 include_once(
"./Services/RTE/classes/class.ilRTE.php");
167 parent::loadFromDb($question_id);
175 if ($this->
id <= 0) {
180 $this_id = $this->
getId();
184 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
188 if ((
int) $testObjId > 0) {
189 $clone->setObjId($testObjId);
210 $clone->copyPageOfQuestion($this_id);
212 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
214 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
224 if ($this->
id <= 0) {
230 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
233 $source_questionpool_id = $this->
getObjId();
234 $clone->setObjId($target_questionpool_id);
245 $clone->onCopy($source_questionpool_id,
$original_id, $clone->getObjId(), $clone->getId());
252 if ($this->
id <= 0) {
257 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
260 $sourceParentId = $this->
getObjId();
266 $clone->setObjId($targetParentId);
268 if ($targetQuestionTitle) {
269 $clone->setTitle($targetQuestionTitle);
274 $clone->copyPageOfQuestion($sourceQuestionId);
276 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
278 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
305 if ($returndetails) {
306 throw new ilTestException(
'return details not implemented for ' . __METHOD__);
310 if (is_null(
$pass)) {
346 $this->lng->loadLanguageModule(
"form");
348 $_FILES[
"upload"][
"name"] = rtrim($_FILES[
"upload"][
"name"],
'/');
351 $filename_arr = pathinfo($_FILES[
"upload"][
"name"]);
352 $suffix = $filename_arr[
"extension"];
353 $mimetype = $_FILES[
"upload"][
"type"];
354 $size_bytes = $_FILES[
"upload"][
"size"];
355 $temp_name = $_FILES[
"upload"][
"tmp_name"];
356 $error = $_FILES[
"upload"][
"error"];
366 case UPLOAD_ERR_INI_SIZE:
371 case UPLOAD_ERR_FORM_SIZE:
376 case UPLOAD_ERR_PARTIAL:
381 case UPLOAD_ERR_NO_FILE:
386 case UPLOAD_ERR_NO_TMP_DIR:
391 case UPLOAD_ERR_CANT_WRITE:
396 case UPLOAD_ERR_EXTENSION:
405 if (!strlen($suffix)) {
417 if (strlen($temp_name)) {
419 if ($vir[0] ==
false) {
420 ilUtil::sendFailure($this->lng->txt(
"form_msg_file_virus_found") .
"<br />" . $vir[1],
true);
432 if (is_null($question_id)) {
433 $question_id = $this->
getId();
435 return CLIENT_WEB_DIR .
"/assessment/tst_$test_id/$active_id/$question_id/files/";
443 return CLIENT_WEB_DIR .
"/assessment/qst_preview/$userId/{$this->getId()}/fileuploads/";
453 if (is_null($question_id)) {
454 $question_id = $this->
getId();
456 include_once
"./Services/Utilities/classes/class.ilUtil.php";
466 include_once
"./Services/Utilities/classes/class.ilUtil.php";
479 $ilDB = $DIC[
'ilDB'];
481 if (is_null(
$pass)) {
486 "SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s AND authorized = %s AND value1 IS NOT NULL ORDER BY tstamp",
487 array(
"integer",
"integer",
"integer",
'integer'),
488 array($active_id, $this->
getId(),
$pass, (
int) $authorized)
494 array_push($found,
$data);
513 $ilDB = $DIC[
'ilDB'];
517 "SELECT test_fi FROM tst_active WHERE active_id = %s",
525 foreach ($found as $idx =>
$data) {
526 $found[$idx][
'webpath'] = $path;
540 $ilDB = $DIC[
'ilDB'];
544 foreach ($files as $solution_id) {
546 "SELECT * FROM tst_solutions WHERE solution_id = %s AND authorized = %s",
547 array(
"integer",
'integer'),
548 array($solution_id, (
int) $authorized)
553 $active_id =
$data[
'active_fi'];
557 foreach ($files as $solution_id) {
558 $affectedRows =
$ilDB->manipulateF(
559 "DELETE FROM tst_solutions WHERE solution_id = %s AND authorized = %s",
560 array(
"integer",
'integer'),
561 array($solution_id, $authorized)
573 protected function deleteUnusedFiles(
$test_id, $active_id,
$pass)
578 $solutions = array_merge(
585 $used_files = array();
586 foreach ($solutions as $solution) {
587 $used_files[] = $solution[
'value1'];
593 if (is_dir($uploadPath) && is_readable($uploadPath)) {
594 $iter = new \RegexIterator(
new \
DirectoryIterator($uploadPath),
'/^file_' . $active_id .
'_' .
$pass .
'_(.*)/');
595 foreach ($iter as $file) {
597 if ($file->isFile() && !in_array($file->getFilename(), $used_files)) {
598 unlink($file->getPathname());
607 foreach ($files as
$name) {
608 if (isset($userSolution[$name])) {
609 unset($userSolution[$name]);
614 return $userSolution;
626 $max_filesize = sprintf(
"%d Bytes",
$size);
627 } elseif (
$size < 1024 * 1024) {
628 $max_filesize = sprintf(
"%.1f KB",
$size / 1024);
630 $max_filesize = sprintf(
"%.1f MB",
$size / 1024 / 1024);
633 return $max_filesize;
647 $umf = get_cfg_var(
"upload_max_filesize");
649 $pms = get_cfg_var(
"post_max_size");
652 $multiplier_a = array(
"K" => 1024,
"M" => 1024 * 1024,
"G" => 1024 * 1024 * 1024);
654 $umf_parts = preg_split(
"/(\d+)([K|G|M])/", $umf, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
655 $pms_parts = preg_split(
"/(\d+)([K|G|M])/", $pms, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
657 if (count($umf_parts) == 2) {
658 $umf = $umf_parts[0] * $multiplier_a[$umf_parts[1]];
660 if (count($pms_parts) == 2) {
661 $pms = $pms_parts[0] * $multiplier_a[$pms_parts[1]];
665 $max_filesize = min($umf, $pms);
667 if (!$max_filesize) {
668 $max_filesize = max($umf, $pms);
670 return $max_filesize;
692 $entered_values =
false;
694 $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use (&$entered_values, $uploadHandlingRequired,
$test_id, $active_id,
$pass, $authorized) {
695 if ($authorized ==
false) {
701 foreach (
$_POST[self::DELETE_FILES_TBL_POSTVAR] as $solution_id) {
709 foreach (
$_POST[self::REUSE_FILES_TBL_POSTVAR] as $solutionId) {
723 if ($uploadHandlingRequired) {
728 $solutionFileVersioningUploadTS = time();
729 $filename_arr = pathinfo($_FILES[
"upload"][
"name"]);
730 $extension = $filename_arr[
"extension"];
731 $newfile =
"file_" . $active_id .
"_" .
$pass .
"_" . $solutionFileVersioningUploadTS .
"." . $extension;
733 include_once
'Services/Utilities/classes/class.ilFileUtils.php';
745 $solutionFileVersioningUploadTS
748 $entered_values =
true;
764 if ($entered_values) {
765 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
770 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
791 if (!count($solution)) {
795 foreach ($solution as $row) {
796 if (!empty($row[
'value1'])) {
800 $solution = $cleaned;
818 $ilDB = $DIC[
'ilDB'];
820 $result = parent::removeIntermediateSolution($active_id,
$pass);
838 if (!is_array($userSolution)) {
839 $userSolution = array();
862 $filename_arr = pathinfo($_FILES[
"upload"][
"name"]);
863 $extension = $filename_arr[
"extension"];
864 $newfile =
"file_" . md5($_FILES[
"upload"][
"name"]) .
"_" . $version .
"." . $extension;
867 $userSolution[$newfile] = array(
868 'solution_id' => $newfile,
869 'value1' => $newfile,
870 'value2' => $_FILES[
'upload'][
'name'],
871 'tstamp' => $version,
910 include_once
'Modules/Test/classes/class.ilObjTestAccess.php';
911 include_once
'Services/Tracking/classes/class.ilLPStatusWrapper.php';
926 return "assFileUpload";
936 return "qpl_qst_fileupload";
964 $text = parent::getRTETextWithMediaObjects();
973 parent::setExportDetailsXLS($worksheet, $startrow, $active_id,
$pass);
977 foreach ($solutions as $solution) {
978 $worksheet->setCell($startrow +
$i, 0, $this->lng->txt(
"result"));
979 $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow +
$i));
980 if (strlen($solution[
"value1"])) {
981 $worksheet->setCell($startrow +
$i, 2, $solution[
"value1"]);
982 $worksheet->setCell($startrow +
$i, 3, $solution[
"value2"]);
987 return $startrow +
$i + 1;
1002 public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping, array $solutionhints = [])
1004 include_once
"./Modules/TestQuestionPool/classes/import/qti12/class.assFileUploadImport.php";
1006 $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
1015 public function toXML($a_include_header =
true, $a_include_binary =
true, $a_shuffle =
false, $test_output =
false, $force_image_references =
false)
1017 include_once
"./Modules/TestQuestionPool/classes/export/qti12/class.assFileUploadExport.php";
1019 return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
1029 $user_solution = array();
1030 return $user_solution;
1050 $this->maxsize = $a_value;
1060 if (strlen($this->allowedextensions)) {
1061 return array_filter(array_map(
'trim', explode(
",", $this->allowedextensions)));
1083 $this->allowedextensions = strtolower(trim($a_value));
1095 case "allowedextensions":
1098 case 'completion_by_submission':
1102 return parent::__get($value);
1116 case "allowedextensions":
1119 case 'completion_by_submission':
1123 parent::__set($key, $value);
1138 $ilDB = $DIC[
'ilDB'];
1140 SELECT tst_solutions.solution_id 1141 FROM tst_solutions, tst_active, qpl_questions 1142 WHERE tst_solutions.active_fi = tst_active.active_id 1143 AND tst_solutions.question_fi = qpl_questions.question_id 1144 AND tst_solutions.question_fi = %s AND tst_active.test_fi = %s 1145 AND tst_solutions.value1 is not null";
1148 array(
"integer",
"integer"),
1166 $ilDB = $DIC[
'ilDB'];
1169 require_once
'Modules/TestQuestionPool/classes/class.ilAssFileUploadUploadsExporter.php';
1172 $exporter->setRefId($ref_id);
1174 $exporter->setTestTitle($test_title);
1175 $exporter->setQuestion($this);
1180 $exporter->getFinalZipFilePath(),
1181 $exporter->getDispoZipFileName(),
1182 $exporter->getZipFileMimeType(),
1212 $this->completion_by_submission = (bool) $bool;
1231 return $numExistingSolutionRecords > 0;
1266 return parent::buildTestPresentationConfig()
1268 ->setFormChangeDetectionEnabled(
false);
1278 require_once
'Modules/TestQuestionPool/classes/questions/class.ilAssFileUploadFileTableDeleteButton.php';
1319 if (!isset($_FILES[
'upload'])) {
1323 if (!isset($_FILES[
'upload'][
'tmp_name'])) {
1327 return strlen($_FILES[
'upload'][
'tmp_name']) > 0;
getPreviewFileUploadPathWeb($userId)
Returns the filesystem path for file uploads.
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
static makeDirParents($a_dir)
Create a new directory and all parent directories.
static logAction($logtext="", $active_id="", $question_id="")
Logs an action into the Test&Assessment log.
getId()
Gets the id of the assQuestion object.
getAllowedExtensions()
Get allowed file extensions.
static getInstance($identifier)
savePreviewData(ilAssQuestionPreviewSession $previewSession)
static _getOriginalId($question_id)
Returns the original id of a question.
setSuggestedSolution($solution_id="", $subquestion_index=0, $is_import=false)
Sets a suggested solution for the question.
Class for file upload question exports.
saveWorkingData($active_id, $pass=null, $authorized=true)
Saves the learners input of the question to the database.
deliverFileUploadZIPFile($ref_id, $test_id, $test_title)
Generates a ZIP file containing all file uploads for a given test and the original id of the question...
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
setAllowedExtensions($a_value)
Set allowed file extensions.
forceExistingIntermediateSolution($activeId, $passIndex, $considerDummyRecordCreation)
deleteUploadedFiles($files, $test_id, $active_id, $authorized)
Delete uploaded files.
static getNumExistingSolutionRecords($activeId, $pass, $questionId)
returns the number of existing solution records for the given test active / pass and given question i...
__set($key, $value)
Object setter.
static virusHandling($a_file, $a_orig_name="", $a_clean=true)
scan file for viruses and clean files if possible
static _getParticipantId($active_id)
Get user id for active id.
hasFileUploads($test_id)
Checks if file uploads exist for a given test and the original id of the question.
getPoints()
Returns the maximum available points for the question.
getBestSolution($active_id, $pass)
Returns the best solution for a given pass of a participant.
$completion_by_submission
Abstract basic class which is to be extended by the concrete assessment question type classes...
setExportDetailsXLS($worksheet, $startrow, $active_id, $pass)
{}
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
intermediateSolutionExists($active_id, $pass)
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
deleteDummySolutionRecord($activeId, $passIndex)
static isObligationPossible($questionId)
returns boolean wether it is possible to set this question type as obligatory or not considering the ...
getSolutionValues($active_id, $pass=null, $authorized=true)
Loads solutions of a given user from the database an returns it.
setId($id=-1)
Sets the id of the assQuestion object.
fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping, array $solutionhints=[])
Creates a question from a QTI file.
getSolutionMaxPass($active_id)
Returns the maximum pass a users question solution.
Interface ilObjFileHandlingQuestionType.
setEstimatedWorkingTime($hour=0, $min=0, $sec=0)
Sets the estimated working time of a question from given hour, minute and second. ...
isComplete()
Returns true, if the question is complete for use.
getParticipantsSolution()
deletePreviewFileUploads($userId, $userSolution, $files)
setNrOfTries($a_nr_of_tries)
const REUSE_FILES_TBL_POSTVAR
copyObject($target_questionpool_id, $title="")
Copies an assFileUpload object.
setAdditionalContentEditingMode($additinalContentEditingMode)
setter for additional content editing mode for this question
getFileUploadPathWeb($test_id, $active_id, $question_id=null)
Returns the file upload path for web accessible files of a question.
static _getObjectIDFromActiveID($active_id)
Returns the ILIAS test object id for a given active id.
isFileReuseHandlingRequired()
static _replaceMediaObjectImageSrc($a_text, $a_direction=0, $nic=IL_INST_ID)
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getMaxSize()
Get max file size.
handleSubmission($active_id, $pass, $obligationsAnswered, $authorized)
This method is called after an user submitted one or more files.
getObjId()
Get the object id of the container object.
getAllowedExtensionsArray()
Get allowed file extensions.
static _getMaximumPoints($question_id)
Returns the maximum points, a learner can reach answering the question.
Class for file upload question imports.
Base Exception for all Exceptions relating to Modules/Test.
duplicate($for_test=true, $title="", $author="", $owner="", $testObjId=null)
Duplicates an assFileUpload.
saveToDb($original_id="")
Saves a assFileUpload object to a database.
setParticipantsSolution($participantSolution)
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
removeSolutionRecordById($solutionId)
static _getLogLanguage()
retrieve the log language for assessment logging
setAuthor($author="")
Sets the authors name of the assQuestion object.
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
const DELETE_FILES_TBL_POSTVAR
updateCurrentSolutionsAuthorization($activeId, $pass, $authorized, $keepTime=false)
getUserSolutionPreferingIntermediate($active_id, $pass=null)
Get the user solution preferring the intermediate solution.
saveCurrentSolution($active_id, $pass, $value1, $value2, $authorized=true, $tstamp=null)
static moveUploadedFile($a_file, $a_name, $a_target, $a_raise_errors=true, $a_mode="move_uploaded")
move uploaded file
getMaxFilesizeAsString()
Return the maximum allowed file size as string.
checkUpload()
Check file upload.
calculateReachedPointsForSolution($userSolution)
getPreviewFileUploads(ilAssQuestionPreviewSession $previewSession)
getQuestionType()
Returns the question type of the question.
setMaxSize($a_value)
Set max file size.
removeIntermediateSolution($active_id, $pass)
Remove an intermediate soluton (overridden to remove unused fies)
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
static removeTrailingPathSeparators($path)
getUploadedFilesForWeb($active_id, $pass)
Returns the web accessible uploaded files for an active user in a given pass.
isDummySolutionRecord($solutionRecord)
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
setPoints($a_points)
Sets the maximum available points for the question.
saveQuestionDataToDb($original_id="")
buildTestPresentationConfig()
Get the test question configuration Overridden from parent to disable the form change detection Other...
toXML($a_include_header=true, $a_include_binary=true, $a_shuffle=false, $test_output=false, $force_image_references=false)
Returns a QTI xml representation of the question and sets the internal domxml variable with the DOM X...
getPreviewFileUploadPath($userId)
Returns the filesystem path for file uploads.
getFileUploadPath($test_id, $active_id, $question_id=null)
Returns the filesystem path for file uploads.
getAnswerTableName()
Returns the name of the answer table in the database.
setQuestion($question="")
Sets the question string of the question object.
Interface ilObjQuestionScoringAdjustable.
removeCurrentSolution($active_id, $pass, $authorized=true)
ensureCurrentTestPass($active_id, $pass)
__construct(Container $dic, ilPlugin $plugin)
getTestPresentationConfig()
Get the test question configuration (initialised once)
setOriginalId($original_id)
getCurrentSolutionResultSet($active_id, $pass, $authorized=true)
Get a restulset for the current user solution for a this question by active_id and pass...
getAdditionalTableName()
Returns the name of the additional question data table in the database.
setLifecycle(ilAssQuestionLifecycle $lifecycle)
loadFromDb($question_id)
Loads a assFileUpload object from a database.
getUploadedFiles($active_id, $pass=null, $authorized=true)
Returns the uploaded files for an active user in a given pass.
isFileDeletionSubmitAvailable()
__construct( $title="", $comment="", $author="", $owner=-1, $question="")
assFileUpload constructor
getMaxFilesizeInBytes()
Return the maximum allowed file size in bytes.
setCompletionBySubmission($bool)
Enabled/Disable completion by submission.
setTitle($title="")
Sets the title string of the assQuestion object.
setObjId($obj_id=0)
Set the object id of the container object.
setComment($comment="")
Sets the comment string of the assQuestion object.
__get($value)
Object getter.
static _setReachedPoints($active_id, $question_id, $points, $maxpoints, $pass, $manualscoring, $obligationsEnabled)
Sets the points, a learner has reached answering the question Additionally objective results are upda...
static getDraftInstance()
static getValidFilename($a_filename)
Get valid filename.
deleteAnswers($question_id)
Deletes datasets from answers tables.
static deliverFile( $a_file, $a_filename, $a_mime='', $isInline=false, $removeAfterDelivery=false, $a_exit_after=true)
deliver file for download via browser.
isNonEmptyItemListPostSubmission($postSubmissionFieldname)
setOwner($owner="")
Sets the creator/owner ID of the assQuestion object.
isCompletionBySubmissionEnabled()
Checks whether completion by submission is enabled or not.
isAnswered($active_id, $pass=null)
returns boolean wether the question is answered during test pass or not
getSolutionRecordById($solutionId)
isFileReuseSubmitAvailable()