ILIAS  trunk Revision v12.0_alpha-377-g3641b37b9db
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
43 public array $material;
44 public bool $complete;
45 protected array $cumulated;
46 private array $arrData; // question data
47 protected ilLogger $log;
48
49 protected \ILIAS\SurveyQuestionPool\Export\ImportSessionRepository $import_manager;
50
51 public function __construct(
52 string $title = "",
53 string $description = "",
54 string $author = "",
55 string $questiontext = "",
56 int $owner = -1
57 ) {
58 global $DIC;
59
60 $this->user = $DIC->user();
61 $this->db = $DIC->database();
62 $lng = $DIC->language();
63 $ilUser = $DIC->user();
64
65 $this->lng = $lng;
66 $this->complete = 0;
67 $this->title = $title;
68 $this->description = $description;
69 $this->questiontext = $questiontext;
70 $this->author = $author ?: $ilUser->getFullname();
71 $this->cumulated = array();
72 $this->owner = $owner;
73 if ($this->owner === -1) {
74 $this->owner = $ilUser->getId();
75 }
76 $this->id = -1;
77 $this->survey_id = -1;
78 $this->obligatory = 1;
79 $this->orientation = 0;
80 $this->materials = array();
81 $this->material = array();
82 $this->arrData = array();
83
84 $this->log = ilLoggerFactory::getLogger('svy');
85 $this->import_manager = $DIC->surveyQuestionPool()
86 ->internal()
87 ->repo()
88 ->import();
89
90 $this->edit_manager = $DIC->surveyQuestionPool()
91 ->internal()
92 ->repo()
93 ->editing();
94 }
95
96 public function setComplete(bool $a_complete): void
97 {
98 $this->complete = $a_complete;
99 }
100
101 public function isComplete(): bool
102 {
103 return false;
104 }
105
106 public function questionTitleExists(
107 string $title,
108 int $questionpool_object = 0
109 ): bool {
110 $ilDB = $this->db;
111
112 $refwhere = "";
113 if ($questionpool_object > 0) {
114 $refwhere = sprintf(
115 " AND obj_fi = %s",
116 $ilDB->quote($questionpool_object, 'integer')
117 );
118 }
119 $result = $ilDB->queryF(
120 "SELECT question_id FROM svy_question WHERE title = %s$refwhere",
121 array('text'),
122 array($title)
123 );
124 return $result->numRows() > 0;
125 }
126
127 public function setTitle(string $title = ""): void
128 {
129 $this->title = $title;
130 }
131
132 public function setObligatory(bool $obligatory = true): void
133 {
134 $this->obligatory = $obligatory;
135 }
136
137 public function setOrientation(int $orientation = 0): void
138 {
139 $this->orientation = $orientation;
140 }
141
142 public function setId(int $id = -1): void
143 {
144 $this->id = $id;
145 }
146
147 public function setSurveyId(int $id = -1): void
148 {
149 $this->survey_id = $id;
150 }
151
152 public function setDescription(string $description = ""): void
153 {
154 $this->description = $description;
155 }
156
157 public function addMaterials(
158 string $materials_file,
159 string $materials_name = ""
160 ): void {
161 if (empty($materials_name)) {
162 $materials_name = $materials_file;
163 }
164 if ((!empty($materials_name)) && (!array_key_exists($materials_name, $this->materials))) {
165 $this->materials[$materials_name] = $materials_file;
166 }
167 }
168
172 public function setMaterialsfile(
173 string $materials_filename,
174 string $materials_tempfilename = "",
175 string $materials_name = ""
176 ): void {
177 if (!empty($materials_filename)) {
178 $materialspath = $this->getMaterialsPath();
179 if (!file_exists($materialspath)) {
180 ilFileUtils::makeDirParents($materialspath);
181 }
183 $materials_tempfilename,
184 $materials_filename,
185 $materialspath . $materials_filename
186 )) {
187 print "image not uploaded!!!! ";
188 } else {
189 $this->addMaterials($materials_filename, $materials_name);
190 }
191 }
192 }
193
194 public function deleteMaterial(
195 string $materials_name = ""
196 ): void {
197 foreach ($this->materials as $key => $value) {
198 if (strcmp($key, $materials_name) === 0) {
199 if (file_exists($this->getMaterialsPath() . $value)) {
200 unlink($this->getMaterialsPath() . $value);
201 }
202 unset($this->materials[$key]);
203 }
204 }
205 }
206
211 public function flushMaterials(): void
212 {
213 $this->materials = array();
214 }
215
216 public function setAuthor(string $author = ""): void
217 {
218 $this->author = $author ?: $this->user->getFullname();
219 }
220
221 public function setQuestiontext(string $questiontext = ""): void
222 {
223 $this->questiontext = $questiontext;
224 }
225
229 public function setOwner(int $owner = 0): void
230 {
231 $this->owner = $owner;
232 }
233
234 public function getTitle(): string
235 {
236 return $this->title;
237 }
238
239 public function getLabel(): string
240 {
241 return $this->label;
242 }
243
244 public function getId(): int
245 {
246 return $this->id;
247 }
248
249 public function getObligatory(): bool
250 {
251 return $this->obligatory;
252 }
253
254 public function getSurveyId(): int
255 {
256 return $this->survey_id;
257 }
258
262 public function getOrientation(): int
263 {
264 switch ($this->orientation) {
265 case 0:
266 case 1:
267 case 2:
268 break;
269 default:
270 $this->orientation = 0;
271 break;
272 }
273 return $this->orientation;
274 }
275
276
277 public function getDescription(): string
278 {
279 return $this->description;
280 }
281
282 public function getAuthor(): string
283 {
284 return $this->author;
285 }
286
287 public function getOwner(): int
288 {
289 return $this->owner;
290 }
291
292 public function getQuestiontext(): string
293 {
294 return $this->questiontext;
295 }
296
300 public function getObjId(): int
301 {
302 return $this->obj_id;
303 }
304
308 public function setObjId(int $obj_id = 0): void
309 {
310 $this->obj_id = $obj_id;
311 }
312
313 public function duplicate(
314 bool $for_survey = true,
315 string $title = "",
316 string $author = "",
317 int $owner = 0,
318 int $a_survey_id = 0
319 ): ?int {
320 if ($this->getId() <= 0) {
321 // The question has not been saved. It cannot be duplicated
322 return null;
323 }
324 // duplicate the question in database
325 $clone = $this;
326 $original_id = $this->getId();
327 $clone->setId(-1);
328 if ($a_survey_id > 0) {
329 $clone->setObjId($a_survey_id);
330 }
331 if ($title) {
332 $clone->setTitle($title);
333 }
334 if ($author) {
335 $clone->setAuthor($author);
336 }
337 if ($owner) {
338 $clone->setOwner($owner);
339 }
340 if ($for_survey) {
341 $clone->saveToDb($original_id);
342 } else {
343 $clone->saveToDb();
344 }
345 // copy XHTML media objects
346 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
347 return $clone->getId();
348 }
349
350 public function copyObject(
351 int $target_questionpool,
352 string $title = ""
353 ): ?int {
354 if ($this->getId() <= 0) {
355 // The question has not been saved. It cannot be copied
356 return null;
357 }
358 $clone = $this;
359 $original_id = self::_getOriginalId($this->getId(), false);
360 $clone->setId(-1);
361 $source_questionpool = $this->getObjId();
362 $clone->setObjId($target_questionpool);
363 if ($title) {
364 $clone->setTitle($title);
365 }
366
367 $clone->saveToDb();
368
369 // copy XHTML media objects
370 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
371 return $clone->getId();
372 }
373
378 int $a_q_id
379 ): void {
380 $mobs = ilObjMediaObject::_getMobsOfObject("spl:html", $a_q_id);
381 foreach ($mobs as $mob) {
382 ilObjMediaObject::_saveUsage($mob, "spl:html", $this->getId());
383 }
384 }
385
390 public function loadFromDb(int $question_id): void
391 {
392 $this->material = [];
393 }
394
398 public static function _isComplete(int $question_id): bool
399 {
400 global $DIC;
401
402 $ilDB = $DIC->database();
403
404 $result = $ilDB->queryF(
405 "SELECT complete FROM svy_question WHERE question_id = %s",
406 array('integer'),
407 array($question_id)
408 );
409 if ($result->numRows()) {
410 $row = $ilDB->fetchAssoc($result);
411 if ((int) $row["complete"] === 1) {
412 return true;
413 }
414 }
415 return false;
416 }
417
421 public function saveCompletionStatus(
422 int $original_id = 0
423 ): void {
424 $ilDB = $this->db;
425
426 $question_id = $this->getId();
427 if ($original_id > 0) {
428 $question_id = $original_id;
429 }
430
431 if ($this->getId() > 0) {
432 $this->log->debug("UPDATE svy_question question_id=" . $question_id);
433
434 // update existing dataset
435 $affectedRows = $ilDB->manipulateF(
436 "UPDATE svy_question SET complete = %s, tstamp = %s WHERE question_id = %s",
437 array('text', 'integer', 'integer'),
438 array($this->isComplete(), time(), $question_id)
439 );
440 }
441 }
442
446 public function saveToDb(int $original_id = 0): int
447 {
448 $ilDB = $this->db;
449
450 // cleanup RTE images which are not inserted into the question text
451 ilRTE::_cleanupMediaObjectUsage($this->getQuestiontext(), "spl:html", $this->getId());
452 $affectedRows = 0;
453 if ($this->getId() === -1) {
454 // Write new dataset
455 $next_id = $ilDB->nextId('svy_question');
456 $affectedRows = $ilDB->insert("svy_question", array(
457 "question_id" => array("integer", $next_id),
458 "questiontype_fi" => array("integer", $this->getQuestionTypeID()),
459 "obj_fi" => array("integer", $this->getObjId()),
460 "owner_fi" => array("integer", $this->getOwner()),
461 "title" => array("text", $this->getTitle()),
462 "label" => array("text", (strlen($this->label ?? "")) ? $this->label : null),
463 "description" => array("text", $this->getDescription()),
464 "author" => array("text", $this->getAuthor()),
465 "questiontext" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getQuestiontext(), 0)),
466 "obligatory" => array("text", $this->getObligatory()),
467 "complete" => array("text", $this->isComplete()),
468 "created" => array("integer", time()),
469 "original_id" => array("integer", ($original_id) ?: null),
470 "tstamp" => array("integer", time())
471 ));
472
473 //$this->log->debug("INSERT: svy_question id=".$next_id." questiontype_fi=".$this->getQuestionTypeID()." obj_fi".$this->getObjId()." title=".$this->getTitle()." ...");
474
475 $this->setId($next_id);
476 } else {
477 // update existing dataset
478 $affectedRows = $ilDB->update("svy_question", array(
479 "title" => array("text", $this->getTitle()),
480 "label" => array("text", (strlen($this->label ?? "")) ? $this->label : null),
481 "description" => array("text", $this->getDescription()),
482 "author" => array("text", $this->getAuthor()),
483 "questiontext" => array("clob", ilRTE::_replaceMediaObjectImageSrc($this->getQuestiontext(), 0)),
484 "obligatory" => array("text", $this->getObligatory()),
485 "complete" => array("text", $this->isComplete()),
486 "tstamp" => array("integer", time())
487 ), array(
488 "question_id" => array("integer", $this->getId())
489 ));
490
491 $this->log->debug("UPDATE svy_question id=" . $this->getId() . " SET: title=" . $this->getTitle() . " ...");
492 }
493 return $affectedRows;
494 }
495
501 public function createNewQuestion(): int
502 {
503 $ilDB = $this->db;
504
505 $obj_id = $this->getObjId();
506 if ($obj_id > 0) {
507 $next_id = $ilDB->nextId('svy_question');
508 $affectedRows = $ilDB->manipulateF(
509 "INSERT INTO svy_question (question_id, questiontype_fi, " .
510 "obj_fi, owner_fi, title, description, author, questiontext, obligatory, complete, " .
511 "created, original_id, tstamp) VALUES " .
512 "(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
513 array('integer', 'integer', 'integer', 'integer', 'text', 'text', 'text', 'text',
514 'text', 'text', 'integer', 'integer', 'integer'),
515 array(
516 $next_id,
517 $this->getQuestionTypeID(),
518 $obj_id,
519 $this->getOwner(),
520 null,
521 null,
522 $this->getAuthor(),
523 null,
524 "1",
525 "0",
526 time(),
527 null,
528 0
529 )
530 );
531 $this->log->debug("INSERT INTO svy_question question_id= " . $next_id . " questiontype_fi= " . $this->getQuestionTypeID());
532
533 $this->setId($next_id);
534 }
535 return $this->getId();
536 }
537
541 public function getImagePath(): string
542 {
543 return CLIENT_WEB_DIR . "/survey/$this->obj_id/$this->id/images/";
544 }
545
549 public function getMaterialsPath(): string
550 {
551 return CLIENT_WEB_DIR . "/survey/$this->obj_id/$this->id/materials/";
552 }
553
557 public function getImagePathWeb(): string
558 {
559 $webdir = ilFileUtils::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/survey/$this->obj_id/$this->id/images/";
560 return str_replace(
563 $webdir
564 );
565 }
566
570 public function getMaterialsPathWeb(): string
571 {
572 $webdir = ilFileUtils::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/survey/$this->obj_id/$this->id/materials/";
573 return str_replace(
576 $webdir
577 );
578 }
579
583 public function saveCategoryToDb(
584 string $categorytext,
585 int $neutral = 0
586 ): int {
587 $ilUser = $this->user;
588 $ilDB = $this->db;
589
590 $result = $ilDB->queryF(
591 "SELECT title, category_id FROM svy_category WHERE title = %s AND neutral = %s AND owner_fi = %s",
592 array('text','text','integer'),
593 array($categorytext, $neutral, $ilUser->getId())
594 );
595 $insert = false;
596 $returnvalue = "";
597 $insert = true;
598 if ($result->numRows()) {
599 while ($row = $ilDB->fetchAssoc($result)) {
600 if (strcmp($row["title"], $categorytext) === 0) {
601 $returnvalue = $row["category_id"];
602 $insert = false;
603 }
604 }
605 }
606 if ($insert) {
607 $next_id = $ilDB->nextId('svy_category');
608 $affectedRows = $ilDB->manipulateF(
609 "INSERT INTO svy_category (category_id, title, neutral, owner_fi, tstamp) VALUES (%s, %s, %s, %s, %s)",
610 array('integer','text','text','integer','integer'),
611 array($next_id, $categorytext, $neutral, $ilUser->getId(), time())
612 );
613
614 $this->log->debug("INSERT INTO svy_category id=" . $next_id);
615
616 $returnvalue = $next_id;
617 }
618 return $returnvalue;
619 }
620
624 public function deleteAdditionalTableData(int $question_id): void
625 {
626 $ilDB = $this->db;
627
628 $this->log->debug("DELETE FROM " . $this->getAdditionalTableName());
629
630 $ilDB->manipulateF(
631 "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
632 array('integer'),
633 array($question_id)
634 );
635 }
636
640 public function delete(int $question_id): void
641 {
642 $ilDB = $this->db;
643 $this->log->debug("Question Delete... " . $question_id);
644 if ($question_id < 1) {
645 return;
646 }
647
648 $result = $ilDB->queryF(
649 "SELECT obj_fi FROM svy_question WHERE question_id = %s",
650 array('integer'),
651 array($question_id)
652 );
653 if ($result->numRows() === 1) {
654 $row = $ilDB->fetchAssoc($result);
655 $obj_id = $row["obj_fi"];
656 } else {
657 return;
658 }
659
660 $affectedRows = $ilDB->manipulateF(
661 "DELETE FROM svy_answer WHERE question_fi = %s",
662 array('integer'),
663 array($question_id)
664 );
665
666 $affectedRows = $ilDB->manipulateF(
667 "DELETE FROM svy_constraint WHERE question_fi = %s",
668 array('integer'),
669 array($question_id)
670 );
671
672 $result = $ilDB->queryF(
673 "SELECT constraint_fi FROM svy_qst_constraint WHERE question_fi = %s",
674 array('integer'),
675 array($question_id)
676 );
677 while ($row = $ilDB->fetchObject($result)) {
678 $affectedRows = $ilDB->manipulateF(
679 "DELETE FROM svy_constraint WHERE constraint_id = %s",
680 array('integer'),
681 array($row->constraint_fi)
682 );
683 }
684
685 $affectedRows = $ilDB->manipulateF(
686 "DELETE FROM svy_qst_constraint WHERE question_fi = %s",
687 array('integer'),
688 array($question_id)
689 );
690 $affectedRows = $ilDB->manipulateF(
691 "DELETE FROM svy_qblk_qst WHERE question_fi = %s",
692 array('integer'),
693 array($question_id)
694 );
695 $affectedRows = $ilDB->manipulateF(
696 "DELETE FROM svy_svy_qst WHERE question_fi = %s",
697 array('integer'),
698 array($question_id)
699 );
700 $affectedRows = $ilDB->manipulateF(
701 "DELETE FROM svy_variable WHERE question_fi = %s",
702 array('integer'),
703 array($question_id)
704 );
705 $affectedRows = $ilDB->manipulateF(
706 "DELETE FROM svy_question WHERE question_id = %s",
707 array('integer'),
708 array($question_id)
709 );
710
711 $this->deleteAdditionalTableData($question_id);
712
713 $affectedRows = $ilDB->manipulateF(
714 "DELETE FROM svy_material WHERE question_fi = %s",
715 array('integer'),
716 array($question_id)
717 );
718
719 $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);
720
721 ilInternalLink::_deleteAllLinksOfSource("sqst", $question_id);
722
723 $directory = CLIENT_WEB_DIR . "/survey/" . $obj_id . "/$question_id";
724 if (preg_match("/\d+/", $obj_id) and preg_match("/\d+/", $question_id) and is_dir($directory)) {
725 ilFileUtils::delDir($directory);
726 }
727
728 $mobs = ilObjMediaObject::_getMobsOfObject("spl:html", $question_id);
729 // remaining usages are not in text anymore -> delete them
730 // and media objects (note: delete method of ilObjMediaObject
731 // checks whether object is used in another context; if yes,
732 // the object is not deleted!)
733 foreach ($mobs as $mob) {
734 ilObjMediaObject::_removeUsage($mob, "spl:html", $question_id);
735 $mob_obj = new ilObjMediaObject($mob);
736 $mob_obj->delete();
737 }
738 $this->log->debug("Call ilSurveySkill::handleQuestionDeletion, q id: " . $question_id .
739 ", obj id: " . $obj_id);
740 ilSurveySkill::handleQuestionDeletion($question_id, $obj_id);
741
742 $this->log->debug("UPDATE svy_question");
743
744 // #12772 - untie question copies from pool question
745 $ilDB->manipulate("UPDATE svy_question" .
746 " SET original_id = NULL" .
747 " WHERE original_id = " . $ilDB->quote($question_id, "integer"));
748 }
749
753 public static function _getQuestionType(int $question_id): string
754 {
755 global $DIC;
756
757 $ilDB = $DIC->database();
758
759 if ($question_id < 1) {
760 return "";
761 }
762
763 $result = $ilDB->queryF(
764 "SELECT type_tag FROM svy_question, svy_qtype WHERE svy_question.question_id = %s AND svy_question.questiontype_fi = svy_qtype.questiontype_id",
765 array('integer'),
766 array($question_id)
767 );
768 if ($result->numRows() === 1) {
769 $data = $ilDB->fetchAssoc($result);
770 return $data["type_tag"];
771 } else {
772 return "";
773 }
774 }
775
779 public static function _getTitle(int $question_id): string
780 {
781 global $DIC;
782
783 $ilDB = $DIC->database();
784
785 $result = $ilDB->queryF(
786 "SELECT title FROM svy_question WHERE svy_question.question_id = %s",
787 array('integer'),
788 array($question_id)
789 );
790
791 if ($data = $ilDB->fetchAssoc($result)) {
792 return (string) $data["title"];
793 }
794 return "";
795 }
796
800 public static function _getOriginalId(
801 int $question_id,
802 bool $a_return_question_id_if_no_original = true
803 ): int {
804 global $DIC;
805
806 $ilDB = $DIC->database();
807 $result = $ilDB->queryF(
808 "SELECT * FROM svy_question WHERE question_id = %s",
809 array('integer'),
810 array($question_id)
811 );
812 if ($result->numRows() > 0) {
813 $row = $ilDB->fetchAssoc($result);
814 if ($row["original_id"] > 0) {
815 return (int) $row["original_id"];
816 } elseif ($a_return_question_id_if_no_original) { // #12419
817 return (int) $row["question_id"];
818 }
819 }
820 return 0;
821 }
822
823 public function syncWithOriginal(): void
824 {
825 $ilDB = $this->db;
826
827 if ($this->getOriginalId()) {
828 $id = $this->getId();
829 $original = $this->getOriginalId();
830
831 $this->setId($this->getOriginalId());
832 $this->setOriginalId(null);
833 $this->saveToDb();
834
835 $this->setId($id);
836 $this->setOriginalId($original);
837
838 $this->log->debug("DELETE FROM svy_material WHERE question_fi = " . $this->getOriginalId());
839
840 $affectedRows = $ilDB->manipulateF(
841 "DELETE FROM svy_material WHERE question_fi = %s",
842 array('integer'),
843 array($this->getOriginalId())
844 );
845 ilInternalLink::_deleteAllLinksOfSource("sqst", $this->original_id);
846 if (strlen($this->material["internal_link"] ?? "")) {
847 $next_id = $ilDB->nextId('svy_material');
848 $affectedRows = $ilDB->manipulateF(
849 "INSERT INTO svy_material (material_id, question_fi, internal_link, import_id, material_title, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
850 array('integer', 'integer', 'text', 'text', 'text', 'integer'),
851 array($next_id, $this->getOriginalId(), $this->material["internal_link"], $this->material["import_id"], $this->material["title"], time())
852 );
853
854 $this->log->debug("INSERT svy_material material_id=" . $next_id . " question_fi=" . $this->getOriginalId());
855
856 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $this->material["internal_link"], $matches)) {
857 ilInternalLink::_saveLink("sqst", $this->getOriginalId(), $matches[2], $matches[3], $matches[1]);
858 }
859 }
860 }
861 }
862
863 public static function _questionExists(int $question_id): bool
864 {
865 global $DIC;
866
867 $ilDB = $DIC->database();
868
869 if ($question_id < 1) {
870 return false;
871 }
872
873 $result = $ilDB->queryF(
874 "SELECT question_id FROM svy_question WHERE question_id = %s",
875 array('integer'),
876 array($question_id)
877 );
878 return $result->numRows() === 1;
879 }
880
881
882 public static function _resolveInternalLink(
883 string $internal_link
884 ): string {
885 $resolved_link = "";
886 if (preg_match("/il_(\d+)_(\w+)_(\d+)/", $internal_link, $matches)) {
887 switch ($matches[2]) {
888 case "lm":
889 $resolved_link = ilLMObject::_getIdForImportId($internal_link);
890 break;
891 case "pg":
892 $resolved_link = ilInternalLink::_getIdForImportId("PageObject", $internal_link);
893 break;
894 case "st":
895 $resolved_link = ilInternalLink::_getIdForImportId("StructureObject", $internal_link);
896 break;
897 case "git":
898 $resolved_link = ilInternalLink::_getIdForImportId("GlossaryItem", $internal_link);
899 break;
900 case "mob":
901 $resolved_link = ilInternalLink::_getIdForImportId("MediaObject", $internal_link);
902 break;
903 }
904 if (strcmp($resolved_link, "") === 0) {
905 $resolved_link = $internal_link;
906 }
907 } else {
908 $resolved_link = $internal_link;
909 }
910 return $resolved_link;
911 }
912
913 public static function _resolveIntLinks(
914 int $question_id
915 ): void {
916 global $DIC;
917
918 $ilDB = $DIC->database();
919 $resolvedlinks = 0;
920 $result = $ilDB->queryF(
921 "SELECT * FROM svy_material WHERE question_fi = %s",
922 array('integer'),
923 array($question_id)
924 );
925 if ($result->numRows()) {
926 while ($row = $ilDB->fetchAssoc($result)) {
927 $internal_link = $row["internal_link"];
928 $resolved_link = self::_resolveInternalLink($internal_link);
929 if (strcmp($internal_link, $resolved_link) !== 0) {
930 // internal link was resolved successfully
931 $affectedRows = $ilDB->manipulateF(
932 "UPDATE svy_material SET internal_link = %s, tstamp = %s WHERE material_id = %s",
933 array('text', 'integer', 'integer'),
934 array($resolved_link, time(), $row["material_id"])
935 );
936 $resolvedlinks++;
937 }
938 }
939 }
940 if ($resolvedlinks) {
941 // there are resolved links -> reenter theses links to the database
942
943 // delete all internal links from the database
944 ilInternalLink::_deleteAllLinksOfSource("sqst", $question_id);
945
946 $result = $ilDB->queryF(
947 "SELECT * FROM svy_material WHERE question_fi = %s",
948 array('integer'),
949 array($question_id)
950 );
951 if ($result->numRows()) {
952 while ($row = $ilDB->fetchAssoc($result)) {
953 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $row["internal_link"], $matches)) {
954 ilInternalLink::_saveLink("sqst", $question_id, $matches[2], $matches[3], $matches[1]);
955 }
956 }
957 }
958 }
959 }
960
961 public static function _getInternalLinkHref(
962 string $target = "",
963 ?int $a_parent_ref_id = null
964 ): string {
965 $linktypes = array(
966 "lm" => "LearningModule",
967 "pg" => "PageObject",
968 "st" => "StructureObject",
969 "git" => "GlossaryItem",
970 "mob" => "MediaObject"
971 );
972 $href = "";
973 if (preg_match("/il__(\w+)_(\d+)/", $target, $matches)) {
974 $type = $matches[1];
975 $target_id = $matches[2];
976 switch ($linktypes[$matches[1]]) {
977 case "StructureObject":
978 case "PageObject":
979 case "GlossaryItem":
980 case "LearningModule":
981 $href = ilFileUtils::removeTrailingPathSeparators(ILIAS_HTTP_PATH) . "/goto.php?target=" . $type . "_" . $target_id;
982 break;
983 case "MediaObject":
985 ILIAS_HTTP_PATH
986 ) . "/ilias.php?baseClass=ilLMPresentationGUI&obj_type=" . $linktypes[$type] . "&cmd=media&ref_id=" . $a_parent_ref_id . "&mob_id=" . $target_id;
987 break;
988 }
989 }
990 return $href;
991 }
992
996 public static function _isWriteable(
997 int $question_id,
998 int $user_id
999 ): bool {
1000 global $DIC;
1001
1002 $ilDB = $DIC->database();
1003
1004 if (($question_id < 1) || ($user_id < 1)) {
1005 return false;
1006 }
1007
1008 $result = $ilDB->queryF(
1009 "SELECT obj_fi FROM svy_question WHERE question_id = %s",
1010 array('integer'),
1011 array($question_id)
1012 );
1013 if ($result->numRows() === 1) {
1014 $row = $ilDB->fetchAssoc($result);
1015 $qpl_object_id = $row["obj_fi"];
1016 return ilObjSurveyQuestionPool::_isWriteable($qpl_object_id);
1017 }
1018
1019 return false;
1020 }
1021
1022 public function getQuestionTypeID(): int
1023 {
1024 $ilDB = $this->db;
1025 $result = $ilDB->queryF(
1026 "SELECT questiontype_id FROM svy_qtype WHERE type_tag = %s",
1027 array('text'),
1028 array($this->getQuestionType())
1029 );
1030 if ($result->numRows() === 1) {
1031 $row = $ilDB->fetchAssoc($result);
1032 return (int) $row["questiontype_id"];
1033 }
1034
1035 return 0;
1036 }
1037
1038 public function getQuestionType(): string
1039 {
1040 return "";
1041 }
1042
1047 public static function _includeClass(
1048 string $question_type,
1049 int $gui = 0
1050 ): bool {
1051 $type = $question_type;
1052 if ($gui === 1) {
1053 $type .= "GUI";
1054 } elseif ($gui === 2) {
1055 $type .= "Evaluation";
1056 }
1057 if (file_exists("./components/ILIAS/SurveyQuestionPool/Questions/class." . $type . ".php")) {
1058 return true;
1059 }
1060 return false;
1061 }
1062
1067 public static function _getQuestionTypeName(
1068 string $type_tag
1069 ): string {
1070 global $DIC;
1071 $lng = $DIC->language();
1072 return $lng->txt($type_tag);
1073 }
1074
1075
1079 public static function _instanciateQuestion(int $question_id): ?SurveyQuestion
1080 {
1081 $question_type = self::_getQuestionType($question_id);
1082 if ($question_type) {
1083 self::_includeClass($question_type);
1084 $question = new $question_type();
1085 $question->loadFromDb($question_id);
1086 return $question;
1087 }
1088 return null;
1089 }
1090
1094 public static function _instanciateQuestionGUI(
1095 int $question_id
1096 ): ?SurveyQuestionGUI {
1097 $question_type = self::_getQuestionType($question_id);
1098 if ($question_type) {
1099 self::_includeClass($question_type, 1);
1100 $guitype = $question_type . "GUI";
1101 $question = new $guitype($question_id);
1102 return $question;
1103 }
1104 return null;
1105 }
1106
1107 public static function _instanciateQuestionEvaluation(
1108 int $question_id,
1109 ?array $a_finished_ids = null
1111 $question = self::_instanciateQuestion($question_id);
1112 if (is_null($a_finished_ids)) {
1113 $a_finished_ids = [];
1114 }
1115 if ($question) {
1116 $question_type = self::_getQuestionType($question_id);
1117 self::_includeClass($question_type, 2);
1118 $class = $question_type . "Evaluation";
1119 $ev = new $class($question, $a_finished_ids);
1120 return $ev;
1121 }
1122 return null;
1123 }
1124
1128 public function isHTML(string $a_text): bool
1129 {
1130 if (preg_match("/<[^>]*?>/", $a_text)) {
1131 return true;
1132 }
1133
1134 return false;
1135 }
1136
1140 public function QTIMaterialToString(ilQTIMaterial $a_material): string
1141 {
1142 $svy_log = ilLoggerFactory::getLogger("svy");
1143 $svy_log->debug("material count: " . $a_material->getMaterialCount());
1144
1145 $result = "";
1146 for ($i = 0; $i < $a_material->getMaterialCount(); $i++) {
1147 $material = $a_material->getMaterial($i);
1148 if (strcmp($material["type"], "mattext") === 0) {
1149 $result .= $material["material"]->getContent();
1150 }
1151 if (strcmp($material["type"], "matimage") === 0) {
1152 $matimage = $material["material"];
1153 if (preg_match("/(il_([0-9]+)_mob_([0-9]+))/", $matimage->getLabel(), $matches)) {
1154 // import an mediaobject which was inserted using tiny mce
1155 $this->import_manager->addMob(
1156 $matimage->getLabel(),
1157 $matimage->getUri()
1158 );
1159 }
1160 }
1161 }
1162 return $result;
1163 }
1164
1168 public function addMaterialTag(
1169 ilXmlWriter $a_xml_writer,
1170 string $a_material,
1171 bool $close_material_tag = true,
1172 bool $add_mobs = true,
1173 ?array $a_attrs = null
1174 ): void {
1175 $a_xml_writer->xmlStartTag("material");
1176 $attrs = array(
1177 "type" => "text/plain"
1178 );
1179 if ($this->isHTML($a_material)) {
1180 $attrs["type"] = "text/xhtml";
1181 }
1182 if (is_array($a_attrs)) {
1183 $attrs = array_merge($attrs, $a_attrs);
1184 }
1185 $a_xml_writer->xmlElement("mattext", $attrs, ilRTE::_replaceMediaObjectImageSrc($a_material, 0));
1186
1187 if ($add_mobs) {
1188 $mobs = ilObjMediaObject::_getMobsOfObject("spl:html", $this->getId());
1189 foreach ($mobs as $mob) {
1190 $mob_obj = new ilObjMediaObject($mob);
1191 $imgattrs = array(
1192 "label" => "il_" . IL_INST_ID . "_mob_" . $mob,
1193 "uri" => "objects/" . "il_" . IL_INST_ID . "_mob_" . $mob . "/" . $mob_obj->getTitle(),
1194 "type" => "spl:html",
1195 "id" => $this->getId()
1196 );
1197 $a_xml_writer->xmlElement("matimage", $imgattrs, null);
1198 }
1199 }
1200 if ($close_material_tag) {
1201 $a_xml_writer->xmlEndTag("material");
1202 }
1203 }
1204
1208 public function prepareTextareaOutput(
1209 string $txt_output,
1210 bool $prepare_for_latex_output = false
1211 ): string {
1212 return ilLegacyFormElementsUtil::prepareTextareaOutput($txt_output, $prepare_for_latex_output);
1213 }
1214
1218 public function getQuestionDataArray(int $id): array
1219 {
1220 return array();
1221 }
1222
1227 public function getWorkingDataFromUserInput(array $post_data): array
1228 {
1229 // overwrite in inherited classes
1230 $data = array();
1231 return $data;
1232 }
1233
1239 public function importAdditionalMetadata(array $a_meta): void
1240 {
1241 // overwrite in inherited classes
1242 }
1243
1247 public function importResponses(array $a_data): void
1248 {
1249 // overwrite in inherited classes
1250 }
1251
1255 public function importAdjectives(array $a_data): void
1256 {
1257 // overwrite in inherited classes
1258 }
1259
1263 public function importMatrix(array $a_data): void
1264 {
1265 // overwrite in inherited classes
1266 }
1267
1271 public function usableForPrecondition(): bool
1272 {
1273 // overwrite in inherited classes
1274 return false;
1275 }
1276
1280 public function getAvailableRelations(): array
1281 {
1282 // overwrite in inherited classes
1283 return array();
1284 }
1285
1289 public function getPreconditionOptions(): array
1290 {
1291 // overwrite in inherited classes
1292 return [];
1293 }
1294
1300 public function getPreconditionValueOutput(string $value): string
1301 {
1302 // overwrite in inherited classes
1303 return $value;
1304 }
1305
1310 string $default,
1311 string $title,
1312 string $variable
1313 ): ?ilFormPropertyGUI {
1314 // overwrite in inherited classes
1315 return null;
1316 }
1317
1318 public function setOriginalId(?int $original_id): void
1319 {
1320 $this->original_id = $original_id;
1321 }
1322
1323 public function getOriginalId(): ?int
1324 {
1325 return $this->original_id;
1326 }
1327
1328 public function getMaterial(): array
1329 {
1330 return $this->material;
1331 }
1332
1333 public function setSubtype(int $a_subtype): void
1334 {
1335 // do nothing
1336 }
1337
1338 public function getSubtype(): ?int
1339 {
1340 // do nothing
1341 return null;
1342 }
1343
1344 public function __get(string $value): ?string
1345 {
1346 switch ($value) {
1347 default:
1348 if (array_key_exists($value, $this->arrData)) {
1349 return (string) $this->arrData[$value];
1350 }
1351
1352 return null;
1353 }
1354 }
1355
1356 public function __set(string $key, string $value): void
1357 {
1358 switch ($key) {
1359 default:
1360 $this->arrData[$key] = $value;
1361 break;
1362 }
1363 }
1364
1368 public static function _changeOriginalId(
1369 int $a_question_id,
1370 int $a_original_id,
1371 int $a_object_id
1372 ): void {
1373 global $DIC;
1374
1375 $ilDB = $DIC->database();
1376
1377 $ilDB->manipulate("UPDATE svy_question" .
1378 " SET original_id = " . $ilDB->quote($a_original_id, "integer") . "," .
1379 " obj_fi = " . $ilDB->quote($a_object_id, "integer") .
1380 " WHERE question_id = " . $ilDB->quote($a_question_id, "integer"));
1381 }
1382
1383 public function getCopyIds(
1384 bool $a_group_by_survey = false
1385 ): array {
1386 $ilDB = $this->db;
1387
1388 $set = $ilDB->query("SELECT q.question_id,s.obj_fi" .
1389 " FROM svy_question q" .
1390 " JOIN svy_svy_qst sq ON (sq.question_fi = q.question_id)" .
1391 " JOIN svy_svy s ON (s.survey_id = sq.survey_fi)" .
1392 " WHERE original_id = " . $ilDB->quote($this->getId(), "integer"));
1393 $res = array();
1394 while ($row = $ilDB->fetchAssoc($set)) {
1395 if (!$a_group_by_survey) {
1396 $res[] = (int) $row["question_id"];
1397 } else {
1398 $res[$row["obj_fi"]][] = (int) $row["question_id"];
1399 }
1400 }
1401 return $res;
1402 }
1403
1404 public function hasCopies(): bool
1405 {
1406 return (bool) count($this->getCopyIds());
1407 }
1408
1409 public static function _lookupSurveyObjId(
1410 int $a_question_id
1411 ): ?int {
1412 global $DIC;
1413
1414 $ilDB = $DIC->database();
1415
1416 $set = $ilDB->query("SELECT svy_svy.obj_fi FROM svy_svy_qst" .
1417 " JOIN svy_svy ON (svy_svy.survey_id = svy_svy_qst.survey_fi)" .
1418 " WHERE svy_svy_qst.question_fi = " . $ilDB->quote($a_question_id, "integer"));
1419 $row = $ilDB->fetchAssoc($set);
1420 if ($ilDB->numRows($set)) {
1421 return (int) $row["obj_fi"];
1422 }
1423 return null;
1424 }
1425
1426 public static function lookupObjFi(
1427 int $a_qid
1428 ): ?int {
1429 global $DIC;
1430
1431 $ilDB = $DIC->database();
1432
1433 $set = $ilDB->query(
1434 "SELECT obj_fi FROM svy_question " .
1435 " WHERE question_id = " . $ilDB->quote($a_qid, "integer")
1436 );
1437 if ($rec = $ilDB->fetchAssoc($set)) {
1438 return (int) $rec["obj_fi"];
1439 }
1440 return null;
1441 }
1442
1447 public function stripSlashesAddSpaceFallback(string $a_str): string
1448 {
1449 $str = ilUtil::stripSlashes($a_str);
1450 if ($str !== $a_str) {
1451 $str = ilUtil::stripSlashes(str_replace("<", "< ", $a_str));
1452 }
1453 return $str;
1454 }
1455
1459 public static function getMaxSumScore(int $survey_id): int
1460 {
1461 return 0;
1462 }
1463}
$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 _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 _getMobsOfObject(string $a_type, int $a_id, int|false $a_usage_hist_nr=0, string $a_lang="-")
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