ILIAS  release_7 Revision v7.30-3-g800a261c036
class.SurveyMatrixQuestion.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (c) 1998-2019 ILIAS open source, Extended GPL, see docs/LICENSE */
4
12{
16 protected $user;
17
21 protected $db;
22
28 public $columns;
29
35 public $rows;
36
43
50
58
66
74
75 /*
76 * Layout of the matrix question
77 *
78 * @var array
79 */
80 public $layout;
81
82 /*
83 * Use placeholders for the column titles
84 *
85 * @var boolean
86 */
88
89 /*
90 * Show a legend
91 *
92 * @var boolean
93 */
94 public $legend;
95
97
99
101
102 /*
103 * Use random order for rows
104 *
105 * @var boolean
106 */
108
110
112
114
115 public $openRows;
116
117
132 public $subtype;
133
144 public function __construct($title = "", $description = "", $author = "", $questiontext = "", $owner = -1)
145 {
146 global $DIC;
147
148 $this->user = $DIC->user();
149 $this->db = $DIC->database();
151
152 $this->subtype = 0;
153 $this->columns = new SurveyCategories();
154 $this->rows = new SurveyCategories();
155 $this->bipolar_adjective1 = "";
156 $this->bipolar_adjective2 = "";
157 $this->rowSeparators = 0;
158 $this->columnSeparators = 0;
159 $this->neutralColumnSeparator = 1;
160 }
161
169 public function getColumnCount()
170 {
171 return $this->columns->getCategoryCount();
172 }
173
181 public function removeColumn($index)
182 {
183 $this->columns->removeCategory($index);
184 }
185
193 public function removeColumns($array)
194 {
195 $this->columns->removeCategories($array);
196 }
197
206 {
207 $this->columns->removeCategoryWithName($name);
208 }
209
213 public function getColumns()
214 {
215 return $this->columns;
216 }
217
226 public function getColumn($index)
227 {
228 return $this->columns->getCategory($index);
229 }
230
231 public function getColumnForScale($scale)
232 {
233 return $this->columns->getCategoryForScale($scale);
234 }
235
243 public function getColumnIndex($name)
244 {
245 return $this->columns->getCategoryIndex($name);
246 }
247
248
255 public function flushColumns()
256 {
257 $this->columns->flushCategories();
258 }
259
266 public function getRowCount()
267 {
268 return $this->rows->getCategoryCount();
269 }
270
276 public function addRow($a_text, $a_other, $a_label)
277 {
278 $this->rows->addCategory($a_text, $a_other, 0, $a_label);
279 }
280
287 public function addRowAtPosition($a_text, $a_other, $a_position)
288 {
289 $this->rows->addCategoryAtPosition($a_text, $a_position, $a_other);
290 }
291
298 public function flushRows()
299 {
300 $this->rows = new SurveyCategories();
301 }
302
309 public function getRow($a_index)
310 {
311 return $this->rows->getCategory($a_index);
312 }
313
314 public function moveRowUp($index)
315 {
316 $this->rows->moveCategoryUp($index);
317 }
318
319 public function moveRowDown($index)
320 {
321 $this->rows->moveCategoryDown($index);
322 }
323
331 public function removeRows($array)
332 {
333 $this->rows->removeCategories($array);
334 }
335
341 public function removeRow($index)
342 {
343 $this->rows->removeCategory($index);
344 }
345
353 public function getBipolarAdjective($a_index)
354 {
355 switch ($a_index) {
356 case 1:
357 return (strlen($this->bipolar_adjective2)) ? $this->bipolar_adjective2 : null;
358 break;
359 case 0:
360 default:
361 return (strlen($this->bipolar_adjective1)) ? $this->bipolar_adjective1 : null;
362 break;
363 }
364 return null;
365 }
366
374 public function setBipolarAdjective($a_index, $a_value)
375 {
376 switch ($a_index) {
377 case 1:
378 $this->bipolar_adjective2 = $a_value;
379 break;
380 case 0:
381 default:
382 $this->bipolar_adjective1 = $a_value;
383 break;
384 }
385 }
386
393 public function addPhrase($phrase_id)
394 {
397
398 $result = $ilDB->queryF(
399 "SELECT svy_category.* FROM svy_category, svy_phrase_cat WHERE svy_phrase_cat.category_fi = svy_category.category_id AND svy_phrase_cat.phrase_fi = %s AND (svy_category.owner_fi = %s OR svy_category.owner_fi = %s) ORDER BY svy_phrase_cat.sequence",
400 array('integer', 'integer', 'integer'),
401 array($phrase_id, 0, $ilUser->getId())
402 );
403 while ($row = $ilDB->fetchAssoc($result)) {
404 $neutral = $row["neutral"];
405 if (($row["defaultvalue"] == 1) && ($row["owner_fi"] == 0)) {
406 $this->columns->addCategory($this->lng->txt($row["title"]), 0, $neutral);
407 } else {
408 $this->columns->addCategory($row["title"], 0, $neutral);
409 }
410 }
411 }
412
420 public function getQuestionDataArray($id)
421 {
423
424 $result = $ilDB->queryF(
425 "SELECT svy_question.*, " . $this->getAdditionalTableName() . ".* FROM svy_question, " . $this->getAdditionalTableName() . " WHERE svy_question.question_id = %s AND svy_question.question_id = " . $this->getAdditionalTableName() . ".question_fi",
426 array('integer'),
427 array($id)
428 );
429 if ($result->numRows() == 1) {
430 return $ilDB->fetchAssoc($result);
431 } else {
432 return array();
433 }
434 }
435
442 public function loadFromDb($id)
443 {
445 $result = $ilDB->queryF(
446 "SELECT svy_question.*, " . $this->getAdditionalTableName() . ".* FROM svy_question LEFT JOIN " . $this->getAdditionalTableName() . " ON " . $this->getAdditionalTableName() . ".question_fi = svy_question.question_id WHERE svy_question.question_id = %s",
447 array('integer'),
448 array($id)
449 );
450 if ($result->numRows() == 1) {
451 $data = $ilDB->fetchAssoc($result);
452 $this->setId($data["question_id"]);
453 $this->setTitle($data["title"]);
454 $this->label = $data['label'];
455 $this->setDescription($data["description"]);
456 $this->setObjId($data["obj_fi"]);
457 $this->setAuthor($data["author"]);
458 $this->setOwner($data["owner_fi"]);
459 $this->setQuestiontext(ilRTE::_replaceMediaObjectImageSrc($data["questiontext"], 1));
460 $this->setObligatory($data["obligatory"]);
461 $this->setComplete($data["complete"]);
462 $this->setOriginalId($data["original_id"]);
463 $this->setSubtype($data["subtype"]);
464 $this->setRowSeparators($data["row_separators"]);
465 $this->setNeutralColumnSeparator($data["neutral_column_separator"]);
466 $this->setColumnSeparators($data["column_separators"]);
467 $this->setColumnPlaceholders($data["column_placeholders"]);
468 $this->setLegend($data["legend"]);
469 $this->setSingleLineRowCaption($data["singleline_row_caption"]);
470 $this->setRepeatColumnHeader($data["repeat_column_header"]);
471 $this->setColumnHeaderPosition($data["column_header_position"]);
472 $this->setRandomRows($data["random_rows"]);
473 $this->setColumnOrder($data["column_order"]);
474 $this->setColumnImages($data["column_images"]);
475 $this->setRowImages($data["row_images"]);
476 $this->setBipolarAdjective(0, $data["bipolar_adjective1"]);
477 $this->setBipolarAdjective(1, $data["bipolar_adjective2"]);
478 $this->setLayout($data["layout"]);
479 $this->flushColumns();
480
481 $result = $ilDB->queryF(
482 "SELECT svy_variable.*, svy_category.title, svy_category.neutral FROM svy_variable, svy_category WHERE svy_variable.question_fi = %s AND svy_variable.category_fi = svy_category.category_id ORDER BY sequence ASC",
483 array('integer'),
484 array($id)
485 );
486 if ($result->numRows() > 0) {
487 while ($data = $ilDB->fetchAssoc($result)) {
488 $this->columns->addCategory($data["title"], $data["other"], $data["neutral"], null, ($data['scale']) ? $data['scale'] : ($data['sequence'] + 1));
489 }
490 }
491
492 $result = $ilDB->queryF(
493 "SELECT * FROM svy_qst_matrixrows WHERE question_fi = %s ORDER BY sequence",
494 array('integer'),
495 array($id)
496 );
497 while ($row = $ilDB->fetchAssoc($result)) {
498 $this->addRow($row["title"], $row['other'], $row['label']);
499 }
500 }
501 parent::loadFromDb($id);
502 }
503
510 public function isComplete()
511 {
512 if (
513 strlen($this->getTitle()) &&
514 strlen($this->getAuthor()) &&
515 strlen($this->getQuestiontext()) &&
516 $this->getColumnCount() &&
517 $this->getRowCount()
518 ) {
519 return 1;
520 } else {
521 return 0;
522 }
523 }
524
530 public function saveToDb($original_id = null, $withanswers = true)
531 {
533
534 $affectedRows = parent::saveToDb($original_id);
535
536 if ($affectedRows == 1) {
537 $affectedRows = $ilDB->manipulateF(
538 "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
539 array('integer'),
540 array($this->getId())
541 );
542 $affectedRows = $ilDB->manipulateF(
543 "INSERT INTO " . $this->getAdditionalTableName() . " (
544 question_fi, subtype, column_separators, row_separators, neutral_column_separator,column_placeholders,
545 legend, singleline_row_caption, repeat_column_header, column_header_position, random_rows,
546 column_order, column_images, row_images, bipolar_adjective1, bipolar_adjective2, layout, tstamp)
547 VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
548 array(
549 'integer', 'integer', 'text', 'text', 'text', 'integer', 'text', 'text', 'text',
550 'text', 'text', 'text', 'text', 'text', 'text', 'text', 'text', 'integer'
551 ),
552 array(
553 $this->getId(),
554 $this->getSubtype(),
555 $this->getColumnSeparators(),
556 $this->getRowSeparators(),
558 $this->getColumnPlaceholders(),
559 $this->getLegend(),
561 $this->getRepeatColumnHeader(),
563 $this->getRandomRows(),
564 $this->getColumnOrder(),
565 $this->getColumnImages(),
566 $this->getRowImages(),
567 $this->getBipolarAdjective(0),
568 $this->getBipolarAdjective(1),
569 serialize($this->getLayout()),
570 time()
571 )
572 );
573
574 // saving material uris in the database
575 $this->saveMaterial();
576
577 $this->saveColumnsToDb();
578 $this->saveRowsToDb();
579 }
580 }
581
582 public function saveBipolarAdjectives($adjective1, $adjective2)
583 {
585
586 $affectedRows = $ilDB->manipulateF(
587 "UPDATE " . $this->getAdditionalTableName() . " SET bipolar_adjective1 = %s, bipolar_adjective2 = %s WHERE question_fi = %s",
588 array('text', 'text', 'integer'),
589 array((strlen($adjective1)) ? $adjective1 : null, (strlen($adjective2)) ? $adjective2 : null, $this->getId())
590 );
591 }
592
601 public function saveColumnToDb($columntext, $neutral = 0)
602 {
605
606 $result = $ilDB->queryF(
607 "SELECT title, category_id FROM svy_category WHERE title = %s AND neutral = %s AND owner_fi = %s",
608 array('text', 'text', 'integer'),
609 array($columntext, $neutral, $ilUser->getId())
610 );
611 $insert = false;
612 $returnvalue = "";
613 if ($result->numRows()) {
614 $insert = true;
615 while ($row = $ilDB->fetchAssoc($result)) {
616 if (strcmp($row["title"], $columntext) == 0) {
617 $returnvalue = $row["category_id"];
618 $insert = false;
619 }
620 }
621 } else {
622 $insert = true;
623 }
624 if ($insert) {
625 $next_id = $ilDB->nextId('svy_category');
626 $affectedRows = $ilDB->manipulateF(
627 "INSERT INTO svy_category (category_id, title, defaultvalue, owner_fi, neutral, tstamp) VALUES (%s, %s, %s, %s, %s, %s)",
628 array('integer', 'text', 'text', 'integer', 'text', 'integer'),
629 array($next_id, $columntext, 0, $ilUser->getId(), $neutral, time())
630 );
631 $returnvalue = $next_id;
632 }
633 return $returnvalue;
634 }
635
636 public function saveColumnsToDb($original_id = "")
637 {
639
640 // save columns
641 $question_id = $this->getId();
642 if (strlen($original_id)) {
643 $question_id = $original_id;
644 }
645
646 // delete existing column relations
647 $affectedRows = $ilDB->manipulateF(
648 "DELETE FROM svy_variable WHERE question_fi = %s",
649 array('integer'),
650 array($question_id)
651 );
652 // create new column relations
653 for ($i = 0; $i < $this->getColumnCount(); $i++) {
654 $cat = $this->getColumn($i);
655 $column_id = $this->saveColumnToDb($cat->title, $cat->neutral);
656 $next_id = $ilDB->nextId('svy_variable');
657 $affectedRows = $ilDB->manipulateF(
658 "INSERT INTO svy_variable (variable_id, category_fi, question_fi, value1, other, sequence, scale, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)",
659 array('integer','integer','integer','float','integer','integer', 'integer','integer'),
660 array($next_id, $column_id, $question_id, ($i + 1), $cat->other, $i, ($cat->scale > 0) ? $cat->scale : null, time())
661 );
662 }
663 $this->saveCompletionStatus($original_id);
664 }
665
666 public function saveRowsToDb($original_id = "")
667 {
669
670 // save rows
671 $question_id = $this->getId();
672 if (strlen($original_id)) {
673 $question_id = $original_id;
674 }
675
676 // delete existing rows
677 $affectedRows = $ilDB->manipulateF(
678 "DELETE FROM svy_qst_matrixrows WHERE question_fi = %s",
679 array('integer'),
680 array($question_id)
681 );
682 // create new rows
683 for ($i = 0; $i < $this->getRowCount(); $i++) {
684 $row = $this->getRow($i);
685 $next_id = $ilDB->nextId('svy_qst_matrixrows');
686 $affectedRows = $ilDB->manipulateF(
687 "INSERT INTO svy_qst_matrixrows (id_svy_qst_matrixrows, title, label, other, sequence, question_fi) VALUES (%s, %s, %s, %s, %s, %s)",
688 array('integer','text','text','integer','integer','integer'),
689 array($next_id, $row->title, $row->label, ($row->other) ? 1 : 0, $i, $question_id)
690 );
691 }
692 $this->saveCompletionStatus($original_id);
693 }
694
701 public function toXML($a_include_header = true, $obligatory_state = "")
702 {
703 $a_xml_writer = new ilXmlWriter;
704 $a_xml_writer->xmlHeader();
705 $this->insertXML($a_xml_writer, $a_include_header, $obligatory_state);
706 $xml = $a_xml_writer->xmlDumpMem(false);
707 if (!$a_include_header) {
708 $pos = strpos($xml, "?>");
709 $xml = substr($xml, $pos + 2);
710 }
711 return $xml;
712 }
713
721 public function insertXML(&$a_xml_writer, $a_include_header = true)
722 {
723 $attrs = array(
724 "id" => $this->getId(),
725 "title" => $this->getTitle(),
726 "type" => $this->getQuestiontype(),
727 "subtype" => $this->getSubtype(),
728 "obligatory" => $this->getObligatory()
729 );
730 $a_xml_writer->xmlStartTag("question", $attrs);
731
732 $a_xml_writer->xmlElement("description", null, $this->getDescription());
733 $a_xml_writer->xmlElement("author", null, $this->getAuthor());
734 $a_xml_writer->xmlStartTag("questiontext");
735 $this->addMaterialTag($a_xml_writer, $this->getQuestiontext());
736 $a_xml_writer->xmlEndTag("questiontext");
737
738 $a_xml_writer->xmlStartTag("matrix");
739 $a_xml_writer->xmlStartTag("matrixrows");
740 for ($i = 0; $i < $this->getRowCount(); $i++) {
741 $attrs = array(
742 "id" => $i
743 );
744 if (strlen($this->getRow($i)->label)) {
745 $attrs['label'] = $this->getRow($i)->label;
746 }
747 if ($this->getRow($i)->other) {
748 $attrs['other'] = 1;
749 }
750 $a_xml_writer->xmlStartTag("matrixrow", $attrs);
751 $this->addMaterialTag($a_xml_writer, $this->getRow($i)->title);
752 $a_xml_writer->xmlEndTag("matrixrow");
753 }
754 $a_xml_writer->xmlEndTag("matrixrows");
755
756 $a_xml_writer->xmlStartTag("responses");
757 if (strlen($this->getBipolarAdjective(0)) && (strlen($this->getBipolarAdjective(1)))) {
758 $a_xml_writer->xmlStartTag("bipolar_adjectives");
759 $attribs = array(
760 "label" => "0"
761 );
762 $a_xml_writer->xmlElement("adjective", $attribs, $this->getBipolarAdjective(0));
763 $attribs = array(
764 "label" => "1"
765 );
766 $a_xml_writer->xmlElement("adjective", $attribs, $this->getBipolarAdjective(1));
767 $a_xml_writer->xmlEndTag("bipolar_adjectives");
768 }
769 for ($i = 0; $i < $this->getColumnCount(); $i++) {
770 $attrs = array(
771 "id" => $i
772 );
773 if ($this->getColumn($i)->neutral) {
774 $attrs['label'] = 'neutral';
775 }
776 switch ($this->getSubtype()) {
777 case 0:
778 $a_xml_writer->xmlStartTag("response_single", $attrs);
779 break;
780 case 1:
781 $a_xml_writer->xmlStartTag("response_multiple", $attrs);
782 break;
783 }
784 $this->addMaterialTag($a_xml_writer, $this->getColumn($i)->title);
785 switch ($this->getSubtype()) {
786 case 0:
787 $a_xml_writer->xmlEndTag("response_single");
788 break;
789 case 1:
790 $a_xml_writer->xmlEndTag("response_multiple");
791 break;
792 }
793 }
794
795 $a_xml_writer->xmlEndTag("responses");
796 $a_xml_writer->xmlEndTag("matrix");
797
798 if (count($this->material)) {
799 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $this->material["internal_link"], $matches)) {
800 $attrs = array(
801 "label" => $this->material["title"]
802 );
803 $a_xml_writer->xmlStartTag("material", $attrs);
804 $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
805 if (strcmp($matches[1], "") != 0) {
806 $intlink = $this->material["internal_link"];
807 }
808 $a_xml_writer->xmlElement("mattext", null, $intlink);
809 $a_xml_writer->xmlEndTag("material");
810 }
811 }
812
813 $a_xml_writer->xmlStartTag("metadata");
814 $a_xml_writer->xmlStartTag("metadatafield");
815 $a_xml_writer->xmlElement("fieldlabel", null, "column_separators");
816 $a_xml_writer->xmlElement("fieldentry", null, $this->getColumnSeparators());
817 $a_xml_writer->xmlEndTag("metadatafield");
818
819 $a_xml_writer->xmlStartTag("metadatafield");
820 $a_xml_writer->xmlElement("fieldlabel", null, "row_separators");
821 $a_xml_writer->xmlElement("fieldentry", null, $this->getRowSeparators());
822 $a_xml_writer->xmlEndTag("metadatafield");
823
824 $a_xml_writer->xmlStartTag("metadatafield");
825 $a_xml_writer->xmlElement("fieldlabel", null, "neutral_column_separator");
826 $a_xml_writer->xmlElement("fieldentry", null, $this->getNeutralColumnSeparator());
827 $a_xml_writer->xmlEndTag("metadatafield");
828
829 $a_xml_writer->xmlStartTag("metadatafield");
830 $a_xml_writer->xmlElement("fieldlabel", null, "layout");
831 $a_xml_writer->xmlElement("fieldentry", null, serialize($this->getLayout()));
832 $a_xml_writer->xmlEndTag("metadatafield");
833
834 $a_xml_writer->xmlEndTag("metadata");
835
836 $a_xml_writer->xmlEndTag("question");
837 }
838
839 public function syncWithOriginal()
840 {
841 if ($this->getOriginalId()) {
842 parent::syncWithOriginal();
843 $this->saveColumnsToDb($this->getOriginalId());
844 $this->saveRowsToDb($this->getOriginalId());
845 }
846 }
847
848
856 public function addStandardNumbers($lower_limit, $upper_limit)
857 {
858 for ($i = $lower_limit; $i <= $upper_limit; $i++) {
859 $this->columns->addCategory($i);
860 }
861 }
862
870 public function savePhrase($title)
871 {
874
875 $next_id = $ilDB->nextId('svy_phrase');
876 $affectedRows = $ilDB->manipulateF(
877 "INSERT INTO svy_phrase (phrase_id, title, defaultvalue, owner_fi, tstamp) VALUES (%s, %s, %s, %s, %s)",
878 array('integer','text','text','integer','integer'),
879 array($next_id, $title, 1, $ilUser->getId(), time())
880 );
881 $phrase_id = $next_id;
882
883 $counter = 1;
884 foreach ($_SESSION['save_phrase_data'] as $data) {
885 $next_id = $ilDB->nextId('svy_category');
886 $affectedRows = $ilDB->manipulateF(
887 "INSERT INTO svy_category (category_id, title, defaultvalue, owner_fi, tstamp, neutral) VALUES (%s, %s, %s, %s, %s, %s)",
888 array('integer','text','text','integer','integer','text'),
889 array($next_id, $data['answer'], 1, $ilUser->getId(), time(), $data['neutral'])
890 );
891 $category_id = $next_id;
892 $next_id = $ilDB->nextId('svy_phrase_cat');
893 $affectedRows = $ilDB->manipulateF(
894 "INSERT INTO svy_phrase_cat (phrase_category_id, phrase_fi, category_fi, sequence, other, scale) VALUES (%s, %s, %s, %s, %s, %s)",
895 array('integer', 'integer', 'integer','integer', 'integer', 'integer'),
896 array($next_id, $phrase_id, $category_id, $counter, ($data['other']) ? 1 : 0, $data['scale'])
897 );
898 $counter++;
899 }
900 }
901
908 public function getQuestionType()
909 {
910 return "SurveyMatrixQuestion";
911 }
912
919 public function getAdditionalTableName()
920 {
921 return "svy_qst_matrix";
922 }
923
930 public function &getWorkingDataFromUserInput($post_data)
931 {
932 $data = array();
933 foreach ($post_data as $key => $value) {
934 switch ($this->getSubtype()) {
935 case 0:
936 if (preg_match("/matrix_" . $this->getId() . "_(\d+)/", $key, $matches)) {
937 if (is_array($value)) {
938 foreach ($value as $val) {
939 array_push($data, array("value" => $val, "rowvalue" => $matches[1], "textanswer" => $post_data['matrix_other_' . $this->getId() . '_' . $matches[1]]));
940 }
941 } else {
942 array_push($data, array("value" => $value, "rowvalue" => $matches[1], "textanswer" => $post_data['matrix_other_' . $this->getId() . '_' . $matches[1]]));
943 }
944 }
945 break;
946 case 1:
947 if (preg_match("/matrix_" . $this->getId() . "_(\d+)/", $key, $matches)) {
948 if (is_array($value)) {
949 foreach ($value as $val) {
950 array_push($data, array("value" => $val, "rowvalue" => $matches[1], "textanswer" => $post_data['matrix_other_' . $this->getId() . '_' . $matches[1]]));
951 }
952 } else {
953 array_push($data, array("value" => $value, "rowvalue" => $matches[1], "textanswer" => $post_data['matrix_other_' . $this->getId() . '_' . $matches[1]]));
954 }
955 }
956 break;
957 }
958 }
959 return $data;
960 }
961
971 public function checkUserInput($post_data, $survey_id)
972 {
973 if (!$this->getObligatory($survey_id)) {
974 return "";
975 }
976 switch ($this->getSubtype()) {
977 case 0:
978 $counter = 0;
979 foreach ($post_data as $key => $value) {
980 if (preg_match("/matrix_" . $this->getId() . "_(\d+)/", $key, $matches)) {
981 if (array_key_exists('matrix_other_' . $this->getId() . "_" . $matches[1], $post_data) && strlen($post_data['matrix_other_' . $this->getId() . "_" . $matches[1]]) == 0) {
982 return $this->lng->txt("question_mr_no_other_answer");
983 }
984 $counter++;
985 }
986 }
987 if ($counter != $this->getRowCount()) {
988 return $this->lng->txt("matrix_question_radio_button_not_checked");
989 }
990 break;
991 case 1:
992 $counter = 0;
993 foreach ($post_data as $key => $value) {
994 if (preg_match("/matrix_" . $this->getId() . "_(\d+)/", $key, $matches)) {
995 if (array_key_exists('matrix_other_' . $this->getId() . "_" . $matches[1], $post_data) && strlen($post_data['matrix_other_' . $this->getId() . "_" . $matches[1]]) == 0) {
996 return $this->lng->txt("question_mr_no_other_answer");
997 }
998 $counter++;
999 if ((!is_array($value)) || (count($value) < 1)) {
1000 return $this->lng->txt("matrix_question_checkbox_not_checked");
1001 }
1002 }
1003 }
1004 if ($counter != $this->getRowCount()) {
1005 return $this->lng->txt("matrix_question_checkbox_not_checked");
1006 }
1007 break;
1008 }
1009 return "";
1010 }
1011
1012 public function saveUserInput($post_data, $active_id, $a_return = false)
1013 {
1014 $ilDB = $this->db;
1015
1016 $answer_data = array();
1017
1018 // gather data
1019 switch ($this->getSubtype()) {
1020 case 0:
1021 foreach ($post_data as $key => $value) {
1022 if (preg_match("/matrix_" . $this->getId() . "_(\d+)/", $key, $matches)) {
1023 if (strlen($value)) {
1024 $other_value = (array_key_exists('matrix_other_' . $this->getId() . '_' . $matches[1], $post_data))
1025 ? $this->stripSlashesAddSpaceFallback($post_data['matrix_other_' . $this->getId() . '_' . $matches[1]])
1026 : null;
1027 $answer_data[] = array("value" => $value,
1028 "textanswer" => $other_value,
1029 "rowvalue" => $matches[1]);
1030 }
1031 }
1032 }
1033 break;
1034
1035 case 1:
1036 foreach ($post_data as $key => $value) {
1037 if (preg_match("/matrix_" . $this->getId() . "_(\d+)/", $key, $matches)) {
1038 $other_value = (array_key_exists('matrix_other_' . $this->getId() . '_' . $matches[1], $post_data))
1039 ? $this->stripSlashesAddSpaceFallback($post_data['matrix_other_' . $this->getId() . '_' . $matches[1]])
1040 : null;
1041 foreach ($value as $checked) {
1042 $answer_data[] = array("value" => $checked,
1043 "textanswer" => $other_value,
1044 "rowvalue" => $matches[1]);
1045 }
1046 }
1047 }
1048 break;
1049 }
1050
1051 if ($a_return) {
1052 return $answer_data;
1053 }
1054
1055 // #16387 - only if any input
1056 if (sizeof($answer_data)) {
1057 // save data
1058 foreach ($answer_data as $item) {
1059 $next_id = $ilDB->nextId('svy_answer');
1060 #20216
1061 $fields = array();
1062 $fields['answer_id'] = array("integer", $next_id);
1063 $fields['question_fi'] = array("integer", $this->getId());
1064 $fields['active_fi'] = array("integer", $active_id);
1065 $fields['value'] = array("float", $item['value']);
1066 $fields['textanswer'] = array("clob", $item['textanswer']);
1067 $fields['rowvalue'] = array("integer", $item['rowvalue']);
1068 $fields['tstamp'] = array("integer", time());
1069
1070 $affectedRows = $ilDB->insert("svy_answer", $fields);
1071 }
1072 }
1073 }
1074
1081 public function deleteAdditionalTableData($question_id)
1082 {
1083 parent::deleteAdditionalTableData($question_id);
1084
1085 $ilDB = $this->db;
1086 $affectedRows = $ilDB->manipulateF(
1087 "DELETE FROM svy_qst_matrixrows WHERE question_fi = %s",
1088 array('integer'),
1089 array($question_id)
1090 );
1091 }
1092
1099 public function getSubtype()
1100 {
1101 return $this->subtype;
1102 }
1103
1110 public function setSubtype($a_subtype = 0)
1111 {
1112 switch ($a_subtype) {
1113 case 1:
1114 case 2:
1115 case 3:
1116 case 4:
1117 case 5:
1118 case 6:
1119 $this->subtype = $a_subtype;
1120 break;
1121 case 0:
1122 default:
1123 $this->subtype = 0;
1124 break;
1125 }
1126 }
1127
1134 public function setColumnSeparators($enable = 0)
1135 {
1136 switch ($enable) {
1137 case 1:
1138 $this->columnSeparators = 1;
1139 break;
1140 case 0:
1141 default:
1142 $this->columnSeparators = 0;
1143 break;
1144 }
1145 }
1146
1153 public function getColumnSeparators()
1154 {
1155 return ($this->columnSeparators) ? 1 : 0;
1156 }
1157
1164 public function setRowSeparators($enable = 0)
1165 {
1166 switch ($enable) {
1167 case 1:
1168 $this->rowSeparators = 1;
1169 break;
1170 case 0:
1171 default:
1172 $this->rowSeparators = 0;
1173 break;
1174 }
1175 }
1176
1183 public function getRowSeparators()
1184 {
1185 return ($this->rowSeparators) ? 1 : 0;
1186 }
1187
1194 public function setNeutralColumnSeparator($enable = 0)
1195 {
1196 switch ($enable) {
1197 case 1:
1198 $this->neutralColumnSeparator = 1;
1199 break;
1200 case 0:
1201 default:
1202 $this->neutralColumnSeparator = 0;
1203 break;
1204 }
1205 }
1206
1214 {
1215 return ($this->neutralColumnSeparator) ? 1 : 0;
1216 }
1217
1226 public function importAdditionalMetadata($a_meta)
1227 {
1228 foreach ($a_meta as $key => $value) {
1229 switch ($value["label"]) {
1230 case "column_separators":
1231 $this->setColumnSeparators($value["entry"]);
1232 break;
1233 case "row_separators":
1234 $this->setRowSeparators($value["entry"]);
1235 break;
1236 case "layout":
1237 $this->setLayout($value["entry"]);
1238 break;
1239 case "neutral_column_separator":
1240 $this->setNeutralColumnSeparator($value["entry"]);
1241 break;
1242 }
1243 }
1244 }
1245
1252 public function importAdjectives($a_data)
1253 {
1254 $i = 0;
1255 foreach ($a_data as $adjective) {
1256 if (is_numeric($adjective["label"])) {
1257 $this->setBipolarAdjective($adjective["label"], $adjective["text"]);
1258 } else {
1259 $this->setBipolarAdjective($i, $adjective["text"]);
1260 }
1261 $i++;
1262 }
1263 }
1264
1271 public function importMatrix($a_data)
1272 {
1273 foreach ($a_data as $row) {
1274 $this->addRow($row['title'], $row['other'], $row['label']);
1275 }
1276 }
1277
1284 public function importResponses($a_data)
1285 {
1286 foreach ($a_data as $id => $data) {
1287 $column = "";
1288 foreach ($data["material"] as $material) {
1289 $column .= $material["text"];
1290 }
1291 $this->columns->addCategory($column, null, (strcmp($data["label"], "neutral") == 0) ? true : false);
1292 }
1293 }
1294
1301 public function usableForPrecondition()
1302 {
1303 return false;
1304 }
1305
1313 public function getPreconditionValueOutput($value)
1314 {
1315 return $value;
1316 }
1317
1324 public function getPreconditionSelectValue($default = "", $title, $variable)
1325 {
1326 $step3 = new ilSelectInputGUI($title, $variable);
1327 $options = $this->getPreconditionOptions();
1328 $step3->setOptions($options);
1329 $step3->setValue($default);
1330 return $step3;
1331 }
1332
1342 public function saveLayout($percent_row, $percent_columns, $percent_bipolar_adjective1 = "", $percent_bipolar_adjective2 = "", $percent_neutral)
1343 {
1344 $ilDB = $this->db;
1345
1346 $layout = array(
1347 "percent_row" => $percent_row,
1348 "percent_columns" => $percent_columns,
1349 "percent_bipolar_adjective1" => $percent_bipolar_adjective1,
1350 "percent_bipolar_adjective2" => $percent_bipolar_adjective2,
1351 "percent_neutral" => $percent_neutral
1352 );
1353 $affectedRows = $ilDB->manipulateF(
1354 "UPDATE " . $this->getAdditionalTableName() . " SET layout = %s WHERE question_fi = %s",
1355 array('text', 'integer'),
1356 array(serialize($layout), $this->getId())
1357 );
1358 }
1359
1360 public function getLayout()
1361 {
1362 if (!is_array($this->layout) || count($this->layout) == 0) {
1363 if ($this->hasBipolarAdjectives() && $this->hasNeutralColumn()) {
1364 $this->layout = array(
1365 "percent_row" => 30,
1366 "percent_columns" => 40,
1367 "percent_bipolar_adjective1" => 10,
1368 "percent_bipolar_adjective2" => 10,
1369 "percent_neutral" => 10
1370 );
1371 } elseif ($this->hasBipolarAdjectives()) {
1372 $this->layout = array(
1373 "percent_row" => 30,
1374 "percent_columns" => 50,
1375 "percent_bipolar_adjective1" => 10,
1376 "percent_bipolar_adjective2" => 10,
1377 "percent_neutral" => 0
1378 );
1379 } elseif ($this->hasNeutralColumn()) {
1380 $this->layout = array(
1381 "percent_row" => 30,
1382 "percent_columns" => 50,
1383 "percent_bipolar_adjective1" => 0,
1384 "percent_bipolar_adjective2" => 0,
1385 "percent_neutral" => 20
1386 );
1387 } else {
1388 $this->layout = array(
1389 "percent_row" => 30,
1390 "percent_columns" => 70,
1391 "percent_bipolar_adjective1" => 0,
1392 "percent_bipolar_adjective2" => 0,
1393 "percent_neutral" => 0
1394 );
1395 }
1396 }
1397 return $this->layout;
1398 }
1399
1400 public function setLayout($layout)
1401 {
1402 if (is_array($layout)) {
1403 $this->layout = $layout;
1404 } else {
1405 $this->layout = unserialize($layout);
1406 }
1407 }
1408
1414 public function hasBipolarAdjectives()
1415 {
1416 if ((strlen($this->getBipolarAdjective(0))) && (strlen($this->getBipolarAdjective(1)))) {
1417 return true;
1418 } else {
1419 return false;
1420 }
1421 }
1422
1428 public function hasNeutralColumn()
1429 {
1430 for ($i = 0; $i < $this->getColumnCount(); $i++) {
1431 $column = $this->getColumn($i);
1432 if ($column->neutral && strlen($column->title)) {
1433 return true;
1434 }
1435 }
1436 return false;
1437 }
1438
1444 public function setColumnPlaceholders($a_value = 0)
1445 {
1446 $this->columnPlaceholders = ($a_value) ? 1 : 0;
1447 }
1448
1454 public function getColumnPlaceholders()
1455 {
1456 return ($this->columnPlaceholders) ? 1 : 0;
1457 }
1458
1464 public function setLegend($a_value = 0)
1465 {
1466 $this->legend = ($a_value) ? 1 : 0;
1467 }
1468
1474 public function getLegend()
1475 {
1476 return ($this->legend) ? 1 : 0;
1477 }
1478
1479 public function setSingleLineRowCaption($a_value = 0)
1480 {
1481 $this->singleLineRowCaption = ($a_value) ? 1 : 0;
1482 }
1483
1484 public function getSingleLineRowCaption()
1485 {
1486 return ($this->singleLineRowCaption) ? 1 : 0;
1487 }
1488
1489 public function setRepeatColumnHeader($a_value = 0)
1490 {
1491 $this->repeatColumnHeader = ($a_value) ? 1 : 0;
1492 }
1493
1494 public function getRepeatColumnHeader()
1495 {
1496 return ($this->repeatColumnHeader) ? 1 : 0;
1497 }
1498
1499 public function setColumnHeaderPosition($a_value)
1500 {
1501 $this->columnHeaderPosition = $a_value;
1502 }
1503
1504 public function getColumnHeaderPosition()
1505 {
1506 return ($this->columnHeaderPosition) ? $this->columnHeaderPosition : 0;
1507 }
1508
1509 public function setRandomRows($a_value = 0)
1510 {
1511 $this->randomRows = ($a_value) ? 1 : 0;
1512 }
1513
1514 public function getRandomRows()
1515 {
1516 return ($this->randomRows) ? 1 : 0;
1517 }
1518
1519 public function setColumnOrder($a_value)
1520 {
1521 $this->columnOrder = $a_value;
1522 }
1523
1524 public function getColumnOrder()
1525 {
1526 return ($this->columnOrder) ? $this->columnOrder : 0;
1527 }
1528
1529 public function setColumnImages($a_value = 0)
1530 {
1531 $this->columnImages = ($a_value) ? 1 : 0;
1532 }
1533
1534 public function getColumnImages()
1535 {
1536 return ($this->columnImages) ? 1 : 0;
1537 }
1538
1539 public function setRowImages($a_value = 0)
1540 {
1541 $this->rowImages = ($a_value) ? 1 : 0;
1542 }
1543
1544 public function getRowImages()
1545 {
1546 return ($this->rowImages) ? 1 : 0;
1547 }
1548
1549 public function getRows()
1550 {
1551 return $this->rows;
1552 }
1553
1557 public static function getMaxSumScore(int $survey_id) : int
1558 {
1559 global $DIC;
1560
1561 // we need max scale values of matrix rows * number of rows (type 5)
1562 $db = $DIC->database();
1563
1564 $set = $db->queryF(
1565 "SELECT MAX(scale) max_sum_score, q.question_id FROM svy_svy_qst sq " .
1566 "JOIN svy_question q ON (sq.question_fi = q.question_id) " .
1567 "JOIN svy_variable v ON (v.question_fi = q.question_id) " .
1568 "WHERE sq.survey_fi = %s AND q.questiontype_fi = %s " .
1569 "GROUP BY (q.question_id)",
1570 ["integer", "integer"],
1571 [$survey_id, 5]
1572 );
1573 $max_score = [];
1574 while ($rec = $db->fetchAssoc($set)) {
1575 $max_score[$rec["question_id"]] = $rec["max_sum_score"];
1576 }
1577
1578 $set = $db->queryF(
1579 "SELECT COUNT(mr.id_svy_qst_matrixrows) cnt_rows, q.question_id FROM svy_svy_qst sq " .
1580 "JOIN svy_question q ON (sq.question_fi = q.question_id) " .
1581 "JOIN svy_qst_matrixrows mr ON (mr.question_fi = q.question_id) " .
1582 "WHERE sq.survey_fi = %s AND q.questiontype_fi = %s " .
1583 "GROUP BY (q.question_id)",
1584 ["integer", "integer"],
1585 [$survey_id, 5]
1586 );
1587 $cnt_rows = [];
1588 while ($rec = $db->fetchAssoc($set)) {
1589 $cnt_rows[$rec["question_id"]] = $rec["cnt_rows"];
1590 }
1591
1592 $sum_sum_score = 0;
1593 foreach ($max_score as $qid => $s) {
1594 $sum_sum_score += $s * $cnt_rows[$qid];
1595 }
1596
1597 return $sum_sum_score;
1598 }
1599}
$result
user()
Definition: user.php:4
$_SESSION["AccountId"]
An exception for terminatinating execution or to throw for unit testing.
Class SurveyCategories.
The SurveyMatrixQuestion class defines and encapsulates basic methods and attributes for matrix quest...
hasNeutralColumn()
Returns TRUE if a neutral column exists.
addRow($a_text, $a_other, $a_label)
Adds a row to the question.
addStandardNumbers($lower_limit, $upper_limit)
Adds standard numbers as columns.
setSubtype($a_subtype=0)
Sets the subtype of the matrix question.
__construct($title="", $description="", $author="", $questiontext="", $owner=-1)
SurveyMatrixQuestion constructor The constructor takes possible arguments an creates an instance of t...
getAdditionalTableName()
Returns the name of the additional question data table in the database.
setRowSeparators($enable=0)
Enables/Disables separators for the matrix rows.
setBipolarAdjective($a_index, $a_value)
Sets one of the bipolar adjectives.
importMatrix($a_data)
Import matrix rows from the question import file.
removeRow($index)
Removes a row.
importAdjectives($a_data)
Import bipolar adjectives from the question import file.
saveLayout($percent_row, $percent_columns, $percent_bipolar_adjective1="", $percent_bipolar_adjective2="", $percent_neutral)
Saves the layout of a matrix question.
getColumnIndex($name)
Returns the index of a column with a given name.
removeRows($array)
Removes rows from the question.
getQuestionDataArray($id)
Returns the question data fields from the database.
flushRows()
Empties the row list.
getBipolarAdjective($a_index)
Returns one of the bipolar adjectives.
saveUserInput($post_data, $active_id, $a_return=false)
removeColumnWithName($name)
Removes a column from the list of columns.
setColumnSeparators($enable=0)
Enables/Disables separators for the matrix columns.
getSubtype()
Returns the subtype of the matrix question.
savePhrase($title)
Saves a set of columns to a default phrase.
getNeutralColumnSeparator()
Gets the separator enable state for the neutral column.
getLegend()
Get whether the legend should be shown or not.
saveColumnToDb($columntext, $neutral=0)
Saves a column to the database.
saveToDb($original_id=null, $withanswers=true)
Saves a SurveyMatrixQuestion object to a database.
& getWorkingDataFromUserInput($post_data)
Creates the user data of the svy_answer table from the POST data.
getQuestionType()
Returns the question type of the question.
getColumn($index)
Returns the name of a column for a given index.
flushColumns()
Empties the columns list.
usableForPrecondition()
Returns if the question is usable for preconditions.
checkUserInput($post_data, $survey_id)
Checks the input of the active user for obligatory status and entered values.
setNeutralColumnSeparator($enable=0)
Enables/Disables a separator for the neutral column.
addPhrase($phrase_id)
Adds a phrase to the question.
importAdditionalMetadata($a_meta)
Import additional meta data from the question import file.
setColumnPlaceholders($a_value=0)
Set whether placeholders should be used for the column titles or not.
getColumnSeparators()
Gets the separators enable state for the matrix columns.
setLegend($a_value=0)
Set whether the legend should be shown or not.
removeColumn($index)
Removes a column from the list of columns.
removeColumns($array)
Removes many columns from the list of columns.
toXML($a_include_header=true, $obligatory_state="")
Returns an xml representation of the question.
getColumnPlaceholders()
Get whether placeholders should be used for the column titles or not.
saveBipolarAdjectives($adjective1, $adjective2)
getColumnCount()
Returns the number of columns.
hasBipolarAdjectives()
Returns TRUE if bipolar adjectives exist.
getPreconditionValueOutput($value)
Returns the output for a precondition value.
loadFromDb($id)
Loads a SurveyMatrixQuestion object from the database.
insertXML(&$a_xml_writer, $a_include_header=true)
Adds the question XML to a given XMLWriter object.
getRow($a_index)
Returns a specific row.
importResponses($a_data)
Import response data from the question import file.
deleteAdditionalTableData($question_id)
Deletes datasets from the additional question table in the database.
getPreconditionSelectValue($default="", $title, $variable)
Creates a form property for the precondition value.
getRowCount()
Returns the number of rows in the question.
static getMaxSumScore(int $survey_id)
@inheritDoc
addRowAtPosition($a_text, $a_other, $a_position)
Adds a row at a given position.
getRowSeparators()
Gets the separators enable state for the matrix rows.
isComplete()
Returns 1 if the question is complete for use.
Basic class for all survey question types.
setQuestiontext($questiontext="")
Sets the questiontext of the SurveyQuestion object.
setId($id=-1)
Sets the id of the SurveyQuestion object.
setAuthor($author="")
Sets the authors name of the SurveyQuestion object.
stripSlashesAddSpaceFallback($a_str)
Strip slashes with add space fallback, see https://mantis.ilias.de/view.php?id=19727 and https://mant...
getDescription()
Gets the description string of the SurveyQuestion object.
getId()
Gets the id of the SurveyQuestion object.
setDescription($description="")
Sets the description string of the SurveyQuestion object.
setObjId($obj_id=0)
Set the reference id of the container object.
getAuthor()
Gets the authors name of the SurveyQuestion object.
setOriginalId($original_id)
getQuestiontext()
Gets the questiontext of the SurveyQuestion object.
getObligatory($survey_id="")
Gets the obligatory state of the question.
getTitle()
Gets the title string of the SurveyQuestion object.
setComplete($a_complete)
Sets the complete state of the question.
getPreconditionOptions()
Returns the options for preconditions.
saveMaterial()
save material to db
setOwner($owner="")
Sets the creator/owner ID of the SurveyQuestion object.
setTitle($title="")
Sets the title string of the SurveyQuestion object.
saveCompletionStatus($original_id="")
Saves the complete flag to the database.
addMaterialTag(&$a_xml_writer, $a_material, $close_material_tag=true, $add_mobs=true, $a_attrs=null)
Creates an XML material tag from a plain text or xhtml text.
setObligatory($obligatory=1)
Sets the obligatory state of the question.
static _replaceMediaObjectImageSrc($a_text, $a_direction=0, $nic=IL_INST_ID)
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
This class represents a selection list property in a property form.
XML writer class.
xmlHeader()
Writes xml header @access public.
const IL_INST_ID
Definition: constants.php:38
global $DIC
Definition: goto.php:24
$ilUser
Definition: imgupload.php:18
if($format !==null) $name
Definition: metadata.php:230
$index
Definition: metadata.php:128
$i
Definition: metadata.php:24
$xml
Definition: metadata.php:332
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
global $ilDB
$data
Definition: storeScorm.php:23