19 declare(strict_types=1);
    71         protected int $ordering_type = self::OQ_TERMS
    79         if ($elements_list === [] && $this->element_list_for_deferred_saving !== null) {
    80             $elements_list = $this->element_list_for_deferred_saving->getElements();
    82         $elements = array_filter(
    84             fn($element) => trim($element->getContent()) != 
''    87         $has_at_least_two_elements = count($elements) > 1;
    93             && $has_at_least_two_elements;
   100         if (is_null($this->oq_repository)) {
   111         if ($this->element_list_for_deferred_saving !== null) {
   125         $result = $this->db->queryF(
   130         if ($result->numRows() == 1) {
   131             $data = $this->db->fetchAssoc($result);
   132             $this->
setId($question_id);
   135             $this->
setComment((
string) $data[
"description"]);
   142             $this->ordering_type = $data[
"ordering_type"] !== null ? (
int) $data[
"ordering_type"] : self::OQ_TERMS;
   143             if ($data[
'thumb_geometry'] !== null && $data[
'thumb_geometry'] >= $this->
getMinimumThumbSize()) {
   146             $this->element_height = $data[
"element_height"] ? (
int) $data[
'element_height'] : null;
   160         parent::loadFromDb($question_id);
   167             ->withQuestionId($target->
getId());
   168         $list->distributeNewRandomIdentifiers();
   169         $target->setOrderingElementList($list);
   176         int $source_question_id,
   177         int $source_parent_id,
   178         int $target_question_id,
   179         int $target_parent_id
   185         $image_source_path = $this->
getImagePath($source_question_id, $source_parent_id);
   186         $image_target_path = $this->
getImagePath($target_question_id, $target_parent_id);
   188         if (!file_exists($image_target_path)) {
   200             if (!file_exists($image_source_path . 
$filename)
   201                 || !copy($image_source_path . $filename, $image_target_path . $filename)) {
   202                 $this->log->root()->warning(
'Image could not be cloned for object for question: ' . $target_question_id);
   204             if (!file_exists($image_source_path . $this->
getThumbPrefix() . $filename)
   206                 $this->log->root()->warning(
'Image thumbnails could not be cloned for object for question: ' . $target_question_id);
   216             self::OQ_NESTED_PICTURES,
   217             self::OQ_NESTED_TERMS
   224             throw new \InvalidArgumentException(
'Must be valid ordering type.');
   226         $this->ordering_type = $ordering_type;
   231         return $this->ordering_type;
   237             self::OQ_NESTED_TERMS,
   238             self::OQ_NESTED_PICTURES
   247             self::OQ_NESTED_PICTURES
   255             self::OQ_CT_PICTURES,
   258             throw new \InvalidArgumentException(
"use OQ content-type", 1);
   260         if ($ct == self::OQ_CT_PICTURES) {
   268         if ($ct == self::OQ_CT_TERMS) {
   300         bool $force_correct_solution,
   304         if ($force_correct_solution || !$active_id || $pass_index === null) {
   310         if (!count($solution_values)) {
   332         if (count($indexedSolutionValues)) {
   343         $value = explode(
':', $value2);
   345         $random_identifier = (
int) $value[0];
   346         $selected_position = $value1;
   347         $selected_indentation = (
int) $value[1];
   351         $element->setPosition($selected_position);
   352         $element->setIndentation($selected_indentation);
   361         $solution_identifier = $value1;
   362         $selected_position = ($value2 - 1);
   363         $selected_indentation = 0;
   365         $element = $this->
getOrderingElementList()->getElementBySolutionIdentifier($solution_identifier)->getClone();
   367         $element->setPosition($selected_position);
   368         $element->setIndentation($selected_indentation);
   379         $solution_ordering_list->setQuestionId($this->
getId());
   381         foreach ($indexed_solution_values as $value1 => $value2) {
   388             $solution_ordering_list->addElement($element);
   395         return $solution_ordering_list;
   405         $shuffledRandomIdentifierIndex = $this->
getShuffler()->transform(
   410         $shuffledElementList->reorderByRandomIdentifiers($shuffledRandomIdentifierIndex);
   411         $shuffledElementList->resetElementsIndentations();
   413         return $shuffledElementList;
   429         if ($this->
getId() <= 0) {
   430             $this->element_list_for_deferred_saving = $list;
   436         foreach ($elements as 
$e) {
   475         bool $authorized_solution = 
true   477         if ($pass === null) {
   481         $solution_value_pairs = $this->
getSolutionValues($active_id, $pass, $authorized_solution);
   483         if ($solution_value_pairs === []) {
   500         $solution_ordering_element_list = unserialize(
   502             [
'allowed_classes' => 
true]
   529         if (preg_match(
"/.*\\.(\\w+)$/", 
$filename, $matches)) {
   530             $extension = $matches[1];
   532         return md5(
$filename) . 
"." . $extension;
   540                 foreach ($contents as 
$f) {
   541                     if (strcmp($f[
'type'], 
'file') == 0) {
   544                             if (strcmp($f[
'entry'], $orderElement->getContent()) == 0) {
   547                             if (strcmp($f[
'entry'], $this->
getThumbPrefix() . $orderElement->getContent()) == 0) {
   552                             if (@file_exists($this->
getImagePath() . $f[
'entry'])) {
   574         if (!strlen($imageFilename)) {
   578         $result = @unlink($this->
getImagePath() . $imageFilename);
   586         if (!strlen($imageFilename)) {
   590         if (!file_exists($this->
getImagePath() . $imageFilename)) {
   611     public function storeImageFile(
string $upload_file, 
string $upload_name): ?string
   613         $name_parts = explode(
".", $upload_name);
   614         $suffix = strtolower(array_pop($name_parts));
   615         if (!in_array($suffix, self::VALID_UPLOAD_SUFFIXES)) {
   621         $target_filepath = $this->
getImagePath() . $target_filename;
   626             return $target_filename;
   634         $existing_image_path = $this->
getImagePath() . $existing_image_name;
   636         $target_filepath = $this->
getImagePath() . $target_filename;
   642             return $target_filename;
   645         return $existing_image_name;
   652         if (!$submittedSolutionList->hasElements()) {
   662         bool $authorized = 
true   664         if ($this->questionpool_request->raw(
'test_answer_changed') === null) {
   668         if (is_null($pass)) {
   673             function () use ($active_id, $pass, $authorized) {
   677                     $value1 = $orderingElement->getStorageValue1($this->
getOrderingType());
   678                     $value2 = $orderingElement->getStorageValue2($this->
getOrderingType());
   680                     $this->
saveCurrentSolution($active_id, $pass, $value1, trim((
string) $value2), $authorized);
   698         $this->db->manipulateF(
   704         $this->db->manipulateF(
   705             "INSERT INTO " . $this->
getAdditionalTableName() . 
" (question_fi, ordering_type, thumb_geometry, element_height)   706                             VALUES (%s, %s, %s, %s)",
   707             [
"integer", 
"text", 
"integer", 
"integer"],
   710                 $this->ordering_type,
   735         return "assOrderingQuestion";
   746         return "qpl_qst_ordering";
   757         return "qpl_a_ordering";
   766         $text = parent::getRTETextWithMediaObjects();
   769             $text .= $orderingElement->getContent();
   791         $this->element_height = ($a_height < 20) ? null : $a_height;
   801                 if ($orderingElement->getContent() !== 
'') {
   820             switch (strtoupper($path_info[
'extension'])) {
   841         $result[
'id'] = $this->
getId();
   846         $result[
'shuffle'] = 
true;
   848         $result[
'feedback'] = [
   849             'onenotcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), 
false)),
   850             'allcorrect' => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), 
true))
   859             $answers[$counter] = $orderingElement->getContent();
   862         $answers = $this->
getShuffler()->transform($answers);
   864         foreach ($answers as $order => $answer) {
   866                 "answertext" => (
string) $answer,
   867                 "order" => (
int) $order
   870         $result[
'answers'] = $arr;
   873         $result[
'mobs'] = $mobs;
   875         return json_encode($result);
   898                 $formField->setInteractionEnabled(
true);
   906                 $formField->setEditElementOccuranceEnabled(
true);
   907                 $formField->setEditElementOrderEnabled(
true);
   916         $formField->
setInfo($this->
lng->txt(
'ordering_answer_sequence_info'));
   929             self::ORDERING_ELEMENT_FORM_FIELD_POSTVAR
   934         return $orderingElementInput;
   946             self::ORDERING_ELEMENT_FORM_FIELD_POSTVAR
   949         $orderingElementInput->setImageUploadCommand(self::ORDERING_ELEMENT_FORM_CMD_UPLOAD_IMG);
   950         $orderingElementInput->setImageRemovalCommand(self::ORDERING_ELEMENT_FORM_CMD_REMOVE_IMG);
   954         return $orderingElementInput;
   965             $form_data_converter,
   966             self::ORDERING_ELEMENT_FORM_FIELD_POSTVAR
   969         $ordering_element_input->setUniquePrefix($this->
getId());
   971         $ordering_element_input->setElementImagePath($this->
getImagePathWeb());
   976         return $ordering_element_input;
   983         $ordering_gui->setValueByArray($user_solution_post);
   985         if (!$ordering_gui->checkInput()) {
   993         foreach ($ordering_gui->getElementList($this->getId()) as $submitted_element) {
   994             $solution_element = $stored_element_list->getElementByRandomIdentifier(
   995                 $submitted_element->getRandomIdentifier()
   998             $solution_element->setPosition($submitted_element->getPosition());
  1001                 $solution_element->setIndentation($submitted_element->getIndentation());
  1004             $solution_ordering_element_list->addElement($solution_element);
  1007         return $solution_ordering_element_list;
  1014         if ($this->postSolutionOrderingElementList === null) {
  1016                 $this->
http->request()->getParsedBody()
  1018             $this->postSolutionOrderingElementList = $list;
  1029             $user_element = $solution_ordering_element_list->
getElementByPosition($correct_element->getPosition());
  1030             if (!$correct_element->isSameElement($user_element)) {
  1031                 $reached_points = 0;
  1036         return $reached_points;
  1041         return ilOperatorsExpressionMapping::getOperatorsByExpression($expression);
  1062             $data = $this->db->queryF(
  1063                 "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s ORDER BY value1 ASC ",
  1064                 [
"integer", 
"integer", 
"integer",
"integer"],
  1065                 [$active_id, $pass, $this->
getId(), $maxStep]
  1068             $data = $this->db->queryF(
  1069                 "SELECT value1, value2 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s ORDER BY value1 ASC ",
  1070                 [
"integer", 
"integer", 
"integer"],
  1071                 [$active_id, $pass, $this->
getId()]
  1076         while ($row = $this->db->fetchAssoc(
$data)) {
  1077             $newKey = explode(
":", $row[
"value2"]);
  1082                     if ($answer->getSolutionIdentifier() == $row[
"value1"]) {
  1083                         $elements[$row[
"value2"]] = $answer->getSolutionIdentifier() + 1;
  1087                     if ($answer->getRandomIdentifier() == $newKey[0]) {
  1088                         $elements[$row[
"value1"]] = $answer->getSolutionIdentifier() + 1;
  1097         foreach (array_values($elements) as $element) {
  1098             $result->addKeyValue($element, $element);
  1104         $result->setReachedPercentage((
$points / $max_points) * 100);
  1118         if ($index !== null) {
  1135         return parent::buildTestPresentationConfig()
  1138             ->setUseUnchangedAnswerLabel($this->
lng->txt(
'tst_unchanged_order_is_correct'));
  1154         $solution_submit = [];
  1156         if (isset($form_submission_data_structure[
'orderresult'])) {
  1157             $orderresult = $form_submission_data_structure[
'orderresult'];
  1159             if (strlen($orderresult)) {
  1160                 $orderarray = explode(
":", $orderresult);
  1162                 foreach ($orderarray as $index) {
  1164                     if (preg_match(
"/id_(\\d+)/", $index, $idmatch)) {
  1165                         $randomid = $idmatch[1];
  1167                             if ($answer->getRandomIdentifier() == $randomid) {
  1168                                 $solution_submit[$answeridx] = $ordervalue;
  1177             foreach ($form_submission_data_structure[
'content'] as $randomId => $content) {
  1178                 $indentation = $form_submission_data_structure[
'indentation'];
  1181                 $value2 = implode(
':', [$randomId, $indentation]);
  1183                 $solution_submit[$value1] = $value2;
  1186             foreach ($form_submission_data_structure as $key => $value) {
  1188                 if (preg_match(
"/^order_(\d+)/", $key, $matches)) {
  1189                     if (!(preg_match(
"/initial_value_\d+/", $value))) {
  1190                         if (strlen($value)) {
  1192                                 if ($answer->getRandomIdentifier() == $matches[1]) {
  1193                                     $solution_submit[$answeridx] = $value;
  1202         return $solution_submit;
  1211         $converter->setPostVar(self::ORDERING_ELEMENT_FORM_FIELD_POSTVAR);
  1224         $formDataConverter->setImageRemovalCommand(self::ORDERING_ELEMENT_FORM_CMD_REMOVE_IMG);
  1226         $formDataConverter->setImageFsPath($this->
getImagePath());
  1231         return $formDataConverter;
  1241         return $form_data_converter;
  1253             $form_data_converter->setImageRemovalCommand(self::ORDERING_ELEMENT_FORM_CMD_REMOVE_IMG);
  1255             $form_data_converter->setThumbnailPrefix($this->
getThumbPrefix());
  1258         return $form_data_converter;
  1264             AdditionalInformationGenerator::KEY_QUESTION_TYPE => (string) $this->
getQuestionType(),
  1267             AdditionalInformationGenerator::KEY_QUESTION_ORDERING_NESTING_TYPE => array_reduce(
  1269                 static fn(
string $string, 
string $lang_var) => $string . $additional_info->
getTagForLangVar($lang_var),
  1272             AdditionalInformationGenerator::KEY_QUESTION_REACHABLE_POINTS => $this->
getPoints(),
  1274             AdditionalInformationGenerator::KEY_FEEDBACK => [
  1275                 AdditionalInformationGenerator::KEY_QUESTION_FEEDBACK_ON_INCOMPLETE => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), 
false)),
  1276                 AdditionalInformationGenerator::KEY_QUESTION_FEEDBACK_ON_COMPLETE => $this->
formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), 
true))
  1283         switch ($ordering_type) {
  1284             case self::OQ_PICTURES:
  1285                 return [
'qst_nested_nested_answers_off', 
'oq_btn_use_order_pictures'];
  1286             case self::OQ_TERMS:
  1287                 return [
'qst_nested_nested_answers_off', 
'oq_btn_use_order_terms'];
  1288             case self::OQ_NESTED_PICTURES:
  1289                 return [
'qst_nested_nested_answers_on', 
'oq_btn_use_order_pictures'];
  1290             case self::OQ_NESTED_TERMS:
  1291                 return [
'qst_nested_nested_answers_on', 
'oq_btn_use_order_terms'];
  1303         $answers_gui->setInteractionEnabled(
false);
  1304         $answers_gui->setElementList($solution_ordering_list);
  1306         return $answers_gui->getHTML();
  1311         array $solution_values
  1313         if ($solution_values === []) {
  1325         if ($solution_values === []) {
  1359                     $indentation .= 
' |';
 static _replaceMediaObjectImageSrc(string $a_text, int $a_direction=0, string $nic='')
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
 
ilAssOrderingElementList $element_list_for_deferred_saving
 
setNrOfTries(int $a_nr_of_tries)
 
initOrderingElementAuthoringProperties(ilFormPropertyGUI $formField)
 
getSolutionValues(int $active_id, ?int $pass=null, bool $authorized=true)
Loads solutions of a given user from the database an returns it. 
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
static getInstance($identifier)
 
updateImageFile(string $existing_image_name)
 
const HAS_SPECIFIC_FEEDBACK
 
const PercentageResultExpression
 
solutionValuesToText(array $solution_values)
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
buildOrderingImagesFormDataConverter()
 
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test. 
 
setOrderingType(int $ordering_type=self::OQ_TERMS)
 
const VALID_UPLOAD_SUFFIXES
 
setIsUnchangedAnswerPossible($isUnchangedAnswerPossible)
Set if the saving of an unchanged answer is supported with an additional checkbox. 
 
buildOrderingImagesInputGui()
 
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
 
getCorrectSolutionForTextOutput(int $active_id, int $pass)
 
saveWorkingData(int $active_id, ?int $pass=null, bool $authorized=true)
 
buildOrderingTextsFormDataConverter()
 
withElements(array $elements)
 
removeAllImageFiles(string $image_target_path)
 
getSolutionListFromPostSubmit()
 
ensureNonNegativePoints(float $points)
 
initOrderingElementFormFieldLabels(ilFormPropertyGUI $formField)
 
getQuestionType()
Returns the question type of the question. 
 
getOrderElements()
Returns the answers array. 
 
getImagePathWeb()
Returns the web image path for web accessable images of a question. 
 
setThumbSize(int $a_size)
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
static buildInstance(int $question_id, array $elements=[])
 
setOrderingElementList(ilAssOrderingElementList $list)
 
savePreviewData(ilAssQuestionPreviewSession $previewSession)
 
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
 
getParticipantsSolution()
 
static makeDirParents(string $a_dir)
Create a new directory and all parent directories. 
 
setComment(string $comment="")
 
isImageReplaced(ilAssOrderingElement $newElement, ilAssOrderingElement $oldElement)
 
Base Exception for all Exceptions relating to Modules/Test. 
 
dropImageFile($imageFilename)
 
buildOrderingElementInputGui()
 
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table. 
 
setParticipantsSolution($participantSolution)
 
getAnswer(int $index=0)
Returns the ordering element from the given position. 
 
setElementHeight(?int $a_height)
 
__construct(string $title="", string $comment="", string $author="", int $owner=-1, string $question="", protected int $ordering_type=self::OQ_TERMS)
 
buildOrderingElementFormDataConverter()
 
saveCurrentSolution(int $active_id, int $pass, $value1, $value2, bool $authorized=true, $tstamp=0)
 
getSolutionValuePairBrandedOrderingElementByRandomIdentifier(int $value1, string $value2)
 
static http()
Fetches the global http state from ILIAS. 
 
getImagePath($question_id=null, $object_id=null)
Returns the image path for web accessable images of a question. 
 
solutionValuesToLog(AdditionalInformationGenerator $additional_info, array $solution_values)
 
getExpressionTypes()
Get all available expression types for a specific question. 
 
buildHashedImageFilename(string $plain_image_filename, bool $unique=false)
 
const ORDERING_ELEMENT_FORM_FIELD_POSTVAR
 
fetchSolutionSubmit(array $form_submission_data_structure)
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
getAnswerTableName()
Returns the name of the answer table in the database. 
 
const NumericResultExpression
 
deleteAnswer(int $random_identifier)
 
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively 
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
toJSON()
Returns a JSON representation of the question. 
 
deductHintPointsFromReachedPoints(ilAssQuestionPreviewSession $preview_session, $reached_points)
 
buildNestedOrderingFormDataConverter()
 
cloneQuestionTypeSpecificProperties(\assQuestion $target)
 
const ORDERING_ELEMENT_FORM_CMD_REMOVE_IMG
 
getElementArrayWithIdentationsForTextOutput(array $elements)
 
getSolutionOutputForLog()
 
static getDir(string $a_dir, bool $a_rec=false, ?string $a_sub_dir="")
get directory 
 
static moveUploadedFile(string $a_file, string $a_name, string $a_target, bool $a_raise_errors=true, string $a_mode="move_uploaded")
move uploaded file 
 
saveQuestionDataToDb(?int $original_id=null)
 
const OrderingResultExpression
 
static convertImage(string $a_from, string $a_to, string $a_target_format="", string $a_geometry="", string $a_background_color="")
 
getEncryptedFilename($filename)
 
saveToDb(?int $original_id=null)
 
fetchIndexedValuesFromValuePairs(array $value_pairs)
 
fetchSolutionListFromFormSubmissionData(array $user_solution_post)
 
getSolutionMaxPass(int $active_id)
 
setNestingType(bool $nesting)
 
removeCurrentSolution(int $active_id, int $pass, bool $authorized=true)
 
storeImageFile(string $upload_file, string $upload_name)
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
OQRepository $oq_repository
 
__construct(Container $dic, ilPlugin $plugin)
 
setOriginalId(?int $original_id)
 
ilAssOrderingElementList $postSolutionOrderingElementList
 
getTestOutputSolutions(int $activeId, int $pass)
 
cloneImages(int $source_question_id, int $source_parent_id, int $target_question_id, int $target_parent_id)
 
setTitle(string $title="")
 
Class for ordering questions. 
 
buildOrderingTextsInputGui()
 
getOperators(string $expression)
Get all available operations for a specific question. 
 
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples 
 
setLifecycle(ilAssQuestionLifecycle $lifecycle)
 
toLog(AdditionalInformationGenerator $additional_info)
 
getShuffledOrderingElementList()
 
getElementByPosition(int $position)
 
buildTestPresentationConfig()
Get the test question configuration. 
 
static rename(string $a_source, string $a_target)
 
getSolutionOrderingElementList(array $indexed_solution_values)
 
calculateReachedPoints(int $active_id, ?int $pass=null, bool $authorized_solution=true)
 
saveToDb(?int $original_id=null)
 
hasOrderingTypeUploadSupport()
 
isImageFileStored($imageFilename)
 
getSolutionOrderingElementListForTestOutput(ilAssNestedOrderingElementsInputGUI $input_gui, array $last_post, int $active_id, int $pass)
 
lookupMaxStep(int $active_id, int $pass)
 
setAuthor(string $author="")
 
getOrderingElementListForSolutionOutput(bool $force_correct_solution, int $active_id, ?int $pass_index)
 
buildNestedOrderingElementInputGui()
 
getUserQuestionResult(int $active_id, int $pass)
Get the user solution for a question by active_id and the test pass. 
 
withQuestionId(int $question_id)
 
calculateReachedPointsForSolution(ilAssOrderingElementList $solution_ordering_element_list)
 
setAdditionalContentEditingMode(?string $additionalContentEditingMode)
 
loadFromDb($question_id)
Loads a assOrderingQuestion object from a database. 
 
getSolutionValuePairBrandedOrderingElementBySolutionIdentifier(int $value1, string $value2)
 
generateThumbForFile($path, $file)
 
static getDraftInstance()
 
ensureValidIdentifiers(ilAssOrderingElement $element)
 
saveAnswerSpecificDataToDb()
Saves the answer specific records into a question types answer table. 
 
getOrderingTypeLangVars(int $ordering_type)
 
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
 
getAdditionalTableName()
Returns the name of the additional question data table in the database. 
 
const ORDERING_ELEMENT_FORM_CMD_UPLOAD_IMG
 
setQuestion(string $question="")
 
const EmptyAnswerExpression
 
calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $preview_session)