ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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"]) ? $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
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)
$xml
Definition: metadata.php:240
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.
Create styles array
The data for the language used.
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.
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
setObjId($obj_id=0)
Set the reference id of the container object.
$key
Definition: croninfo.php:18
if(!isset($_REQUEST['ReturnTo'])) if(!isset($_REQUEST['AuthId'])) $options
Definition: as_login.php:20
setTitle($title="")
Sets the title string of the SurveyQuestion object.