ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilObjQuestionPoolGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
32use ILIAS\Data\Factory as DataFactory;
33use ILIAS\GlobalScreen\Services as GlobalScreen;
38use ILIAS\UI\Component\Modal\RoundTrip as RoundTripModal;
39use ILIAS\HTTP\Services as HTTPServices;
40use ILIAS\Style\Content\Service as ContentStyle;
41
68{
70
72 MimeType::APPLICATION__X_ZIP_COMPRESSED,
73 MimeType::APPLICATION__ZIP,
74 MimeType::TEXT__XML
75 ];
76 public const DEFAULT_CMD = 'questions';
77
78 protected Service $taxonomy;
79 protected ilDBInterface $db;
81 protected ilHelpGUI $help;
82 protected GlobalScreen $global_screen;
87 protected DataFactory $data_factory;
92 private ContentStyle $content_style;
93
97
98 public function __construct()
99 {
101 global $DIC;
102 $this->type = 'qpl';
103
104 $this->db = $DIC['ilDB'];
105 $this->log = $DIC['ilLog'];
106 $this->help = $DIC['ilHelp'];
107 $this->global_screen = $DIC['global_screen'];
108 $this->component_factory = $DIC['component.factory'];
109 $this->component_repository = $DIC['component.repository'];
110 $this->navigation_history = $DIC['ilNavigationHistory'];
111 $this->ui_service = $DIC->uiService();
112 $this->taxonomy = $DIC->taxonomy();
113 $this->archives = $DIC->archives();
114 $this->content_style = $DIC->contentStyle();
115
116 $this->data_factory = new DataFactory();
117
118 $local_dic = QuestionPoolDIC::dic();
119 $this->request_data_collector = $local_dic['request_data_collector'];
120 $this->questionrepository = $local_dic['question.general_properties.repository'];
121 $this->global_test_settings = $local_dic['global_test_settings'];
122
123 parent::__construct('', $this->request_data_collector->getRefId(), true, false);
124
125 $this->ctrl->saveParameter($this, [
126 'ref_id',
127 'test_ref_id',
128 'test_express_mode',
129 'q_id',
130 'tax_node',
131 'consumer_context'
132 ]);
133 $this->ctrl->saveParameterByClass('ilAssQuestionPageGUI', 'consumer_context');
134 $this->ctrl->saveParameterByClass('ilobjquestionpoolgui', 'consumer_context');
135
136 $this->lng->loadLanguageModule('assessment');
137
138 $here_uri = $this->data_factory->uri($this->request->getUri()->__toString());
139 $url_builder = new URLBuilder($here_uri);
140 $query_params_namespace = ['qpool', 'table'];
142 $query_params_namespace,
143 'action', //this is the actions's parameter name
144 'qids' //this is the parameter name to be used for row-ids
145 );
146 $this->url_builder = $url_builder;
147 $this->action_parameter_token = $action_parameter_token;
148 $this->row_id_token = $row_id_token;
149
150 $this->notes_service->gui()->initJavascript();
151 }
152
153 public function executeCommand(): void
154 {
155 $write_access = $this->access->checkAccess('write', '', $this->request_data_collector->getRefId());
156
157 if ((!$this->access->checkAccess('read', '', $this->request_data_collector->getRefId()))
158 && (!$this->access->checkAccess('visible', '', $this->request_data_collector->getRefId()))) {
159 $this->ilias->raiseError($this->lng->txt('permission_denied'), $this->ilias->error_obj->MESSAGE);
160 }
161
162 if (!$this->getCreationMode() &&
163 $this->access->checkAccess('read', '', $this->request_data_collector->getRefId())) {
164 if ('qpl' === $this->object->getType()) {
165 $this->navigation_history->addItem(
166 $this->request_data_collector->getRefId(),
167 ilLink::_getLink($this->request_data_collector->getRefId(), "qpl"),
168 'qpl',
169 );
170 }
171 }
172
173 $cmd = $this->ctrl->getCmd(self::DEFAULT_CMD);
174 $next_class = $this->ctrl->getNextClass($this);
175 $q_id = $this->request_data_collector->getQuestionId() ?? null;
176
177 if (in_array($next_class, ['', 'ilobjquestionpoolgui']) && $cmd == self::DEFAULT_CMD) {
178 $q_id = -1;
179 }
180
181 $this->prepareOutput();
182
183 $this->tpl->addCss(ilUtil::getStyleSheetLocation('output', 'test_print.css'), 'print');
184
185 $q_type = $this->request_data_collector->string('question_type');
186 switch ($next_class) {
187 case 'ilcommonactiondispatchergui':
189 $this->ctrl->forwardCommand($gui);
190 break;
191
192 case 'ilobjectmetadatagui':
193 if (!$this->access->checkAccess('write', '', $this->object->getRefId())) {
194 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->WARNING);
195 }
196 $md_gui = new ilObjectMetaDataGUI($this->object);
197 $this->ctrl->forwardCommand($md_gui);
198 break;
199
200 case 'ilassquestionpreviewgui':
201 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
203 }
204
205 $this->ctrl->saveParameterByClass(ilAssQuestionPreviewGUI::class, 'q_id');
206 $this->ctrl->saveParameter($this, 'q_id');
207 $gui = new ilAssQuestionPreviewGUI(
208 $this->ctrl,
209 $this->rbac_system,
210 $this->tabs_gui,
211 $this->toolbar,
212 $this->tpl,
213 $this->ui_factory,
214 $this->lng,
215 $this->db,
216 $this->refinery->random(),
217 $this->global_screen,
218 $this->http,
219 $this->refinery,
220 $this->ref_id
221 );
222
223 $question_gui = assQuestion::instantiateQuestionGUI($this->request_data_collector->int('q_id'));
224 $gui->setPrimaryCmd(
225 $this->lng->txt('edit_question'),
226 $this->ctrl->getLinkTargetByClass(
227 get_class($question_gui),
228 'editQuestion'
229 )
230 );
231 $gui->addAdditionalCmd(
232 $this->lng->txt('edit_page'),
233 $this->ctrl->getLinkTargetByClass(
234 ilAssQuestionPageGUI::class,
235 'edit'
236 )
237 );
238
239 $gui->initQuestion(
240 $question_gui,
241 $this->object->getId()
242 );
243 $gui->initPreviewSettings($this->object->getRefId());
244 $gui->initPreviewSession($this->user->getId(), $this->fetchAuthoringQuestionIdParamater());
245 $this->ctrl->clearParameterByClass(self::class, 'q_id');
246 $this->tabs_gui->setBackTarget(
247 $this->lng->txt('backtocallingpool'),
248 $this->ctrl->getLinkTargetByClass(self::class, self::DEFAULT_CMD)
249 );
250
251 $this->help->setScreenIdComponent('qpl');
252
253 $this->ctrl->forwardCommand($gui);
254 break;
255
256 case 'ilassquestionpagegui':
257 if ($cmd == 'finishEditing') {
258 $this->ctrl->redirectByClass('ilassquestionpreviewgui', 'show');
259 break;
260 }
261 if ($cmd === 'edit' && !$this->access->checkAccess('write', '', $this->object->getRefId())) {
263 }
264 $this->tpl->setCurrentBlock('ContentStyle');
265 $this->tpl->setVariable('LOCATION_CONTENT_STYLESHEET', ilObjStyleSheet::getContentStylePath(0));
266 $this->tpl->parseCurrentBlock();
267
268 $this->tpl->setCurrentBlock('SyntaxStyle');
269 $this->tpl->setVariable('LOCATION_SYNTAX_STYLESHEET', ilObjStyleSheet::getSyntaxStylePath());
270 $this->tpl->parseCurrentBlock();
272 $question_gui->setRenderPurpose(assQuestionGUI::RENDER_PURPOSE_PREVIEW);
273 $question_gui->setQuestionTabs();
274 $question_gui->getObject()->setObjId($this->object->getId());
275 $question_gui->setQuestionActionCmd('');
276
277 if ($this->object->getType() === 'qpl') {
278 $question_gui->addHeaderAction();
279 }
280
281 $question = $question_gui->getObject();
282
283 if ($this->questionrepository->isInActiveTest($question->getObjId())) {
284 $this->tpl->setOnScreenMessage(
285 'failure',
286 $this->lng->txt('question_is_part_of_running_test'),
287 true
288 );
289 $this->ctrl->redirectByClass('ilAssQuestionPreviewGUI', ilAssQuestionPreviewGUI::CMD_SHOW);
290 }
291
292 $this->ctrl->saveParameter($this, 'q_id');
293 $this->lng->loadLanguageModule('content');
294 $this->ctrl->setReturnByClass('ilAssQuestionPageGUI', 'view');
295 $this->ctrl->setReturn($this, self::DEFAULT_CMD);
296 $page_gui = new ilAssQuestionPageGUI($this->request_data_collector->getQuestionId());
297 $page_gui->setFileDownloadLink(
298 $this->ctrl->getLinkTargetByClass(ilObjQuestionPoolGUI::class, 'downloadFile')
299 );
300 $page_gui->obj->addUpdateListener(
301 $question,
302 'updateTimestamp'
303 );
304 $page_gui->setEditPreview(true);
305 $page_gui->setEnabledTabs(false);
306 $page_gui->setQuestionHTML([$question_gui->getObject()->getId() => $question_gui->getPreview(true)]);
307 $page_gui->setTemplateTargetVar('ADM_CONTENT');
308 $page_gui->setOutputMode('edit');
309 $page_gui->setHeader($question->getTitleForHTMLOutput());
310 $page_gui->setPresentationTitle($question->getTitleForHTMLOutput());
311 $ret = $this->ctrl->forwardCommand($page_gui);
312 if ($ret != '') {
313 $this->tpl->setContent($ret);
314 }
315 break;
316
317 case 'ilpermissiongui':
318 $perm_gui = new ilPermissionGUI($this);
319 $this->ctrl->forwardCommand($perm_gui);
320 break;
321
322 case 'ilobjectcopygui':
323 $cp = new ilObjectCopyGUI($this);
324 $cp->setType('qpl');
325 $this->ctrl->forwardCommand($cp);
326 break;
327
328 case 'ilexportgui':
329 $exp_gui = new ilExportGUI($this);
330 $ret = $this->ctrl->forwardCommand($exp_gui);
331 break;
332
333 case strtolower(ilInfoScreenGUI::class):
334 $this->infoScreenForward();
335 break;
336
337 case 'illocalunitconfigurationgui':
338 if (!$this->access->checkAccess('write', '', $this->object->getRefId())) {
339 $this->error->raiseError($this->lng->txt('permission_denied'), $this->error->WARNING);
340 }
341 $question_gui = assQuestionGUI::_getQuestionGUI(
342 $q_type,
344 );
345 $question = $question_gui->getObject();
346 $question->setObjId($this->object->getId());
347 $question_gui->setObject($question);
348 $question_gui->setQuestionTabs();
349
350 $this->ctrl->setReturn($this, self::DEFAULT_CMD);
352 new ilUnitConfigurationRepository($this->request_data_collector->getQuestionId())
353 );
354 $this->ctrl->forwardCommand($gui);
355 break;
356
357 case 'ilassquestionfeedbackeditinggui':
358 if (!$this->access->checkAccess('write', '', $this->object->getRefId())) {
360 }
361
362 $this->ctrl->setReturn($this, self::DEFAULT_CMD);
363 $question_gui = assQuestionGUI::_getQuestionGUI(
364 $q_type,
366 );
367 $question = $question_gui->getObject();
368 $question->setObjId($this->object->getId());
369 $question_gui->setObject($question);
370 $question_gui->setQuestionTabs();
371
372 if ($this->questionrepository->isInActiveTest($question_gui->getObject()->getObjId())) {
373 $this->tpl->setOnScreenMessage(
374 'failure',
375 $this->lng->txt('question_is_part_of_running_test'),
376 true
377 );
378 $this->ctrl->redirectByClass('ilAssQuestionPreviewGUI', ilAssQuestionPreviewGUI::CMD_SHOW);
379 }
380
381 $this->help->setScreenIdComponent('qpl');
382
383 if ($this->object->getType() == 'qpl' && $write_access) {
384 $question_gui->addHeaderAction();
385 }
387 $question_gui,
388 $this->ctrl,
389 $this->access,
390 $this->tpl,
391 $this->tabs_gui,
392 $this->lng,
393 $this->help,
394 $this->request_data_collector,
395 $this->content_style,
396 true
397 );
398 $this->ctrl->forwardCommand($gui);
399
400 break;
401
402 case 'ilobjquestionpoolsettingsgeneralgui':
404 $this->ctrl,
405 $this->access,
406 $this->lng,
407 $this->tpl,
408 $this->tabs_gui,
409 $this,
410 $this->refinery,
411 $this->ui_factory,
412 $this->ui_renderer,
413 $this->request,
414 );
415 $this->ctrl->forwardCommand($gui);
416 break;
417
418 case strtolower(ilTaxonomySettingsGUI::class):
419 if (!$this->access->checkAccess('write', '', $this->object->getRefId())) {
421 }
422
424 $obj = $this->object;
426 $this->object,
427 $this->db,
428 $this->refinery,
429 $this->component_repository,
430 $this->ctrl,
431 $this->tabs_gui,
432 $this->lng,
433 $this->taxonomy
434 );
435
436 $forwarder->forward();
437
438 break;
439
440 case 'ilquestionpoolskilladministrationgui':
441 $obj = $this->object;
443 $this->ilias,
444 $this->ctrl,
445 $this->refinery,
446 $this->access,
447 $this->tabs_gui,
448 $this->tpl,
449 $this->lng,
450 $this->db,
451 $this->component_repository,
452 $obj,
453 $this->ref_id
454 );
455
456 $this->ctrl->forwardCommand($gui);
457 break;
458
459 case 'ilbulkeditquestionsgui':
460 if (!$this->access->checkAccess('read', '', $this->object->getRefId())) {
462 }
463 $this->tabs_gui->setBackTarget(
464 $this->lng->txt('backtocallingpool'),
465 $this->ctrl->getLinkTargetByClass(self::class, self::DEFAULT_CMD)
466 );
467 $this->tabs_gui->addTarget(
468 'edit_questions',
469 '#',
470 '',
471 $this->ctrl->getCmdClass(),
472 ''
473 );
474 $this->tabs_gui->setTabActive('edit_questions');
475
476 $gui = new \ilBulkEditQuestionsGUI(
477 $this->tpl,
478 $this->ctrl,
479 $this->lng,
480 $this->ui_factory,
481 $this->ui_renderer,
482 $this->refinery,
483 $this->request,
484 $this->request_wrapper,
485 $this->object->getId(),
486 );
487 $this->ctrl->forwardCommand($gui);
488 break;
489
490 case 'ilobjquestionpoolgui':
491 case '':
492 //table actions.
493 if ($action = $this->request_data_collector->string($this->action_parameter_token->getName())) {
494 $ids = $this->request_data_collector->raw($this->row_id_token->getName()) ?? null;
495
496 if (is_null($ids)) {
497 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('msg_no_questions_selected'), true);
498 $this->ctrl->redirect($this, self::DEFAULT_CMD);
499 }
500 if ($ids[0] === 'ALL_OBJECTS') {
501 $ids = $this->object->getAllQuestionIds();
502 }
503 if (!is_array($ids)) {
504 $ids = explode(',', $ids);
505 }
506 $ids = array_map('intval', $ids);
507
508 $this->ctrl->setParameterByClass(ilAssQuestionPreviewGUI::class, 'q_id', current($ids));
509
510 switch ($action) {
511 case 'preview':
512 $this->ctrl->redirectToURL(
513 $this->ctrl->getLinkTargetByClass(ilAssQuestionPreviewGUI::class, ilAssQuestionPreviewGUI::CMD_SHOW)
514 );
515 break;
516 case 'statistics':
517 $this->ctrl->redirectToURL(
518 $this->ctrl->getLinkTargetByClass(ilAssQuestionPreviewGUI::class, ilAssQuestionPreviewGUI::CMD_STATISTICS)
519 );
520 break;
521 case 'edit_question':
522 $class = strtolower($this->questionrepository->getForQuestionId(current($ids))->getGuiClassName());
523 $this->ctrl->setParameterByClass($class, 'q_id', current($ids));
524 $this->ctrl->redirectToURL(
525 $this->ctrl->getLinkTargetByClass($class, 'editQuestion')
526 );
527 break;
528 case 'edit_page':
529 $this->ctrl->setParameterByClass(ilAssQuestionPageGUI::class, 'q_id', current($ids));
530 $this->ctrl->redirectToURL(
531 $this->ctrl->getLinkTargetByClass(ilAssQuestionPageGUI::class, 'edit')
532 );
533 break;
534 case 'feedback':
535 $this->ctrl->setParameterByClass(ilAssQuestionFeedbackEditingGUI::class, 'q_id', current($ids));
536 $this->ctrl->redirectToURL(
537 $this->ctrl->getLinkTargetByClass(ilAssQuestionFeedbackEditingGUI::class, ilAssQuestionFeedbackEditingGUI::CMD_SHOW)
538 );
539 break;
540 case 'move':
541 $this->moveQuestions($ids);
542 $this->ctrl->redirectByClass(self::class, self::DEFAULT_CMD);
543 break;
544 case 'copy':
545 $this->copyQuestions($ids);
546 $this->ctrl->redirectByClass(self::class, self::DEFAULT_CMD);
547 break;
548 case 'delete':
549 $this->confirmDeleteQuestions($ids);
550 break;
551 case 'export':
552 $this->exportQuestions($ids);
553 $this->ctrl->redirectByClass(self::class, self::DEFAULT_CMD);
554 break;
555 case 'comments':
558 $this->object->getRefId(),
559 'quest',
560 $this->object->getId(),
561 'quest',
562 current($ids)
563 );
564 echo ''
565 . '<script>'
566 . ' event = new Event("click");'
568 . '</script>'
569 ;
570 exit();
571
575 $this->ctrl->clearParameters($this);
576 $this->ctrl->setParameterByClass(
577 ilBulkEditQuestionsGUI::class,
579 implode(',', $ids)
580 );
581 $this->ctrl->redirectToURL(
582 $this->ctrl->getLinkTargetByClass(
583 ilBulkEditQuestionsGUI::class,
584 $action
585 )
586 );
587 break;
588
589 default:
590 throw new \Exception("'{$action}' not implemented");
591 }
592 break;
593 }
594
595
596 if ($cmd == self::DEFAULT_CMD) {
597 $this->ctrl->setParameterByClass(self::class, 'q_id', '');
598 }
599 $cmd .= 'Object';
600 $ret = $this->$cmd();
601 break;
602
603 default:
604 if (in_array(
605 $cmd,
606 ['editQuestion', 'save', 'suggestedsolution', 'uploadImage', 'removeImage']
607 ) && !$this->access->checkAccess(
608 'write',
609 '',
610 $this->object->getRefId()
611 )) {
613 }
614
615 $this->ctrl->setReturnByClass(self::class, self::DEFAULT_CMD);
616
617 $qid = $this->fetchAuthoringQuestionIdParamater();
618 $question_gui = assQuestionGUI::_getQuestionGUI(
619 $q_type,
620 $qid
621 );
622 $question_gui->setEditContext(assQuestionGUI::EDIT_CONTEXT_AUTHORING);
623 $question = $question_gui->getObject();
624 $question->setObjId($this->object->getId());
625 $question_gui->setObject($question);
626
627 if ($this->object->getType() === 'qpl') {
628 $question_gui->setTaxonomyIds($this->object->getTaxonomyIds());
629
630 if ($write_access) {
631 $question_gui->addHeaderAction();
632 }
633 }
634
635 $this->help->setScreenIdComponent('qpl');
636
637 if ($qid === 0 && $question_gui->cmdNeedsExistingQuestion($cmd)) {
638 $question_gui->getObject()->createNewQuestion();
639 }
640
641 $question_gui->setQuestionTabs();
642
643 if (!in_array($cmd, ['save', 'saveReturn'])) {
644 $question_gui->$cmd();
645 return;
646 }
647
648 if (!$question_gui->saveQuestion()) {
649 return;
650 }
651 $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_obj_modified'), true);
652 if ($cmd === 'saveReturn') {
653 $this->ctrl->setParameterByClass(
654 ilAssQuestionPreviewGUI::class,
655 'q_id',
656 (string) $question_gui->getObject()->getId()
657 );
658 $this->ctrl->redirectToURL(
659 $this->ctrl->getLinkTargetByClass(ilAssQuestionPreviewGUI::class, ilAssQuestionPreviewGUI::CMD_SHOW)
660 );
661 }
662
663 if ($cmd === 'save') {
664 $this->tabs_gui->activateTab('edit_question');
665 $question_gui->editQuestion(false, false);
666 }
667 break;
668 }
669
670 if (!(strtolower($this->request_data_collector->raw('baseClass')) == 'iladministrationgui'
671 || strtolower($this->request_data_collector->raw('baseClass')) == 'ilrepositorygui')
672 && $this->getCreationMode() != true) {
673 $this->tpl->printToStdout();
674 }
675 }
676
677 protected function redirectAfterMissingWrite()
678 {
679 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('no_permission'), true);
680 $target_class = get_class($this->object) . 'GUI';
681 $this->ctrl->setParameterByClass($target_class, 'ref_id', $this->ref_id);
682 $this->ctrl->redirectByClass($target_class);
683 }
684
689 protected function exportObject(): void
690 {
691 $this->ctrl->redirectByClass('ilQuestionPoolExportGUI');
692 }
693
694 public function downloadFileObject(): void
695 {
696 $file = explode('_', $this->request_data_collector->raw('file_id'));
697 $fileObj = new ilObjFile((int) $file[count($file) - 1], false);
698 $fileObj->sendFile();
699 exit;
700 }
701
705 public function fullscreenObject(): void
706 {
707 $page_gui = new ilAssQuestionPageGUI($this->request_data_collector->raw('pg_id'));
708 $page_gui->setFileDownloadLink(
709 $this->ctrl->getLinkTargetByClass(ilObjQuestionPoolGUI::class, 'downloadFile')
710 );
711 $page_gui->showMediaFullscreen();
712 }
713
717 public function download_paragraphObject(): void
718 {
719 $pg_obj = new ilAssQuestionPage($this->request_data_collector->raw('pg_id'));
720 $pg_obj->sendParagraph($this->request_data_collector->raw('par_id'), $this->request_data_collector->raw('downloadtitle'));
721 exit;
722 }
723
724 public function importVerifiedFileObject(): void
725 {
726 if ($this->creation_mode
727 && !$this->checkPermissionBool('create', '', $this->request_data_collector->string('new_type'))
728 || !$this->creation_mode
729 && !$this->checkPermissionBool('read', '', $this->object->getType())) {
731 return;
732 }
733
734 $file_to_import = ilSession::get('path_to_import_file');
735 list($subdir, $importdir, $xmlfile, $qtifile) = $this->buildImportDirectoriesFromImportFile($file_to_import);
736
737 $new_obj = new ilObjQuestionPool(0, true);
738 $new_obj->setType($this->request_data_collector->raw('new_type'));
739 $new_obj->setTitle('dummy');
740 $new_obj->setDescription('questionpool import');
741 $new_obj->create(true);
742 $new_obj->createReference();
743 $new_obj->putInTree($this->request_data_collector->getRefId());
744 $new_obj->setPermissions($this->request_data_collector->getRefId());
745
747 'importVerifiedFile',
748 $importdir,
749 $qtifile,
750 $this->request
751 );
752
753 if (is_file($importdir . DIRECTORY_SEPARATOR . 'manifest.xml')) {
755 $new_obj,
756 $selected_questions,
757 $file_to_import
758 );
759 } else {
761 $new_obj,
762 $selected_questions,
763 $qtifile,
764 $importdir,
765 $xmlfile
766 );
767
768 $new_obj->fromXML($xmlfile);
769
770 $new_obj->update();
771 $new_obj->saveToDb();
772 }
773 $this->cleanupAfterImport($importdir);
774
775 $this->tpl->setOnScreenMessage('success', $this->lng->txt('object_imported'), true);
776 $this->ctrl->setParameterByClass(self::class, 'ref_id', $new_obj->getRefId());
777 $this->ctrl->redirectByClass(self::class);
778 }
779
780 public function importVerifiedQuestionsFileObject(): void
781 {
782 $file_to_import = ilSession::get('path_to_import_file');
783
784 if (mb_substr($file_to_import, -3) === 'xml') {
785 $importdir = dirname($file_to_import);
787 'importVerifiedQuestionsFile',
788 $importdir,
789 $file_to_import,
790 $this->request
791 );
793 $this->getObject(),
794 $selected_questions,
795 $file_to_import,
796 $importdir
797 );
798 } else {
799 list($subdir, $importdir, $xmlfile, $qtifile) = $this->buildImportDirectoriesFromImportFile($file_to_import);
801 'importVerifiedQuestionsFile',
802 $importdir,
803 $qtifile,
804 $this->request
805 );
806 if (is_file($importdir . DIRECTORY_SEPARATOR . 'manifest.xml')) {
808 $this->getObject(),
809 $selected_questions,
810 $file_to_import
811 );
812 } else {
814 $this->getObject(),
815 $selected_questions,
816 $qtifile,
817 $importdir,
818 $xmlfile
819 );
820 }
821 }
822
823 $this->cleanupAfterImport($importdir);
824
825 $this->tpl->setOnScreenMessage('success', $this->lng->txt('object_imported'), true);
826 $this->questionsObject();
827 }
828
829 public function uploadQuestionsImportObject(): void
830 {
831 $import_questions_modal = $this->buildImportQuestionsModal()->withRequest($this->request);
832 $data = $import_questions_modal->getData();
833 if ($data === null) {
834 $this->questionsObject(
835 $import_questions_modal->withOnLoad(
836 $import_questions_modal->getShowSignal()
837 )
838 );
839 return;
840 }
841 $path_to_imported_file_in_temp_dir = $data['import_file'][0];
842 $this->importQuestionsFile($path_to_imported_file_in_temp_dir);
843 }
844
845 private function buildImportQuestionsModal(): RoundTripModal
846 {
847 $constraint = $this->refinery->custom()->constraint(
848 function ($vs): bool {
849 if ($vs === []) {
850 return false;
851 }
852 return true;
853 },
854 $this->lng->txt('msg_no_files_selected')
855 );
856
857 $file_upload_input = $this->ui_factory->input()->field()
858 ->file(new \QuestionPoolImportUploadHandlerGUI(), $this->lng->txt('import_file'))
859 ->withAcceptedMimeTypes(self::SUPPORTED_IMPORT_MIME_TYPES)
860 ->withMaxFiles(1)
861 ->withAdditionalTransformation($constraint);
862 return $this->ui_factory->modal()->roundtrip(
863 $this->lng->txt('import'),
864 [],
865 ['import_file' => $file_upload_input],
866 $this->ctrl->getFormActionByClass(self::class, 'uploadQuestionsImport')
867 )->withSubmitLabel($this->lng->txt('import'));
868 }
869
872 array $selected_questions,
873 string $file_to_import
874 ): void {
875
876 ilSession::set('qpl_import_selected_questions', $selected_questions);
877 $imp = new ilImport($this->request_data_collector->getRefId());
878 $map = $imp->getMapping();
879 $map->addMapping('components/ILIAS/TestQuestionPool', 'qpl', 'new_id', (string) $obj->getId());
880 $imp->importObject($obj, $file_to_import, basename($file_to_import), 'qpl', 'components/ILIAS/TestQuestionPool', true);
881 }
882
885 array $selected_questions,
886 string $qtifile,
887 string $importdir,
888 string $xmlfile = ''
889 ): void {
890 $qti_parser = new ilQTIParser(
891 $importdir,
892 $qtifile,
893 ilQTIParser::IL_MO_PARSE_QTI,
894 $obj->getId(),
895 $selected_questions
896 );
897 $qti_parser->startParsing();
898
899 if ($xmlfile === '') {
900 return;
901 }
902
903 $cont_parser = new ilQuestionPageParser(
904 $obj,
905 $xmlfile,
906 $importdir
907 );
908 $cont_parser->setQuestionMapping($qti_parser->getImportMapping());
909 $cont_parser->startParsing();
910 }
911
912 private function cleanupAfterImport(string $importdir): void
913 {
914 ilFileUtils::delDir($importdir);
915 $this->deleteUploadedImportFile(ilSession::get('path_to_uploaded_file_in_temp_dir'));
916 ilSession::clear('path_to_import_file');
917 ilSession::clear('path_to_uploaded_file_in_temp_dir');
918 }
919
920 public function createQuestionObject(): void
921 {
922 $form = $this->buildQuestionCreationForm()->withRequest($this->request);
923 $data_with_section = $form->getData();
924 if ($data_with_section === null) {
925 $this->createQuestionFormObject($form);
926 return;
927 }
928 $data = $data_with_section[0];
929
930 $this->ctrl->setReturnByClass(self::class, self::DEFAULT_CMD);
931
933 $question_gui = assQuestionGUI::_getQuestionGUI(
935 );
936 $question = $question_gui->getObject();
937 $question->setObjId($this->object->getId());
938 $question->setAdditionalContentEditingMode($data['editing_type']);
939 $question_gui->setObject($question);
940 $question_gui->setQuestionTabs();
941 $question_gui->editQuestion();
942 }
943
944 public function afterSave(ilObject $new_object): void
945 {
946 // always send a message
947 $this->tpl->setOnScreenMessage('success', $this->lng->txt('object_added'), true);
948
950 'ilias.php?ref_id=' . $new_object->getRefId() .
951 '&baseClass=ilObjQuestionPoolGUI'
952 );
953 }
954
955 public function confirmDeleteQuestions(array $ids): void
956 {
957 $rbacsystem = $this->rbac_system;
958
959 $questionIdsToDelete = array_filter(array_map('intval', $ids));
960 if (0 === count($questionIdsToDelete)) {
961 $this->tpl->setOnScreenMessage('info', $this->lng->txt('qpl_delete_select_none'), true);
962 $this->ctrl->redirect($this, self::DEFAULT_CMD);
963 }
964
965 $this->tpl->setOnScreenMessage('question', $this->lng->txt('qpl_confirm_delete_questions'));
966 $deleteable_questions = $this->object->getDeleteableQuestionDetails($questionIdsToDelete);
967 $table_gui = new ilQuestionBrowserTableGUI($this, self::DEFAULT_CMD, (($rbacsystem->checkAccess('write', $this->request_data_collector->getRefId()) ? true : false)), true);
968 $table_gui->setShowRowsSelector(false);
969 $table_gui->setLimit(PHP_INT_MAX);
970 $table_gui->setEditable($rbacsystem->checkAccess('write', $this->request_data_collector->getRefId()));
971 $table_gui->setData($deleteable_questions);
972 $this->tpl->setVariable('ADM_CONTENT', $table_gui->getHTML());
973 }
974
978 public function deleteQuestionsObject(): void
979 {
980 $rbacsystem = $this->rbac_system;
981
982 $questionIdsToDelete = $this->request_data_collector->isset('q_id') ? (array) $this->request_data_collector->raw('q_id') : [];
983 if ($questionIdsToDelete === [] && $this->request_data_collector->isset('q_id')) {
984 $questionIdsToDelete = [$this->request_data_collector->getQuestionId()];
985 }
986
987 $questionIdsToDelete = array_filter(array_map('intval', $questionIdsToDelete));
988 if ($questionIdsToDelete === []) {
989 $this->tpl->setOnScreenMessage('info', $this->lng->txt('qpl_delete_select_none'), true);
990 $this->ctrl->redirect($this, self::DEFAULT_CMD);
991 }
992
993 $this->tpl->setOnScreenMessage('question', $this->lng->txt('qpl_confirm_delete_questions'));
994 $deleteable_questions = &$this->object->getDeleteableQuestionDetails($questionIdsToDelete);
995 $table_gui = new ilQuestionBrowserTableGUI(
996 $this,
997 self::DEFAULT_CMD,
998 (($rbacsystem->checkAccess('write', $this->request_data_collector->getRefId()) ? true : false)),
999 true
1000 );
1001 $table_gui->setShowRowsSelector(false);
1002 $table_gui->setLimit(PHP_INT_MAX);
1003 $table_gui->setEditable($rbacsystem->checkAccess('write', $this->request_data_collector->getRefId()));
1004 $table_gui->setData($deleteable_questions);
1005 $this->tpl->setVariable('ADM_CONTENT', $table_gui->getHTML());
1006 }
1007
1011 public function confirmDeleteQuestionsObject(): void
1012 {
1013 $qst_ids = $this->request_data_collector->intArray('q_id');
1014 foreach ($qst_ids as $value) {
1015 $this->object->deleteQuestion((int) $value);
1016 $this->object->cleanupClipboard((int) $value);
1017 }
1018 if ($qst_ids !== []) {
1019 $this->tpl->setOnScreenMessage('success', $this->lng->txt('qpl_questions_deleted'), true);
1020 }
1021
1022 $this->ctrl->setParameter($this, 'q_id', '');
1023 $this->ctrl->redirect($this, self::DEFAULT_CMD);
1024 }
1025
1026 public function cancelDeleteQuestionsObject(): void
1027 {
1028 $this->ctrl->redirect($this, self::DEFAULT_CMD);
1029 }
1030
1031 public function exportQuestions(array $ids): void
1032 {
1033 if ($ids !== []) {
1034 $qpl_exp = new ilQuestionpoolExport($this->object, 'xml', $ids);
1035 // @PHP8-CR: This seems to be a pointer to an issue with exports. I like to leave this open for now and
1036 // schedule a thorough examination / analysis for later, eventually involved T&A TechSquad
1037 $export_file = $qpl_exp->buildExportFile();
1038 $filename = $export_file;
1039 $filename = preg_replace('/.*\//', '', $filename);
1040 if ($export_file === '') {
1041 $export_file = 'StandIn';
1042 }
1044 exit();
1045 } else {
1046 $this->tpl->setOnScreenMessage('info', $this->lng->txt('qpl_export_select_none'), true);
1047 }
1048 }
1049
1050 protected function renoveImportFailsObject(): void
1051 {
1052 $qsaImportFails = new ilAssQuestionSkillAssignmentImportFails($this->object->getId());
1053 $qsaImportFails->deleteRegisteredImportFails();
1054
1055 $this->ctrl->redirectByClass(
1056 [
1057 ilRepositoryGUI::class,
1058 self::class,
1059 ilInfoScreenGUI::class
1060 ]
1061 );
1062 }
1063
1067 public function questionsObject(?RoundTripModal $import_questions_modal = null): void
1068 {
1069 if (!$this->access->checkAccess("read", "", $this->request_data_collector->getRefId())) {
1070 $this->infoScreenForward();
1071 return;
1072 }
1073
1074 $this->object->purgeQuestions();
1075 $qsa_import_fails = new ilAssQuestionSkillAssignmentImportFails($this->object->getId());
1076 if ($qsa_import_fails->failedImportsRegistered()) {
1077 $button = $this->ui_factory->button()->standard(
1078 $this->lng->txt('ass_skl_import_fails_remove_btn'),
1079 $this->ctrl->getLinkTargetByClass([ilRepositoryGUI::class, self::class], 'renoveImportFails')
1080 );
1081 $this->tpl->setOnScreenMessage(
1082 'failure',
1083 $qsa_import_fails->getFailedImportsMessage($this->lng) . '<br />' . $this->ui_renderer->render(
1084 $button
1085 )
1086 );
1087 }
1088
1089 $out = [];
1090 if ($this->rbac_system->checkAccess('write', $this->request_data_collector->getRefId())) {
1091 $btn = $this->ui_factory->button()->primary(
1092 $this->lng->txt('ass_create_question'),
1093 $this->ctrl->getLinkTargetByClass([ilRepositoryGUI::class, self::class], 'createQuestionForm')
1094 );
1095 $this->toolbar->addComponent($btn);
1096
1097 if ($import_questions_modal === null) {
1098 $import_questions_modal = $this->buildImportQuestionsModal();
1099 }
1100
1101 $btn_import = $this->ui_factory->button()->standard(
1102 $this->lng->txt('import'),
1103 $import_questions_modal->getShowSignal()
1104 );
1105 $this->toolbar->addComponent($btn_import);
1106 $out[] = $this->ui_renderer->render($import_questions_modal);
1107
1108 if (ilSession::get('qpl_clipboard') != null && count(ilSession::get('qpl_clipboard'))) {
1109 $btn_paste = $this->ui_factory->button()->standard(
1110 $this->lng->txt('paste'),
1111 $this->ctrl->getLinkTargetByClass([ilRepositoryGUI::class, self::class], 'paste')
1112 );
1113 $this->toolbar->addComponent($btn_paste);
1114 }
1115 }
1116
1117 $this->tpl->setPermanentLink($this->object->getType(), $this->object->getRefId());
1118 $out[] = $this->getTable();
1119 $this->tpl->setContent(implode('', $out));
1120 }
1121
1123 {
1124 $q_id = $this->request_data_collector->getQuestionId();
1125
1126 if ($q_id === 0 || $this->object->checkQuestionParent($q_id)) {
1127 return $q_id;
1128 }
1129
1130 throw new ilTestQuestionPoolException('question id does not relate to parent object!');
1131 }
1132
1133 private function createQuestionFormObject(?Form $form = null): void
1134 {
1135 $this->help->setScreenId('assQuestions');
1136 if ($this->global_test_settings->isPageEditorEnabled()) {
1137 $this->help->setSubScreenId('createQuestion_editMode');
1138 } else {
1139 $this->help->setSubScreenId('createQuestion');
1140 }
1141
1142 $this->tpl->setContent(
1143 $this->ui_renderer->render(
1144 $form ?? $this->buildQuestionCreationForm()
1145 )
1146 );
1147 }
1148
1150 {
1151 $inputs['question_type'] = $this->buildInputQuestionType();
1152 $inputs['editing_type'] = $this->buildInputEditingType();
1153
1154 $section = [
1155 $this->ui_factory->input()->field()->section($inputs, $this->lng->txt('ass_create_question'))
1156 ];
1157
1158 $form = $this->ui_factory->input()->container()->form()->standard(
1159 $this->ctrl->getFormAction($this, 'createQuestion'),
1160 $section
1161 )->withSubmitLabel($this->lng->txt('create'));
1162
1163 return $form;
1164 }
1165
1166 private function buildInputQuestionType(): Select
1167 {
1168 $question_types = (new ilObjQuestionPool())->getQuestionTypes(false, true, false);
1169 $options = [];
1170 foreach ($question_types as $label => $data) {
1171 $options[$data['question_type_id']] = $label;
1172 }
1173
1174 return $this->ui_factory->input()->field()->select(
1175 $this->lng->txt('question_type'),
1176 $options
1177 )->withRequired(true);
1178 }
1179
1180 private function buildInputEditingType(): Input
1181 {
1182 if (!$this->global_test_settings->isPageEditorEnabled()) {
1183 return $this->ui_factory->input()->field()->hidden()->withValue(
1185 );
1186 }
1187
1188 return $this->ui_factory->input()->field()->radio($this->lng->txt('tst_add_quest_cont_edit_mode'))
1189 ->withOption(
1191 $this->lng->txt('tst_add_quest_cont_edit_mode_IPE'),
1192 $this->lng->txt('tst_add_quest_cont_edit_mode_IPE_info')
1193 )->withOption(
1195 $this->lng->txt('tst_add_quest_cont_edit_mode_RTE'),
1196 $this->lng->txt('tst_add_quest_cont_edit_mode_RTE_info')
1197 )
1199 }
1200
1201 public function printObject(): void
1202 {
1203 $this->tabs_gui->activateTab('print_view');
1204 $this->ctrl->setParameter($this, 'output', 'overview');
1205 $output_link = $this->ctrl->getLinkTargetByClass([ilRepositoryGUI::class, self::class], 'print');
1206 $this->ctrl->setParameter($this, 'output', 'detailed_output_solutions');
1207 $output_link_detailed = $this->ctrl->getLinkTargetByClass([ilRepositoryGUI::class, self::class], 'print');
1208 $this->ctrl->setParameter($this, 'output', 'detailed_output_printview');
1209 $output_link_printview = $this->ctrl->getLinkTargetByClass([ilRepositoryGUI::class, self::class], 'print');
1210
1211 $mode = $this->ui_factory->dropdown()->standard([
1212 $this->ui_factory->button()->shy($this->lng->txt('overview'), $output_link),
1213 $this->ui_factory->button()->shy($this->lng->txt('detailed_output_solutions'), $output_link_detailed),
1214 $this->ui_factory->button()->shy($this->lng->txt('detailed_output_printview'), $output_link_printview)
1215 ])->withLabel($this->lng->txt('output_mode'));
1216
1217 $output = $this->request_data_collector->raw('output') ?? '';
1218
1219 $table_gui = new ilQuestionPoolPrintViewTableGUI($this, 'print', $output);
1220 $data = $this->object->getPrintviewQuestions();
1221 $totalPoints = 0;
1222 foreach ($data as $d) {
1223 $totalPoints += $d['points'];
1224 }
1225 $table_gui->setTotalPoints($totalPoints);
1226 $table_gui->initColumns();
1227 $table_gui->setData($data);
1228 $this->tpl->setContent($this->ui_renderer->render($mode) . $table_gui->getHTML());
1229 }
1230
1231 public function updateObject(): void
1232 {
1233 $this->object->update();
1234 $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_obj_modified'), true);
1235 }
1236
1237 public function pasteObject(): void
1238 {
1239 if (ilSession::get('qpl_clipboard') != null) {
1240 if ($this->object->pasteFromClipboard()) {
1241 $this->tpl->setOnScreenMessage('success', $this->lng->txt('qpl_paste_success'), true);
1242 } else {
1243 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('qpl_paste_error'), true);
1244 }
1245 } else {
1246 $this->tpl->setOnScreenMessage('info', $this->lng->txt('qpl_paste_no_objects'), true);
1247 }
1248 $this->ctrl->redirect($this, self::DEFAULT_CMD);
1249 }
1250
1251 public function copyQuestions(array $ids): void
1252 {
1253 if ($ids) {
1254 foreach ($ids as $id) {
1255 $this->object->copyToClipboard($id);
1256 }
1257 $this->tpl->setOnScreenMessage('info', $this->lng->txt('qpl_copy_insert_clipboard'), true);
1258 } else {
1259 $this->tpl->setOnScreenMessage('info', $this->lng->txt('qpl_copy_select_none'), true);
1260 }
1261 }
1262
1263 public function moveQuestions(array $ids): void
1264 {
1265 if ($this->checkPermission('write')) {
1266 $this->tpl->setOnScreenMessage('failure', 'permission_denied');
1267 return;
1268 }
1269
1270 if ($ids === []) {
1271 $this->tpl->setOnScreenMessage('info', $this->lng->txt('qpl_move_select_none'), true);
1272 return;
1273 }
1274
1275 foreach ($ids as $id) {
1276 $this->object->moveToClipboard($id);
1277 }
1278 $this->tpl->setOnScreenMessage('info', $this->lng->txt('qpl_move_insert_clipboard'), true);
1279 }
1280
1281 public function createExportExcel(): void
1282 {
1283 $rbacsystem = $this->rbac_system;
1284 if ($rbacsystem->checkAccess('write', $this->request_data_collector->getRefId())) {
1285 $question_ids = &$this->object->getAllQuestionIds();
1286 $qpl_exp = new ilQuestionpoolExport($this->object, 'xlsx', $question_ids);
1287 $qpl_exp->buildExportFile();
1288 $this->ctrl->redirectByClass('ilquestionpoolexportgui', '');
1289 }
1290 }
1291
1292 public function editQuestionForTestObject(): void
1293 {
1294 $this->ctrl->redirectByClass(ilAssQuestionPreviewGUI::class, 'show');
1295 }
1296
1297 protected function importQuestionsFile(string $path_to_uploaded_file_in_temp_dir): void
1298 {
1299 if (!$this->temp_file_system->hasDir($path_to_uploaded_file_in_temp_dir)
1300 || ($files = $this->temp_file_system->listContents($path_to_uploaded_file_in_temp_dir)) === []) {
1301 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('obj_import_file_error'));
1302 }
1303
1304 $file_to_import = $this->import_temp_directory . DIRECTORY_SEPARATOR . $files[0]->getPath();
1305 $qtifile = $file_to_import;
1306 $importdir = dirname($file_to_import);
1307
1308
1309 if ($this->temp_file_system->getMimeType($files[0]->getPath()) === MimeType::APPLICATION__ZIP) {
1311 ->withZipOutputPath($this->getImportTempDirectory());
1312 $unzip = $this->archives->unzip($this->temp_file_system->readStream($files[0]->getPath()), $options);
1313 $unzip->extract();
1314 list($subdir, $importdir, $xmlfile, $qtifile) = $this->buildImportDirectoriesFromImportFile($file_to_import);
1315 }
1316 if (!file_exists($qtifile)) {
1317 ilFileUtils::delDir($importdir);
1318 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('cannot_find_xml'), true);
1319 $this->questionsObject();
1320 return;
1321 }
1322
1323 ilSession::set('path_to_import_file', $file_to_import);
1324 ilSession::set('path_to_uploaded_file_in_temp_dir', $path_to_uploaded_file_in_temp_dir);
1325
1326 $form = $this->buildImportQuestionsSelectionForm(
1327 'importVerifiedQuestionsFile',
1328 $importdir,
1329 $qtifile,
1330 $path_to_uploaded_file_in_temp_dir
1331 );
1332
1333 if ($form === null) {
1334 return;
1335 }
1336
1337 $panel = $this->ui_factory->panel()->standard(
1338 $this->lng->txt('import_question'),
1339 [
1340 $this->ui_factory->legacy()->content($this->lng->txt('qpl_import_verify_found_questions')),
1341 $form
1342 ]
1343 );
1344 $this->tpl->setContent($this->ui_renderer->render($panel));
1345 $this->tpl->printToStdout();
1346 exit;
1347 }
1348
1349 protected function importFile(string $file_to_import, string $path_to_uploaded_file_in_temp_dir): void
1350 {
1351 list($subdir, $importdir, $xmlfile, $qtifile) = $this->buildImportDirectoriesFromImportFile($file_to_import);
1352
1354 ->withZipOutputPath($this->getImportTempDirectory());
1355
1356 $unzip = $this->archives->unzip(Streams::ofResource(fopen($file_to_import, 'r')), $options);
1357 $unzip->extract();
1358
1359 if (!file_exists($qtifile)) {
1360 ilFileUtils::delDir($importdir);
1361 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('cannot_find_xml'), true);
1362 return;
1363 }
1364
1365 ilSession::set('path_to_import_file', $file_to_import);
1366 ilSession::set('path_to_uploaded_file_in_temp_dir', $path_to_uploaded_file_in_temp_dir);
1367
1368 $this->ctrl->setParameterByClass(self::class, 'new_type', $this->type);
1369 $form = $this->buildImportQuestionsSelectionForm(
1370 'importVerifiedFile',
1371 $importdir,
1372 $qtifile,
1373 $path_to_uploaded_file_in_temp_dir
1374 );
1375
1376 if ($form === null) {
1377 return;
1378 }
1379
1380 $panel = $this->ui_factory->panel()->standard(
1381 $this->lng->txt('import_qpl'),
1382 [
1383 $this->ui_factory->legacy()->content($this->lng->txt('qpl_import_verify_found_questions')),
1384 $form
1385 ]
1386 );
1387 $this->tpl->setContent($this->ui_renderer->render($panel));
1388 $this->tpl->printToStdout();
1389 exit;
1390 }
1391
1392 public function addLocatorItems(): void
1393 {
1394 $ilLocator = $this->locator;
1395
1396 switch ($this->ctrl->getCmd()) {
1397 case 'create':
1398 case 'importFile':
1399 case 'cancel':
1400 break;
1401 default:
1402 $this->ctrl->clearParameterByClass(self::class, 'q_id');
1403 $ilLocator->addItem(
1404 $this->object->getTitle(),
1405 $this->ctrl->getLinkTargetByClass([ilRepositoryGUI::class, self::class], ''),
1406 '',
1407 $this->request_data_collector->getRefId()
1408 );
1409 $this->ctrl->setParameter($this, 'q_id', $this->request_data_collector->getQuestionId());
1410 break;
1411 }
1412
1413 if (!is_array($this->request_data_collector->raw('q_id')) && $this->request_data_collector->raw('q_id') > 0 && $this->request_data_collector->raw(
1414 'cmd'
1415 ) !== self::DEFAULT_CMD) {
1416 $question_gui = assQuestionGUI::_getQuestionGUI('', $this->request_data_collector->getQuestionId());
1417 if ($question_gui !== null && $question_gui->getObject() instanceof assQuestion) {
1418 $question = $question_gui->getObject();
1419 $question->setObjId($this->object->getId());
1420 $question_gui->setObject($question);
1421 $title = $question_gui->getObject()->getTitleForHTMLOutput();
1422 if (!$title) {
1423 $title = $this->lng->txt('new') . ': ' . $this->questionrepository->getForQuestionId(
1424 $question_gui->getObject()->getId()
1425 )->getTypeName($this->lng);
1426 }
1427 $ilLocator->addItem($title, $this->ctrl->getLinkTargetByClass(get_class($question_gui), 'editQuestion'));
1428 } else {
1429 // Workaround for context issues: If no object was found, redirect without q_id parameter
1430 $this->ctrl->setParameter($this, 'q_id', '');
1431 $this->ctrl->redirect($this);
1432 }
1433 }
1434 }
1435
1439 public function setTitleAndDescription(): void
1440 {
1441 parent::setTitleAndDescription();
1442
1443 if (!is_array($this->request_data_collector->raw('q_id')) && $this->request_data_collector->raw('q_id') > 0 && $this->request_data_collector->raw(
1444 'cmd'
1445 ) !== self::DEFAULT_CMD) {
1446 $question_gui = assQuestionGUI::_getQuestionGUI('', $this->request_data_collector->getQuestionId());
1447 if ($question_gui->getObject() instanceof assQuestion) {
1448 $question = $question_gui->getObject();
1449 $question->setObjId($this->object->getId());
1450 $question_gui->setObject($question);
1451 $title = $this->object->getTitle() . ': ' . $question_gui->getObject()->getTitleForHTMLOutput();
1452 if (!$title) {
1453 $title = $this->lng->txt('new') . ': ' . $this->questionrepository->getForQuestionId(
1454 $question_gui->getObject()->getId()
1455 )->getTypeName($this->lng);
1456 }
1457 $this->tpl->setTitle(
1458 $this->refinery->encode()->htmlSpecialCharsAsEntities()->transform(
1459 $title,
1460 )
1461 );
1462 $this->tpl->setDescription(
1463 $question_gui->getObject()->getDescriptionForHTMLOutput()
1464 );
1465 $this->tpl->setTitleIcon(ilObject2::_getIcon($this->object->getId(), 'big', $this->object->getType()));
1466 } else {
1467 // Workaround for context issues: If no object was found, redirect without q_id parameter
1468 $this->ctrl->setParameter($this, 'q_id', '');
1469 $this->ctrl->redirect($this);
1470 }
1471 } else {
1472 $this->tpl->setTitle(
1473 $this->refinery->encode()->htmlSpecialCharsAsEntities()->transform(
1474 $this->object->getTitle()
1475 )
1476 );
1477 $this->tpl->setDescription(
1478 $this->refinery->encode()->htmlSpecialCharsAsEntities()->transform(
1479 $this->object->getLongDescription()
1480 )
1481 );
1482 $this->tpl->setTitleIcon(ilObject2::_getIcon($this->object->getId(), 'big', $this->object->getType()));
1483 }
1484 }
1485
1491 public function getTabs(): void
1492 {
1493 $with_write_access = $this->access->checkAccess('write', '', $this->object->getRefId());
1494 $with_read_access = $this->access->checkAccess('read', '', $this->object->getRefId());
1495
1496 $this->help->setScreenIdComponent('qpl');
1497
1498 switch ($this->ctrl->getNextClass()) {
1499 case '':
1500 case strtolower(ilInfoScreenGUI::class):
1501 case strtolower(ilPermissionGUI::class):
1502 case strtolower(ilObjectMetaDataGUI::class):
1503 case strtolower(ilExportGUI::class):
1504 case strtolower(ilQuestionPoolSkillAdministrationGUI::class):
1505 break;
1506
1507 case strtolower(ilTaxonomySettingsGUI::class):
1508 case strtolower(ilObjQuestionPoolSettingsGeneralGUI::class):
1509 if ($with_write_access) {
1510 $this->addSettingsSubTabs($this->tabs_gui);
1511 }
1512
1513 break;
1514
1515 default:
1516 return;
1517 }
1518 // questions
1519 $force_active = false;
1520 $commands = $this->request_data_collector->raw('cmd');
1521 if (is_array($commands)) {
1522 foreach ($commands as $key => $value) {
1523 if (preg_match('/^delete_.*/', $key, $matches) ||
1524 preg_match('/^addSelectGap_.*/', $key, $matches) ||
1525 preg_match('/^addTextGap_.*/', $key, $matches) ||
1526 preg_match('/^deleteImage_.*/', $key, $matches) ||
1527 preg_match('/^upload_.*/', $key, $matches) ||
1528 preg_match('/^addSuggestedSolution_.*/', $key, $matches)
1529 ) {
1530 $force_active = true;
1531 }
1532 }
1533 }
1534
1535 $force_active = $force_active || $this->request_data_collector->isset('imagemap_x');
1536 if (!$force_active) {
1537 $force_active = strtolower($this->ctrl->getCmdClass()) === strtolower(self::class)
1538 || $this->ctrl->getCmdClass() === '' && $this->ctrl->getCmd() === ''
1539 ? true
1540 : false;
1541 }
1542 if ($with_read_access) {
1543 $this->tabs_gui->addTarget(
1544 'assQuestions',
1545 $this->ctrl->getLinkTargetByClass(
1546 [ilRepositoryGUI::class, self::class],
1547 self::DEFAULT_CMD
1548 ),
1549 [
1550 self::DEFAULT_CMD,
1551 'filter',
1552 'resetFilter',
1553 'createQuestion',
1554 'importQuestions',
1555 'deleteQuestions',
1556 'filterQuestionBrowser',
1557 'view',
1558 'preview',
1559 'editQuestion',
1560 'exec_pg',
1561 'addItem',
1562 'upload',
1563 'save',
1564 'cancel',
1565 'addSuggestedSolution',
1566 'cancelExplorer',
1567 'linkChilds',
1568 'removeSuggestedSolution',
1569 'add',
1570 'addYesNo',
1571 'addTrueFalse',
1572 'createGaps',
1573 'setMediaMode',
1574 'uploadingImage',
1575 'uploadingImagemap',
1576 'addArea',
1577 'deletearea',
1578 'saveShape',
1579 'back',
1580 'addPair',
1581 'uploadingJavaapplet',
1582 'addParameter',
1583 'assessment',
1584 'addGIT',
1585 'addST',
1586 'addPG',
1587 'delete',
1588 'toggleGraphicalAnswers',
1589 'deleteAnswer',
1590 'deleteImage',
1591 'removeJavaapplet'
1592 ],
1593 '',
1594 '',
1595 $force_active
1596 );
1597 }
1598 if ($with_read_access) {
1599 $this->tabs_gui->addTab(
1600 'info_short',
1601 $this->lng->txt('info_short'),
1602 $this->ctrl->getLinkTargetByClass(
1603 [
1604 ilRepositoryGUI::class,
1605 self::class,
1606 ilInfoScreenGUI::class
1607 ]
1608 )
1609 );
1610 }
1611
1612 if ($with_write_access) {
1613 // properties
1614 $this->tabs_gui->addTarget(
1615 'settings',
1616 $this->ctrl->getLinkTargetByClass(ilObjQuestionPoolSettingsGeneralGUI::class),
1617 [],
1618 [ilObjQuestionPoolSettingsGeneralGUI::class, ilObjTaxonomyGUI::class]
1619 );
1620
1621 // skill service
1622 if ($this->isSkillsTabRequired()) {
1623 $link = $this->ctrl->getLinkTargetByClass(
1624 [ilQuestionPoolSkillAdministrationGUI::class, ilAssQuestionSkillAssignmentsGUI::class],
1626 );
1627
1628 $this->tabs_gui->addTarget('qpl_tab_competences', $link, [], []);
1629 }
1630 }
1631
1632 if ($with_read_access) {
1633 // print view
1634 $this->tabs_gui->addTarget(
1635 'print_view',
1636 $this->ctrl->getLinkTargetByClass([ilRepositoryGUI::class, self::class], 'print'),
1637 ['print'],
1638 '',
1639 ''
1640 );
1641 }
1642
1643 if ($with_write_access) {
1644 $mdgui = new ilObjectMetaDataGUI($this->object);
1645 $mdtab = $mdgui->getTab();
1646 if ($mdtab) {
1647 $this->tabs_gui->addTarget(
1648 'meta_data',
1649 $mdtab,
1650 '',
1651 'ilmdeditorgui'
1652 );
1653 }
1654 }
1655
1656 if ($with_write_access) {
1657 $this->tabs_gui->addTarget(
1658 'export',
1659 $this->ctrl->getLinkTargetByClass(ilExportGUI::class, ''),
1660 '',
1661 'ilexportgui'
1662 );
1663 }
1664
1665 if ($this->access->checkAccess('edit_permission', '', $this->object->getRefId())) {
1666 $this->tabs_gui->addTarget(
1667 'perm_settings',
1668 $this->ctrl->getLinkTargetByClass([ilRepositoryGUI::class, self::class, ilPermissionGUI::class], 'perm'),
1669 ['perm', 'info', 'owner'],
1670 'ilpermissiongui'
1671 );
1672 }
1673 }
1674
1675 private function isSkillsTabRequired(): bool
1676 {
1677 if (!($this->object instanceof ilObjQuestionPool)) {
1678 return false;
1679 }
1680
1681 if (!$this->object->isSkillServiceEnabled()) {
1682 return false;
1683 }
1684
1686 return false;
1687 }
1688
1689 return true;
1690 }
1691
1692 private function addSettingsSubTabs(ilTabsGUI $tabs): void
1693 {
1694 $tabs->addSubTab(
1696 $this->lng->txt('qpl_settings_subtab_general'),
1697 $this->ctrl->getLinkTargetByClass(ilObjQuestionPoolSettingsGeneralGUI::class),
1698 );
1699
1700 $tabs->addSubTab(
1701 'tax_settings',
1702 $this->lng->txt('qpl_settings_subtab_taxonomies'),
1703 $this->ctrl->getLinkTargetByClass(ilTaxonomySettingsGUI::class, ''),
1704 );
1705 }
1706
1707 public function infoScreenObject(): void
1708 {
1709 $this->ctrl->redirectByClass(
1710 [
1711 ilRepositoryGUI::class,
1712 self::class,
1713 ilInfoScreenGUI::class
1714 ]
1715 );
1716 }
1717
1718 public function infoScreenForward(): void
1719 {
1720 if (!$this->access->checkAccess('visible', '', $this->ref_id)) {
1721 $this->error->raiseError($this->lng->txt('msg_no_perm_read'));
1722 }
1723
1724 $this->tabs_gui->activateTab('info_short');
1725 $info = new ilInfoScreenGUI($this);
1726 $info->enablePrivateNotes();
1727 $info->addMetaDataSections($this->object->getId(), 0, $this->object->getType());
1728
1729 $this->ctrl->forwardCommand($info);
1730 }
1731
1732 public static function _goto($a_target): void
1733 {
1735 global $DIC;
1736 $main_tpl = $DIC->ui()->mainTemplate();
1737 $ilAccess = $DIC['ilAccess'];
1738 $ilErr = $DIC['ilErr'];
1739 $lng = $DIC['lng'];
1740 $ctrl = $DIC['ilCtrl'];
1741
1742 $target_ref_id = (int) $a_target;
1743
1744 if ($ilAccess->checkAccess('write', '', $target_ref_id)
1745 || $ilAccess->checkAccess('read', '', $target_ref_id)
1746 ) {
1747 $ctrl->setParameterByClass(ilObjQuestionPoolGUI::class, 'ref_id', $a_target);
1748 $ctrl->redirectByClass([ilRepositoryGUI::class, ilObjQuestionPoolGUI::class], self::DEFAULT_CMD);
1749 return;
1750 }
1751 if ($ilAccess->checkAccess('visible', '', $target_ref_id)) {
1752 $DIC->ctrl()->setParameterByClass(ilInfoScreenGUI::class, 'ref_id', $a_target);
1753 $DIC->ctrl()->redirectByClass(
1754 [
1755 ilRepositoryGUI::class,
1756 self::class,
1757 ilInfoScreenGUI::class
1758 ]
1759 );
1760 }
1761 if ($ilAccess->checkAccess('read', '', ROOT_FOLDER_ID)) {
1762 $main_tpl->setOnScreenMessage(
1763 'info',
1764 sprintf(
1765 $lng->txt('msg_no_perm_read_item'),
1767 ),
1768 true
1769 );
1771 return;
1772 }
1773 $ilErr->raiseError($lng->txt('msg_no_perm_read_lm'), $ilErr->FATAL);
1774 }
1775
1776 protected function getTable(): string
1777 {
1778 $f = $this->ui_factory;
1779 $r = $this->ui_renderer;
1780
1781 $table = new QuestionTable(
1782 $f,
1783 $r,
1784 $this->data_factory,
1785 $this->refinery,
1786 $this->url_builder,
1787 $this->action_parameter_token,
1788 $this->row_id_token,
1789 $this->db,
1790 $this->lng,
1791 $this->component_repository,
1792 $this->rbac_system,
1793 $this->user,
1794 $this->taxonomy->domain(),
1795 $this->notes_service,
1796 $this->object->getId(),
1797 $this->request_data_collector->getRefId()
1798 );
1799
1804 $filter_action = $this->ctrl->getLinkTarget($this, self::DEFAULT_CMD);
1805 $filter = $table->getFilter($this->ui_service, $filter_action);
1806
1807 $filter_params = $this->ui_service->filter()->getData($filter);
1808
1809 if ($filter_params) {
1810 foreach (array_filter($filter_params) as $item => $value) {
1811 switch ($item) {
1812 case 'taxonomies':
1813 foreach ($value as $tax_value) {
1814 if ($tax_value === 'null') {
1815 $table->addTaxonomyFilterNoTaxonomySet(true);
1816 } else {
1817 $tax_nodes = explode('-', $tax_value);
1818 $tax_id = array_shift($tax_nodes);
1819 $table->addTaxonomyFilter(
1820 $tax_id,
1821 $tax_nodes,
1822 $this->object->getId(),
1823 $this->object->getType()
1824 );
1825 }
1826 }
1827 break;
1828 case 'commented':
1829 $table->setCommentFilter((int) $value);
1830 break;
1831 default:
1832 $table->addFieldFilter($item, $value);
1833 }
1834 }
1835 }
1836
1837 return $r->render([
1838 $filter,
1839 $table->getTable()
1840 ->withRequest($this->request)
1841 ]);
1842 }
1843}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$filename
Definition: buildRTE.php:78
$out
Definition: buildRTE.php:24
Builds data types.
Definition: Factory.php:36
Mime type determination.
Definition: MimeType.php:30
Stream factory which enables the user to create streams without the knowledge of the concrete class.
Definition: Streams.php:32
Class Services.
Definition: Services.php:38
acquireParameters(array $namespace, string ... $names)
Definition: URLBuilder.php:138
error(string $a_errmsg)
return true
static _getQuestionGUI(string $question_type='', int $question_id=-1)
Creates a question gui representation and returns the alias to the question gui.
const ADDITIONAL_CONTENT_EDITING_MODE_RTE
const ADDITIONAL_CONTENT_EDITING_MODE_IPE
Question page GUI class.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getInstanceFromAjaxCall()
(Re-)Build instance from ajax call
static buildAjaxHash(int $node_type, ?int $node_id, string $obj_type, int $obj_id, ?string $sub_type=null, ?int $sub_id=null, int $news_id=0)
Build ajax hash.
Component logger with individual log levels by component id.
Export User Interface Class.
static deliverFileLegacy(string $a_file, ?string $a_filename=null, ?string $a_mime=null, ?bool $isInline=false, ?bool $removeAfterDelivery=false, ?bool $a_exit_after=true)
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
Help GUI class.
Import class.
Class ilInfoScreenGUI.
Class ilLocalUnitConfigurationGUI.
Last visited history for repository items.
static getListCommentsJSCall(string $a_hash, ?string $a_update_code=null)
Get list comments js call.
Class ilObjFile.
Class ilObjQuestionPoolGUI.
confirmDeleteQuestionsObject()
delete questions after confirmation
GlobalTestSettings $global_test_settings
updateObject()
updates object entry in object_data
download_paragraphObject()
download source code paragraph
afterSave(ilObject $new_object)
Post (successful) object creation hook.
deleteQuestionsObject()
delete questions confirmation screen
getTabs()
adds tabs to tab gui object
importQuestionsFromQtiFile(ilObjQuestionPool $obj, array $selected_questions, string $qtifile, string $importdir, string $xmlfile='')
addLocatorItems()
should be overwritten to add object specific items (repository items are preloaded)
cleanupAfterImport(string $importdir)
importFile(string $file_to_import, string $path_to_uploaded_file_in_temp_dir)
ilComponentFactory $component_factory
ilNavigationHistory $navigation_history
questionsObject(?RoundTripModal $import_questions_modal=null)
list questions of question pool
setTitleAndDescription()
called by prepare output
RequestDataCollector $request_data_collector
importQuestionsFile(string $path_to_uploaded_file_in_temp_dir)
createQuestionFormObject(?Form $form=null)
exportObject()
Gateway for exports initiated from workspace, as there is a generic forward to {objTypeMainGUI}::expo...
importQuestionPoolWithValidManifest(ilObjQuestionPool $obj, array $selected_questions, string $file_to_import)
ilComponentRepository $component_repository
GeneralQuestionPropertiesRepository $questionrepository
fullscreenObject()
show fullscreen view
static getQuestionTypeByTypeId($type_id)
static getContentStylePath(int $a_style_id, bool $add_random=true, bool $add_token=true)
get content style path static (to avoid full reading)
GUI class for the workflow of copying objects.
Class ilObjectGUI Basic methods of all Output classes.
static _gotoRepositoryRoot(bool $raise_error=false)
Goto repository root.
checkPermissionBool(string $perm, string $cmd="", string $type="", ?int $ref_id=null)
prepareOutput(bool $show_sub_objects=true)
Class ilObjectMetaDataGUI.
Class ilObject Basic functions for all objects.
static _getIcon(int $obj_id=0, string $size="big", string $type="", bool $offline=false)
Get icon for repository item.
static _lookupObjId(int $ref_id)
static _lookupTitle(int $obj_id)
startParsing()
stores xml data in array
Legacy Content Object Parser.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static get(string $a_var)
static clear(string $a_var)
static set(string $a_var, $a_val)
Set a value.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
addSubTab(string $a_id, string $a_text, string $a_link, string $a_frame="")
Filter service.
Class ilUnitConfigurationRepository.
static getStyleSheetLocation(string $mode="output", string $a_css_name="")
get full style sheet file name (path inclusive) of current user
static redirect(string $a_script)
const ROOT_FOLDER_ID
Definition: constants.php:32
exit
$info
Definition: entry_point.php:21
This describes commonalities between all forms.
Definition: Form.php:33
This describes select field.
Definition: Select.php:29
This describes commonalities between all inputs.
Definition: Input.php:47
withValue($value)
Get an input like this with another value displayed on the client side.
Readable part of repository interface to ilComponentDataDB.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Interface ilDBInterface.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
buildImportQuestionsSelectionForm(string $form_cmd, string $importdir, string $qtifile, ?string $path_to_uploaded_file_in_temp_dir=null)
buildImportDirectoriesFromImportFile(string $file_to_import)
retrieveSelectedQuestionsFromImportQuestionsSelectionForm(string $form_cmd, string $importdir, string $qtifile, ServerRequestInterface $request)
Class ilObjForumAdministration.
global $lng
Definition: privfeed.php:31
$ilErr
Definition: raiseError.php:33
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26