ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.SurveyMultipleChoiceQuestion.php
Go to the documentation of this file.
1 <?php
2  /*
3  +----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +----------------------------------------------------------------------------+
22 */
23 
24 include_once "./Modules/SurveyQuestionPool/classes/class.SurveyQuestion.php";
25 
38 {
42  protected $db;
43 
49  public $categories;
50 
60  public function __construct($title = "", $description = "", $author = "", $questiontext = "", $owner = -1, $orientation = 0)
61  {
62  global $DIC;
63 
64  $this->db = $DIC->database();
65  $this->lng = $DIC->language();
66  parent::__construct($title, $description, $author, $questiontext, $owner);
67 
68  $this->orientation = $orientation;
69  include_once "./Modules/SurveyQuestionPool/classes/class.SurveyCategories.php";
70  $this->categories = new SurveyCategories();
71  }
72 
80  public function getQuestionDataArray($id)
81  {
82  $ilDB = $this->db;
83 
84  $result = $ilDB->queryF(
85  "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",
86  array('integer'),
87  array($id)
88  );
89  if ($result->numRows() == 1) {
90  return $ilDB->fetchAssoc($result);
91  } else {
92  return array();
93  }
94  }
95 
102  public function loadFromDb($id)
103  {
104  $ilDB = $this->db;
105 
106  $result = $ilDB->queryF(
107  "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",
108  array('integer'),
109  array($id)
110  );
111  if ($result->numRows() == 1) {
112  $data = $ilDB->fetchAssoc($result);
113  $this->setId($data["question_id"]);
114  $this->setTitle($data["title"]);
115  $this->label = $data['label'];
116  $this->setDescription($data["description"]);
117  $this->setObjId($data["obj_fi"]);
118  $this->setAuthor($data["author"]);
119  $this->setOwner($data["owner_fi"]);
120  include_once("./Services/RTE/classes/class.ilRTE.php");
121  $this->setQuestiontext(ilRTE::_replaceMediaObjectImageSrc($data["questiontext"], 1));
122  $this->setObligatory($data["obligatory"]);
123  $this->setComplete($data["complete"]);
124  $this->setOriginalId($data["original_id"]);
125  $this->setOrientation($data["orientation"]);
126  $this->use_min_answers = ($data['use_min_answers']) ? true : false;
127  $this->nr_min_answers = $data['nr_min_answers'];
128  $this->nr_max_answers = $data['nr_max_answers'];
129 
130  $this->categories->flushCategories();
131  $result = $ilDB->queryF(
132  "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",
133  array('integer'),
134  array($id)
135  );
136  if ($result->numRows() > 0) {
137  while ($data = $ilDB->fetchAssoc($result)) {
138  $this->categories->addCategory($data["title"], $data["other"], $data["neutral"], null, ($data['scale']) ? $data['scale'] : ($data['sequence'] + 1));
139  }
140  }
141  }
142  parent::loadFromDb($id);
143  }
144 
151  public function isComplete()
152  {
153  if (
154  strlen($this->getTitle()) &&
155  strlen($this->getAuthor()) &&
156  strlen($this->getQuestiontext()) &&
157  $this->categories->getCategoryCount()
158  ) {
159  return 1;
160  } else {
161  return 0;
162  }
163  }
164 
170  public function saveToDb($original_id = "")
171  {
172  $ilDB = $this->db;
173 
174  $affectedRows = parent::saveToDb($original_id);
175  if ($affectedRows == 1) {
176  $affectedRows = $ilDB->manipulateF(
177  "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
178  array('integer'),
179  array($this->getId())
180  );
181  $affectedRows = $ilDB->manipulateF(
182  "INSERT INTO " . $this->getAdditionalTableName() . " (question_fi, orientation, use_min_answers, nr_min_answers, nr_max_answers) VALUES (%s, %s, %s, %s, %s)",
183  array('integer', 'text', 'integer', 'integer', 'integer'),
184  array(
185  $this->getId(),
186  $this->getOrientation(),
187  ($this->use_min_answers) ? 1 : 0,
188  ($this->nr_min_answers > 0) ? $this->nr_min_answers : null,
189  ($this->nr_max_answers > 0) ? $this->nr_max_answers : null
190  )
191  );
192 
193  // saving material uris in the database
194  $this->saveMaterial();
195  $this->saveCategoriesToDb();
196  }
197  }
198 
199  public function saveCategoriesToDb()
200  {
201  $ilDB = $this->db;
202 
203  $affectedRows = $ilDB->manipulateF(
204  "DELETE FROM svy_variable WHERE question_fi = %s",
205  array('integer'),
206  array($this->getId())
207  );
208 
209  for ($i = 0; $i < $this->categories->getCategoryCount(); $i++) {
210  $cat = $this->categories->getCategory($i);
211  $category_id = $this->saveCategoryToDb($cat->title, $cat->neutral);
212  $next_id = $ilDB->nextId('svy_variable');
213  $affectedRows = $ilDB->manipulateF(
214  "INSERT INTO svy_variable (variable_id, category_fi, question_fi, value1, other, sequence, scale, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)",
215  array('integer','integer','integer','float','integer','integer', 'integer','integer'),
216  array($next_id, $category_id, $this->getId(), ($i + 1), $cat->other, $i, ($cat->scale > 0) ? $cat->scale : null, time())
217  );
218  }
219  $this->saveCompletionStatus();
220  }
221 
228  public function toXML($a_include_header = true, $obligatory_state = "")
229  {
230  include_once("./Services/Xml/classes/class.ilXmlWriter.php");
231  $a_xml_writer = new ilXmlWriter;
232  $a_xml_writer->xmlHeader();
233  $this->insertXML($a_xml_writer, $a_include_header, $obligatory_state);
234  $xml = $a_xml_writer->xmlDumpMem(false);
235  if (!$a_include_header) {
236  $pos = strpos($xml, "?>");
237  $xml = substr($xml, $pos + 2);
238  }
239  return $xml;
240  }
241 
249  public function insertXML(&$a_xml_writer, $a_include_header = true)
250  {
251  $attrs = array(
252  "id" => $this->getId(),
253  "title" => $this->getTitle(),
254  "type" => $this->getQuestiontype(),
255  "obligatory" => $this->getObligatory()
256  );
257  $a_xml_writer->xmlStartTag("question", $attrs);
258 
259  $a_xml_writer->xmlElement("description", null, $this->getDescription());
260  $a_xml_writer->xmlElement("author", null, $this->getAuthor());
261  if (strlen($this->label)) {
262  $attrs = array(
263  "label" => $this->label,
264  );
265  } else {
266  $attrs = array();
267  }
268  $a_xml_writer->xmlStartTag("questiontext", $attrs);
269  $this->addMaterialTag($a_xml_writer, $this->getQuestiontext());
270  $a_xml_writer->xmlEndTag("questiontext");
271 
272  $a_xml_writer->xmlStartTag("responses");
273 
274  for ($i = 0; $i < $this->categories->getCategoryCount(); $i++) {
275  $attrs = array(
276  "id" => $i
277  );
278  if (strlen($this->categories->getCategory($i)->other)) {
279  $attrs['other'] = $this->categories->getCategory($i)->other;
280  }
281  if (strlen($this->categories->getCategory($i)->neutral)) {
282  $attrs['neutral'] = $this->categories->getCategory($i)->neutral;
283  }
284  if (strlen($this->categories->getCategory($i)->label)) {
285  $attrs['label'] = $this->categories->getCategory($i)->label;
286  }
287  if (strlen($this->categories->getCategory($i)->scale)) {
288  $attrs['scale'] = $this->categories->getCategory($i)->scale;
289  }
290  $a_xml_writer->xmlStartTag("response_multiple", $attrs);
291  $this->addMaterialTag($a_xml_writer, $this->categories->getCategory($i)->title);
292  $a_xml_writer->xmlEndTag("response_multiple");
293  }
294 
295  $a_xml_writer->xmlEndTag("responses");
296 
297  if (count($this->material)) {
298  if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $this->material["internal_link"], $matches)) {
299  $attrs = array(
300  "label" => $this->material["title"]
301  );
302  $a_xml_writer->xmlStartTag("material", $attrs);
303  $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
304  if (strcmp($matches[1], "") != 0) {
305  $intlink = $this->material["internal_link"];
306  }
307  $a_xml_writer->xmlElement("mattext", null, $intlink);
308  $a_xml_writer->xmlEndTag("material");
309  }
310  }
311 
312  $a_xml_writer->xmlStartTag("metadata");
313  $a_xml_writer->xmlStartTag("metadatafield");
314  $a_xml_writer->xmlElement("fieldlabel", null, "orientation");
315  $a_xml_writer->xmlElement("fieldentry", null, $this->getOrientation());
316  $a_xml_writer->xmlEndTag("metadatafield");
317  $a_xml_writer->xmlStartTag("metadatafield");
318  $a_xml_writer->xmlElement("fieldlabel", null, "use_min_answers");
319  $a_xml_writer->xmlElement("fieldentry", null, $this->use_min_answers);
320  $a_xml_writer->xmlEndTag("metadatafield");
321  $a_xml_writer->xmlStartTag("metadatafield");
322  $a_xml_writer->xmlElement("fieldlabel", null, "nr_min_answers");
323  $a_xml_writer->xmlElement("fieldentry", null, $this->nr_min_answers);
324  $a_xml_writer->xmlEndTag("metadatafield");
325  $a_xml_writer->xmlStartTag("metadatafield");
326  $a_xml_writer->xmlElement("fieldlabel", null, "nr_max_answers");
327  $a_xml_writer->xmlElement("fieldentry", null, $this->nr_max_answers);
328  $a_xml_writer->xmlEndTag("metadatafield");
329  $a_xml_writer->xmlEndTag("metadata");
330 
331  $a_xml_writer->xmlEndTag("question");
332  }
333 
340  public function getQuestionType()
341  {
342  return "SurveyMultipleChoiceQuestion";
343  }
344 
351  public function getAdditionalTableName()
352  {
353  return "svy_qst_mc";
354  }
355 
362  public function &getWorkingDataFromUserInput($post_data)
363  {
364  $entered_value = $post_data[$this->getId() . "_value"];
365  $data = array();
366  if (is_array($entered_value)) {
367  foreach ($entered_value as $idx => $value) {
368  array_push($data, array("value" => $value, "textanswer" => $post_data[$this->getId() . '_' . $value . '_other']));
369  }
370  }
371  for ($i = 0; $i < $this->categories->getCategoryCount(); $i++) {
372  $cat = $this->categories->getCategory($i);
373  if ($cat->other) {
374  // #18212
375  if (!is_array($entered_value) || !in_array($i, $entered_value)) {
376  if (strlen($post_data[$this->getId() . "_" . $i . "_other"])) {
377  array_push($data, array("value" => $i, "textanswer" => $post_data[$this->getId() . '_' . $i . '_other'], "uncheck" => true));
378  }
379  }
380  }
381  }
382  return $data;
383  }
384 
394  public function checkUserInput($post_data, $survey_id)
395  {
396  $entered_value = (array) $post_data[$this->getId() . "_value"];
397  if (!$this->getObligatory($survey_id) && (!is_array($entered_value) || count($entered_value) == 0)) {
398  return "";
399  }
400  if ($this->use_min_answers && $this->nr_min_answers > 0 && $this->nr_max_answers > 0 && $this->nr_min_answers == $this->nr_max_answers && count($entered_value) != $this->nr_max_answers) {
401  return sprintf($this->lng->txt("err_no_exact_answers"), $this->nr_min_answers);
402  }
403  if ($this->use_min_answers && $this->nr_min_answers > 0 && count($entered_value) < $this->nr_min_answers) {
404  return sprintf($this->lng->txt("err_no_min_answers"), $this->nr_min_answers);
405  }
406  if ($this->use_min_answers && $this->nr_max_answers > 0 && count($entered_value) > $this->nr_max_answers) {
407  return sprintf($this->lng->txt("err_no_max_answers"), $this->nr_max_answers);
408  }
409  if (count($entered_value) == 0) {
410  return $this->lng->txt("question_mr_not_checked");
411  }
412  for ($i = 0; $i < $this->categories->getCategoryCount(); $i++) {
413  $cat = $this->categories->getCategory($i);
414  if ($cat->other) {
415  if (in_array($i, $entered_value)) {
416  if (array_key_exists($this->getId() . "_" . $i . "_other", $post_data) && !strlen($post_data[$this->getId() . "_" . $i . "_other"])) {
417  return $this->lng->txt("question_mr_no_other_answer");
418  }
419  } else {
420  if (strlen($post_data[$this->getId() . "_" . $i . "_other"])) {
421  return $this->lng->txt("question_mr_no_other_answer_checked");
422  }
423  }
424  }
425  }
426  return "";
427  }
428 
429  public function saveUserInput($post_data, $active_id, $a_return = false)
430  {
431  $ilDB = $this->db;
432 
433  if ($a_return) {
434  $return_data = array();
435  }
436  if (is_array($post_data[$this->getId() . "_value"])) {
437  foreach ($post_data[$this->getId() . "_value"] as $entered_value) {
438  if (strlen($entered_value) > 0) {
439  if (!$a_return) {
440  $next_id = $ilDB->nextId('svy_answer');
441 
442  #20216
443  $fields = array();
444  $fields['answer_id'] = array("integer", $next_id);
445  $fields['question_fi'] = array("integer", $this->getId());
446  $fields['active_fi'] = array("integer", $active_id);
447  $fields['value'] = array("float", (strlen($entered_value)) ? $entered_value : null);
448  $fields['textanswer'] = array("clob", ($post_data[$this->getId() . "_" . $entered_value . "_other"]) ? $this->stripSlashesAddSpaceFallback($post_data[$this->getId() . "_" . $entered_value . "_other"]) : null);
449  $fields['tstamp'] = array("integer", time());
450 
451  $affectedRows = $ilDB->insert("svy_answer", $fields);
452  } else {
453  $return_data[] = array("value" => $entered_value,
454  "textanswer" => $post_data[$this->getId() . "_" . $entered_value . "_other"]);
455  }
456  }
457  }
458  }
459  if ($a_return) {
460  return $return_data;
461  }
462  }
463 
472  public function importAdditionalMetadata($a_meta)
473  {
474  foreach ($a_meta as $key => $value) {
475  switch ($value["label"]) {
476  case "orientation":
477  $this->setOrientation($value["entry"]);
478  break;
479  case "use_min_answers":
480  $this->use_min_answers = $value["entry"];
481  break;
482  case "nr_min_answers":
483  $this->nr_min_answers = $value["entry"];
484  break;
485  case "nr_max_answers":
486  $this->nr_max_answers = $value["entry"];
487  break;
488  }
489  }
490  }
491 
498  public function importResponses($a_data)
499  {
500  foreach ($a_data as $id => $data) {
501  $categorytext = "";
502  foreach ($data["material"] as $material) {
503  $categorytext .= $material["text"];
504  }
505  $this->categories->addCategory(
506  $categorytext,
507  strlen($data['other']) ? $data['other'] : 0,
508  strlen($data['neutral']) ? $data['neutral'] : 0,
509  strlen($data['label']) ? $data['label'] : null,
510  strlen($data['scale']) ? $data['scale'] : null
511  );
512  }
513  }
514 
521  public function usableForPrecondition()
522  {
523  return true;
524  }
525 
532  public function getAvailableRelations()
533  {
534  return array("=", "<>");
535  }
536 
542  public function getPreconditionOptions()
543  {
544  $lng = $this->lng;
545 
546  $options = array();
547  for ($i = 0; $i < $this->categories->getCategoryCount(); $i++) {
548  $category = $this->categories->getCategory($i);
549  $options[$category->scale - 1] = $category->scale . " - " . $category->title;
550  }
551  return $options;
552  }
553 
560  public function getPreconditionSelectValue($default = "", $title, $variable)
561  {
562  include_once "./Services/Form/classes/class.ilSelectInputGUI.php";
563  $step3 = new ilSelectInputGUI($title, $variable);
564  $options = $this->getPreconditionOptions();
565  $step3->setOptions($options);
566  $step3->setValue($default);
567  return $step3;
568  }
569 
577  public function getPreconditionValueOutput($value)
578  {
579  // #18136
580  $category = $this->categories->getCategoryForScale($value + 1);
581 
582  // #17895 - see getPreconditionOptions()
583  return $category->scale .
584  " - " .
585  ((strlen($category->title)) ? $category->title : $this->lng->txt('other_answer'));
586  }
587 
588  public function getCategories()
589  {
590  return $this->categories;
591  }
592 }
getPreconditionOptions()
Returns the options for preconditions.
getQuestionType()
Returns the question type of the question.
saveCategoryToDb($categorytext, $neutral=0)
Saves a category to the database.
saveUserInput($post_data, $active_id, $a_return=false)
saveCompletionStatus($original_id="")
Saves the complete flag to the database.
importAdditionalMetadata($a_meta)
Import additional meta data from the question import file.
getAuthor()
Gets the authors name of the SurveyQuestion object.
getTitle()
Gets the title string of the SurveyQuestion object.
This class represents a selection list property in a property form.
$result
getObligatory($survey_id="")
Gets the obligatory state of the question.
global $DIC
Definition: saml.php:7
stripSlashesAddSpaceFallback($a_str)
Strip slashes with add space fallback, see https://mantis.ilias.de/view.php?id=19727 and https://mant...
setObligatory($obligatory=1)
Sets the obligatory state of the question.
setOrientation($orientation=0)
Sets the orientation of the question output.
& getWorkingDataFromUserInput($post_data)
Creates the user data of the svy_answer table from the POST data.
setId($id=-1)
Sets the id of the SurveyQuestion object.
XML writer class.
loadFromDb($id)
Loads a SurveyMultipleChoiceQuestion object from the database.
getQuestionDataArray($id)
Returns the question data fields from the database.
getQuestiontext()
Gets the questiontext of the SurveyQuestion object.
getOrientation()
Gets the orientation of the question output.
toXML($a_include_header=true, $obligatory_state="")
Returns an xml representation of the question.
checkUserInput($post_data, $survey_id)
Checks the input of the active user for obligatory status and entered values.
getAdditionalTableName()
Returns the name of the additional question data table in the database.
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...
setOwner($owner="")
Sets the creator/owner ID of the SurveyQuestion object.
setComplete($a_complete)
Sets the complete state of the question.
importResponses($a_data)
Import response data from the question import file.
__construct($title="", $description="", $author="", $questiontext="", $owner=-1, $orientation=0)
The constructor takes possible arguments an creates an instance of the SurveyMultipleChoiceQuestion o...
setOriginalId($original_id)
setQuestiontext($questiontext="")
Sets the questiontext of the SurveyQuestion object.
Class SurveyCategories.
getId()
Gets the id of the SurveyQuestion object.
saveToDb($original_id="")
Saves a SurveyMultipleChoiceQuestion object to a 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.
Basic class for all survey question types.
saveMaterial()
save material to db
insertXML(&$a_xml_writer, $a_include_header=true)
Adds the question XML to a given XMLWriter object.
xmlHeader()
Writes xml header public.
usableForPrecondition()
Returns if the question is usable for preconditions.
getPreconditionValueOutput($value)
Returns the output for a precondition value.
$default
Definition: build.php:20
getAvailableRelations()
Returns the available relations for the question.
setAuthor($author="")
Sets the authors name of the SurveyQuestion object.
setDescription($description="")
Sets the description string of the SurveyQuestion object.
getPreconditionSelectValue($default="", $title, $variable)
Creates a form property for the precondition value.
global $ilDB
$i
Definition: disco.tpl.php:19
isComplete()
Returns true if the question is complete for use.
getDescription()
Gets the description string of the SurveyQuestion object.
setObjId($obj_id=0)
Set the reference id of the container object.
$key
Definition: croninfo.php:18
$data
Definition: bench.php:6
setTitle($title="")
Sets the title string of the SurveyQuestion object.