ILIAS  release_8 Revision v8.23
class.ilSurveyPageEditGUI.php
Go to the documentation of this file.
1 <?php
2 
26 {
27  protected \ILIAS\Survey\PrintView\GUIService $print;
28  protected \ILIAS\HTTP\Services $http;
29  protected \ILIAS\DI\UIServices $ui;
30  protected bool $suppress_clipboard_msg = false;
31  protected string $pgov;
32  protected \ILIAS\Survey\Editing\EditingGUIRequest $svy_request;
33  protected \ILIAS\Survey\Editing\EditManager $edit_manager;
34  protected ilCtrl $ctrl;
36  protected ilDBInterface $db;
37  protected ilTabsGUI $tabs;
40  protected ilObjUser $user;
41  protected int $ref_id;
42  protected ilLanguage $lng;
43  protected ilObjSurvey $object;
45  protected ?int $current_page = null;
46  protected bool $has_previous_page;
47  protected bool $has_next_page;
48  protected bool $has_datasets;
49  protected bool $use_pool;
50  protected ilLogger $log;
51 
52  public function __construct(
53  ilObjSurvey $a_survey,
54  ilSurveyEditorGUI $a_survey_editor_gui
55  ) {
56  global $DIC;
57 
58  $this->lng = $DIC->language();
59  $this->ctrl = $DIC->ctrl();
60  $this->rbacsystem = $DIC->rbac()->system();
61  $this->db = $DIC->database();
62  $this->tabs = $DIC->tabs();
63  $this->tpl = $DIC["tpl"];
64  $this->toolbar = $DIC->toolbar();
65  $this->user = $DIC->user();
66  $this->editor_gui = $a_survey_editor_gui;
67  $this->ref_id = $a_survey->getRefId();
68  $this->object = $a_survey;
69  $this->log = ilLoggerFactory::getLogger("svy");
70  $this->edit_manager = $DIC->survey()
71  ->internal()
72  ->domain()
73  ->edit();
74  $this->svy_request = $DIC->survey()
75  ->internal()
76  ->gui()
77  ->editing()
78  ->request();
79  $this->pgov = $this->svy_request->getTargetPosition();
80  $this->ui = $DIC->ui();
81  $this->http = $DIC->http();
82  $this->print = $DIC->survey()
83  ->internal()
84  ->gui()
85  ->print();
86  }
87 
88  public function executeCommand(): void
89  {
90  $lng = $this->lng;
91  $ilCtrl = $this->ctrl;
92  $rbacsystem = $this->rbacsystem;
93 
94  $cmd = $ilCtrl->getCmd("renderPage");
95  $next_class = $ilCtrl->getNextClass($this);
96 
97  switch ($next_class) {
98  default:
99  $this->determineCurrentPage();
100 
101  $has_content = false;
102 
103  if ($rbacsystem->checkAccess("write", $this->ref_id)) {
104  // add page?
105  if ($this->svy_request->getNewId()) {
106  $this->insertNewQuestion($this->svy_request->getNewId());
107  $ilCtrl->setParameter($this->editor_gui, "pgov", $this->current_page);
108  $ilCtrl->redirect($this, "questions");
109  }
110 
111  // subcommands
112  if ($this->svy_request->getHForm("subcmd")) {
113  $subcmd = $this->svy_request->getHForm("subcmd");
114 
115  // make sure that it is set for current and next requests
116  $ilCtrl->setParameter($this->editor_gui, "pgov", $this->current_page);
117  $this->pgov = $this->current_page;
118  // this is necessary, since ILIAS 7
119  // wrote the REQUEST parameter
120  $this->editor_gui->setRequestedPgov($this->pgov);
121 
122  $id = explode("_", $this->svy_request->getHForm("node"));
123  $id = (int) ($id[1] ?? 0);
124 
125  // multi operation
126  if (strpos($this->svy_request->getHForm("subcmd"), "multi") === 0) {
127  if ($this->svy_request->getHForm("multi")) {
128  // removing types as we only allow questions anyway
129  $id = array();
130  foreach (explode(";", $this->svy_request->getHForm("multi")) as $item) {
131  $item_arr = explode("_", $item);
132  $id[] = (int) array_pop($item_arr);
133  }
134 
135  if ($subcmd === "multiDelete") {
136  $subcmd = "deleteQuestion";
137  }
138  } elseif ($subcmd === "multiDelete") {
139  // #9525
140  $this->tpl->setOnScreenMessage('failure', $lng->txt("no_checkbox"), true);
141  $ilCtrl->redirect($this, "renderPage");
142  } else {
143  $this->tpl->setOnScreenMessage('failure', $lng->txt("no_checkbox"));
144  }
145  }
146 
147  if (strpos($subcmd, "addQuestion") === 0) {
148  $type = explode("_", $subcmd);
149  $type = (int) $type[1];
150  $has_content = $this->addQuestion(
151  $type,
152  $this->object->getPoolUsage(),
153  $id,
154  $this->svy_request->getHForm("node")
155  );
156  } else {
157  switch ($subcmd) {
158  case "deleteQuestion":
159  $has_content = true;
160  $ids = (!is_array($id))
161  ? [$id]
162  : $id;
163  $this->deleteQuestion($ids);
164  break;
165  default:
166  if ($id === 0 && in_array($subcmd, ["multiCut", "multiCopy"])) {
167  $id = [];
168  }
169  $has_content = $this->$subcmd($id, $this->svy_request->getHForm("node"));
170  break;
171 
172  }
173  }
174  }
175  }
176 
177  if (!$has_content) {
178  $this->$cmd();
179  }
180  break;
181  }
182  }
183 
184  public function determineCurrentPage(): void
185  {
186  $current_page = null;
187  $jump = $this->svy_request->getJump();
188  if ($jump != "") {
189  $jump_parts = explode("__", $jump);
190  $current_page = (int) ($jump_parts[0] ?? 1);
191  }
192 
193  if (!$current_page) {
194  $current_page = $this->pgov;
195  }
196  if (!$current_page) {
197  $current_page = $this->svy_request->getPage();
198  }
199  if (!$current_page) {
200  $current_page = 1;
201  }
202  $this->current_page = (int) $current_page;
203  }
204 
210  protected function appendNewQuestionToSurvey(
211  int $a_new_id,
212  bool $a_duplicate = true,
213  bool $a_force_duplicate = false
214  ): int {
215  $ilDB = $this->db;
216  $this->log->debug("append question, id: " . $a_new_id . ", duplicate: " . $a_duplicate . ", force: " . $a_force_duplicate);
217 
218  // get maximum sequence index in test
219  $result = $ilDB->queryF(
220  "SELECT survey_question_id FROM svy_svy_qst WHERE survey_fi = %s",
221  array('integer'),
222  array($this->object->getSurveyId())
223  );
224  $sequence = $result->numRows();
225 
226  // create duplicate if pool question (or forced for question blocks copy)
227  if ($a_duplicate) {
228  // this does nothing if this is not a pool question and $a_force_duplicate is false
229  $survey_question_id = $this->object->duplicateQuestionForSurvey($a_new_id, $a_force_duplicate);
230  }
231  // used by copy & paste
232  else {
233  $survey_question_id = $a_new_id;
234  }
235 
236  // check if question is not already in the survey, see #22018
237  if ($this->object->isQuestionInSurvey($survey_question_id)) {
238  return $survey_question_id;
239  }
240  // append to survey
241  $next_id = $ilDB->nextId('svy_svy_qst');
242  $affectedRows = $ilDB->manipulateF(
243  "INSERT INTO svy_svy_qst (survey_question_id, survey_fi," .
244  "question_fi, sequence, tstamp) VALUES (%s, %s, %s, %s, %s)",
245  array('integer', 'integer', 'integer', 'integer', 'integer'),
246  array($next_id, $this->object->getSurveyId(), $survey_question_id, $sequence, time())
247  );
248 
249  $this->log->debug("insert svy_svy_qst, id: " . $next_id . ", qfi: " . $survey_question_id . ", seq: " . $sequence);
250 
251  return $survey_question_id;
252  }
253 
257  public function insertNewQuestion(
258  int $a_new_id
259  ): void {
260  $lng = $this->lng;
261  if (!SurveyQuestion::_isComplete($a_new_id)) {
262  $this->tpl->setOnScreenMessage('failure', $lng->txt("survey_error_insert_incomplete_question"));
263  } else {
264  $a_new_id = $this->appendNewQuestionToSurvey($a_new_id);
265  $this->object->loadQuestionsFromDb();
266  $this->object->saveCompletionStatus();
267 
268  $pos = $this->svy_request->getTargetQuestionPosition();
269 
270  // a[fter]/b[efore] on same page
271  if (substr($pos, -1) !== "c") {
272  // block handling
273  $current = $this->object->getSurveyPages();
274  $current = $current[$this->current_page - 1];
275  if (count($current) === 1) {
276  // as questions are moved to first block question
277  // always use existing as first
278  // the new question is moved later on (see below)
279  $this->object->createQuestionblock(
280  $this->getAutoBlockTitle(),
281  true,
282  false,
283  array((int) $pos, $a_new_id)
284  );
285  } else {
286  $block_id = array_pop($current);
287  $block_id = $block_id["questionblock_id"];
288 
289  $this->object->addQuestionToBlock($a_new_id, $block_id);
290  }
291  }
292  // c: as new page (from toolbar/pool)
293  elseif ((int) $pos) {
294  $pos = (int) $pos . "a";
295  $this->current_page++;
296  }
297  // at the beginning
298  else {
299  $first = $this->object->getSurveyPages();
300  $first = $first[0];
301  $first = array_shift($first);
302  $pos = $first["question_id"] . "b";
303  $this->current_page = 1;
304  }
305 
306  // move to target position
307  $this->object->moveQuestions(
308  array($a_new_id),
309  (int) $pos,
310  ((substr($pos, -1) === "a") ? 1 : 0)
311  );
312 
313  $this->object->fixSequenceStructure();
314  }
315  }
316 
320  public function insertQuestionBlock(
321  int $a_block_id
322  ): void {
323  $new_ids = array();
324  $question_ids = $this->object->getQuestionblockQuestionIds($a_block_id);
325  foreach ($question_ids as $qid) {
326  $new_ids[] = $this->appendNewQuestionToSurvey($qid, true, true);
327  }
328 
329  if (count($new_ids)) {
330  $this->object->loadQuestionsFromDb();
331 
332  $pos = $this->svy_request->getTargetQuestionPosition();
333 
334  // a[fter]/b[efore] on same page
335  if (substr($pos, -1) !== "c") {
336  // block handling
337  $current = $this->object->getSurveyPages();
338  $current = $current[$this->current_page - 1];
339  if (count($current) === 1) {
340  // as questions are moved to first block question
341  // always use existing as first
342  // the new question is moved later on (see below)
343  $this->object->createQuestionblock(
344  $this->getAutoBlockTitle(),
345  true,
346  false,
347  array((int) $pos) + $new_ids
348  );
349  } else {
350  $block_id = array_pop($current);
351  $block_id = $block_id["questionblock_id"];
352 
353  foreach ($new_ids as $qid) {
354  $this->object->addQuestionToBlock($qid, $block_id);
355  }
356  }
357  }
358  // c: as new page (from toolbar/pool)
359  else {
360  // re-create block
361  $this->object->createQuestionblock(
362  $this->getAutoBlockTitle(),
363  true,
364  false,
365  $new_ids
366  );
367 
368  // after given question
369  if ((int) $pos) {
370  $pos = (int) $pos . "a";
371  }
372  // at the beginning
373  else {
374  $first = $this->object->getSurveyPages();
375  $first = $first[0];
376  $first = array_shift($first);
377  $pos = $first["question_id"] . "b";
378  }
379  }
380 
381  // move to target position
382  $this->object->moveQuestions(
383  $new_ids,
384  (int) $pos,
385  ((substr($pos, -1) === "a") ? 1 : 0)
386  );
387  }
388  }
389 
398  protected function addQuestion(
399  int $a_type,
400  bool $a_use_pool,
401  string $a_pos,
402  string $a_special_position
403  ): bool {
404  $ilCtrl = $this->ctrl;
405  $ilTabs = $this->tabs;
406 
407  // get translated type
408  $type_trans = "";
410  foreach ($questiontypes as $item) {
411  if ($item["questiontype_id"] == $a_type) {
412  $type_trans = $item["type_tag"];
413  }
414  }
415 
416  $id = $a_pos;
417 
418  // new page behind current (from toolbar)
419  if ($a_special_position === "toolbar") {
420  $id = $this->object->getSurveyPages();
421  if ($a_pos && $a_pos !== "fst") {
422  $id = $id[(int) $a_pos - 1];
423  $id = array_pop($id);
424  $id = $id["question_id"] . "c";
425  } else {
426  $id = "0c";
427  }
428  }
429  // append current page
430  elseif ($a_special_position === "page_end") {
431  $id = $this->object->getSurveyPages();
432  $id = $id[$this->current_page - 1];
433  $id = array_pop($id);
434  $id = $id["question_id"] . "a";
435  } else {
436  $id .= "b";
437  }
438 
439  if ($a_use_pool) {
440  $ilCtrl->setParameter($this->editor_gui, "pgov_pos", $id);
441  $ilCtrl->setParameter($this->editor_gui, "sel_question_types", $type_trans);
442  if ($this->svy_request->getPoolUsage() === 0) {
443  $ilTabs->clearSubTabs(); // #17193
444  $this->editor_gui->createQuestionObject(null, $type_trans, $id);
445  } else {
446  $this->editor_gui->executeCreateQuestionObject($type_trans, null, $id);
447  }
448  return true;
449  } else {
450  // create question and redirect to question form
451 
452  $q_gui = SurveyQuestionGUI::_getQuestionGUI($type_trans);
453  $q_gui->object->setObjId($this->object->getId());
454  $q_gui->object->createNewQuestion();
455  $q_gui_class = get_class($q_gui);
456 
457  // #12531
458  $ilCtrl->setParameterByClass($q_gui_class, "pgov", $this->current_page);
459  $ilCtrl->setParameterByClass($q_gui_class, "pgov_pos", $id);
460  $ilCtrl->setParameterByClass($q_gui_class, "ref_id", $this->ref_id);
461  $ilCtrl->setParameterByClass($q_gui_class, "new_for_survey", $this->ref_id);
462  $ilCtrl->setParameterByClass($q_gui_class, "q_id", $q_gui->object->getId());
463  $ilCtrl->setParameterByClass($q_gui_class, "sel_question_types", $q_gui->getQuestionType());
464  $ilCtrl->redirectByClass($q_gui_class, "editQuestion");
465  }
466  return false;
467  }
468 
472  protected function cutQuestion(int $a_id): void
473  {
474  $lng = $this->lng;
475 
476  $this->tpl->setOnScreenMessage('success', $lng->txt("survey_questions_to_clipboard_cut"));
477  $this->suppress_clipboard_msg = true;
478 
479  $this->edit_manager->setQuestionClipboard(
480  $this->ref_id,
481  $this->current_page,
482  "cut",
483  array($a_id)
484  );
485  }
486 
490  protected function copyQuestion(int $a_id): void
491  {
492  $lng = $this->lng;
493 
494  $this->tpl->setOnScreenMessage('success', $lng->txt("survey_questions_to_clipboard_copy"));
495  $this->suppress_clipboard_msg = true;
496 
497  $this->edit_manager->setQuestionClipboard(
498  $this->ref_id,
499  $this->current_page,
500  "copy",
501  array($a_id)
502  );
503  }
504 
510  protected function multiCut(array $a_id): void
511  {
512  $lng = $this->lng;
513 
514  if (count($a_id) > 0) {
515  $this->tpl->setOnScreenMessage('success', $lng->txt("survey_questions_to_clipboard_cut"));
516  $this->suppress_clipboard_msg = true;
517 
518  $this->edit_manager->setQuestionClipboard(
519  $this->ref_id,
520  $this->current_page,
521  "cut",
522  $a_id
523  );
524  }
525  }
526 
531  protected function multiCopy(array $a_id): void
532  {
533  $lng = $this->lng;
534 
535  if (count($a_id) > 0) {
536  $this->tpl->setOnScreenMessage('success', $lng->txt("survey_questions_to_clipboard_copy"));
537  $this->suppress_clipboard_msg = true;
538 
539  $this->edit_manager->setQuestionClipboard(
540  $this->ref_id,
541  $this->current_page,
542  "copy",
543  $a_id
544  );
545  }
546  }
547 
551  protected function clearClipboard(): void
552  {
553  $this->edit_manager->clearQuestionClipboard($this->ref_id);
554  }
555 
560  protected function paste(int $a_id): void
561  {
562  $source_page = $this->edit_manager->getQuestionClipboardSourcePage($this->ref_id);
563  $qids = $this->edit_manager->getQuestionClipboardQuestions($this->ref_id);
564  $mode = $this->edit_manager->getQuestionClipboardMode($this->ref_id);
565  $pages = $this->object->getSurveyPages();
566  $source = $pages[$source_page - 1];
567  $target = $pages[$this->current_page - 1];
568 
569  // #12558 - use order of source page
570  $nodes = array();
571  foreach ($source as $src_qst) {
572  if (in_array($src_qst["question_id"], $qids)) {
573  $nodes[] = $src_qst["question_id"];
574  }
575  }
576 
577  // append to last position?
578  $pos = 0;
579  if ($this->svy_request->getHForm("node") === "page_end") {
580  $a_id = $target;
581  $a_id = array_pop($a_id);
582  $a_id = $a_id["question_id"];
583  $pos = 1;
584  }
585 
586  // cut
587  if ($mode === "cut") {
588  // special case: paste cut on same page (no block handling needed)
589  if ($source_page == $this->current_page) {
590  // re-order nodes in page
591  if (count($nodes) <= count($source)) {
592  $this->object->moveQuestions($nodes, $a_id, $pos);
593  }
594  $this->clearClipboard();
595  return;
596  } else {
597  // only if source has block
598  $source_block_id = false;
599  if (count($source) > 1) {
600  $source_block_id = $source;
601  $source_block_id = array_shift($source_block_id);
602  $source_block_id = $source_block_id["questionblock_id"];
603 
604  // remove from block
605  if (count($source) > count($nodes)) {
606  foreach ($nodes as $qid) {
607  $this->object->removeQuestionFromBlock($qid, $source_block_id);
608  }
609  }
610  // remove complete block
611  else {
612  $this->object->unfoldQuestionblocks(array($source_block_id));
613  }
614  }
615 
616  // page will be "deleted" by operation
617  if (count($source) === count($nodes) && $source_page < $this->current_page) {
618  $this->current_page--;
619  }
620  }
621  }
622 
623  // copy
624  elseif ($mode === "copy") {
625  $titles = array();
626  foreach ($this->object->getSurveyPages() as $page) {
627  foreach ($page as $question) {
628  $titles[] = $question["title"];
629  }
630  }
631 
632  // copy questions
633  $question_pointer = array();
634  foreach ($nodes as $qid) {
635  // create new questions
636  $question = ilObjSurvey::_instanciateQuestion($qid);
637  // handle exisiting copies
638  $title = $question->getTitle();
639  $max = 0;
640  foreach ($titles as $existing_title) {
641  #21278 preg_quote with delimiter
642  if (preg_match("/" . preg_quote($title, "/") . " \(([0-9]+)\)$/", $existing_title, $match)) {
643  $max = max($match[1], $max);
644  }
645  }
646  if ($max) {
647  $title .= " (" . ($max + 1) . ")";
648  } else {
649  $title .= " (2)";
650  }
651  $titles[] = $title;
652  $question->setTitle($title);
653 
654  $question->id = -1;
655  $question->saveToDb();
656 
657  $question_pointer[$qid] = $question->getId();
658  $this->appendNewQuestionToSurvey($question->getId(), false);
659  }
660 
661  // copy textblocks
662  $this->object->cloneTextblocks($question_pointer);
663 
664  $this->object->loadQuestionsFromDb();
665 
666  $nodes = array_values($question_pointer);
667  }
668 
669 
670  // paste
671 
672  // create new block
673  if (count($target) === 1) {
674  $nodes = array_merge(array($a_id), $nodes);
675 
676  // moveQuestions() is called within
677  $this->object->createQuestionblock(
678  $this->getAutoBlockTitle(),
679  true,
680  false,
681  $nodes
682  );
683  }
684  // add to existing block
685  else {
686  $target_block_id = $target;
687  $target_block_id = array_shift($target_block_id);
688  $target_block_id = $target_block_id["questionblock_id"];
689 
690  foreach ($nodes as $qid) {
691  $this->object->addQuestionToBlock($qid, $target_block_id);
692  }
693 
694  // move to new position
695  $this->object->moveQuestions($nodes, $a_id, $pos);
696  }
697 
698  $this->clearClipboard();
699  }
700 
704  protected function dnd(): void
705  {
706  $source_arr = explode("_", $this->svy_request->getHForm("source"));
707  $target_arr = explode("_", $this->svy_request->getHForm("target"));
708  $source_id = (int) array_pop($source_arr);
709  if ($this->svy_request->getHForm("target") !== "droparea_end") {
710  $target_id = (int) array_pop($target_arr);
711  $pos = 0;
712  } else {
713  $page = $this->object->getSurveyPages();
714  $page = $page[$this->current_page - 1];
715  $last = array_pop($page);
716  $target_id = (int) $last["question_id"];
717  $pos = 1;
718  }
719  if ($source_id !== $target_id) {
720  $this->object->moveQuestions(array($source_id), $target_id, $pos);
721  }
722  }
723 
727  protected function deleteBlock(): void
728  {
729  $lng = $this->lng;
730  $ilCtrl = $this->ctrl;
731 
732  $ilCtrl->setParameter($this->editor_gui, "pgov", $this->current_page);
733  $this->tpl->setOnScreenMessage('question', $lng->txt("remove_questions"));
734 
735  $page = $this->object->getSurveyPages();
736  $page = $page[$this->current_page - 1];
737 
738  // #10567
739  if ($this->svy_request->getCheckSum() !== md5(print_r($page, true))) {
740  $ilCtrl->redirect($this, "renderPage");
741  }
742 
743  $page = array_shift($page);
744  $block_id = $page["questionblock_id"];
745  if ($block_id) {
746  $this->editor_gui->removeQuestionsForm(array($block_id), array(), array());
747  } else {
748  $this->editor_gui->removeQuestionsForm(array(), array($page["question_id"]), array());
749  }
750  }
751 
758  protected function deleteQuestion(array $a_id): void
759  {
760  $ilCtrl = $this->ctrl;
761  $ilCtrl->setParameter($this->editor_gui, "pgov", $this->current_page);
762  $this->editor_gui->removeQuestionsForm(array(), $a_id, array());
763  }
764 
768  protected function confirmRemoveQuestions(): void
769  {
770  $ilCtrl = $this->ctrl;
771  $ids = $this->svy_request->getQuestionIds();
772 
773  $pages = $this->object->getSurveyPages();
774  $source = $pages[$this->current_page - 1];
775 
776  $block_id = $source;
777  $block_id = array_shift($block_id);
778  $block_id = $block_id["questionblock_id"];
779 
780  if (count($ids) && count($source) > count($ids)) {
781  // block is obsolete
782  if (count($source) - count($ids) === 1) {
783  $this->object->unfoldQuestionblocks(array($block_id));
784  }
785  // block will remain, remove question(s) from block
786  else {
787  foreach ($ids as $qid) {
788  $this->object->removeQuestionFromBlock($qid, $block_id);
789  }
790  }
791 
792  $this->object->removeQuestions($ids, array());
793  }
794  // all items on page
795  else {
796  // remove complete block
797  if ($block_id) {
798  $this->object->removeQuestions(array(), array($block_id));
799  }
800  // remove single question
801  else {
802  $this->object->removeQuestions($ids, array());
803  }
804 
805  // render previous page
806  if ($this->current_page > 1) {
807  $this->current_page--;
808  }
809  }
810 
811  $this->object->saveCompletionStatus();
812 
813  // #10567
814  $ilCtrl->setParameter($this, "pgov", $this->current_page);
815  $ilCtrl->redirect($this, "renderPage");
816  }
817 
821  protected function editBlock(int $a_id): void
822  {
823  $this->callEditor("editQuestionblock", "bl_id", $a_id);
824  }
825 
829  protected function addHeading(int $a_id): void
830  {
831  $this->callEditor("addHeading", "q_id", $a_id);
832  }
833 
837  protected function editHeading(int $a_id): void
838  {
839  $this->callEditor("editHeadingObject", "q_id", $a_id);
840  }
841 
845  protected function deleteHeading(int $a_id): void
846  {
847  $this->callEditor("removeHeading", "q_id", $a_id);
848  }
849 
850  protected function callEditor(
851  string $a_cmd,
852  string $a_param,
853  string $a_value
854  ): void {
855  $ilTabs = $this->tabs;
856 
857  $ilTabs->clearSubTabs();
858  $ctrl = $this->ctrl;
859 
860  $ctrl->setParameter($this->editor_gui, $a_param, $a_value);
861  $ctrl->redirect($this->editor_gui, $a_cmd);
862 
863  //$_REQUEST[$a_param] = $a_value;
864  //call_user_func(array($this->editor_gui, $a_cmd));
865  }
866 
870  protected function splitPage(
871  int $a_id
872  ): void {
873  $pages = $this->object->getSurveyPages();
874  $source = $pages[$this->current_page - 1];
875 
876  $block_questions = array();
877  $add = $block_id = false;
878  foreach ($source as $idx => $item) {
879  if ($item["question_id"] == $a_id) {
880  $block_id = $item["questionblock_id"];
881  $add = $idx;
882  }
883  if ($add) {
884  $block_questions[] = $item["question_id"];
885  }
886  }
887 
888  // just 1 question left: block is obsolete
889  if ($add === 1) {
890  $this->object->unfoldQuestionblocks(array($block_id));
891  }
892  // remove questions from block
893  else {
894  foreach ($block_questions as $qid) {
895  $this->object->removeQuestionFromBlock($qid, $block_id);
896  }
897  }
898 
899  // more than 1 moved?
900  if (count($block_questions) > 1) {
901  // create new block and move target questions
902  $this->object->createQuestionblock(
903  $this->getAutoBlockTitle(),
904  true,
905  false,
906  $block_questions
907  );
908  }
909 
910  $this->current_page++;
911  }
912 
916  protected function moveNext(int $a_id): void
917  {
918  $pages = $this->object->getSurveyPages();
919  $source = $pages[$this->current_page - 1];
920  $target = $pages[$this->current_page];
921  if (count($target)) {
922  $target_id = $target;
923  $target_id = array_shift($target_id);
924  $target_block_id = $target_id["questionblock_id"];
925  $target_id = $target_id["question_id"];
926 
927  // nothing to do if no block
928  if (count($source) > 1) {
929  $block_id = $source;
930  $block_id = array_shift($block_id);
931  $block_id = $block_id["questionblock_id"];
932 
933  // source pages block is obsolete
934  if (count($source) === 2) {
935  // delete block
936  $this->object->unfoldQuestionblocks(array($block_id));
937  } else {
938  // remove question from block
939  $this->object->removeQuestionFromBlock($a_id, $block_id);
940  }
941  }
942 
943  // move source question to target
944  $this->object->moveQuestions(array($a_id), $target_id, 0);
945 
946  // new page has no block yet
947  if (count($target) < 2) {
948  // create block and move target question and source into block
949  $this->object->createQuestionblock(
950  $this->getAutoBlockTitle(),
951  true,
952  false,
953  array($a_id, $target_id)
954  );
955  } else {
956  // add source question to block
957  $this->object->addQuestionToBlock($a_id, $target_block_id);
958  }
959 
960  // only if current page is not "deleted"
961  if (count($source) > 1) {
962  $this->current_page++;
963  }
964  }
965  }
966 
970  protected function movePrevious(
971  int $a_id
972  ): void {
973  $pages = $this->object->getSurveyPages();
974  $source = $pages[$this->current_page - 1];
975  $target = $pages[$this->current_page - 2];
976  if (count($target)) {
977  $target_id = $target;
978  $target_id = array_pop($target_id);
979  $target_block_id = $target_id["questionblock_id"];
980  $target_id = $target_id["question_id"];
981 
982  // nothing to do if no block
983  if (count($source) > 1) {
984  $block_id = $source;
985  $block_id = array_shift($block_id);
986  $block_id = $block_id["questionblock_id"];
987 
988  // source pages block is obsolete
989  if (count($source) === 2) {
990  // delete block
991  $this->object->unfoldQuestionblocks(array($block_id));
992  } else {
993  // remove question from block
994  $this->object->removeQuestionFromBlock($a_id, $block_id);
995  }
996  }
997 
998  // move source question to target
999  $this->object->moveQuestions(array($a_id), $target_id, 1);
1000 
1001  // new page has no block yet
1002  if (count($target) < 2) {
1003  // create block and move target question and source into block
1004  $this->object->createQuestionblock(
1005  $this->getAutoBlockTitle(),
1006  true,
1007  false,
1008  array($target_id, $a_id)
1009  );
1010  } else {
1011  // add source question to block
1012  $this->object->addQuestionToBlock($a_id, $target_block_id);
1013  }
1014 
1015  $this->current_page--;
1016  }
1017  }
1018 
1019  protected function editQuestion(int $a_id): void
1020  {
1021  $ilCtrl = $this->ctrl;
1022 
1023  $data = $this->object->getSurveyQuestions();
1024  $data = $data[$a_id];
1025 
1026  $q_gui = $data["type_tag"] . "GUI";
1027  $ilCtrl->setParameterByClass($q_gui, "pgov", $this->current_page);
1028  $ilCtrl->setParameterByClass($q_gui, "q_id", $a_id);
1029 
1030  $ilCtrl->redirectByClass($q_gui, "editQuestion");
1031  }
1032 
1036  protected function addQuestionToolbarForm(): void
1037  {
1038  $lng = $this->lng;
1039  $ilCtrl = $this->ctrl;
1040  $tpl = $this->tpl;
1041 
1042  $form = new ilPropertyFormGUI();
1043  $form->setFormAction($ilCtrl->getFormAction($this, "addQuestionToolbar"));
1044  $form->setTitle($lng->txt("survey_add_new_question"));
1045 
1046  // question types
1047  $questiontypes = ilObjSurveyQuestionPool::_getQuestiontypes();
1048  $type_map = array();
1049  foreach ($questiontypes as $trans => $item) {
1050  $type_map[$item["questiontype_id"]] = $trans;
1051  }
1052  $si = new ilSelectInputGUI($lng->txt("question_type"), "qtype");
1053  $si->setOptions($type_map);
1054  $form->addItem($si);
1055 
1056  $pages = $this->object->getSurveyPages();
1057  if ($pages) {
1058  $pages_drop = array("fst" => $lng->txt("survey_at_beginning"));
1059  foreach ($pages as $idx => $questions) {
1060  $question = array_shift($questions);
1061  if ($question["questionblock_id"]) {
1062  $pages_drop[$idx + 1] = $lng->txt("survey_behind_page") . " " . $question["questionblock_title"];
1063  } else {
1064  $pages_drop[$idx + 1] = $lng->txt("survey_behind_page") . " " . strip_tags($question["title"]);
1065  }
1066  }
1067  $pos = new ilSelectInputGUI($lng->txt("position"), "pgov");
1068  $pos->setOptions($pages_drop);
1069  $form->addItem($pos);
1070 
1071  $pos->setValue($this->current_page);
1072  } else {
1073  // #9089: 1st page
1074  $pos = new ilHiddenInputGUI("pgov");
1075  $pos->setValue("fst");
1076  $form->addItem($pos);
1077  }
1078 
1079  if ($this->object->getPoolUsage()) {
1080  $this->editor_gui->createQuestionObject($form);
1081  }
1082 
1083  $form->addCommandButton("addQuestionToolbar", $lng->txt("create"));
1084  $form->addCommandButton("renderPage", $lng->txt("cancel"));
1085 
1086  $tpl->setContent($form->getHTML());
1087  }
1088 
1092  protected function addQuestionToolbar(): void
1093  {
1094  $ilCtrl = $this->ctrl;
1095  $lng = $this->lng;
1096 
1097  $pool_active = $this->object->getPoolUsage();
1098 
1099  if ($this->svy_request->getPoolUsage() === 0 && $pool_active) {
1100  $this->tpl->setOnScreenMessage('failure', $lng->txt("select_one"), true);
1101  $this->addQuestionToolbarForm();
1102  return;
1103  }
1104 
1105  // make sure that it is set for current and next requests
1106  $ilCtrl->setParameter($this->editor_gui, "pgov", $this->current_page);
1107  if (!$this->addQuestion(
1108  $this->svy_request->getQuestionType(),
1109  $pool_active,
1110  $this->pgov,
1111  "toolbar"
1112  )) {
1113  $this->renderPage();
1114  }
1115  }
1116 
1120  protected function movePageForm(): void
1121  {
1122  $lng = $this->lng;
1123  $ilCtrl = $this->ctrl;
1124  $tpl = $this->tpl;
1125 
1126  $form = new ilPropertyFormGUI();
1127  $form->setFormAction($ilCtrl->getFormAction($this, "movePage"));
1128  $form->setTitle($lng->txt("survey_move_page"));
1129 
1130  $old_pos = new ilHiddenInputGUI("old_pos");
1131  $old_pos->setValue($this->current_page);
1132  $form->addItem($old_pos);
1133 
1134  $pages = $this->object->getSurveyPages();
1135  if ($pages) {
1136  $pages_drop = array();
1137  if ((int) $this->current_page !== 1) {
1138  $pages_drop["fst"] = $lng->txt("survey_at_beginning");
1139  }
1140  foreach ($pages as $idx => $questions) {
1141  if (($idx + 1) != $this->current_page && ($idx + 2) != $this->current_page) {
1142  $question = array_shift($questions);
1143  if ($question["questionblock_id"]) {
1144  $pages_drop[$idx + 1] = $lng->txt("survey_behind_page") . " " . $question["questionblock_title"];
1145  } else {
1146  $pages_drop[$idx + 1] = $lng->txt("survey_behind_page") . " " . strip_tags($question["title"]);
1147  }
1148  }
1149  }
1150  $pos = new ilSelectInputGUI($lng->txt("position"), "pgov");
1151  $pos->setOptions($pages_drop);
1152  $form->addItem($pos);
1153  }
1154 
1155  $form->addCommandButton("movePage", $lng->txt("submit"));
1156  $form->addCommandButton("renderPage", $lng->txt("cancel"));
1157 
1158  $tpl->setContent($form->getHTML());
1159  }
1160 
1165  protected function movePage(): void
1166  {
1167  $lng = $this->lng;
1168  $ilCtrl = $this->ctrl;
1169 
1170  $questions = [];
1171 
1172  // current_page is already set to new position
1173  $target_page = $this->current_page - 1;
1174  $source_page = $this->svy_request->getOldPosition() - 1;
1175 
1176  $pages = $this->object->getSurveyPages();
1177  foreach ($pages[$source_page] as $question) {
1178  $questions[] = $question["question_id"];
1179  }
1180 
1181  // move to first position
1182  $position = 0;
1183  if ($this->pgov !== "fst") {
1184  $position = 1;
1185  }
1186 
1187  $target = $pages[$target_page];
1188  if ($position === 0) { // before
1189  $target = array_shift($target); // ... use always the first question of the page
1190  } else { // after
1191  $target = array_pop($target); // ... use always the last question of the page
1192  }
1193  $this->object->moveQuestions($questions, $target["question_id"], $position);
1194 
1195  if ($target_page < $source_page && $position) {
1196  $this->current_page++;
1197  }
1198 
1199  $this->tpl->setOnScreenMessage('success', $lng->txt("survey_page_moved"), true);
1200  $ilCtrl->setParameter($this, "pgov", $this->current_page);
1201  $ilCtrl->redirect($this, "renderPage");
1202  }
1203 
1207  protected function renderToolbar(?array $a_pages): void
1208  {
1209  $ilToolbar = $this->toolbar;
1210  $ilCtrl = $this->ctrl;
1211  $lng = $this->lng;
1212  $ilUser = $this->user;
1213  $pages_drop = null;
1214 
1215  if (!$this->has_datasets) {
1216  $button = ilLinkButton::getInstance();
1217  $button->setCaption("survey_add_new_question");
1218  $button->setUrl($ilCtrl->getLinkTarget($this, "addQuestionToolbarForm"));
1219  $ilToolbar->addStickyItem($button);
1220 
1221  if ($this->object->getPoolUsage()) {
1222  //$ilToolbar->addSeparator();
1223 
1224  $last_on_page = 0;
1225  if ($a_pages &&
1226  isset($a_pages[$this->current_page - 1])) {
1227  $last_on_page = $a_pages[$this->current_page - 1];
1228  $last_on_page = array_pop($last_on_page);
1229  $last_on_page = $last_on_page["question_id"];
1230  }
1231 
1232  $ilCtrl->setParameter($this->editor_gui, "pgov", $this->current_page);
1233  $ilCtrl->setParameter($this->editor_gui, "pgov_pos", $last_on_page . "c");
1234 
1235  $cmd = ((int) $ilUser->getPref('svy_insert_type') === 1 ||
1236  ($ilUser->getPref('svy_insert_type') ?? '') === '')
1237  ? 'browseForQuestions'
1238  : 'browseForQuestionblocks';
1239 
1240  $button = ilLinkButton::getInstance();
1241  $button->setCaption("browse_for_questions");
1242  $button->setUrl($ilCtrl->getLinkTarget($this->editor_gui, $cmd));
1243  $ilToolbar->addStickyItem($button);
1244 
1245  $ilCtrl->setParameter($this->editor_gui, "pgov", "");
1246  $ilCtrl->setParameter($this->editor_gui, "pgov_pos", "");
1247  }
1248 
1249  if ($a_pages) {
1250 // $ilToolbar->addSeparator();
1251  }
1252  }
1253 
1254  // parse data for pages drop-down
1255  if ($a_pages) {
1256  // previous/next
1257 
1258  $ilCtrl->setParameter($this, "pg", $this->current_page - 1);
1259  $button = ilLinkButton::getInstance();
1260  $button->setCaption("survey_prev_question");
1261  if ($this->has_previous_page) {
1262  $button->setUrl($ilCtrl->getLinkTarget($this, "renderPage"));
1263  }
1264  $button->setDisabled(!$this->has_previous_page);
1265  $ilToolbar->addStickyItem($button);
1266 
1267  $ilCtrl->setParameter($this, "pg", (string) ((int) $this->current_page + 1));
1268  $button = ilLinkButton::getInstance();
1269  $button->setCaption("survey_next_question");
1270  if ($this->has_next_page) {
1271  $button->setUrl($ilCtrl->getLinkTarget($this, "renderPage"));
1272  }
1273  $button->setDisabled(!$this->has_next_page);
1274  $ilToolbar->addStickyItem($button);
1275 
1276  $ilCtrl->setParameter($this, "pg", $this->current_page); // #14615
1277 
1278  foreach ($a_pages as $idx => $questions) {
1279  $page = $questions;
1280  $page = array_shift($page);
1281  if ($page["questionblock_id"]) {
1282  $pages_drop[$idx + 1] = $page["questionblock_title"];
1283 
1284  if (count($questions) > 1) {
1285  foreach ($questions as $question) {
1286  $pages_drop[($idx + 1) . "__" . $question["question_id"]] = "- " . $question["title"];
1287  }
1288  }
1289  } else {
1290  $pages_drop[$idx + 1] = strip_tags($page["title"]);
1291  }
1292  }
1293  }
1294 
1295  // jump to page
1296  if (is_array($pages_drop) && count($pages_drop) > 1) {
1297  //$ilToolbar->addSeparator();
1298 
1299  $ilToolbar->setFormAction($ilCtrl->getFormAction($this));
1300 
1301  $si = new ilSelectInputGUI($lng->txt("survey_jump_to"), "jump");
1302  $si->addCustomAttribute("onChange=\"forms['ilToolbar'].submit();\"");
1303  $si->setOptions($pages_drop);
1304  $si->setValue($this->current_page);
1305  $ilToolbar->addInputItem($si, true);
1306 
1307  // we need this to have to right cmd
1308  $cmd = new ilHiddenInputGUI("cmd[renderPage]");
1309  $cmd->setValue("1");
1310  $ilToolbar->addInputItem($cmd);
1311 
1312  if (!$this->has_datasets) {
1313  $ilToolbar->addSeparator();
1314 
1315  $ilCtrl->setParameter($this, "csum", md5(print_r($a_pages[$this->current_page - 1], true)));
1316  $url = $ilCtrl->getLinkTarget($this, "deleteBlock");
1317  $ilCtrl->setParameter($this, "csum", "");
1318 
1319  $button = ilLinkButton::getInstance();
1320  $button->setCaption("survey_delete_page");
1321  $button->setUrl($url);
1322  $ilToolbar->addButtonInstance($button);
1323 
1324  $ilToolbar->addSeparator();
1325 
1326  $button = ilLinkButton::getInstance();
1327  $button->setCaption("survey_move_page");
1328  $button->setUrl($ilCtrl->getLinkTarget($this, "movePageForm"));
1329  $ilToolbar->addButtonInstance($button);
1330  }
1331  }
1332 
1333  // print view
1334  if (is_array($pages_drop)) {
1335  $ilToolbar->addSeparator();
1336  $print_view = $this->print->page($this->ref_id);
1337  $modal_elements = $print_view->getModalElements(
1338  $this->ctrl->getLinkTarget(
1339  $this,
1340  "printViewSelection"
1341  )
1342  );
1343  $ilToolbar->addComponent($modal_elements->button);
1344  $ilToolbar->addComponent($modal_elements->modal);
1345  }
1346  }
1347 
1351  protected function renderPage(): void
1352  {
1353  $ilCtrl = $this->ctrl;
1354  $lng = $this->lng;
1355  $tpl = $this->tpl;
1356  $rbacsystem = $this->rbacsystem;
1357 
1358  $pages = $this->object->getSurveyPages();
1359  $this->has_next_page = ($this->current_page < count($pages));
1360  $this->has_previous_page = ($this->current_page > 1);
1361  $this->has_datasets = ilObjSurvey::_hasDatasets($this->object->getSurveyId());
1362 
1363  $mess = "";
1364  if ($this->has_datasets) {
1365  $mbox = new ilSurveyContainsDataMessageBoxGUI();
1366  $mess = $mbox->getHTML();
1367  }
1368 
1369  $ilCtrl->setParameter($this, "pg", $this->current_page);
1370  $ilCtrl->setParameter($this, "pgov", "");
1371 
1372  $this->renderToolbar($pages);
1373  if ($pages) {
1374  $ttpl = new ilTemplate("tpl.il_svy_svy_page_view.html", true, true, "Modules/Survey");
1375  $tpl->addOnLoadCode("ilSurveyPageView.init();");
1376  $ttpl->setVariable("FORM_ACTION", $ilCtrl->getFormAction($this));
1377  $lng->loadLanguageModule("form");
1378 
1379  $read_only = ($this->has_datasets || !$rbacsystem->checkAccess("write", $this->ref_id));
1380 
1381  $commands = $multi_commands = array();
1382 
1383  if (!$read_only) {
1384  // clipboard is empty
1385  if ($this->edit_manager->isQuestionClipboardEmpty($this->ref_id)) {
1386  $multi_commands[] = array("cmd" => "multiDelete", "text" => $lng->txt("delete"));
1387  $multi_commands[] = array("cmd" => "multiCut", "text" => $lng->txt("cut"));
1388  $multi_commands[] = array("cmd" => "multiCopy", "text" => $lng->txt("copy"));
1389  $multi_commands[] = array("cmd" => "selectAll", "text" => $lng->txt("select_all"));
1390  } else {
1391  if (!$this->suppress_clipboard_msg) {
1392  $this->tpl->setOnScreenMessage('info', $lng->txt("survey_clipboard_notice"));
1393  }
1394  $multi_commands[] = array("cmd" => "clearClipboard", "text" => $lng->txt("survey_dnd_clear_clipboard"));
1395  }
1396 
1397  // help - see ilPageObjectGUI::insertHelp()
1398  $lng->loadLanguageModule("content");
1399  $ttpl->setCurrentBlock("help_section");
1400  $ttpl->setVariable("TXT_ADD_EL", $lng->txt("cont_add_elements"));
1401  $ttpl->setVariable("PLUS", ilGlyphGUI::get(ilGlyphGUI::ADD));
1402  $ttpl->setVariable("DRAG_ARROW", ilGlyphGUI::get(ilGlyphGUI::DRAG));
1403  $ttpl->setVariable("TXT_DRAG", $lng->txt("cont_drag_and_drop_elements"));
1404  $ttpl->setVariable("TXT_SEL", $lng->txt("cont_double_click_to_delete"));
1405  $ttpl->parseCurrentBlock();
1406 
1407  $ttpl->setVariable("DND_INIT_JS", "initDragElements();");
1408 
1409 
1410  // tiny mce
1411 
1412  $tags = ilObjAdvancedEditing::_getUsedHTMLTags("survey");
1413 
1420  $tiny = new ilTinyMCE();
1421  $ttpl->setVariable("WYSIWYG_BLOCKFORMATS", $tiny->_buildAdvancedBlockformatsFromHTMLTags($tags));
1422  $ttpl->setVariable("WYSIWYG_VALID_ELEMENTS", $tiny->_getValidElementsFromHTMLTags($tags));
1423 
1424  $buttons_1 = $tiny->_buildAdvancedButtonsFromHTMLTags(1, $tags);
1425  $buttons_2 = $tiny->_buildAdvancedButtonsFromHTMLTags(2, $tags) . ',' .
1426  $tiny->_buildAdvancedTableButtonsFromHTMLTags($tags) .
1427  ($tiny->getStyleSelect() ? ',styleselect' : '');
1428  $buttons_3 = $tiny->_buildAdvancedButtonsFromHTMLTags(3, $tags);
1429  $ttpl->setVariable('WYSIWYG_BUTTONS_1', ilTinyMCE::removeRedundantSeparators($buttons_1));
1430  $ttpl->setVariable('WYSIWYG_BUTTONS_2', ilTinyMCE::removeRedundantSeparators($buttons_2));
1431  $ttpl->setVariable('WYSIWYG_BUTTONS_3', ilTinyMCE::removeRedundantSeparators($buttons_3));
1432  }
1433 
1434  // commands
1435  if (count($multi_commands) > 0) {
1436  foreach ($multi_commands as $cmd) {
1437  $ttpl->setCurrentBlock("multi_cmd");
1438  $ttpl->setVariable("ORG_CMD_MULTI", "renderPage");
1439  $ttpl->setVariable("MULTI_CMD", $cmd["cmd"]);
1440  $ttpl->setVariable("MULTI_CMD_TXT", $cmd["text"]);
1441  $ttpl->parseCurrentBlock();
1442  }
1443 
1444  $ttpl->setCurrentBlock("multi_cmds");
1445  $ttpl->setVariable("MCMD_ALT", $lng->txt("commands"));
1446  $ttpl->setVariable("MCMD_IMG", ilUtil::getImagePath("arrow_downright.svg"));
1447  $ttpl->parseCurrentBlock();
1448  }
1449 
1450  // nodes
1451  $ttpl->setVariable("NODES", $this->getPageNodes(
1452  $pages[$this->current_page - 1] ?? [],
1453  $this->has_previous_page,
1454  $this->has_next_page,
1455  $read_only
1456  ));
1457 
1458  $tpl->setContent($mess . $ttpl->get());
1459 
1460  // add js to template
1462  $tpl->addJavaScript("./Modules/Survey/js/SurveyPageView.js");
1463  }
1464  }
1465 
1470  public function getPageNodes(
1471  array $a_questions,
1472  bool $a_has_previous_page = false,
1473  bool $a_has_next_page = false,
1474  bool $a_readonly = false
1475  ): string {
1476  $ilCtrl = $this->ctrl;
1477  $lng = $this->lng;
1478 
1479  $ttpl = new ilTemplate("tpl.il_svy_svy_page_view_nodes.html", true, true, "Modules/Survey");
1480 
1481  $has_clipboard = !$this->edit_manager->isQuestionClipboardEmpty($this->ref_id);
1482 
1483  // question block ?
1484 
1485  $first_question = $a_questions;
1486  $first_question = array_shift($first_question);
1487 
1488  $compress_view = false;
1489  if ($first_question["questionblock_id"] ?? false) {
1490  $menu = array();
1491 
1492  if (!$a_readonly && !$has_clipboard) {
1493  $menu[] = array("cmd" => "editBlock", "text" => $lng->txt("edit"));
1494  }
1495 
1496  if ($first_question["questionblock_show_blocktitle"]) {
1497  $block_status = $lng->txt("survey_block_visible");
1498  } else {
1499  $block_status = $lng->txt("survey_block_hidden");
1500  }
1501 
1502  $this->renderPageNode(
1503  $ttpl,
1504  "block",
1505  $first_question["questionblock_id"],
1506  $first_question["questionblock_title"] . " (" . $block_status . ")",
1507  $menu,
1508  false,
1509  false,
1510  $block_status
1511  );
1512 
1513  if (count($a_questions) > 1) {
1514  $compress_view = $first_question["questionblock_compress_view"];
1515  }
1516  }
1517 
1518 
1519  // questions/headings
1520 
1521  $questiontypes = ilObjSurveyQuestionPool::_getQuestiontypes();
1522  foreach ($a_questions as $idx => $question) {
1523  // drop area
1524 
1525  $menu = array();
1526 
1527  if (!$a_readonly) {
1528  if (!$has_clipboard) {
1529  foreach ($questiontypes as $trans => $item) {
1530  $menu[] = array("cmd" => "addQuestion_" . $item["questiontype_id"],
1531  "text" => sprintf($lng->txt("svy_page_add_question"), $trans));
1532  }
1533 
1534  if ($this->object->getPoolUsage()) {
1535  $menu[] = array("cmd" => "addPoolQuestion",
1536  "text" => $lng->txt("browse_for_questions"));
1537  }
1538  } else {
1539  $menu[] = array("cmd" => "paste", "text" => $lng->txt("survey_dnd_paste"));
1540  }
1541  }
1542 
1543  $this->renderPageNode($ttpl, "droparea", $question["question_id"], null, $menu, true);
1544 
1545  // question
1546  $question_gui = $this->object->getQuestionGUI($question["type_tag"], $question["question_id"]);
1547  $question_form = $question_gui->getWorkingForm(
1548  array(),
1549  $this->object->getShowQuestionTitles(),
1550  $question["questionblock_show_questiontext"],
1551  "",
1552  $this->object->getSurveyId(),
1553  $compress_view
1554  );
1555 
1556  $menu = array();
1557 
1558  if (!$a_readonly && !$has_clipboard) {
1559  $menu[] = array("cmd" => "editQuestion", "text" => $lng->txt("edit"));
1560  $menu[] = array("cmd" => "cutQuestion", "text" => $lng->txt("cut"));
1561  $menu[] = array("cmd" => "copyQuestion", "text" => $lng->txt("copy"));
1562 
1563  if (count($a_questions) > 1 && $idx > 0) {
1564  $menu[] = array("cmd" => "splitPage", "text" => $lng->txt("survey_dnd_split_page"));
1565  }
1566  if ($a_has_next_page) {
1567  $menu[] = array("cmd" => "moveNext", "text" => $lng->txt("survey_dnd_move_next"));
1568  }
1569  if ($a_has_previous_page) {
1570  $menu[] = array("cmd" => "movePrevious", "text" => $lng->txt("survey_dnd_move_previous"));
1571  }
1572 
1573  $menu[] = array("cmd" => "deleteQuestion", "text" => $lng->txt("delete"));
1574 
1575  // heading
1576  if ($question["heading"]) {
1577  $menu[] = array("cmd" => "editHeading", "text" => $lng->txt("survey_edit_heading"));
1578  $menu[] = array("cmd" => "deleteHeading", "text" => $lng->txt("survey_delete_heading"));
1579  } else {
1580  $menu[] = array("cmd" => "addHeading", "text" => $lng->txt("add_heading"));
1581  }
1582  }
1583 
1584  if ($first_question["questionblock_show_questiontext"]) {
1585  $question_title_status = $lng->txt("survey_question_text_visible");
1586  } else {
1587  $question_title_status = $lng->txt("survey_question_text_hidden");
1588  }
1589 
1590  $this->renderPageNode(
1591  $ttpl,
1592  "question",
1593  $question["question_id"],
1594  $question_form,
1595  $menu,
1596  false,
1597  $question["title"],
1598  $question_title_status,
1599  $question["heading"]
1600  );
1601 
1602  $ilCtrl->setParameter($this, "eqid", "");
1603  }
1604 
1605 
1606  // last position (no question id)
1607 
1608  $menu = array();
1609 
1610  if (!$a_readonly) {
1611  if (!$has_clipboard) {
1612  foreach ($questiontypes as $trans => $item) {
1613  $menu[] = array("cmd" => "addQuestion_" . $item["questiontype_id"],
1614  "text" => sprintf($lng->txt("svy_page_add_question"), $trans));
1615  }
1616 
1617  if ($this->object->getPoolUsage()) {
1618  $menu[] = array("cmd" => "addPoolQuestion",
1619  "text" => $lng->txt("browse_for_questions"));
1620  }
1621  } else {
1622  $menu[] = array("cmd" => "paste", "text" => $lng->txt("survey_dnd_paste"));
1623  }
1624  }
1625 
1626  $this->renderPageNode($ttpl, "page", "end", null, $menu, true);
1627 
1628  return $ttpl->get();
1629  }
1630 
1634  public function renderPageNode(
1635  ilTemplate $a_tpl,
1636  string $a_type,
1637  string $a_id,
1638  ?string $a_content = null,
1639  ?array $a_menu = null,
1640  bool $a_spacer = false,
1641  string $a_subtitle = "",
1642  ?string $a_status = null,
1643  ?string $a_heading = null
1644  ): void {
1645  $ilCtrl = $this->ctrl;
1646  $lng = $this->lng;
1647 
1648  $node_id = $a_type . "_" . $a_id;
1649 
1650  if ($a_spacer) {
1651  if ($a_menu) {
1652  // drop area menu
1653  foreach ($a_menu as $mcnt => $menu_item) {
1654  $ilCtrl->setParameter($this, "il_hform_node", $node_id);
1655  $ilCtrl->setParameter($this, "il_hform_subcmd", $menu_item["cmd"]);
1656  $url = $ilCtrl->getLinkTarget($this, "renderPage");
1657  $ilCtrl->setParameter($this, "il_hform_subcmd", "");
1658  $ilCtrl->setParameter($this, "il_hform_node", "");
1659 
1660  $a_tpl->setCurrentBlock("menu_cmd");
1661  $a_tpl->setVariable("TXT_MENU_CMD", $menu_item["text"]);
1662  $a_tpl->setVariable("URL_MENU_CMD", $url);
1663  $a_tpl->parseCurrentBlock();
1664  }
1665  }
1666 
1667  $a_tpl->setCurrentBlock("drop_area");
1668  $a_tpl->setVariable("ICON_ADD", ilGlyphGUI::get(ilGlyphGUI::ADD));
1669  $a_tpl->setVariable("DROP_ID", $a_id);
1670  $a_tpl->parseCurrentBlock();
1671  } elseif ($a_menu) {
1672  // question action menu
1673  foreach ($a_menu as $mcnt => $menu_item) {
1674  $ilCtrl->setParameter($this, "il_hform_node", $node_id);
1675  $ilCtrl->setParameter($this, "il_hform_subcmd", $menu_item["cmd"]);
1676  $url = $ilCtrl->getLinkTarget($this, "renderPage");
1677  $ilCtrl->setParameter($this, "il_hform_subcmd", "");
1678  $ilCtrl->setParameter($this, "il_hform_node", "");
1679 
1680  $a_tpl->setCurrentBlock("action_cmd");
1681  $a_tpl->setVariable("TXT_ACTION_CMD", $menu_item["text"]);
1682  $a_tpl->setVariable("URL_ACTION_CMD", $url);
1683  $a_tpl->parseCurrentBlock();
1684  }
1685  }
1686 
1687  // add heading to content
1688  if ($a_content !== null &&
1689  $a_type === "question" &&
1690  $a_heading) {
1691  $a_content = "<div class=\"questionheading\">" . $a_heading . "</div>" .
1692  $a_content;
1693  }
1694 
1695  if ($a_menu) {
1696  $a_tpl->setVariable("TXT_NODE_CONTENT_ACTIONS", $a_content);
1697  } else {
1698  $a_tpl->setVariable("TXT_NODE_CONTENT_NO_ACTIONS", $a_content);
1699  }
1700 
1701  if ($a_content !== null) {
1702  $drag = "";
1703  $selectable = false;
1704  switch ($a_type) {
1705  case "block":
1706  $caption = $lng->txt("questionblock");
1707  break;
1708 
1709  case "question":
1710  $caption = $lng->txt("question") . ": " . $a_subtitle;
1711  $drag = "_drag";
1712  $selectable = true;
1713  break;
1714 
1715  case "heading":
1716  $caption = $lng->txt("heading");
1717  break;
1718 
1719  default:
1720  return;
1721  }
1722 
1723  if ($a_status) {
1724  $caption .= " (" . $a_status . ")";
1725  }
1726 
1727  $a_tpl->setCurrentBlock("list_item");
1728  $a_tpl->setVariable("NODE_ID", $node_id);
1729  $a_tpl->setVariable("NODE_DRAG", $drag);
1730  $a_tpl->setVariable("TXT_NODE_TYPE", $caption);
1731  if ($selectable) {
1732  $a_tpl->setVariable("SELECTABLE", " selectable");
1733  }
1734  $a_tpl->parseCurrentBlock();
1735  }
1736 
1737  $a_tpl->touchBlock("element");
1738  }
1739 
1743  public function getAutoBlockTitle(): string
1744  {
1745  $lng = $this->lng;
1746  return $lng->txt("survey_auto_block_title");
1747  }
1748 
1749  public function addPoolQuestion(
1750  string $pos,
1751  string $node
1752  ): void {
1753  $ilCtrl = $this->ctrl;
1754  $ilUser = $this->user;
1755 
1756  if ($node === "page_end") {
1757  $pages = $this->object->getSurveyPages();
1758  $page = array_pop($pages[$this->current_page - 1]);
1759  $pos = $page["question_id"] . "a";
1760  } else {
1761  $pos .= "b";
1762  }
1763 
1764  $ilCtrl->setParameter($this->editor_gui, "pgov", $this->current_page);
1765  $ilCtrl->setParameter($this->editor_gui, "pgov_pos", $pos);
1766 
1767  $cmd = ((int) $ilUser->getPref('svy_insert_type') === 1 || ($ilUser->getPref('svy_insert_type') ?? '') === '') ? 'browseForQuestions' : 'browseForQuestionblocks';
1768  $ilCtrl->redirect($this->editor_gui, $cmd);
1769  }
1770 
1771  public function printViewSelection(): void
1772  {
1773  $view = $this->print->page($this->ref_id);
1774  $view->sendForm();
1775  }
1776 }
parseCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
confirmRemoveQuestions()
Remove question(s) from survey.
$target_arr
Definition: goto.php:50
addQuestionToolbar()
Add question to survey action (used in toolbar)
splitPage(int $a_id)
Split current page in 2 pages.
Class ilSurveyEditorGUI.
__construct(ilObjSurvey $a_survey, ilSurveyEditorGUI $a_survey_editor_gui)
ILIAS Survey PrintView GUIService $print
static getLogger(string $a_component_id)
Get component logger.
static _hasDatasets(int $survey_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
static get(string $a_glyph, string $a_text="")
redirect(object $a_gui_obj, string $a_cmd=null, string $a_anchor=null, bool $is_async=false)
$type
movePageForm()
Move current page.
movePrevious(int $a_id)
Move question to previous page.
renderToolbar(?array $a_pages)
Render toolbar form.
static getImagePath(string $img, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
insertNewQuestion(int $a_new_id)
Add new question to survey.
$target_id
Definition: goto.php:52
ilGlobalTemplateInterface $tpl
multiCopy(array $a_id)
Add questions to be copied to clipboard.
loadLanguageModule(string $a_module)
Load language module.
dnd()
Move questions in page.
ILIAS Survey Editing EditingGUIRequest $svy_request
editBlock(int $a_id)
Edit question block.
editHeading(int $a_id)
Edit question heading.
deleteHeading(int $a_id)
Delete question heading.
global $DIC
Definition: feed.php:28
multiCut(array $a_id)
Add questions to be cut to clipboard.
checkAccess(string $a_operations, int $a_ref_id, string $a_type="")
checkAccess represents the main method of the RBAC-system in ILIAS3 developers want to use With this ...
touchBlock(string $block)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _getQuestionGUI(?string $questiontype, int $question_id=-1)
Creates a question gui representation.
renderPageNode(ilTemplate $a_tpl, string $a_type, string $a_id, ?string $a_content=null, ?array $a_menu=null, bool $a_spacer=false, string $a_subtitle="", ?string $a_status=null, ?string $a_heading=null)
Render single node of dnd page view.
static _isComplete(int $question_id)
Checks whether the question is complete or not.
static http()
Fetches the global http state from ILIAS.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setVariable($variable, $value='')
Sets a variable value.
Definition: IT.php:514
setContent(string $a_html)
Sets content for standard template.
static _instanciateQuestion(int $question_id)
Creates an instance of a question with a given question id.
static removeRedundantSeparators(string $a_string)
Removes redundant seperators and removes ,, and , at the first or last position of the string...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
clearClipboard()
Empty clipboard.
moveNext(int $a_id)
Move question to next page.
addQuestionToolbarForm()
Add question to survey form (used in toolbar)
addJavaScript(string $a_js_file, bool $a_add_version_parameter=true, int $a_batch=2)
Add a javascript file that should be included in the header.
static initDragDrop(?ilGlobalTemplateInterface $a_main_tpl=null)
Init YUI Drag and Drop used in Modules/Survey, Services/Calendar, Services/COPage, Services/Form (Jan 2022)
insertQuestionBlock(int $a_block_id)
Copy and insert questions from block.
addQuestion(int $a_type, bool $a_use_pool, string $a_pos, string $a_special_position)
Call add question to survey form.
addPoolQuestion(string $pos, string $node)
addOnLoadCode(string $a_code, int $a_batch=2)
Add on load code.
deleteBlock()
Confirm removing question block.
copyQuestion(int $a_id)
Add question to be copied to clipboard.
setCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
cutQuestion(int $a_id)
Add question to be cut to clipboard.
callEditor(string $a_cmd, string $a_param, string $a_value)
static _getQuestiontypes()
Get all available question types.
$ilUser
Definition: imgupload.php:34
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
getAutoBlockTitle()
Get name for newly created blocks.
$url
ILIAS Survey Editing EditManager $edit_manager
renderPage()
render questions per page
movePage()
Move current page to new position.
setParameter(object $a_gui_obj, string $a_parameter, $a_value)
appendNewQuestionToSurvey(int $a_new_id, bool $a_duplicate=true, bool $a_force_duplicate=false)
Add new question to survey (database part)
getPageNodes(array $a_questions, bool $a_has_previous_page=false, bool $a_has_next_page=false, bool $a_readonly=false)
$source
Definition: metadata.php:93
static _getUsedHTMLTags(string $a_module="")
Returns an array of all allowed HTML tags for text editing.
deleteQuestion(array $a_id)
Confirm removing question(s) from survey.
addHeading(int $a_id)
Add heading to question.
paste(int $a_id)
Paste from clipboard.