ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.assOrderingHorizontal.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
24
37{
38 protected const HAS_SPECIFIC_FEEDBACK = false;
39 protected const DEFAULT_TEXT_SIZE = 100;
40
41 protected $ordertext;
42 protected $textsize;
43 protected $separator = "::";
44 protected $answer_separator = '{::}';
45
58 public function __construct(
59 $title = "",
60 $comment = "",
61 $author = "",
62 $owner = -1,
63 $question = ""
64 ) {
66 $this->ordertext = "";
67 }
68
74 public function isComplete(): bool
75 {
76 if (strlen($this->title) and ($this->author) and ($this->question) and ($this->getMaximumPoints() > 0)) {
77 return true;
78 } else {
79 return false;
80 }
81 }
82
87 public function saveToDb(?int $original_id = null): void
88 {
91 parent::saveToDb();
92 }
93
97 public function getAnswerSeparator(): string
98 {
100 }
101
102
109 public function loadFromDb($question_id): void
110 {
111 $result = $this->db->queryF(
112 "SELECT qpl_questions.*, " . $this->getAdditionalTableName() . ".* FROM qpl_questions LEFT JOIN " . $this->getAdditionalTableName() . " ON " . $this->getAdditionalTableName() . ".question_fi = qpl_questions.question_id WHERE qpl_questions.question_id = %s",
113 ["integer"],
114 [$question_id]
115 );
116 if ($result->numRows() == 1) {
117 $data = $this->db->fetchAssoc($result);
118 $this->setId($question_id);
119 $this->setObjId($data["obj_fi"]);
120 $this->setTitle((string) $data["title"]);
121 $this->setComment((string) $data["description"]);
122 $this->setOriginalId($data["original_id"]);
123 $this->setNrOfTries($data['nr_of_tries']);
124 $this->setAuthor($data["author"]);
125 $this->setPoints($data["points"]);
126 $this->setOwner($data["owner"]);
127 $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc((string) $data["question_text"], 1));
128 $this->setOrderText($data["ordertext"]);
129 $this->setTextSize($data["textsize"]);
130
131 try {
132 $this->setLifecycle(ilAssQuestionLifecycle::getInstance($data['lifecycle']));
135 }
136
137 try {
138 $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
140 }
141 }
142
143 parent::loadFromDb($question_id);
144 }
145
146 public function getMaximumPoints(): float
147 {
148 return $this->getPoints();
149 }
150
151 public function calculateReachedPoints(
152 int $active_id,
153 ?int $pass = null,
154 bool $authorized_solution = true
155 ): float {
156 if ($pass === null) {
157 $pass = $this->getSolutionMaxPass($active_id);
158 }
159
160 $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorized_solution);
161 $points = 0.0;
162 if ($this->db->numRows($result) > 0) {
163 $data = $this->db->fetchAssoc($result);
165 }
166
167 return $points;
168 }
169
170 public function splitAndTrimOrderElementText(string $in_string, string $separator): array
171 {
172 $result = [];
173
174 if (ilStr::strPos($in_string, $separator, 0) === false) {
175 $result = preg_split("/\\s+/", $in_string);
176 } else {
177 $result = explode($separator, $in_string);
178 }
179
180 foreach ($result as $key => $value) {
181 $result[$key] = trim($value);
182 }
183
184 return $result;
185 }
186
187 protected function getSolutionSubmit(): string
188 {
189 return $this->questionpool_request->string('orderresult');
190 }
191
192 public function saveWorkingData(
193 int $active_id,
194 ?int $pass = null,
195 bool $authorized = true
196 ): bool {
197 if ($this->questionpool_request->raw('test_answer_changed') === null) {
198 return true;
199 }
200
201 if (is_null($pass)) {
202 $pass = ilObjTest::_getPass($active_id);
203 }
204
205 $answer = $this->getSolutionSubmit();
206 $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(
207 function () use ($answer, $active_id, $pass, $authorized) {
208 $this->removeCurrentSolution($active_id, $pass, $authorized);
209
210 if ($answer === '') {
211 return;
212 }
213
214 $this->saveCurrentSolution(
215 $active_id,
216 $pass,
217 $answer,
218 null,
219 $authorized
220 );
221 }
222 );
223
224 return true;
225 }
226
228 {
229 // save additional data
230 $this->db->manipulateF(
231 "DELETE FROM " . $this->getAdditionalTableName()
232 . " WHERE question_fi = %s",
233 [ "integer" ],
234 [ $this->getId() ]
235 );
236
237 $this->db->manipulateF(
238 "INSERT INTO " . $this->getAdditionalTableName()
239 . " (question_fi, ordertext, textsize) VALUES (%s, %s, %s)",
240 [ "integer", "text", "float" ],
241 [
242 $this->getId(),
243 $this->getOrderText(),
244 ($this->getTextSize() < 10) ? null : (float) $this->getTextSize()
245 ]
246 );
247 }
248
254 public function getQuestionType(): string
255 {
256 return "assOrderingHorizontal";
257 }
258
264 public function getAdditionalTableName(): string
265 {
266 return "qpl_qst_horder";
267 }
268
274 public function getAnswerTableName(): string
275 {
276 return "";
277 }
278
284 public function deleteAnswers($question_id): void
285 {
286 }
287
292 public function getRTETextWithMediaObjects(): string
293 {
294 $text = parent::getRTETextWithMediaObjects();
295 return $text;
296 }
297
303 public function getBestSolution($active_id, $pass): array
304 {
305 $user_solution = [];
306 return $user_solution;
307 }
308
314 public function getOrderingElements(): array
315 {
316 return $this->splitAndTrimOrderElementText($this->getOrderText() ?? "", $this->separator);
317 }
318
324 public function getRandomOrderingElements(): array
325 {
326 $elements = $this->getOrderingElements();
327 $elements = $this->getShuffler()->transform($elements);
328 return $elements;
329 }
330
336 public function getOrderText()
337 {
338 return $this->ordertext;
339 }
340
346 public function setOrderText($a_value): void
347 {
348 $this->ordertext = $a_value;
349 }
350
356 public function getTextSize()
357 {
358 return $this->textsize;
359 }
360
366 public function setTextSize(?float $textsize): void
367 {
368 if ($textsize === null || $textsize === 0.0) {
369 $textsize = self::DEFAULT_TEXT_SIZE;
370 }
371 $this->textsize = $textsize;
372 }
373
379 public function getSeparator(): string
380 {
381 return $this->separator;
382 }
383
389 public function setSeparator($a_value): void
390 {
391 $this->separator = $a_value;
392 }
393
397 public function toJSON(): string
398 {
399 $result = [];
400 $result['id'] = $this->getId();
401 $result['type'] = (string) $this->getQuestionType();
402 $result['title'] = $this->getTitleForHTMLOutput();
403 $result['question'] = $this->formatSAQuestion($this->getQuestion());
404 $result['nr_of_tries'] = $this->getNrOfTries();
405 $result['shuffle'] = true;
406 $result['points'] = (bool) $this->getPoints();
407 $result['textsize'] = ((int) $this->getTextSize()) // #10923
408 ? (int) $this->getTextSize()
409 : self::DEFAULT_TEXT_SIZE;
410 $result['feedback'] = [
411 'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
412 'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
413 ];
414
415 $arr = [];
416 foreach ($this->getOrderingElements() as $order => $answer) {
417 array_push($arr, [
418 "answertext" => (string) $answer,
419 "order" => (int) $order + 1
420 ]);
421 }
422 $result['answers'] = $arr;
423
424 $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
425 $result['mobs'] = $mobs;
426
427 return json_encode($result);
428 }
429
430 public function getOperators(string $expression): array
431 {
433 }
434
435 public function getExpressionTypes(): array
436 {
437 return [
442 ];
443 }
444
445 public function getUserQuestionResult(
446 int $active_id,
447 int $pass
449 $result = new ilUserQuestionResult($this, $active_id, $pass);
450
451 $maxStep = $this->lookupMaxStep($active_id, $pass);
452 if ($maxStep > 0) {
453 $data = $this->db->queryF(
454 "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s",
455 ["integer", "integer", "integer","integer"],
456 [$active_id, $pass, $this->getId(), $maxStep]
457 );
458 } else {
459 $data = $this->db->queryF(
460 "SELECT value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s",
461 ["integer", "integer", "integer"],
462 [$active_id, $pass, $this->getId()]
463 );
464 }
465 $row = $this->db->fetchAssoc($data);
466
467 $answer_elements = $this->splitAndTrimOrderElementText($row["value1"] ?? "", $this->answer_separator);
468 $elements = $this->getOrderingElements();
469
470 foreach ($answer_elements as $answer) {
471 foreach ($elements as $key => $element) {
472 if ($element == $answer) {
473 $result->addKeyValue($key + 1, $answer);
474 }
475 }
476 }
477
478 $glue = " ";
479 if ($this->answer_separator = '{::}') {
480 $glue = "";
481 }
482 $result->addKeyValue(null, join($glue, $answer_elements));
483
484 $points = $this->calculateReachedPoints($active_id, $pass);
485 $max_points = $this->getMaximumPoints();
486
487 $result->setReachedPercentage(($points / $max_points) * 100);
488
489 return $result;
490 }
491
495 public function getAvailableAnswerOptions(?int $index = null): array|ASS_AnswerSimple|null
496 {
497 $elements = $this->getOrderingElements();
498 if ($index !== null) {
499 if (array_key_exists($index, $elements)) {
500 return $elements[$index];
501 }
502 return null;
503 } else {
504 return $elements;
505 }
506 }
507
512 protected function calculateReachedPointsForSolution(?string $value): float
513 {
514 $value = $this->splitAndTrimOrderElementText($value ?? "", $this->answer_separator);
515 $value = join($this->answer_separator, $value);
516 if (strcmp($value, join($this->answer_separator, $this->getOrderingElements())) == 0) {
517 $points = $this->getPoints();
518 return $points;
519 }
520 return 0;
521 }
522
524 // hey.
525 {
526 // hey: refactored identifiers
527 return parent::buildTestPresentationConfig()
528 // hey.
530 ->setUseUnchangedAnswerLabel($this->lng->txt('tst_unchanged_order_is_correct'));
531 }
532
533 public function toLog(AdditionalInformationGenerator $additional_info): array
534 {
535 return [
536 AdditionalInformationGenerator::KEY_QUESTION_TYPE => (string) $this->getQuestionType(),
537 AdditionalInformationGenerator::KEY_QUESTION_TITLE => $this->getTitleForHTMLOutput(),
538 AdditionalInformationGenerator::KEY_QUESTION_TEXT => $this->formatSAQuestion($this->getQuestion()),
539 AdditionalInformationGenerator::KEY_QUESTION_TEXTSIZE => ((int) $this->getTextSize()) ? (int) $this->getTextSize() : 100,
540 AdditionalInformationGenerator::KEY_QUESTION_CORRECT_ANSWER_OPTIONS => $this->getOrderText(),
541 AdditionalInformationGenerator::KEY_QUESTION_REACHABLE_POINTS => $this->getPoints(),
542 AdditionalInformationGenerator::KEY_FEEDBACK => [
543 AdditionalInformationGenerator::KEY_QUESTION_FEEDBACK_ON_INCOMPLETE => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
544 AdditionalInformationGenerator::KEY_QUESTION_FEEDBACK_ON_COMPLETE => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
545 ]
546 ];
547 }
548
549 protected function solutionValuesToLog(
550 AdditionalInformationGenerator $additional_info,
551 array $solution_values
552 ): string {
553 if (!array_key_exists(0, $solution_values) ||
554 !array_key_exists('value1', $solution_values[0])) {
555 return '';
556 }
557
558 return str_replace("{::}", " ", $solution_values[0]['value1']);
559 }
560
561 public function solutionValuesToText(array $solution_values): string
562 {
563 if (!array_key_exists(0, $solution_values) ||
564 !array_key_exists('value1', $solution_values[0])) {
565 return '';
566 }
567
568 return str_replace("{::}", " ", $solution_values[0]['value1']);
569 }
570
571 public function getCorrectSolutionForTextOutput(int $active_id, int $pass): string
572 {
573 return $this->getOrderText();
574 }
575}
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class for horizontal ordering questions.
saveWorkingData(int $active_id, ?int $pass=null, bool $authorized=true)
setSeparator($a_value)
Set order text separator.
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
calculateReachedPointsForSolution(?string $value)
solutionValuesToText(array $solution_values)
MUST convert the given solution values into text.
splitAndTrimOrderElementText(string $in_string, string $separator)
isComplete()
Returns true, if a single choice question is complete for use.
getAvailableAnswerOptions(?int $index=null)
setOrderText($a_value)
Set order text.
getAdditionalTableName()
Returns the name of the additional question data table in the database.
setTextSize(?float $textsize)
Set text size.
solutionValuesToLog(AdditionalInformationGenerator $additional_info, array $solution_values)
MUST convert the given solution values into an array or a string that can be stored in the log.
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
toJSON()
Returns a JSON representation of the question.
getAnswerTableName()
Returns the name of the answer table in the database.
loadFromDb($question_id)
Loads a assOrderingHorizontal object from a database.
getRandomOrderingElements()
Get ordering elements from order text in random sequence.
getOrderingElements()
Get ordering elements from order text.
getQuestionType()
Returns the question type of the question.
getSeparator()
Get order text separator.
getOperators(string $expression)
Get all available operations for a specific question.
getExpressionTypes()
Get all available expression types for a specific question.
deleteAnswers($question_id)
Deletes datasets from answers tables.
toLog(AdditionalInformationGenerator $additional_info)
MUST return an array of the question settings that can be stored in the log.
__construct( $title="", $comment="", $author="", $owner=-1, $question="")
assOrderingHorizontal constructor
getCorrectSolutionForTextOutput(int $active_id, int $pass)
calculateReachedPoints(int $active_id, ?int $pass=null, bool $authorized_solution=true)
saveToDb(?int $original_id=null)
Saves a assOrderingHorizontal object to a database.
getUserQuestionResult(int $active_id, int $pass)
Get the user solution for a question by active_id and the test pass.
getBestSolution($active_id, $pass)
Returns the best solution for a given pass of a participant.
setOriginalId(?int $original_id)
setId(int $id=-1)
setAdditionalContentEditingMode(?string $additionalContentEditingMode)
setQuestion(string $question="")
getCurrentSolutionResultSet(int $active_id, int $pass, bool $authorized=true)
setAuthor(string $author="")
setComment(string $comment="")
setObjId(int $obj_id=0)
getSolutionMaxPass(int $active_id)
setOwner(int $owner=-1)
setNrOfTries(int $a_nr_of_tries)
setLifecycle(ilAssQuestionLifecycle $lifecycle)
setTitle(string $title="")
saveQuestionDataToDb(?int $original_id=null)
setPoints(float $points)
static _getMobsOfObject(string $a_type, int $a_id, int $a_usage_hist_nr=0, string $a_lang="-")
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
static getOperatorsByExpression(string $expression)
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...
static strPos(string $a_haystack, string $a_needle, int $a_offset=0)
Definition: class.ilStr.php:39
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setIsUnchangedAnswerPossible($isUnchangedAnswerPossible)
Set if the saving of an unchanged answer is supported with an additional checkbox.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
if(!file_exists('../ilias.ini.php'))