ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.SurveyQuestion.php
Go to the documentation of this file.
1<?php
2
26{
27 protected ?int $original_id;
28 protected \ILIAS\SurveyQuestionPool\Editing\EditSessionRepository $edit_manager;
29 protected ilObjUser $user;
30 protected ilDBInterface $db;
31 public int $id;
32 public string $title;
33 public string $description;
34 public int $owner;
35 public string $author;
36 public array $materials;
37 public int $survey_id;
38 public int $obj_id;
39 public string $questiontext;
40 public bool $obligatory;
42 public int $orientation; // 0 = vertical, 1 = horizontal
44 public array $material;
45 public bool $complete;
46 protected array $cumulated;
47 private array $arrData; // question data
48 protected ilLogger $log;
49
50 protected \ILIAS\SurveyQuestionPool\Export\ImportSessionRepository $import_manager;
51
52 public function __construct(
53 string $title = "",
54 string $description = "",
55 string $author = "",
56 string $questiontext = "",
57 int $owner = -1
58 ) {
59 global $DIC;
60
61 $this->user = $DIC->user();
62 $this->db = $DIC->database();
63 $lng = $DIC->language();
64 $ilUser = $DIC->user();
65
66 $this->lng = $lng;
67 $this->complete = 0;
68 $this->title = $title;
69 $this->description = $description;
70 $this->questiontext = $questiontext;
71 $this->author = $author;
72 $this->cumulated = array();
73 if (!$this->author) {
74 $this->author = $ilUser->fullname;
75 }
76 $this->owner = $owner;
77 if ($this->owner === -1) {
78 $this->owner = $ilUser->getId();
79 }
80 $this->id = -1;
81 $this->survey_id = -1;
82 $this->obligatory = 1;
83 $this->orientation = 0;
84 $this->materials = array();
85 $this->material = array();
86 $this->arrData = array();
87
88 $this->log = ilLoggerFactory::getLogger('svy');
89 $this->import_manager = $DIC->surveyQuestionPool()
90 ->internal()
91 ->repo()
92 ->import();
93
94 $this->edit_manager = $DIC->surveyQuestionPool()
95 ->internal()
96 ->repo()
97 ->editing();
98 }
99
100 public function setComplete(bool $a_complete): void
101 {
102 $this->complete = $a_complete;
103 }
104
105 public function isComplete(): bool
106 {
107 return false;
108 }
109
110 public function questionTitleExists(
111 string $title,
112 int $questionpool_object = 0
113 ): bool {
114 $ilDB = $this->db;
115
116 $refwhere = "";
117 if ($questionpool_object > 0) {
118 $refwhere = sprintf(
119 " AND obj_fi = %s",
120 $ilDB->quote($questionpool_object, 'integer')
121 );
122 }
123 $result = $ilDB->queryF(
124 "SELECT question_id FROM svy_question WHERE title = %s$refwhere",
125 array('text'),
126 array($title)
127 );
128 return $result->numRows() > 0;
129 }
130
131 public function setTitle(string $title = ""): void
132 {
133 $this->title = $title;
134 }
135
136 public function setObligatory(bool $obligatory = true): void
137 {
138 $this->obligatory = $obligatory;
139 }
140
141 public function setOrientation(int $orientation = 0): void
142 {
143 $this->orientation = $orientation;
144 }
145
146 public function setId(int $id = -1): void
147 {
148 $this->id = $id;
149 }
150
151 public function setSurveyId(int $id = -1): void
152 {
153 $this->survey_id = $id;
154 }
155
156 public function setDescription(string $description = ""): void
157 {
158 $this->description = $description;
159 }
160
161 public function addMaterials(
162 string $materials_file,
163 string $materials_name = ""
164 ): void {
165 if (empty($materials_name)) {
166 $materials_name = $materials_file;
167 }
168 if ((!empty($materials_name)) && (!array_key_exists($materials_name, $this->materials))) {
169 $this->materials[$materials_name] = $materials_file;
170 }
171 }
172
176 public function setMaterialsfile(
177 string $materials_filename,
178 string $materials_tempfilename = "",
179 string $materials_name = ""
180 ): void {
181 if (!empty($materials_filename)) {
182 $materialspath = $this->getMaterialsPath();
183 if (!file_exists($materialspath)) {
184 ilFileUtils::makeDirParents($materialspath);
185 }
187 $materials_tempfilename,
188 $materials_filename,
189 $materialspath . $materials_filename
190 )) {
191 print "image not uploaded!!!! ";
192 } else {
193 $this->addMaterials($materials_filename, $materials_name);
194 }
195 }
196 }
197
198 public function deleteMaterial(
199 string $materials_name = ""
200 ): void {
201 foreach ($this->materials as $key => $value) {
202 if (strcmp($key, $materials_name) === 0) {
203 if (file_exists($this->getMaterialsPath() . $value)) {
204 unlink($this->getMaterialsPath() . $value);
205 }
206 unset($this->materials[$key]);
207 }
208 }
209 }
210
215 public function flushMaterials(): void
216 {
217 $this->materials = array();
218 }
219
220 public function setAuthor(string $author = ""): void
221 {
222 $ilUser = $this->user;
223
224 if (!$author) {
225 $author = $ilUser->fullname;
226 }
227 $this->author = $author;
228 }
229
230 public function setQuestiontext(string $questiontext = ""): void
231 {
232 $this->questiontext = $questiontext;
233 }
234
238 public function setOwner(int $owner = 0): void
239 {
240 $this->owner = $owner;
241 }
242
243 public function getTitle(): string
244 {
245 return $this->title;
246 }
247
248 public function getLabel(): string
249 {
250 return $this->label;
251 }
252
253 public function getId(): int
254 {
255 return $this->id;
256 }
257
258 public function getObligatory(): bool
259 {
260 return $this->obligatory;
261 }
262
263 public function getSurveyId(): int
264 {
265 return $this->survey_id;
266 }
267
271 public function getOrientation(): int
272 {
273 switch ($this->orientation) {
274 case 0:
275 case 1:
276 case 2:
277 break;
278 default:
279 $this->orientation = 0;
280 break;
281 }
282 return $this->orientation;
283 }
284
285
286 public function getDescription(): string
287 {
288 return $this->description;
289 }
290
291 public function getAuthor(): string
292 {
293 return $this->author;
294 }
295
296 public function getOwner(): int
297 {
298 return $this->owner;
299 }
300
301 public function getQuestiontext(): string
302 {
303 return $this->questiontext;
304 }
305
309 public function getObjId(): int
310 {
311 return $this->obj_id;
312 }
313
317 public function setObjId(int $obj_id = 0): void
318 {
319 $this->obj_id = $obj_id;
320 }
321
322 public function duplicate(
323 bool $for_survey = true,
324 string $title = "",
325 string $author = "",
326 int $owner = 0,
327 int $a_survey_id = 0
328 ): ?int {
329 if ($this->getId() <= 0) {
330 // The question has not been saved. It cannot be duplicated
331 return null;
332 }
333 // duplicate the question in database
334 $clone = $this;
335 $original_id = $this->getId();
336 $clone->setId(-1);
337 if ($a_survey_id > 0) {
338 $clone->setObjId($a_survey_id);
339 }
340 if ($title) {
341 $clone->setTitle($title);
342 }
343 if ($author) {
344 $clone->setAuthor($author);
345 }
346 if ($owner) {
347 $clone->setOwner($owner);
348 }
349 if ($for_survey) {
350 $clone->saveToDb($original_id);
351 } else {
352 $clone->saveToDb();
353 }
354 // copy XHTML media objects
355 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
356 return $clone->getId();
357 }
358
359 public function copyObject(
360 int $target_questionpool,
361 string $title = ""
362 ): ?int {
363 if ($this->getId() <= 0) {
364 // The question has not been saved. It cannot be copied
365 return null;
366 }
367 $clone = $this;
368 $original_id = self::_getOriginalId($this->getId(), false);
369 $clone->setId(-1);
370 $source_questionpool = $this->getObjId();
371 $clone->setObjId($target_questionpool);
372 if ($title) {
373 $clone->setTitle($title);
374 }
375
376 $clone->saveToDb();
377
378 // copy XHTML media objects
379 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
380 return $clone->getId();
381 }
382
387 int $a_q_id
388 ): void {
389 $mobs = ilObjMediaObject::_getMobsOfObject("spl:html", $a_q_id);
390 foreach ($mobs as $mob) {
391 ilObjMediaObject::_saveUsage($mob, "spl:html", $this->getId());
392 }
393 }
394
399 public function loadFromDb(int $question_id): void
400 {
401 $this->material = [];
402 }
403
407 public static function _isComplete(int $question_id): bool
408 {
409 global $DIC;
410
411 $ilDB = $DIC->database();
412
413 $result = $ilDB->queryF(
414 "SELECT complete FROM svy_question WHERE question_id = %s",
415 array('integer'),
416 array($question_id)
417 );
418 if ($result->numRows()) {
419 $row = $ilDB->fetchAssoc($result);
420 if ((int) $row["complete"] === 1) {
421 return true;
422 }
423 }
424 return false;
425 }
426
430 public function saveCompletionStatus(
431 int $original_id = 0
432 ): void {
433 $ilDB = $this->db;
434
435 $question_id = $this->getId();
436 if ($original_id > 0) {
437 $question_id = $original_id;
438 }
439
440 if ($this->getId() > 0) {
441 $this->log->debug("UPDATE svy_question question_id=" . $question_id);
442
443 // update existing dataset
444 $affectedRows = $ilDB->manipulateF(
445 "UPDATE svy_question SET complete = %s, tstamp = %s WHERE question_id = %s",
446 array('text', 'integer', 'integer'),
447 array($this->isComplete(), time(), $question_id)
448 );
449 }
450 }
451
455 public function saveToDb(int $original_id = 0): int
456 {
457 $ilDB = $this->db;
458
459 // cleanup RTE images which are not inserted into the question text
460 ilRTE::_cleanupMediaObjectUsage($this->getQuestiontext(), "spl:html", $this->getId());
461 $affectedRows = 0;
462 if ($this->getId() === -1) {
463 // Write new dataset
464 $next_id = $ilDB->nextId('svy_question');
465 $affectedRows = $ilDB->insert("svy_question", array(
466 "question_id" => array("integer", $next_id),
467 "questiontype_fi" => array("integer", $this->getQuestionTypeID()),
468 "obj_fi" => array("integer", $this->getObjId()),
469 "owner_fi" => array("integer", $this->getOwner()),
470 "title" => array("text", $this->getTitle()),
471 "label" => array("text", (strlen($this->label ?? "")) ? $this->label : null),
472 "description" => array("text", $this->getDescription()),
473 "author" => array("text", $this->getAuthor()),
474 "questiontext" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getQuestiontext(), 0)),
475 "obligatory" => array("text", $this->getObligatory()),
476 "complete" => array("text", $this->isComplete()),
477 "created" => array("integer", time()),
478 "original_id" => array("integer", ($original_id) ?: null),
479 "tstamp" => array("integer", time())
480 ));
481
482 //$this->log->debug("INSERT: svy_question id=".$next_id." questiontype_fi=".$this->getQuestionTypeID()." obj_fi".$this->getObjId()." title=".$this->getTitle()." ...");
483
484 $this->setId($next_id);
485 } else {
486 // update existing dataset
487 $affectedRows = $ilDB->update("svy_question", array(
488 "title" => array("text", $this->getTitle()),
489 "label" => array("text", (strlen($this->label ?? "")) ? $this->label : null),
490 "description" => array("text", $this->getDescription()),
491 "author" => array("text", $this->getAuthor()),
492 "questiontext" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getQuestiontext(), 0)),
493 "obligatory" => array("text", $this->getObligatory()),
494 "complete" => array("text", $this->isComplete()),
495 "tstamp" => array("integer", time())
496 ), array(
497 "question_id" => array("integer", $this->getId())
498 ));
499
500 $this->log->debug("UPDATE svy_question id=" . $this->getId() . " SET: title=" . $this->getTitle() . " ...");
501 }
502 return $affectedRows;
503 }
504
510 public function createNewQuestion(): int
511 {
512 $ilDB = $this->db;
513
514 $obj_id = $this->getObjId();
515 if ($obj_id > 0) {
516 $next_id = $ilDB->nextId('svy_question');
517 $affectedRows = $ilDB->manipulateF(
518 "INSERT INTO svy_question (question_id, questiontype_fi, " .
519 "obj_fi, owner_fi, title, description, author, questiontext, obligatory, complete, " .
520 "created, original_id, tstamp) VALUES " .
521 "(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
522 array('integer', 'integer', 'integer', 'integer', 'text', 'text', 'text', 'text',
523 'text', 'text', 'integer', 'integer', 'integer'),
524 array(
525 $next_id,
526 $this->getQuestionTypeID(),
527 $obj_id,
528 $this->getOwner(),
529 null,
530 null,
531 $this->getAuthor(),
532 null,
533 "1",
534 "0",
535 time(),
536 null,
537 0
538 )
539 );
540 $this->log->debug("INSERT INTO svy_question question_id= " . $next_id . " questiontype_fi= " . $this->getQuestionTypeID());
541
542 $this->setId($next_id);
543 }
544 return $this->getId();
545 }
546
550 public function getImagePath(): string
551 {
552 return CLIENT_WEB_DIR . "/survey/$this->obj_id/$this->id/images/";
553 }
554
558 public function getMaterialsPath(): string
559 {
560 return CLIENT_WEB_DIR . "/survey/$this->obj_id/$this->id/materials/";
561 }
562
566 public function getImagePathWeb(): string
567 {
568 $webdir = ilFileUtils::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/survey/$this->obj_id/$this->id/images/";
569 return str_replace(
572 $webdir
573 );
574 }
575
579 public function getMaterialsPathWeb(): string
580 {
581 $webdir = ilFileUtils::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/survey/$this->obj_id/$this->id/materials/";
582 return str_replace(
585 $webdir
586 );
587 }
588
592 public function saveCategoryToDb(
593 string $categorytext,
594 int $neutral = 0
595 ): int {
596 $ilUser = $this->user;
597 $ilDB = $this->db;
598
599 $result = $ilDB->queryF(
600 "SELECT title, category_id FROM svy_category WHERE title = %s AND neutral = %s AND owner_fi = %s",
601 array('text','text','integer'),
602 array($categorytext, $neutral, $ilUser->getId())
603 );
604 $insert = false;
605 $returnvalue = "";
606 $insert = true;
607 if ($result->numRows()) {
608 while ($row = $ilDB->fetchAssoc($result)) {
609 if (strcmp($row["title"], $categorytext) === 0) {
610 $returnvalue = $row["category_id"];
611 $insert = false;
612 }
613 }
614 }
615 if ($insert) {
616 $next_id = $ilDB->nextId('svy_category');
617 $affectedRows = $ilDB->manipulateF(
618 "INSERT INTO svy_category (category_id, title, neutral, owner_fi, tstamp) VALUES (%s, %s, %s, %s, %s)",
619 array('integer','text','text','integer','integer'),
620 array($next_id, $categorytext, $neutral, $ilUser->getId(), time())
621 );
622
623 $this->log->debug("INSERT INTO svy_category id=" . $next_id);
624
625 $returnvalue = $next_id;
626 }
627 return $returnvalue;
628 }
629
633 public function deleteAdditionalTableData(int $question_id): void
634 {
635 $ilDB = $this->db;
636
637 $this->log->debug("DELETE FROM " . $this->getAdditionalTableName());
638
639 $ilDB->manipulateF(
640 "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
641 array('integer'),
642 array($question_id)
643 );
644 }
645
649 public function delete(int $question_id): void
650 {
651 $ilDB = $this->db;
652 $this->log->debug("Question Delete... " . $question_id);
653 if ($question_id < 1) {
654 return;
655 }
656
657 $result = $ilDB->queryF(
658 "SELECT obj_fi FROM svy_question WHERE question_id = %s",
659 array('integer'),
660 array($question_id)
661 );
662 if ($result->numRows() === 1) {
663 $row = $ilDB->fetchAssoc($result);
664 $obj_id = $row["obj_fi"];
665 } else {
666 return;
667 }
668
669 $affectedRows = $ilDB->manipulateF(
670 "DELETE FROM svy_answer WHERE question_fi = %s",
671 array('integer'),
672 array($question_id)
673 );
674
675 $affectedRows = $ilDB->manipulateF(
676 "DELETE FROM svy_constraint WHERE question_fi = %s",
677 array('integer'),
678 array($question_id)
679 );
680
681 $result = $ilDB->queryF(
682 "SELECT constraint_fi FROM svy_qst_constraint WHERE question_fi = %s",
683 array('integer'),
684 array($question_id)
685 );
686 while ($row = $ilDB->fetchObject($result)) {
687 $affectedRows = $ilDB->manipulateF(
688 "DELETE FROM svy_constraint WHERE constraint_id = %s",
689 array('integer'),
690 array($row->constraint_fi)
691 );
692 }
693
694 $affectedRows = $ilDB->manipulateF(
695 "DELETE FROM svy_qst_constraint WHERE question_fi = %s",
696 array('integer'),
697 array($question_id)
698 );
699 $affectedRows = $ilDB->manipulateF(
700 "DELETE FROM svy_qblk_qst WHERE question_fi = %s",
701 array('integer'),
702 array($question_id)
703 );
704 $affectedRows = $ilDB->manipulateF(
705 "DELETE FROM svy_svy_qst WHERE question_fi = %s",
706 array('integer'),
707 array($question_id)
708 );
709 $affectedRows = $ilDB->manipulateF(
710 "DELETE FROM svy_variable WHERE question_fi = %s",
711 array('integer'),
712 array($question_id)
713 );
714 $affectedRows = $ilDB->manipulateF(
715 "DELETE FROM svy_question WHERE question_id = %s",
716 array('integer'),
717 array($question_id)
718 );
719
720 $this->deleteAdditionalTableData($question_id);
721
722 $affectedRows = $ilDB->manipulateF(
723 "DELETE FROM svy_material WHERE question_fi = %s",
724 array('integer'),
725 array($question_id)
726 );
727
728 $this->log->debug("SET OF DELETES svy_answer, svy_constraint, svy_qst_constraint, svy_qblk_qst, svy_qst_oblig, svy_svy_qst, svy_variable, svy_question, svy_material WHERE question_fi = " . $question_id);
729
730 ilInternalLink::_deleteAllLinksOfSource("sqst", $question_id);
731
732 $directory = CLIENT_WEB_DIR . "/survey/" . $obj_id . "/$question_id";
733 if (preg_match("/\d+/", $obj_id) and preg_match("/\d+/", $question_id) and is_dir($directory)) {
734 ilFileUtils::delDir($directory);
735 }
736
737 $mobs = ilObjMediaObject::_getMobsOfObject("spl:html", $question_id);
738 // remaining usages are not in text anymore -> delete them
739 // and media objects (note: delete method of ilObjMediaObject
740 // checks whether object is used in another context; if yes,
741 // the object is not deleted!)
742 foreach ($mobs as $mob) {
743 ilObjMediaObject::_removeUsage($mob, "spl:html", $question_id);
744 $mob_obj = new ilObjMediaObject($mob);
745 $mob_obj->delete();
746 }
747 $this->log->debug("Call ilSurveySkill::handleQuestionDeletion, q id: " . $question_id .
748 ", obj id: " . $obj_id);
749 ilSurveySkill::handleQuestionDeletion($question_id, $obj_id);
750
751 $this->log->debug("UPDATE svy_question");
752
753 // #12772 - untie question copies from pool question
754 $ilDB->manipulate("UPDATE svy_question" .
755 " SET original_id = NULL" .
756 " WHERE original_id = " . $ilDB->quote($question_id, "integer"));
757 }
758
762 public static function _getQuestionType(int $question_id): string
763 {
764 global $DIC;
765
766 $ilDB = $DIC->database();
767
768 if ($question_id < 1) {
769 return "";
770 }
771
772 $result = $ilDB->queryF(
773 "SELECT type_tag FROM svy_question, svy_qtype WHERE svy_question.question_id = %s AND svy_question.questiontype_fi = svy_qtype.questiontype_id",
774 array('integer'),
775 array($question_id)
776 );
777 if ($result->numRows() === 1) {
778 $data = $ilDB->fetchAssoc($result);
779 return $data["type_tag"];
780 } else {
781 return "";
782 }
783 }
784
788 public static function _getTitle(int $question_id): string
789 {
790 global $DIC;
791
792 $ilDB = $DIC->database();
793
794 $result = $ilDB->queryF(
795 "SELECT title FROM svy_question WHERE svy_question.question_id = %s",
796 array('integer'),
797 array($question_id)
798 );
799
800 if ($data = $ilDB->fetchAssoc($result)) {
801 return (string) $data["title"];
802 }
803 return "";
804 }
805
809 public static function _getOriginalId(
810 int $question_id,
811 bool $a_return_question_id_if_no_original = true
812 ): int {
813 global $DIC;
814
815 $ilDB = $DIC->database();
816 $result = $ilDB->queryF(
817 "SELECT * FROM svy_question WHERE question_id = %s",
818 array('integer'),
819 array($question_id)
820 );
821 if ($result->numRows() > 0) {
822 $row = $ilDB->fetchAssoc($result);
823 if ($row["original_id"] > 0) {
824 return (int) $row["original_id"];
825 } elseif ($a_return_question_id_if_no_original) { // #12419
826 return (int) $row["question_id"];
827 }
828 }
829 return 0;
830 }
831
832 public function syncWithOriginal(): void
833 {
834 $ilDB = $this->db;
835
836 if ($this->getOriginalId()) {
837 $id = $this->getId();
838 $original = $this->getOriginalId();
839
840 $this->setId($this->getOriginalId());
841 $this->setOriginalId(null);
842 $this->saveToDb();
843
844 $this->setId($id);
845 $this->setOriginalId($original);
846
847 $this->log->debug("DELETE FROM svy_material WHERE question_fi = " . $this->getOriginalId());
848
849 $affectedRows = $ilDB->manipulateF(
850 "DELETE FROM svy_material WHERE question_fi = %s",
851 array('integer'),
852 array($this->getOriginalId())
853 );
854 ilInternalLink::_deleteAllLinksOfSource("sqst", $this->original_id);
855 if (strlen($this->material["internal_link"] ?? "")) {
856 $next_id = $ilDB->nextId('svy_material');
857 $affectedRows = $ilDB->manipulateF(
858 "INSERT INTO svy_material (material_id, question_fi, internal_link, import_id, material_title, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
859 array('integer', 'integer', 'text', 'text', 'text', 'integer'),
860 array($next_id, $this->getOriginalId(), $this->material["internal_link"], $this->material["import_id"], $this->material["title"], time())
861 );
862
863 $this->log->debug("INSERT svy_material material_id=" . $next_id . " question_fi=" . $this->getOriginalId());
864
865 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $this->material["internal_link"], $matches)) {
866 ilInternalLink::_saveLink("sqst", $this->getOriginalId(), $matches[2], $matches[3], $matches[1]);
867 }
868 }
869 }
870 }
871
872 public static function _questionExists(int $question_id): bool
873 {
874 global $DIC;
875
876 $ilDB = $DIC->database();
877
878 if ($question_id < 1) {
879 return false;
880 }
881
882 $result = $ilDB->queryF(
883 "SELECT question_id FROM svy_question WHERE question_id = %s",
884 array('integer'),
885 array($question_id)
886 );
887 return $result->numRows() === 1;
888 }
889
890
891 public static function _resolveInternalLink(
892 string $internal_link
893 ): string {
894 $resolved_link = "";
895 if (preg_match("/il_(\d+)_(\w+)_(\d+)/", $internal_link, $matches)) {
896 switch ($matches[2]) {
897 case "lm":
898 $resolved_link = ilLMObject::_getIdForImportId($internal_link);
899 break;
900 case "pg":
901 $resolved_link = ilInternalLink::_getIdForImportId("PageObject", $internal_link);
902 break;
903 case "st":
904 $resolved_link = ilInternalLink::_getIdForImportId("StructureObject", $internal_link);
905 break;
906 case "git":
907 $resolved_link = ilInternalLink::_getIdForImportId("GlossaryItem", $internal_link);
908 break;
909 case "mob":
910 $resolved_link = ilInternalLink::_getIdForImportId("MediaObject", $internal_link);
911 break;
912 }
913 if (strcmp($resolved_link, "") === 0) {
914 $resolved_link = $internal_link;
915 }
916 } else {
917 $resolved_link = $internal_link;
918 }
919 return $resolved_link;
920 }
921
922 public static function _resolveIntLinks(
923 int $question_id
924 ): void {
925 global $DIC;
926
927 $ilDB = $DIC->database();
928 $resolvedlinks = 0;
929 $result = $ilDB->queryF(
930 "SELECT * FROM svy_material WHERE question_fi = %s",
931 array('integer'),
932 array($question_id)
933 );
934 if ($result->numRows()) {
935 while ($row = $ilDB->fetchAssoc($result)) {
936 $internal_link = $row["internal_link"];
937 $resolved_link = self::_resolveInternalLink($internal_link);
938 if (strcmp($internal_link, $resolved_link) !== 0) {
939 // internal link was resolved successfully
940 $affectedRows = $ilDB->manipulateF(
941 "UPDATE svy_material SET internal_link = %s, tstamp = %s WHERE material_id = %s",
942 array('text', 'integer', 'integer'),
943 array($resolved_link, time(), $row["material_id"])
944 );
945 $resolvedlinks++;
946 }
947 }
948 }
949 if ($resolvedlinks) {
950 // there are resolved links -> reenter theses links to the database
951
952 // delete all internal links from the database
953 ilInternalLink::_deleteAllLinksOfSource("sqst", $question_id);
954
955 $result = $ilDB->queryF(
956 "SELECT * FROM svy_material WHERE question_fi = %s",
957 array('integer'),
958 array($question_id)
959 );
960 if ($result->numRows()) {
961 while ($row = $ilDB->fetchAssoc($result)) {
962 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $row["internal_link"], $matches)) {
963 ilInternalLink::_saveLink("sqst", $question_id, $matches[2], $matches[3], $matches[1]);
964 }
965 }
966 }
967 }
968 }
969
970 public static function _getInternalLinkHref(
971 string $target = "",
972 ?int $a_parent_ref_id = null
973 ): string {
974 $linktypes = array(
975 "lm" => "LearningModule",
976 "pg" => "PageObject",
977 "st" => "StructureObject",
978 "git" => "GlossaryItem",
979 "mob" => "MediaObject"
980 );
981 $href = "";
982 if (preg_match("/il__(\w+)_(\d+)/", $target, $matches)) {
983 $type = $matches[1];
984 $target_id = $matches[2];
985 switch ($linktypes[$matches[1]]) {
986 case "StructureObject":
987 case "PageObject":
988 case "GlossaryItem":
989 case "LearningModule":
990 $href = ilFileUtils::removeTrailingPathSeparators(ILIAS_HTTP_PATH) . "/goto.php?target=" . $type . "_" . $target_id;
991 break;
992 case "MediaObject":
994 ILIAS_HTTP_PATH
995 ) . "/ilias.php?baseClass=ilLMPresentationGUI&obj_type=" . $linktypes[$type] . "&cmd=media&ref_id=" . $a_parent_ref_id . "&mob_id=" . $target_id;
996 break;
997 }
998 }
999 return $href;
1000 }
1001
1005 public static function _isWriteable(
1006 int $question_id,
1007 int $user_id
1008 ): bool {
1009 global $DIC;
1010
1011 $ilDB = $DIC->database();
1012
1013 if (($question_id < 1) || ($user_id < 1)) {
1014 return false;
1015 }
1016
1017 $result = $ilDB->queryF(
1018 "SELECT obj_fi FROM svy_question WHERE question_id = %s",
1019 array('integer'),
1020 array($question_id)
1021 );
1022 if ($result->numRows() === 1) {
1023 $row = $ilDB->fetchAssoc($result);
1024 $qpl_object_id = $row["obj_fi"];
1025 return ilObjSurveyQuestionPool::_isWriteable($qpl_object_id);
1026 }
1027
1028 return false;
1029 }
1030
1031 public function getQuestionTypeID(): int
1032 {
1033 $ilDB = $this->db;
1034 $result = $ilDB->queryF(
1035 "SELECT questiontype_id FROM svy_qtype WHERE type_tag = %s",
1036 array('text'),
1037 array($this->getQuestionType())
1038 );
1039 if ($result->numRows() === 1) {
1040 $row = $ilDB->fetchAssoc($result);
1041 return (int) $row["questiontype_id"];
1042 }
1043
1044 return 0;
1045 }
1046
1047 public function getQuestionType(): string
1048 {
1049 return "";
1050 }
1051
1056 public static function _includeClass(
1057 string $question_type,
1058 int $gui = 0
1059 ): bool {
1060 $type = $question_type;
1061 if ($gui === 1) {
1062 $type .= "GUI";
1063 } elseif ($gui === 2) {
1064 $type .= "Evaluation";
1065 }
1066 if (file_exists("./components/ILIAS/SurveyQuestionPool/Questions/class." . $type . ".php")) {
1067 return true;
1068 }
1069 return false;
1070 }
1071
1076 public static function _getQuestionTypeName(
1077 string $type_tag
1078 ): string {
1079 global $DIC;
1080 $lng = $DIC->language();
1081 return $lng->txt($type_tag);
1082 }
1083
1084
1088 public static function _instanciateQuestion(int $question_id): ?SurveyQuestion
1089 {
1090 $question_type = self::_getQuestionType($question_id);
1091 if ($question_type) {
1092 self::_includeClass($question_type);
1093 $question = new $question_type();
1094 $question->loadFromDb($question_id);
1095 return $question;
1096 }
1097 return null;
1098 }
1099
1103 public static function _instanciateQuestionGUI(
1104 int $question_id
1105 ): ?SurveyQuestionGUI {
1106 $question_type = self::_getQuestionType($question_id);
1107 if ($question_type) {
1108 self::_includeClass($question_type, 1);
1109 $guitype = $question_type . "GUI";
1110 $question = new $guitype($question_id);
1111 return $question;
1112 }
1113 return null;
1114 }
1115
1116 public static function _instanciateQuestionEvaluation(
1117 int $question_id,
1118 ?array $a_finished_ids = null
1120 $question = self::_instanciateQuestion($question_id);
1121 if (is_null($a_finished_ids)) {
1122 $a_finished_ids = [];
1123 }
1124 if ($question) {
1125 $question_type = self::_getQuestionType($question_id);
1126 self::_includeClass($question_type, 2);
1127 $class = $question_type . "Evaluation";
1128 $ev = new $class($question, $a_finished_ids);
1129 return $ev;
1130 }
1131 return null;
1132 }
1133
1137 public function isHTML(string $a_text): bool
1138 {
1139 if (preg_match("/<[^>]*?>/", $a_text)) {
1140 return true;
1141 }
1142
1143 return false;
1144 }
1145
1149 public function QTIMaterialToString(ilQTIMaterial $a_material): string
1150 {
1151 $svy_log = ilLoggerFactory::getLogger("svy");
1152 $svy_log->debug("material count: " . $a_material->getMaterialCount());
1153
1154 $result = "";
1155 for ($i = 0; $i < $a_material->getMaterialCount(); $i++) {
1156 $material = $a_material->getMaterial($i);
1157 if (strcmp($material["type"], "mattext") === 0) {
1158 $result .= $material["material"]->getContent();
1159 }
1160 if (strcmp($material["type"], "matimage") === 0) {
1161 $matimage = $material["material"];
1162 if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches)) {
1163 // import an mediaobject which was inserted using tiny mce
1164 $this->import_manager->addMob(
1165 $matimage->getLabel(),
1166 $matimage->getUri()
1167 );
1168 }
1169 }
1170 }
1171 return $result;
1172 }
1173
1177 public function addMaterialTag(
1178 ilXmlWriter $a_xml_writer,
1179 string $a_material,
1180 bool $close_material_tag = true,
1181 bool $add_mobs = true,
1182 ?array $a_attrs = null
1183 ): void {
1184 $a_xml_writer->xmlStartTag("material");
1185 $attrs = array(
1186 "type" => "text/plain"
1187 );
1188 if ($this->isHTML($a_material)) {
1189 $attrs["type"] = "text/xhtml";
1190 }
1191 if (is_array($a_attrs)) {
1192 $attrs = array_merge($attrs, $a_attrs);
1193 }
1194 $a_xml_writer->xmlElement("mattext", $attrs, ilRTE::_replaceMediaObjectImageSrc($a_material, 0));
1195
1196 if ($add_mobs) {
1197 $mobs = ilObjMediaObject::_getMobsOfObject("spl:html", $this->getId());
1198 foreach ($mobs as $mob) {
1199 $mob_obj = new ilObjMediaObject($mob);
1200 $imgattrs = array(
1201 "label" => "il_" . IL_INST_ID . "_mob_" . $mob,
1202 "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle(),
1203 "type" => "spl:html",
1204 "id" => $this->getId()
1205 );
1206 $a_xml_writer->xmlElement("matimage", $imgattrs, null);
1207 }
1208 }
1209 if ($close_material_tag) {
1210 $a_xml_writer->xmlEndTag("material");
1211 }
1212 }
1213
1217 public function prepareTextareaOutput(
1218 string $txt_output,
1219 bool $prepare_for_latex_output = false
1220 ): string {
1221 return ilLegacyFormElementsUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output);
1222 }
1223
1227 public function getQuestionDataArray(int $id): array
1228 {
1229 return array();
1230 }
1231
1236 public function getWorkingDataFromUserInput(array $post_data): array
1237 {
1238 // overwrite in inherited classes
1239 $data = array();
1240 return $data;
1241 }
1242
1248 public function importAdditionalMetadata(array $a_meta): void
1249 {
1250 // overwrite in inherited classes
1251 }
1252
1256 public function importResponses(array $a_data): void
1257 {
1258 // overwrite in inherited classes
1259 }
1260
1264 public function importAdjectives(array $a_data): void
1265 {
1266 // overwrite in inherited classes
1267 }
1268
1272 public function importMatrix(array $a_data): void
1273 {
1274 // overwrite in inherited classes
1275 }
1276
1280 public function usableForPrecondition(): bool
1281 {
1282 // overwrite in inherited classes
1283 return false;
1284 }
1285
1289 public function getAvailableRelations(): array
1290 {
1291 // overwrite in inherited classes
1292 return array();
1293 }
1294
1298 public function getPreconditionOptions(): array
1299 {
1300 // overwrite in inherited classes
1301 return [];
1302 }
1303
1309 public function getPreconditionValueOutput(string $value): string
1310 {
1311 // overwrite in inherited classes
1312 return $value;
1313 }
1314
1319 string $default,
1320 string $title,
1321 string $variable
1322 ): ?ilFormPropertyGUI {
1323 // overwrite in inherited classes
1324 return null;
1325 }
1326
1327 public function setOriginalId(?int $original_id): void
1328 {
1329 $this->original_id = $original_id;
1330 }
1331
1332 public function getOriginalId(): ?int
1333 {
1334 return $this->original_id;
1335 }
1336
1337 public function getMaterial(): array
1338 {
1339 return $this->material;
1340 }
1341
1342 public function setSubtype(int $a_subtype): void
1343 {
1344 // do nothing
1345 }
1346
1347 public function getSubtype(): ?int
1348 {
1349 // do nothing
1350 return null;
1351 }
1352
1353 public function __get(string $value): ?string
1354 {
1355 switch ($value) {
1356 default:
1357 if (array_key_exists($value, $this->arrData)) {
1358 return (string) $this->arrData[$value];
1359 }
1360
1361 return null;
1362 }
1363 }
1364
1365 public function __set(string $key, string $value): void
1366 {
1367 switch ($key) {
1368 default:
1369 $this->arrData[$key] = $value;
1370 break;
1371 }
1372 }
1373
1377 public static function _changeOriginalId(
1378 int $a_question_id,
1379 int $a_original_id,
1380 int $a_object_id
1381 ): void {
1382 global $DIC;
1383
1384 $ilDB = $DIC->database();
1385
1386 $ilDB->manipulate("UPDATE svy_question" .
1387 " SET original_id = " . $ilDB->quote($a_original_id, "integer") . "," .
1388 " obj_fi = " . $ilDB->quote($a_object_id, "integer") .
1389 " WHERE question_id = " . $ilDB->quote($a_question_id, "integer"));
1390 }
1391
1392 public function getCopyIds(
1393 bool $a_group_by_survey = false
1394 ): array {
1395 $ilDB = $this->db;
1396
1397 $set = $ilDB->query("SELECT q.question_id,s.obj_fi" .
1398 " FROM svy_question q" .
1399 " JOIN svy_svy_qst sq ON (sq.question_fi = q.question_id)" .
1400 " JOIN svy_svy s ON (s.survey_id = sq.survey_fi)" .
1401 " WHERE original_id = " . $ilDB->quote($this->getId(), "integer"));
1402 $res = array();
1403 while ($row = $ilDB->fetchAssoc($set)) {
1404 if (!$a_group_by_survey) {
1405 $res[] = (int) $row["question_id"];
1406 } else {
1407 $res[$row["obj_fi"]][] = (int) $row["question_id"];
1408 }
1409 }
1410 return $res;
1411 }
1412
1413 public function hasCopies(): bool
1414 {
1415 return (bool) count($this->getCopyIds());
1416 }
1417
1418 public static function _lookupSurveyObjId(
1419 int $a_question_id
1420 ): ?int {
1421 global $DIC;
1422
1423 $ilDB = $DIC->database();
1424
1425 $set = $ilDB->query("SELECT svy_svy.obj_fi FROM svy_svy_qst" .
1426 " JOIN svy_svy ON (svy_svy.survey_id = svy_svy_qst.survey_fi)" .
1427 " WHERE svy_svy_qst.question_fi = " . $ilDB->quote($a_question_id, "integer"));
1428 $row = $ilDB->fetchAssoc($set);
1429 if ($ilDB->numRows($set)) {
1430 return (int) $row["obj_fi"];
1431 }
1432 return null;
1433 }
1434
1435 public static function lookupObjFi(
1436 int $a_qid
1437 ): ?int {
1438 global $DIC;
1439
1440 $ilDB = $DIC->database();
1441
1442 $set = $ilDB->query(
1443 "SELECT obj_fi FROM svy_question " .
1444 " WHERE question_id = " . $ilDB->quote($a_qid, "integer")
1445 );
1446 if ($rec = $ilDB->fetchAssoc($set)) {
1447 return (int) $rec["obj_fi"];
1448 }
1449 return null;
1450 }
1451
1456 public function stripSlashesAddSpaceFallback(string $a_str): string
1457 {
1458 $str = ilUtil::stripSlashes($a_str);
1459 if ($str !== $a_str) {
1460 $str = ilUtil::stripSlashes(str_replace("<", "< ", $a_str));
1461 }
1462 return $str;
1463 }
1464
1468 public static function getMaxSumScore(int $survey_id): int
1469 {
1470 return 0;
1471 }
1472}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Basic class for all survey question types The SurveyQuestionGUI class defines and encapsulates basic ...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
importMatrix(array $a_data)
Import matrix rows from the question import file.
static getMaxSumScore(int $survey_id)
Get max sum score for specific survey (and this question type)
static _getTitle(int $question_id)
Returns the question title of a question with a given id.
copyObject(int $target_questionpool, string $title="")
ILIAS SurveyQuestionPool Editing EditSessionRepository $edit_manager
static _getOriginalId(int $question_id, bool $a_return_question_id_if_no_original=true)
Returns the original id of a question.
getCopyIds(bool $a_group_by_survey=false)
getQuestionDataArray(int $id)
Returns the question data.
stripSlashesAddSpaceFallback(string $a_str)
Strip slashes with add space fallback, see https://mantis.ilias.de/view.php?id=19727 and https://mant...
getObjId()
Get the reference(?) id of the container object.
setTitle(string $title="")
ILIAS SurveyQuestionPool Export ImportSessionRepository $import_manager
copyXHTMLMediaObjectsOfQuestion(int $a_q_id)
Copy media object usages from other question.
deleteAdditionalTableData(int $question_id)
Deletes datasets from the additional question table in the database.
static _resolveIntLinks(int $question_id)
static _resolveInternalLink(string $internal_link)
loadFromDb(int $question_id)
load question data into object note: this base implementation only loads the material data
static _instanciateQuestionEvaluation(int $question_id, ?array $a_finished_ids=null)
static _lookupSurveyObjId(int $a_question_id)
createNewQuestion()
Creates a new question with a 0 timestamp when a new question is created This assures that an ID is g...
setMaterialsfile(string $materials_filename, string $materials_tempfilename="", string $materials_name="")
Uploads and adds a material.
QTIMaterialToString(ilQTIMaterial $a_material)
Reads an QTI material tag an creates a text string.
getMaterialsPath()
Returns the materials path for web accessible materials of a question.
duplicate(bool $for_survey=true, string $title="", string $author="", int $owner=0, int $a_survey_id=0)
getPreconditionSelectValue(string $default, string $title, string $variable)
Creates a form property for the precondition value.
importResponses(array $a_data)
Import response data from the question import file.
getWorkingDataFromUserInput(array $post_data)
Creates the user data of the svy_answer table from the POST data.
getMaterialsPathWeb()
Returns the web image path for web accessable images of a question.
getImagePath()
Returns the image path for web accessible images of a question.
static _getInternalLinkHref(string $target="", ?int $a_parent_ref_id=null)
saveCategoryToDb(string $categorytext, int $neutral=0)
Saves a category to the database.
static _getQuestionTypeName(string $type_tag)
Return the translation for a given question type.
deleteMaterial(string $materials_name="")
__set(string $key, string $value)
importAdditionalMetadata(array $a_meta)
Import additional meta data from the question import file.
setQuestiontext(string $questiontext="")
setSubtype(int $a_subtype)
setDescription(string $description="")
static _isWriteable(int $question_id, int $user_id)
is question writeable by a certain user
static _includeClass(string $question_type, int $gui=0)
Include the php class file for a given question type.
getPreconditionOptions()
Returns the options for preconditions.
static _changeOriginalId(int $a_question_id, int $a_original_id, int $a_object_id)
Change original id of existing question in db.
saveToDb(int $original_id=0)
Saves a SurveyQuestion object to a database.
static lookupObjFi(int $a_qid)
setObjId(int $obj_id=0)
Set the reference(?) id of the container object.
setOrientation(int $orientation=0)
static _questionExists(int $question_id)
static _getQuestionType(int $question_id)
Returns the question type of a question with a given id.
__construct(string $title="", string $description="", string $author="", string $questiontext="", int $owner=-1)
setOwner(int $owner=0)
static _instanciateQuestion(int $question_id)
Get question object.
getAvailableRelations()
Returns the available relations for the question.
addMaterials(string $materials_file, string $materials_name="")
setComplete(bool $a_complete)
setOriginalId(?int $original_id)
static _instanciateQuestionGUI(int $question_id)
Get question gui object.
usableForPrecondition()
Returns if the question is usable for preconditions.
getPreconditionValueOutput(string $value)
Returns the output for a precondition value.
flushMaterials()
Deletes all materials uris.
prepareTextareaOutput(string $txt_output, bool $prepare_for_latex_output=false)
Prepares string for a text area output in surveys.
static _isComplete(int $question_id)
Checks whether the question is complete or not.
saveCompletionStatus(int $original_id=0)
Saves the complete flag to the database.
isHTML(string $a_text)
setObligatory(bool $obligatory=true)
getImagePathWeb()
Returns the web image path for web accessible images of a question.
setAuthor(string $author="")
importAdjectives(array $a_data)
Import bipolar adjectives from the question import file.
addMaterialTag(ilXmlWriter $a_xml_writer, string $a_material, bool $close_material_tag=true, bool $add_mobs=true, ?array $a_attrs=null)
Creates an XML material tag from a plain text or xhtml text.
questionTitleExists(string $title, int $questionpool_object=0)
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static removeTrailingPathSeparators(string $path)
static moveUploadedFile(string $a_file, string $a_name, string $a_target, bool $a_raise_errors=true, string $a_mode="move_uploaded")
move uploaded file
This class represents a property in a property form.
static _getIdForImportId(string $a_import_id)
get current object id for import id (static)
language handling
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getLogger(string $a_component_id)
Get component logger.
Component logger with individual log levels by component id.
static _getMobsOfObject(string $a_type, int $a_id, int $a_usage_hist_nr=0, string $a_lang="-")
static _removeUsage(int $a_mob_id, string $a_type, int $a_id, int $a_usage_hist_nr=0, string $a_lang="-")
Remove usage of mob in another container.
static _saveUsage(int $a_mob_id, string $a_type, int $a_id, int $a_usage_hist_nr=0, string $a_lang="-")
Save usage of mob within another container (e.g.
static _isWriteable(int $object_id)
Returns true, if the question pool is writeable for the current user.
User class.
getMaterial(int $a_index)
static _cleanupMediaObjectUsage(string $a_text, string $a_usage_type, int $a_usage_id)
Synchronises appearances of media objects in $a_text with media object usage table.
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 handleQuestionDeletion(int $a_question_id, int $a_obj_id)
Remove question skill assignment.
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
xmlElement(string $tag, $attrs=null, $data=null, $encode=true, $escape=true)
Writes a basic element (no children, just textual content)
xmlEndTag(string $tag)
Writes an endtag.
const CLIENT_WEB_DIR
Definition: constants.php:47
const IL_INST_ID
Definition: constants.php:40
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Interface ilDBInterface.
$res
Definition: ltiservices.php:69
global $lng
Definition: privfeed.php:31
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26