ILIAS  trunk Revision v11.0_alpha-1761-g6dbbfa7b760
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
class.SurveyMetricQuestion.php
Go to the documentation of this file.
1 <?php
2 
26 {
27  public const SUBTYPE_NON_RATIO = 3;
28  public const SUBTYPE_RATIO_NON_ABSOLUTE = 4;
29  public const SUBTYPE_RATIO_ABSOLUTE = 5;
30 
31  public int $subtype;
32 
33  public ?float $minimum;
34  public ?float $maximum;
35 
36  public function __construct(
37  string $title = "",
38  string $description = "",
39  string $author = "",
40  string $questiontext = "",
41  int $owner = -1,
42  int $subtype = self::SUBTYPE_NON_RATIO
43  ) {
44  global $DIC;
45 
46  $this->db = $DIC->database();
48 
49  $this->subtype = $subtype;
50  $this->minimum = null;
51  $this->maximum = null;
52  }
53 
54  public function setSubtype(int $a_subtype = self::SUBTYPE_NON_RATIO): void
55  {
56  $this->subtype = $a_subtype;
57  }
58 
59  public function setMinimum(?float $minimum = null): void
60  {
61  $this->minimum = $minimum;
62  }
63 
64  public function setMaximum(?float $maximum = null): void
65  {
66  $this->maximum = $maximum;
67  }
68 
69  public function getSubtype(): ?int
70  {
71  return $this->subtype;
72  }
73 
74  public function getMinimum(): ?float
75  {
76  if (is_null($this->minimum) && $this->getSubtype() > 3) {
77  $this->minimum = 0;
78  }
79  return $this->minimum;
80  }
81 
82  public function getMaximum(): ?float
83  {
84  return $this->maximum;
85  }
86 
87  public function getQuestionDataArray(int $id): array
88  {
89  $ilDB = $this->db;
90 
91  $result = $ilDB->queryF(
92  "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",
93  array('integer'),
94  array($id)
95  );
96  if ($result->numRows() === 1) {
97  return $ilDB->fetchAssoc($result);
98  } else {
99  return array();
100  }
101  }
102 
103  public function loadFromDb(int $question_id): void
104  {
105  $ilDB = $this->db;
106 
107  $result = $ilDB->queryF(
108  "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",
109  array('integer'),
110  array($question_id)
111  );
112  if ($result->numRows() === 1) {
113  $data = $ilDB->fetchAssoc($result);
114  $this->setId((int) $data["question_id"]);
115  $this->setTitle((string) $data["title"]);
116  $this->setDescription((string) $data["description"]);
117  $this->setObjId((int) $data["obj_fi"]);
118  $this->setAuthor((string) $data["author"]);
119  $this->setOwner((int) $data["owner_fi"]);
120  $this->label = (string) $data['label'];
121  $this->setQuestiontext(ilRTE::_replaceMediaObjectImageSrc((string) $data["questiontext"], 1));
122  $this->setObligatory((bool) $data["obligatory"]);
123  $this->setComplete((bool) $data["complete"]);
124  $this->setOriginalId((int) $data["original_id"]);
125  $this->setSubtype((int) $data["subtype"]);
126 
127  $result = $ilDB->queryF(
128  "SELECT svy_variable.* FROM svy_variable WHERE svy_variable.question_fi = %s",
129  array('integer'),
130  array($question_id)
131  );
132  if ($result->numRows() > 0) {
133  if ($data = $ilDB->fetchAssoc($result)) {
134  $this->minimum = is_null($data["value1"]) ? null : (float) $data["value1"];
135  if (($data["value2"] < 0) or (strcmp((string) $data["value2"], "") == 0)) {
136  $this->maximum = null;
137  } else {
138  $this->maximum = is_null($data["value2"] ?? null) ? null : (float) $data["value2"];
139  }
140  }
141  }
142  }
143  parent::loadFromDb($question_id);
144  }
145 
146  public function isComplete(): bool
147  {
148  return (
149  $this->getTitle() !== '' &&
150  $this->getAuthor() !== '' &&
151  $this->getQuestiontext() !== ''
152  );
153  }
154 
155  public function saveToDb(int $original_id = 0): int
156  {
157  $ilDB = $this->db;
158 
159  $affectedRows = parent::saveToDb($original_id);
160  if ($affectedRows === 1) {
161  $ilDB->manipulateF(
162  "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
163  array('integer'),
164  array($this->getId())
165  );
166  $ilDB->manipulateF(
167  "INSERT INTO " . $this->getAdditionalTableName() . " (question_fi, subtype) VALUES (%s, %s)",
168  array('integer', 'text'),
169  array($this->getId(), $this->getSubtype())
170  );
171 
172  // save categories
173  $ilDB->manipulateF(
174  "DELETE FROM svy_variable WHERE question_fi = %s",
175  array('integer'),
176  array($this->getId())
177  );
178 
179  if (preg_match("/[\D]/", $this->maximum) or (strcmp($this->maximum, "&infin;") == 0)) {
180  $max = -1;
181  } else {
182  $max = $this->getMaximum();
183  }
184  $next_id = $ilDB->nextId('svy_variable');
185  $ilDB->manipulateF(
186  "INSERT INTO svy_variable (variable_id, category_fi, question_fi, value1, value2, sequence, tstamp) VALUES (%s, %s, %s, %s, %s, %s, %s)",
187  array('integer','integer','integer','float','float','integer','integer'),
188  array($next_id, 0, $this->getId(), $this->getMinimum(), $max, 0, time())
189  );
190  }
191  return $affectedRows;
192  }
193 
194  public function toXML(
195  bool $a_include_header = true
196  ): string {
197  $a_xml_writer = new ilXmlWriter();
198  $a_xml_writer->xmlHeader();
199  $this->insertXML($a_xml_writer, $a_include_header);
200  $xml = $a_xml_writer->xmlDumpMem(false);
201  if (!$a_include_header) {
202  $pos = strpos($xml, "?>");
203  $xml = substr($xml, $pos + 2);
204  }
205  return $xml;
206  }
207 
208  public function insertXML(
209  ilXmlWriter $a_xml_writer,
210  bool $a_include_header = true
211  ): void {
212  $attrs = array(
213  "id" => $this->getId(),
214  "title" => $this->getTitle(),
215  "type" => $this->getQuestionType(),
216  "subtype" => $this->getSubtype(),
217  "obligatory" => $this->getObligatory()
218  );
219  $a_xml_writer->xmlStartTag("question", $attrs);
220 
221  $a_xml_writer->xmlElement("description", null, $this->getDescription());
222  $a_xml_writer->xmlElement("author", null, $this->getAuthor());
223  $a_xml_writer->xmlStartTag("questiontext");
224  $this->addMaterialTag($a_xml_writer, $this->getQuestiontext());
225  $a_xml_writer->xmlEndTag("questiontext");
226 
227  $a_xml_writer->xmlStartTag("responses");
228  switch ($this->getSubtype()) {
229  case 4:
230  case 3:
231  $attrs = array(
232  "id" => "0",
233  "format" => "double"
234  );
235  if ((string) $this->getMinimum() !== '') {
236  $attrs["min"] = $this->getMinimum();
237  }
238  if ((string) $this->getMaximum() !== '') {
239  $attrs["max"] = $this->getMaximum();
240  }
241  break;
242  case 5:
243  $attrs = array(
244  "id" => "0",
245  "format" => "integer"
246  );
247  if ((string) $this->getMinimum() !== '') {
248  $attrs["min"] = $this->getMinimum();
249  }
250  if ((string) $this->getMaximum() !== '') {
251  $attrs["max"] = $this->getMaximum();
252  }
253  break;
254  }
255  $a_xml_writer->xmlStartTag("response_num", $attrs);
256  $a_xml_writer->xmlEndTag("response_num");
257 
258  $a_xml_writer->xmlEndTag("responses");
259 
260  if (count($this->material) && preg_match(
261  "/il_(\d*?)_(\w+)_(\d+)/",
262  $this->material["internal_link"],
263  $matches
264  )) {
265  $attrs = array(
266  "label" => $this->material["title"]
267  );
268  $a_xml_writer->xmlStartTag("material", $attrs);
269  $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
270  if (strcmp($matches[1], "") !== 0) {
271  $intlink = $this->material["internal_link"];
272  }
273  $a_xml_writer->xmlElement("mattext", null, $intlink);
274  $a_xml_writer->xmlEndTag("material");
275  }
276 
277  $a_xml_writer->xmlEndTag("question");
278  }
279 
280  public function getQuestionTypeID(): int
281  {
282  $ilDB = $this->db;
283  $result = $ilDB->queryF(
284  "SELECT questiontype_id FROM svy_qtype WHERE type_tag = %s",
285  array('text'),
286  array($this->getQuestionType())
287  );
288  $row = $ilDB->fetchAssoc($result);
289  return (int) $row["questiontype_id"];
290  }
291 
292  public function getQuestionType(): string
293  {
294  return "SurveyMetricQuestion";
295  }
296 
297  public function getAdditionalTableName(): string
298  {
299  return "svy_qst_metric";
300  }
301 
302  public function getWorkingDataFromUserInput(array $post_data): array
303  {
304  $entered_value = $post_data[$this->getId() . "_metric_question"] ?? "";
305  $data = array();
306  if (strlen($entered_value ?? "")) {
307  $data[] = array("value" => $entered_value);
308  }
309  return $data;
310  }
311 
315  public function checkUserInput(
316  array $post_data,
317  int $survey_id
318  ): string {
319  $entered_value = $post_data[$this->getId() . "_metric_question"];
320  // replace german notation with international notation
321  $entered_value = str_replace(",", ".", $entered_value);
322 
323  if ((!$this->getObligatory()) && (strlen($entered_value ?? "") == 0)) {
324  return "";
325  }
326 
327  if (strlen($entered_value ?? "") == 0) {
328  return $this->lng->txt("survey_question_obligatory");
329  }
330 
331  if (!is_numeric(trim($entered_value))) {
332  return $this->lng->txt("metric_question_not_a_value");
333  }
334 
335  if (strlen($this->getMinimum() ?? "")) {
336  if ($entered_value < $this->getMinimum()) {
337  return $this->lng->txt("metric_question_out_of_bounds");
338  }
339  }
340 
341  if (strlen($this->getMaximum() ?? "")) {
342  if (($this->getMaximum() == 1) && ($this->getMaximum() < $this->getMinimum())) {
343  // old &infty; values as maximum
344  } elseif ($entered_value > $this->getMaximum()) {
345  return $this->lng->txt("metric_question_out_of_bounds");
346  }
347  }
348 
349  if (!is_numeric($entered_value)) {
350  return $this->lng->txt("metric_question_not_a_value");
351  }
352 
353  if ($this->getSubtype() === self::SUBTYPE_RATIO_ABSOLUTE && ((int) $entered_value != (float) $entered_value)) {
354  return $this->lng->txt("metric_question_floating_point");
355  }
356  return "";
357  }
358 
359  public function saveUserInput(
360  array $post_data,
361  int $active_id,
362  bool $a_return = false
363  ): ?array {
364  $ilDB = $this->db;
365 
366  $entered_value = $post_data[$this->getId() . "_metric_question"];
367 
368  // replace german notation with international notation
369  $entered_value = str_replace(",", ".", $entered_value);
370 
371  if ($a_return) {
372  return array(array("value" => $entered_value, "textanswer" => null));
373  }
374 
375  if ($entered_value === '') {
376  return null;
377  }
378 
379  $next_id = $ilDB->nextId('svy_answer');
380  #20216
381  $fields = array();
382  $fields['answer_id'] = array("integer", $next_id);
383  $fields['question_fi'] = array("integer", $this->getId());
384  $fields['active_fi'] = array("integer", $active_id);
385  $fields['value'] = array("float", $entered_value);
386  $fields['textanswer'] = array("clob", null);
387  $fields['tstamp'] = array("integer", time());
388 
389  $ilDB->insert("svy_answer", $fields);
390 
391  return null;
392  }
393 
394  public function importResponses(array $a_data): void
395  {
396  foreach ($a_data as $id => $data) {
397  $this->setMinimum($data["min"]);
398  $this->setMaximum($data["max"]);
399  }
400  }
401 
402  public function usableForPrecondition(): bool
403  {
404  return true;
405  }
406 
407  public function getAvailableRelations(): array
408  {
409  return array("<", "<=", "=", "<>", ">=", ">");
410  }
411 
412  public function outPreconditionSelectValue(
413  ilTemplate $template
414  ): void {
415  $template->setCurrentBlock("textfield");
416  $template->setVariable("TEXTFIELD_VALUE", "");
417  $template->parseCurrentBlock();
418  }
419 
425  public function getPreconditionSelectValue(
426  string $default,
427  string $title,
428  string $variable
429  ): ?ilFormPropertyGUI {
430  $step3 = new ilNumberInputGUI($title, $variable);
431  $step3->setValue($default);
432  return $step3;
433  }
434 
438  public function getMinMaxText(): string
439  {
440  $min = (string) $this->getMinimum();
441  $max = (string) $this->getMaximum();
442  if ($min !== '' && $max !== '') {
443  return "(" . $min . " " . strtolower($this->lng->txt("to")) . " " . $max . ")";
444  } elseif ($min !== '') {
445  return "(&gt;= " . $min . ")";
446  } elseif ($max !== '') {
447  return "(&lt;= " . $max . ")";
448  } else {
449  return "";
450  }
451  }
452 }
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...
parseCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
setQuestiontext(string $questiontext="")
toXML(bool $a_include_header=true)
const IL_INST_ID
Definition: constants.php:40
__construct(string $title="", string $description="", string $author="", string $questiontext="", int $owner=-1, int $subtype=self::SUBTYPE_NON_RATIO)
setObligatory(bool $obligatory=true)
setOriginalId(?int $original_id)
setMaximum(?float $maximum=null)
setComplete(bool $a_complete)
checkUserInput(array $post_data, int $survey_id)
xmlEndTag(string $tag)
Writes an endtag.
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
setAuthor(string $author="")
setVariable($variable, $value='')
Sets a variable value.
Definition: IT.php:544
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.
This class represents a number property in a property form.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $DIC
Definition: shib_login.php:22
setTitle(string $title="")
setMinimum(?float $minimum=null)
setCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
saveUserInput(array $post_data, int $active_id, bool $a_return=false)
outPreconditionSelectValue(ilTemplate $template)
setOwner(int $owner=0)
__construct(Container $dic, ilPlugin $plugin)
getMinMaxText()
Creates a text for the input range of the metric question.
xmlStartTag(string $tag, ?array $attrs=null, bool $empty=false, bool $encode=true, bool $escape=true)
Writes a starttag.
setSubtype(int $a_subtype=self::SUBTYPE_NON_RATIO)
xmlElement(string $tag, $attrs=null, $data=null, $encode=true, $escape=true)
Writes a basic element (no children, just textual content)
getWorkingDataFromUserInput(array $post_data)
setDescription(string $description="")
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getPreconditionSelectValue(string $default, string $title, string $variable)
Creates a form property for the precondition value.
setObjId(int $obj_id=0)
Set the reference(?) id of the container object.
insertXML(ilXmlWriter $a_xml_writer, bool $a_include_header=true)