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