4 require_once
'./Modules/TestQuestionPool/classes/class.assQuestion.php';
5 require_once
'./Modules/Test/classes/inc.AssessmentConstants.php';
6 require_once
'./Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
7 require_once
'./Modules/TestQuestionPool/interfaces/interface.ilObjFileHandlingQuestionType.php';
92 array( $this->
getId() )
96 ) .
" (question_fi, maxsize, allowedextensions, compl_by_submission) VALUES (%s, %s, %s, %s)",
97 array(
"integer",
"float",
"text",
"integer" ),
115 $ilDB = $DIC[
'ilDB'];
123 $this->
setId($question_id);
134 include_once(
"./Services/RTE/classes/class.ilRTE.php");
146 parent::loadFromDb($question_id);
154 if ($this->
id <= 0) {
159 $this_id = $this->
getId();
163 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
167 if ((
int) $testObjId > 0) {
168 $clone->setObjId($testObjId);
189 $clone->copyPageOfQuestion($this_id);
191 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
193 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
203 if ($this->
id <= 0) {
209 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
212 $source_questionpool_id = $this->
getObjId();
213 $clone->setObjId($target_questionpool_id);
224 $clone->onCopy($source_questionpool_id,
$original_id, $clone->getObjId(), $clone->getId());
231 if ($this->
id <= 0) {
236 include_once(
"./Modules/TestQuestionPool/classes/class.assQuestion.php");
239 $sourceParentId = $this->
getObjId();
245 $clone->setObjId($targetParentId);
247 if ($targetQuestionTitle) {
248 $clone->setTitle($targetQuestionTitle);
253 $clone->copyPageOfQuestion($sourceQuestionId);
255 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
257 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
284 if ($returndetails) {
285 throw new ilTestException(
'return details not implemented for ' . __METHOD__);
289 if (is_null(
$pass)) {
325 $this->lng->loadLanguageModule(
"form");
327 $_FILES[
"upload"][
"name"] = rtrim($_FILES[
"upload"][
"name"],
'/');
330 $filename_arr = pathinfo($_FILES[
"upload"][
"name"]);
331 $suffix = $filename_arr[
"extension"];
332 $mimetype = $_FILES[
"upload"][
"type"];
333 $size_bytes = $_FILES[
"upload"][
"size"];
334 $temp_name = $_FILES[
"upload"][
"tmp_name"];
335 $error = $_FILES[
"upload"][
"error"];
345 case UPLOAD_ERR_INI_SIZE:
350 case UPLOAD_ERR_FORM_SIZE:
355 case UPLOAD_ERR_PARTIAL:
360 case UPLOAD_ERR_NO_FILE:
365 case UPLOAD_ERR_NO_TMP_DIR:
370 case UPLOAD_ERR_CANT_WRITE:
375 case UPLOAD_ERR_EXTENSION:
384 if (!strlen($suffix)) {
396 if (strlen($temp_name)) {
398 if ($vir[0] ==
false) {
399 ilUtil::sendFailure($this->lng->txt(
"form_msg_file_virus_found") .
"<br />" . $vir[1],
true);
411 if (is_null($question_id)) {
412 $question_id = $this->
getId();
414 return CLIENT_WEB_DIR .
"/assessment/tst_$test_id/$active_id/$question_id/files/";
422 return CLIENT_WEB_DIR .
"/assessment/qst_preview/$userId/{$this->getId()}/fileuploads/";
432 if (is_null($question_id)) {
433 $question_id = $this->
getId();
435 include_once
"./Services/Utilities/classes/class.ilUtil.php";
445 include_once
"./Services/Utilities/classes/class.ilUtil.php";
458 $ilDB = $DIC[
'ilDB'];
460 if (is_null(
$pass)) {
465 "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",
466 array(
"integer",
"integer",
"integer",
'integer'),
467 array($active_id, $this->
getId(),
$pass, (
int) $authorized)
473 array_push($found,
$data);
492 $ilDB = $DIC[
'ilDB'];
496 "SELECT test_fi FROM tst_active WHERE active_id = %s",
504 foreach ($found as $idx =>
$data) {
505 $found[$idx][
'webpath'] =
$path;
519 $ilDB = $DIC[
'ilDB'];
523 foreach (
$files as $solution_id) {
525 "SELECT * FROM tst_solutions WHERE solution_id = %s AND authorized = %s",
526 array(
"integer",
'integer'),
527 array($solution_id, (
int) $authorized)
532 $active_id =
$data[
'active_fi'];
536 foreach (
$files as $solution_id) {
537 $affectedRows =
$ilDB->manipulateF(
538 "DELETE FROM tst_solutions WHERE solution_id = %s AND authorized = %s",
539 array(
"integer",
'integer'),
540 array($solution_id, $authorized)
552 protected function deleteUnusedFiles(
$test_id, $active_id,
$pass)
557 $solutions = array_merge(
564 $used_files = array();
565 foreach ($solutions as $solution) {
566 $used_files[] = $solution[
'value1'];
572 if (is_dir($uploadPath) && is_readable($uploadPath)) {
573 $iter = new \RegexIterator(
new \
DirectoryIterator($uploadPath),
'/^file_' . $active_id .
'_' .
$pass .
'_(.*)/');
574 foreach ($iter as $file) {
576 if ($file->isFile() && !in_array($file->getFilename(), $used_files)) {
577 unlink($file->getPathname());
587 if (isset($userSolution[$name])) {
588 unset($userSolution[$name]);
593 return $userSolution;
605 $max_filesize = sprintf(
"%d Bytes",
$size);
606 } elseif (
$size < 1024 * 1024) {
607 $max_filesize = sprintf(
"%.1f KB",
$size / 1024);
609 $max_filesize = sprintf(
"%.1f MB",
$size / 1024 / 1024);
612 return $max_filesize;
626 $umf = get_cfg_var(
"upload_max_filesize");
628 $pms = get_cfg_var(
"post_max_size");
631 $multiplier_a = array(
"K" => 1024,
"M" => 1024 * 1024,
"G" => 1024 * 1024 * 1024);
633 $umf_parts = preg_split(
"/(\d+)([K|G|M])/", $umf, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
634 $pms_parts = preg_split(
"/(\d+)([K|G|M])/", $pms, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
636 if (count($umf_parts) == 2) {
637 $umf = $umf_parts[0] * $multiplier_a[$umf_parts[1]];
639 if (count($pms_parts) == 2) {
640 $pms = $pms_parts[0] * $multiplier_a[$pms_parts[1]];
644 $max_filesize = min($umf, $pms);
646 if (!$max_filesize) {
647 $max_filesize = max($umf, $pms);
649 return $max_filesize;
671 $entered_values =
false;
673 $this->
getProcessLocker()->executeUserSolutionUpdateLockOperation(
function () use (&$entered_values, $uploadHandlingRequired,
$test_id, $active_id,
$pass, $authorized) {
674 if ($authorized ==
false) {
680 foreach (
$_POST[self::DELETE_FILES_TBL_POSTVAR] as $solution_id) {
688 foreach (
$_POST[self::REUSE_FILES_TBL_POSTVAR] as $solutionId) {
702 if ($uploadHandlingRequired) {
707 $solutionFileVersioningUploadTS = time();
708 $filename_arr = pathinfo($_FILES[
"upload"][
"name"]);
709 $extension = $filename_arr[
"extension"];
710 $newfile =
"file_" . $active_id .
"_" .
$pass .
"_" . $solutionFileVersioningUploadTS .
"." . $extension;
712 include_once
'Services/Utilities/classes/class.ilFileUtils.php';
716 ilUtil::moveUploadedFile($_FILES[
"upload"][
"tmp_name"], $_FILES[
"upload"][
"name"], $this->
getFileUploadPath(
$test_id, $active_id) . $newfile);
724 $solutionFileVersioningUploadTS
727 $entered_values =
true;
743 if ($entered_values) {
744 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
749 include_once(
"./Modules/Test/classes/class.ilObjAssessmentFolder.php");
770 if (!count($solution)) {
774 foreach ($solution as
$row) {
775 if (!empty($row[
'value1'])) {
779 $solution = $cleaned;
797 $ilDB = $DIC[
'ilDB'];
799 $result = parent::removeIntermediateSolution($active_id,
$pass);
817 if (!is_array($userSolution)) {
818 $userSolution = array();
841 $filename_arr = pathinfo($_FILES[
"upload"][
"name"]);
842 $extension = $filename_arr[
"extension"];
843 $newfile =
"file_" . md5($_FILES[
"upload"][
"name"]) .
"_" .
$version .
"." . $extension;
846 $userSolution[$newfile] = array(
847 'solution_id' => $newfile,
848 'value1' => $newfile,
849 'value2' => $_FILES[
'upload'][
'name'],
889 include_once
'Modules/Test/classes/class.ilObjTestAccess.php';
890 include_once
'Services/Tracking/classes/class.ilLPStatusWrapper.php';
905 return "assFileUpload";
915 return "qpl_qst_fileupload";
943 $text = parent::getRTETextWithMediaObjects();
952 parent::setExportDetailsXLS($worksheet, $startrow, $active_id,
$pass);
956 foreach ($solutions as $solution) {
957 $worksheet->setCell($startrow +
$i, 0, $this->lng->txt(
"result"));
958 $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow +
$i));
959 if (strlen($solution[
"value1"])) {
960 $worksheet->setCell($startrow +
$i, 1, $solution[
"value1"]);
961 $worksheet->setCell($startrow +
$i, 2, $solution[
"value2"]);
966 return $startrow +
$i + 1;
981 public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
983 include_once
"./Modules/TestQuestionPool/classes/import/qti12/class.assFileUploadImport.php";
985 $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
994 public function toXML($a_include_header =
true, $a_include_binary =
true, $a_shuffle =
false, $test_output =
false, $force_image_references =
false)
996 include_once
"./Modules/TestQuestionPool/classes/export/qti12/class.assFileUploadExport.php";
998 return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
1008 $user_solution = array();
1009 return $user_solution;
1029 $this->maxsize = $a_value;
1039 if (strlen($this->allowedextensions)) {
1040 return array_filter(array_map(
'trim', explode(
",", $this->allowedextensions)));
1062 $this->allowedextensions = strtolower(trim($a_value));
1074 case "allowedextensions":
1077 case 'completion_by_submission':
1081 return parent::__get($value);
1095 case "allowedextensions":
1098 case 'completion_by_submission':
1102 parent::__set(
$key, $value);
1117 $ilDB = $DIC[
'ilDB'];
1119 SELECT tst_solutions.solution_id 1120 FROM tst_solutions, tst_active, qpl_questions 1121 WHERE tst_solutions.active_fi = tst_active.active_id 1122 AND tst_solutions.question_fi = qpl_questions.question_id 1123 AND tst_solutions.question_fi = %s AND tst_active.test_fi = %s";
1126 array(
"integer",
"integer"),
1144 $ilDB = $DIC[
'ilDB'];
1147 require_once
'Modules/TestQuestionPool/classes/class.ilAssFileUploadUploadsExporter.php';
1150 $exporter->setRefId($ref_id);
1152 $exporter->setTestTitle($test_title);
1153 $exporter->setQuestion($this);
1158 $exporter->getFinalZipFilePath(),
1159 $exporter->getDispoZipFileName(),
1160 $exporter->getZipFileMimeType(),
1190 $this->completion_by_submission = (bool) $bool;
1209 return $numExistingSolutionRecords > 0;
1244 return parent::buildTestPresentationConfig()
1246 ->setFormChangeDetectionEnabled(
false);
1256 require_once
'Modules/TestQuestionPool/classes/questions/class.ilAssFileUploadFileTableDeleteButton.php';
1297 if (!isset($_FILES[
'upload'])) {
1301 if (!isset($_FILES[
'upload'][
'tmp_name'])) {
1305 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.
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.
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)
fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
Creates a question from a QTI file.
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...
Class for file upload questions.
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)
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)
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.
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 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()