ILIAS  release_8 Revision v8.24
class.ilObjQuestionPool.php
Go to the documentation of this file.
1<?php
2
19include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
20
32{
33 private array $mob_ids;
34 private array $file_ids;
35
41 public $online;
42
48 private $showTaxonomies = null;
49
55 private $navTaxonomyId = null;
56
61
66 private $import_dir;
67
74 public function __construct($a_id = 0, $a_call_by_reference = true)
75 {
76 $this->type = "qpl";
77 parent::__construct($a_id, $a_call_by_reference);
78 $this->setOnline(0);
79
80 $this->skillServiceEnabled = false;
81 }
82
86 public function create($a_upload = false): int
87 {
88 $id = parent::create();
89
90 // meta data will be created by
91 // import parser
92 if (!$a_upload) {
93 $this->createMetaData();
94 }
95 return $id;
96 }
97
104 public function createReference(): int
105 {
106 $result = parent::createReference();
107 $this->saveToDb();
108 return $result;
109 }
110
117 public function update(): bool
118 {
119 $this->updateMetaData();
120 if (!parent::update()) {
121 return false;
122 }
123
124 // put here object specific stuff
125
126 return true;
127 }
128
129 protected function beforeUpdateMetaData(): bool
130 {
131 global $DIC;
132 $ilUser = $DIC['ilUser'];
133 include_once "./Services/MetaData/classes/class.ilMD.php";
134 $md = new ilMD($this->getId(), 0, $this->getType());
135 $md_gen = $md->getGeneral();
136 if ($md_gen == false) {
137 include_once "./Services/MetaData/classes/class.ilMDCreator.php";
138 $md_creator = new ilMDCreator($this->getId(), 0, $this->getType());
139 $md_creator->setTitle($this->getTitle());
140 $md_creator->setTitleLanguage($ilUser->getPref('language'));
141 $md_creator->create();
142 }
143 return true;
144 }
145
151 public function read($a_force_db = false): void
152 {
153 parent::read($a_force_db);
154 $this->loadFromDb();
155 }
156
157
164 public function delete(): bool
165 {
166 // always call parent delete function first!!
167 if (!parent::delete()) {
168 return false;
169 }
170
171 // delete meta data
172 $this->deleteMetaData();
173
174 //put here your module specific stuff
175 $this->deleteQuestionpool();
176
177 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssQuestionSkillAssignmentImportFails.php';
178 $qsaImportFails = new ilAssQuestionSkillAssignmentImportFails($this->getId());
179 $qsaImportFails->deleteRegisteredImportFails();
180
181 return true;
182 }
183
184 public function deleteQuestionpool(): void
185 {
186 $questions = &$this->getAllQuestions();
187
188 if (count($questions)) {
189 foreach ($questions as $question_id) {
190 $this->deleteQuestion($question_id);
191 }
192 }
193
194 // delete export files
195 include_once "./Services/Utilities/classes/class.ilUtil.php";
196 $qpl_data_dir = ilFileUtils::getDataDir() . "/qpl_data";
197 $directory = $qpl_data_dir . "/qpl_" . $this->getId();
198 if (is_dir($directory)) {
199 include_once "./Services/Utilities/classes/class.ilUtil.php";
200 ilFileUtils::delDir($directory);
201 }
202 }
203
210 public function deleteQuestion($question_id): void
211 {
212 include_once "./Modules/Test/classes/class.ilObjTest.php";
213 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
214
215 $question = assQuestion::instantiateQuestion($question_id);
216 $question->delete($question_id);
217 }
218
224 public function loadFromDb(): void
225 {
226 global $DIC;
227 $ilDB = $DIC['ilDB'];
228
229 $result = $ilDB->queryF(
230 "SELECT * FROM qpl_questionpool WHERE obj_fi = %s",
231 array('integer'),
232 array($this->getId())
233 );
234 if ($result->numRows() == 1) {
235 $row = $ilDB->fetchAssoc($result);
236 $this->setOnline($row['isonline']);
237 $this->setShowTaxonomies($row['show_taxonomies']);
238 $this->setNavTaxonomyId($row['nav_taxonomy']);
239 $this->setSkillServiceEnabled($row['skill_service']);
240 }
241 }
242
248 public function saveToDb(): void
249 {
250 global $DIC;
251 $ilDB = $DIC['ilDB'];
252
253 $result = $ilDB->queryF(
254 "SELECT id_questionpool FROM qpl_questionpool WHERE obj_fi = %s",
255 array('integer'),
256 array($this->getId())
257 );
258
259 if ($result->numRows() == 1) {
260 $result = $ilDB->update(
261 'qpl_questionpool',
262 array(
263 'isonline' => array('text', $this->getOnline()),
264 'show_taxonomies' => array('integer', (int) $this->getShowTaxonomies()),
265 'nav_taxonomy' => array('integer', (int) $this->getNavTaxonomyId()),
266 'skill_service' => array('integer', (int) $this->isSkillServiceEnabled()),
267 'tstamp' => array('integer', time())
268 ),
269 array(
270 'obj_fi' => array('integer', $this->getId())
271 )
272 );
273 } else {
274 $next_id = $ilDB->nextId('qpl_questionpool');
275
276 $result = $ilDB->insert('qpl_questionpool', array(
277 'id_questionpool' => array('integer', $next_id),
278 'isonline' => array('text', $this->getOnline()),
279 'show_taxonomies' => array('integer', (int) $this->getShowTaxonomies()),
280 'nav_taxonomy' => array('integer', (int) $this->getNavTaxonomyId()),
281 'skill_service' => array('integer', (int) $this->isSkillServiceEnabled()),
282 'tstamp' => array('integer', time()),
283 'obj_fi' => array('integer', $this->getId())
284 ));
285 }
286 }
287
288 public function getQuestiontype($question_id)
289 {
290 global $DIC;
291 $ilDB = $DIC['ilDB'];
292
293 if ($question_id < 1) {
294 return null;
295 }
296
297 $result = $ilDB->queryF(
298 "SELECT qpl_qst_type.type_tag FROM qpl_questions, qpl_qst_type WHERE qpl_questions.question_type_fi = qpl_qst_type.question_type_id AND qpl_questions.question_id = %s",
299 array('integer'),
300 array($question_id)
301 );
302
303 if ($result->numRows() == 1) {
304 $data = $ilDB->fetchAssoc($result);
305 return $data["type_tag"];
306 }
307 return null;
308 }
309
317 public function isInUse($question_id): bool
318 {
319 global $DIC;
320 $ilDB = $DIC['ilDB'];
321
322 $result = $ilDB->queryF(
323 "SELECT COUNT(solution_id) solution_count FROM tst_solutions WHERE question_fi = %s",
324 array('integer'),
325 array($question_id)
326 );
327 $row = $ilDB->fetchAssoc($result);
328 return $row["solution_count"];
329 }
330
331 public function createQuestion($question_type, $question_id = -1)
332 {
333 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
334 if ($question_id > 0) {
335 return assQuestion::instantiateQuestionGUI($question_id);
336 }
337 assQuestion::_includeClass($question_type, 1);
338 $question_type_gui = $question_type . "GUI";
339 $question_gui = new $question_type_gui();
340 return $question_gui;
341 }
342
349 public function duplicateQuestion($question_id): int
350 {
351 $question = $this->createQuestion("", $question_id);
352 $newtitle = $question->object->getTitle();
353 if ($question->object->questionTitleExists($this->getId(), $question->object->getTitle())) {
354 $counter = 2;
355 while ($question->object->questionTitleExists($this->getId(), $question->object->getTitle() . " ($counter)")) {
356 $counter++;
357 }
358 $newtitle = $question->object->getTitle() . " ($counter)";
359 }
360 $new_id = $question->object->duplicate(false, $newtitle);
361 // update question count of question pool
363 return $new_id;
364 }
365
373 public function copyQuestion($question_id, $questionpool_to): int
374 {
375 $question_gui = $this->createQuestion("", $question_id);
376 if ($question_gui->object->getObjId() == $questionpool_to) {
377 // the question is copied into the same question pool
378 return $this->duplicateQuestion($question_id);
379 } else {
380 // the question is copied into another question pool
381 $newtitle = $question_gui->object->getTitle();
382 if ($question_gui->object->questionTitleExists($this->getId(), $question_gui->object->getTitle())) {
383 $counter = 2;
384 while ($question_gui->object->questionTitleExists($this->getId(), $question_gui->object->getTitle() . " ($counter)")) {
385 $counter++;
386 }
387 $newtitle = $question_gui->object->getTitle() . " ($counter)";
388 }
389 return $question_gui->object->copyObject($this->getId(), $newtitle);
390 }
391 }
392
398 public function getPrintviewQuestions(): array
399 {
400 global $DIC;
401 $ilDB = $DIC['ilDB'];
402
403 $query_result = $ilDB->queryF(
404 "SELECT qpl_questions.*, qpl_qst_type.type_tag, qpl_qst_type.plugin, qpl_questions.tstamp updated FROM qpl_questions, qpl_qst_type WHERE qpl_questions.original_id IS NULL AND qpl_questions.tstamp > 0 AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id AND qpl_questions.obj_fi = %s",
405 array('integer'),
406 array($this->getId())
407 );
408 $rows = array();
409 $types = $this->getQuestionTypeTranslations();
410 if ($query_result->numRows()) {
411 while ($row = $ilDB->fetchAssoc($query_result)) {
412 $row['ttype'] = $types[$row['type_tag']];
413 if ($row["plugin"]) {
414 if ($this->isPluginActive($row["type_tag"])) {
415 array_push($rows, $row);
416 }
417 } else {
418 array_push($rows, $row);
419 }
420 }
421 }
422 return $rows;
423 }
424
428 private function exportXMLSettings($xmlWriter): void
429 {
430 $xmlWriter->xmlStartTag('Settings');
431
432 $xmlWriter->xmlElement('ShowTaxonomies', null, (int) $this->getShowTaxonomies());
433 $xmlWriter->xmlElement('NavTaxonomy', null, (int) $this->getNavTaxonomyId());
434 $xmlWriter->xmlElement('SkillService', null, (int) $this->isSkillServiceEnabled());
435
436 $xmlWriter->xmlEndTag('Settings');
437 }
438
445 public function objectToXmlWriter(ilXmlWriter &$a_xml_writer, $a_inst, $a_target_dir, &$expLog, $questions): void
446 {
447 global $DIC;
448 $ilBench = $DIC['ilBench'];
449
450 $this->mob_ids = array();
451 $this->file_ids = array();
452
453 $attrs = array();
454 $attrs["Type"] = "Questionpool_Test";
455 $a_xml_writer->xmlStartTag("ContentObject", $attrs);
456
457 // MetaData
458 $this->exportXMLMetaData($a_xml_writer);
459
460 // Settings
461 $this->exportXMLSettings($a_xml_writer);
462
463 // PageObjects
464 $expLog->write(date("[y-m-d H:i:s] ") . "Start Export Page Objects");
465 $ilBench->start("ContentObjectExport", "exportPageObjects");
466 $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog, $questions);
467 $ilBench->stop("ContentObjectExport", "exportPageObjects");
468 $expLog->write(date("[y-m-d H:i:s] ") . "Finished Export Page Objects");
469
470 // MediaObjects
471 $expLog->write(date("[y-m-d H:i:s] ") . "Start Export Media Objects");
472 $ilBench->start("ContentObjectExport", "exportMediaObjects");
473 $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
474 $ilBench->stop("ContentObjectExport", "exportMediaObjects");
475 $expLog->write(date("[y-m-d H:i:s] ") . "Finished Export Media Objects");
476
477 // FileItems
478 $expLog->write(date("[y-m-d H:i:s] ") . "Start Export File Items");
479 $ilBench->start("ContentObjectExport", "exportFileItems");
480 $this->exportFileItems($a_target_dir, $expLog);
481 $ilBench->stop("ContentObjectExport", "exportFileItems");
482 $expLog->write(date("[y-m-d H:i:s] ") . "Finished Export File Items");
483
484 // skill assignments
485 $this->populateQuestionSkillAssignmentsXml($a_xml_writer, $questions);
486
487 $a_xml_writer->xmlEndTag("ContentObject");
488 }
489
494 protected function populateQuestionSkillAssignmentsXml(ilXmlWriter &$a_xml_writer, $questions): void
495 {
496 global $DIC;
497 $ilDB = $DIC['ilDB'];
498
499 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php';
500 $assignmentList = new ilAssQuestionSkillAssignmentList($ilDB);
501 $assignmentList->setParentObjId($this->getId());
502 $assignmentList->loadFromDb();
503 $assignmentList->loadAdditionalSkillData();
504
505 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssQuestionSkillAssignmentExporter.php';
506 $skillQuestionAssignmentExporter = new ilAssQuestionSkillAssignmentExporter();
507 $skillQuestionAssignmentExporter->setXmlWriter($a_xml_writer);
508 $skillQuestionAssignmentExporter->setQuestionIds($questions);
509 $skillQuestionAssignmentExporter->setAssignmentList($assignmentList);
510 $skillQuestionAssignmentExporter->export();
511 }
512
519 public function exportXMLMetaData(&$a_xml_writer): void
520 {
521 include_once("Services/MetaData/classes/class.ilMD2XML.php");
522 $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
523 $md2xml->setExportMode(true);
524 $md2xml->startExport();
525 $a_xml_writer->appendXML($md2xml->getXML());
526 }
527
528 public function modifyExportIdentifier($a_tag, $a_param, $a_value)
529 {
530 if ($a_tag == "Identifier" && $a_param == "Entry") {
531 include_once "./Services/Utilities/classes/class.ilUtil.php";
532 $a_value = ilUtil::insertInstIntoID($a_value);
533 }
534
535 return $a_value;
536 }
537
538
545 public function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog, $questions): void
546 {
547 global $DIC;
548 $ilBench = $DIC['ilBench'];
549
550 include_once "./Modules/LearningModule/classes/class.ilLMPageObject.php";
551
552 foreach ($questions as $question_id) {
553 $ilBench->start("ContentObjectExport", "exportPageObject");
554 $expLog->write(date("[y-m-d H:i:s] ") . "Page Object " . $question_id);
555
556 $attrs = array();
557 $a_xml_writer->xmlStartTag("PageObject", $attrs);
558
559
560 // export xml to writer object
561 $ilBench->start("ContentObjectExport", "exportPageObject_XML");
562 include_once("./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php");
563 $page_object = new ilAssQuestionPage($question_id);
564 $page_object->buildDom();
565 $page_object->insertInstIntoIDs($a_inst);
566 $mob_ids = $page_object->collectMediaObjects(false);
567 require_once 'Services/COPage/classes/class.ilPCFileList.php';
568 $file_ids = ilPCFileList::collectFileItems($page_object, $page_object->getDomDoc());
569 $xml = $page_object->getXMLFromDom(false, false, false, "", true);
570 $xml = str_replace("&", "&amp;", $xml);
571 $a_xml_writer->appendXML($xml);
572 $page_object->freeDom();
573 unset($page_object);
574
575 $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
576
577 // collect media objects
578 $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
579 foreach ($mob_ids as $mob_id) {
580 $this->mob_ids[$mob_id] = $mob_id;
581 }
582 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
583
584 // collect all file items
585 $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
586 //$file_ids = $page_obj->getFileItemIds();
587 foreach ($file_ids as $file_id) {
588 $this->file_ids[$file_id] = $file_id;
589 }
590 $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
591
592 $a_xml_writer->xmlEndTag("PageObject");
593
594 $ilBench->stop("ContentObjectExport", "exportPageObject");
595 }
596 }
597
598 public function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog): void
599 {
600 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
601
602 foreach ($this->mob_ids as $mob_id) {
603 $expLog->write(date("[y-m-d H:i:s] ") . "Media Object " . $mob_id);
604 if (ilObjMediaObject::_exists($mob_id)) {
605 $media_obj = new ilObjMediaObject($mob_id);
606 $media_obj->exportXML($a_xml_writer, $a_inst);
607 $media_obj->exportFiles($a_target_dir);
608 unset($media_obj);
609 }
610 }
611 }
612
617 public function exportFileItems($target_dir, &$expLog): void
618 {
619 include_once("./Modules/File/classes/class.ilObjFile.php");
620
621 foreach ($this->file_ids as $file_id) {
622 $expLog->write(date("[y-m-d H:i:s] ") . "File Item " . $file_id);
623 $file_dir = $target_dir . '/objects/il_' . IL_INST_ID . '_file_' . $file_id;
624 ilFileUtils::makeDir($file_dir);
625 $file_obj = new ilObjFile($file_id, false);
626 $source_file = $file_obj->getFile($file_obj->getVersion());
627 if (!is_file($source_file)) {
628 $source_file = $file_obj->getFile();
629 }
630 if (is_file($source_file)) {
631 copy($source_file, $file_dir . '/' . $file_obj->getFileName());
632 }
633 unset($file_obj);
634 }
635 }
636
642 public function createExportDirectory(): void
643 {
644 include_once "./Services/Utilities/classes/class.ilUtil.php";
645 $qpl_data_dir = ilFileUtils::getDataDir() . "/qpl_data";
646 ilFileUtils::makeDir($qpl_data_dir);
647 if (!is_writable($qpl_data_dir)) {
648 $this->ilias->raiseError("Questionpool Data Directory (" . $qpl_data_dir
649 . ") not writeable.", $this->ilias->error_obj->FATAL);
650 }
651
652 // create learning module directory (data_dir/lm_data/lm_<id>)
653 $qpl_dir = $qpl_data_dir . "/qpl_" . $this->getId();
654 ilFileUtils::makeDir($qpl_dir);
655 if (!@is_dir($qpl_dir)) {
656 $this->ilias->raiseError("Creation of Questionpool Directory failed.", $this->ilias->error_obj->FATAL);
657 }
658 // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
660 if (!@is_dir($this->getExportDirectory('xls'))) {
661 $this->ilias->raiseError("Creation of Export Directory failed.", $this->ilias->error_obj->FATAL);
662 }
664 if (!@is_dir($this->getExportDirectory('zip'))) {
665 $this->ilias->raiseError("Creation of Export Directory failed.", $this->ilias->error_obj->FATAL);
666 }
667 }
668
672 public function getExportDirectory($type = ""): string
673 {
674 include_once "./Services/Utilities/classes/class.ilUtil.php";
675 switch ($type) {
676 case 'xml':
677 include_once("./Services/Export/classes/class.ilExport.php");
678 $export_dir = ilExport::_getExportDirectory($this->getId(), $type, $this->getType());
679 break;
680 case 'xls':
681 case 'zip':
682 $export_dir = ilFileUtils::getDataDir() . "/qpl_data" . "/qpl_" . $this->getId() . "/export_$type";
683 break;
684 default:
685 $export_dir = ilFileUtils::getDataDir() . "/qpl_data" . "/qpl_" . $this->getId() . "/export";
686 break;
687 }
688 return $export_dir;
689 }
690
696 public static function _createImportDirectory(): string
697 {
698 global $DIC;
699 $ilias = $DIC['ilias'];
700
701 include_once "./Services/Utilities/classes/class.ilUtil.php";
702 $qpl_data_dir = ilFileUtils::getDataDir() . "/qpl_data";
703 ilFileUtils::makeDir($qpl_data_dir);
704
705 if (!is_writable($qpl_data_dir)) {
706 $ilias->raiseError("Questionpool Data Directory (" . $qpl_data_dir
707 . ") not writeable.", $ilias->error_obj->FATAL);
708 }
709
710 // create questionpool directory (data_dir/qpl_data/qpl_import)
711 $qpl_dir = $qpl_data_dir . "/qpl_import";
712 ilFileUtils::makeDir($qpl_dir);
713 if (!@is_dir($qpl_dir)) {
714 $ilias->raiseError("Creation of Questionpool Directory failed.", $ilias->error_obj->FATAL);
715 }
716 return $qpl_dir;
717 }
718
722 public static function _setImportDirectory($a_import_dir = null): void
723 {
724 if (strlen($a_import_dir)) {
725 ilSession::set("qpl_import_dir", $a_import_dir);
726 } else {
727 ilSession::clear("qpl_import_dir");
728 }
729 }
730
734 public static function _getImportDirectory(): string
735 {
736 return ilSession::get("qpl_import_dir") ?? '';
737 }
738
739 public function getImportDirectory()
740 {
742 }
743
749 public function &getAllQuestions(): array
750 {
751 global $DIC;
752 $ilDB = $DIC['ilDB'];
753
754 $result = $ilDB->queryF(
755 "SELECT question_id FROM qpl_questions WHERE obj_fi = %s AND qpl_questions.tstamp > 0 AND original_id IS NULL",
756 array('integer'),
757 array($this->getId())
758 );
759 $questions = array();
760 while ($row = $ilDB->fetchAssoc($result)) {
761 array_push($questions, $row["question_id"]);
762 }
763 return $questions;
764 }
765
766 public function &getAllQuestionIds(): array
767 {
768 global $DIC;
769 $ilDB = $DIC['ilDB'];
770
771 $query_result = $ilDB->queryF(
772 "SELECT question_id, qpl_qst_type.type_tag, qpl_qst_type.plugin FROM qpl_questions, qpl_qst_type WHERE original_id IS NULL AND qpl_questions.tstamp > 0 AND obj_fi = %s AND complete = %s AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id",
773 array('integer','text'),
774 array($this->getId(), 1)
775 );
776 $questions = array();
777 if ($query_result->numRows()) {
778 while ($row = $ilDB->fetchAssoc($query_result)) {
779 if ($row["plugin"]) {
780 if ($this->isPluginActive($row["type_tag"])) {
781 array_push($questions, $row["question_id"]);
782 }
783 } else {
784 array_push($questions, $row["question_id"]);
785 }
786 }
787 }
788 return $questions;
789 }
790
791 public function checkQuestionParent($questionId): bool
792 {
793 global $DIC; /* @var ILIAS\DI\Container $DIC */
794
795 $row = $DIC->database()->fetchAssoc($DIC->database()->queryF(
796 "SELECT COUNT(question_id) cnt FROM qpl_questions WHERE question_id = %s AND obj_fi = %s",
797 array('integer', 'integer'),
798 array($questionId, $this->getId())
799 ));
800
801 return (bool) $row['cnt'];
802 }
803
808 public function getImportMapping(): array
809 {
810 return array();
811 }
812
820 public function questionsToXML($questions): string
821 {
822 $xml = "";
823 // export button was pressed
824 if (count($questions) > 0) {
825 foreach ($questions as $key => $value) {
826 $question = $this->createQuestion("", $value);
827 $xml .= $question->object->toXML();
828 }
829 if (count($questions) > 1) {
830 $xml = preg_replace("/<\/questestinterop>\s*<.xml.*?>\s*<questestinterop>/", "", $xml);
831 }
832 }
833 $xml = preg_replace("/(<\?xml[^>]*?>)/", "\\1" . "<!DOCTYPE questestinterop SYSTEM \"ims_qtiasiv1p2p1.dtd\">", $xml);
834 return $xml;
835 }
836
845 public static function _getQuestionCount($questionpool_id, $complete_questions_only = false): int
846 {
847 global $DIC;
848 $ilDB = $DIC['ilDB'];
849 if ($complete_questions_only) {
850 $result = $ilDB->queryF(
851 "SELECT COUNT(question_id) question_count FROM qpl_questions WHERE obj_fi = %s AND qpl_questions.tstamp > 0 AND original_id IS NULL AND complete = %s",
852 array('integer', 'text'),
853 array($questionpool_id, 1)
854 );
855 } else {
856 $result = $ilDB->queryF(
857 "SELECT COUNT(question_id) question_count FROM qpl_questions WHERE obj_fi = %s AND qpl_questions.tstamp > 0 AND original_id IS NULL",
858 array('integer'),
859 array($questionpool_id)
860 );
861 }
862 $row = $ilDB->fetchAssoc($result);
863 return $row["question_count"];
864 }
865
873 public function setOnline($a_online_status): void
874 {
875 switch ($a_online_status) {
876 case 0:
877 case 1:
878 $this->online = $a_online_status;
879 break;
880 default:
881 $this->online = 0;
882 break;
883 }
884 }
885
886 public function getOnline(): string
887 {
888 if (strcmp($this->online, "") == 0) {
889 $this->online = "0";
890 }
891 return $this->online;
892 }
893
894 public function setShowTaxonomies($showTaxonomies): void
895 {
896 $this->showTaxonomies = $showTaxonomies;
897 }
898
899 public function getShowTaxonomies(): ?bool
900 {
902 }
903
904 public function setNavTaxonomyId($navTaxonomyId): void
905 {
906 $this->navTaxonomyId = $navTaxonomyId;
907 }
908
909 public function getNavTaxonomyId(): ?int
910 {
912 }
913
914 public function isNavTaxonomyActive(): bool
915 {
916 return $this->getShowTaxonomies() && (int) $this->getNavTaxonomyId();
917 }
918
919 public static function _lookupOnline($a_obj_id, $is_reference = false)
920 {
921 global $DIC;
922 $ilDB = $DIC['ilDB'];
923
924 if ($is_reference) {
925 $result = $ilDB->queryF(
926 "SELECT qpl_questionpool.isonline FROM qpl_questionpool,object_reference WHERE object_reference.ref_id = %s AND object_reference.obj_id = qpl_questionpool.obj_fi",
927 array('integer'),
928 array($a_obj_id)
929 );
930 } else {
931 $result = $ilDB->queryF(
932 "SELECT isonline FROM qpl_questionpool WHERE obj_fi = %s",
933 array('integer'),
934 array($a_obj_id)
935 );
936 }
937 if ($result->numRows() == 1) {
938 $row = $ilDB->fetchAssoc($result);
939 return $row["isonline"];
940 }
941 return 0;
942 }
943
950 public static function _hasEqualPoints($a_obj_id, $is_reference = false): int
951 {
952 global $DIC;
953 $ilDB = $DIC['ilDB'];
954
955 if ($is_reference) {
956 $result = $ilDB->queryF(
957 "SELECT count(DISTINCT qpl_questions.points) equal_points FROM qpl_questions, object_reference WHERE object_reference.ref_id = %s AND qpl_questions.tstamp > 0 AND object_reference.obj_id = qpl_questions.obj_fi AND qpl_questions.original_id IS NULL",
958 array('integer'),
959 array($a_obj_id)
960 );
961 } else {
962 $result = $ilDB->queryF(
963 "SELECT count(DISTINCT points) equal_points FROM qpl_questions WHERE obj_fi = %s AND qpl_questions.tstamp > 0 AND qpl_questions.original_id IS NULL",
964 array('integer'),
965 array($a_obj_id)
966 );
967 }
968 if ($result->numRows() == 1) {
969 $row = $ilDB->fetchAssoc($result);
970 if ($row["equal_points"] == 1) {
971 return 1;
972 } else {
973 return 0;
974 }
975 }
976 return 0;
977 }
978
984 public function pasteFromClipboard(): bool
985 {
986 global $DIC;
987 $ilDB = $DIC['ilDB'];
988
989 $success = false;
990 if (ilSession::get("qpl_clipboard") != null) {
991 $success = true;
992 foreach (ilSession::get("qpl_clipboard") as $question_object) {
993 if (strcmp($question_object["action"], "move") == 0) {
994 $result = $ilDB->queryF(
995 "SELECT obj_fi FROM qpl_questions WHERE question_id = %s",
996 array('integer'),
997 array($question_object["question_id"])
998 );
999 if ($result->numRows() == 1) {
1000 $row = $ilDB->fetchAssoc($result);
1001 $source_questionpool = $row["obj_fi"];
1002 // change the questionpool id in the qpl_questions table
1003 $affectedRows = $ilDB->manipulateF(
1004 "UPDATE qpl_questions SET obj_fi = %s WHERE question_id = %s",
1005 array('integer','integer'),
1006 array($this->getId(), $question_object["question_id"])
1007 );
1008 if (!$affectedRows) {
1009 $success = false;
1010 }
1011
1012 // move question data to the new target directory
1013 $source_path = CLIENT_WEB_DIR . "/assessment/" . $source_questionpool . "/" . $question_object["question_id"] . "/";
1014 if (@is_dir($source_path)) {
1015 $target_path = CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/";
1016 if (!@is_dir($target_path)) {
1017 include_once "./Services/Utilities/classes/class.ilUtil.php";
1018 ilFileUtils::makeDirParents($target_path);
1019 }
1020 rename($source_path, $target_path . $question_object["question_id"]);
1021 }
1022 // update question count of source question pool
1023 ilObjQuestionPool::_updateQuestionCount($source_questionpool);
1024 }
1025 } else {
1026 $new_question_id = $this->copyQuestion($question_object["question_id"], $this->getId());
1027 if (!$new_question_id) {
1028 $success = false;
1029 }
1030 }
1031 }
1032 }
1033 // update question count of question pool
1035 ilSession::clear("qpl_clipboard");
1036
1037 return $success;
1038 }
1039
1046 public function copyToClipboard($question_id): void
1047 {
1048 if (ilSession::get("qpl_clipboard") == null) {
1049 ilSession::set("qpl_clipboard", array());
1050 }
1051 $clip = ilSession::get('qpl_clipboard');
1052 $clip[$question_id] = array("question_id" => $question_id, "action" => "copy");
1053 ilSession::set('qpl_clipboard', $clip);
1054 //$_SESSION["qpl_clipboard"][$question_id] = array("question_id" => $question_id, "action" => "copy");
1055 }
1056
1063 public function moveToClipboard($question_id): void
1064 {
1065 if (ilSession::get("qpl_clipboard") == null) {
1066 ilSession::set("qpl_clipboard", array());
1067 }
1068 $clip = ilSession::get('qpl_clipboard');
1069 $clip[$question_id] = array("question_id" => $question_id, "action" => "move");
1070 ilSession::set('qpl_clipboard', $clip);
1071 //$_SESSION["qpl_clipboard"][$question_id] = array("question_id" => $question_id, "action" => "move");
1072 }
1073
1074 public function cleanupClipboard($deletedQuestionId): void
1075 {
1076 if (ilSession::get('qpl_clipboard') == null) {
1077 return;
1078 }
1079
1080 $clip = ilSession::get('qpl_clipboard');
1081 if (!isset($clip[$deletedQuestionId])) {
1082 return;
1083 }
1084
1085 unset($clip[$deletedQuestionId]);
1086
1087 if (!count($clip)) {
1088 ilSession::clear('qpl_clipboard');
1089 } else {
1090 ilSession::set('qpl_clipboard', $clip);
1091 }
1092 }
1093
1101 public static function _isWriteable($object_id, $user_id): bool
1102 {
1103 global $DIC;
1104 $rbacsystem = $DIC['rbacsystem'];
1105
1106 include_once "./Services/Object/classes/class.ilObject.php";
1107 $refs = ilObject::_getAllReferences($object_id);
1108 if (count($refs)) {
1109 foreach ($refs as $ref_id) {
1110 if ($rbacsystem->checkAccess("write", $ref_id) && (ilObject::_hasUntrashedReference($object_id))) {
1111 return true;
1112 }
1113 }
1114 }
1115 return false;
1116 }
1117
1125 public function &getQuestionDetails($question_ids): array
1126 {
1127 global $DIC;
1128 $ilDB = $DIC['ilDB'];
1129
1130 $result = array();
1131 $query_result = $ilDB->query("SELECT qpl_questions.*, qpl_qst_type.type_tag FROM qpl_questions, qpl_qst_type WHERE qpl_questions.question_type_fi = qpl_qst_type.question_type_id AND " . $ilDB->in('qpl_questions.question_id', $question_ids, false, 'integer') . " ORDER BY qpl_questions.title");
1132 if ($query_result->numRows()) {
1133 while ($row = $ilDB->fetchAssoc($query_result)) {
1134 array_push($result, $row);
1135 }
1136 }
1137 return $result;
1138 }
1139
1148 public function &getDeleteableQuestionDetails($question_ids): array
1149 {
1150 global $DIC;
1151 $ilDB = $DIC['ilDB'];
1152 $ilLog = $DIC['ilLog'];
1153
1154 $result = array();
1155 $query_result = $ilDB->query("SELECT qpl_questions.*, qpl_qst_type.type_tag FROM qpl_questions, qpl_qst_type WHERE qpl_questions.question_type_fi = qpl_qst_type.question_type_id AND " . $ilDB->in('qpl_questions.question_id', $question_ids, false, 'integer') . " ORDER BY qpl_questions.title");
1156 if ($query_result->numRows()) {
1157 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1158 while ($row = $ilDB->fetchAssoc($query_result)) {
1159 if (!assQuestion::_isUsedInRandomTest($row["question_id"])) {
1160 array_push($result, $row);
1161 } else {
1162 // the question was used in a random test prior to ILIAS 3.7 so it was inserted
1163 // as a reference to the original question pool object and not as a copy. To allow
1164 // the deletion of the question pool object, a copy must be created and all database references
1165 // of the original question must changed with the reference of the copy
1166
1167 // 1. Create a copy of the original question
1168 $question = $this->createQuestion("", $row["question_id"]);
1169 $duplicate_id = $question->object->duplicate(true);
1170 if ($duplicate_id > 0) {
1171 // 2. replace the question id in the solutions
1172 $affectedRows = $ilDB->manipulateF(
1173 "UPDATE tst_solutions SET question_fi = %s WHERE question_fi = %s",
1174 array('integer','integer'),
1175 array($duplicate_id, $row["question_id"])
1176 );
1177
1178 // 3. replace the question id in the question list of random tests
1179 $affectedRows = $ilDB->manipulateF(
1180 "UPDATE tst_test_rnd_qst SET question_fi = %s WHERE question_fi = %s",
1181 array('integer','integer'),
1182 array($duplicate_id, $row["question_id"])
1183 );
1184
1185 // 4. replace the question id in the test results
1186 $affectedRows = $ilDB->manipulateF(
1187 "UPDATE tst_test_result SET question_fi = %s WHERE question_fi = %s",
1188 array('integer','integer'),
1189 array($duplicate_id, $row["question_id"])
1190 );
1191
1192 // 5. replace the question id in the test&assessment log
1193 $affectedRows = $ilDB->manipulateF(
1194 "UPDATE ass_log SET question_fi = %s WHERE question_fi = %s",
1195 array('integer','integer'),
1196 array($duplicate_id, $row["question_id"])
1197 );
1198
1199 // 6. The original question can be deleted, so add it to the list of questions
1200 array_push($result, $row);
1201 }
1202 }
1203 }
1204 }
1205 return $result;
1206 }
1207
1214 public function _getFullPathToQpl($ref_id): string
1215 {
1216 global $DIC;
1217 $tree = $DIC['tree'];
1219 $items = array();
1220 $counter = 0;
1221 foreach ($path as $item) {
1222 if (($counter > 0) && ($counter < count($path) - 1)) {
1223 array_push($items, $item["title"]);
1224 }
1225 $counter++;
1226 }
1227 $fullpath = join(" > ", $items);
1228 include_once "./Services/Utilities/classes/class.ilStr.php";
1229 if (strlen($fullpath) > 60) {
1230 $fullpath = ilStr::subStr($fullpath, 0, 30) . "..." . ilStr::subStr($fullpath, ilStr::strLen($fullpath) - 30, 30);
1231 }
1232 return $fullpath;
1233 }
1234
1241 public static function _getAvailableQuestionpools($use_object_id = false, $equal_points = false, $could_be_offline = false, $showPath = false, $with_questioncount = false, $permission = "read", $usr_id = ""): array
1242 {
1243 global $DIC;
1244 $ilUser = $DIC['ilUser'];
1245 $ilDB = $DIC['ilDB'];
1246 $lng = $DIC['lng'];
1247
1248 $result_array = array();
1249 $permission = (strlen($permission) == 0) ? "read" : $permission;
1250 $qpls = ilUtil::_getObjectsByOperations("qpl", $permission, (strlen($usr_id)) ? $usr_id : $ilUser->getId(), -1);
1251 $obj_ids = array();
1252 foreach ($qpls as $ref_id) {
1254 $obj_ids[$ref_id] = $obj_id;
1255 }
1256 $titles = ilObject::_prepareCloneSelection($qpls, "qpl");
1257 if (count($obj_ids)) {
1258 $in = $ilDB->in('object_data.obj_id', $obj_ids, false, 'integer');
1259 if ($could_be_offline) {
1260 $result = $ilDB->query("SELECT qpl_questionpool.*, object_data.title FROM qpl_questionpool, object_data WHERE " .
1261 "qpl_questionpool.obj_fi = object_data.obj_id AND $in ORDER BY object_data.title");
1262 } else {
1263 $result = $ilDB->queryF(
1264 "SELECT qpl_questionpool.*, object_data.title FROM qpl_questionpool, object_data WHERE " .
1265 "qpl_questionpool.obj_fi = object_data.obj_id AND $in AND qpl_questionpool.isonline = %s " .
1266 "ORDER BY object_data.title",
1267 array('text'),
1268 array(1)
1269 );
1270 }
1271 while ($row = $ilDB->fetchAssoc($result)) {
1272 $add = true;
1273 if ($equal_points) {
1274 if (!ilObjQuestionPool::_hasEqualPoints($row["obj_fi"])) {
1275 $add = false;
1276 }
1277 }
1278 if ($add) {
1279 $ref_id = array_search($row["obj_fi"], $obj_ids);
1280 $title = (($showPath) ? $titles[$ref_id] : $row["title"]);
1281 if ($with_questioncount) {
1282 $title .= " [" . $row["questioncount"] . " " . ($row["questioncount"] == 1 ? $lng->txt("ass_question") : $lng->txt("assQuestions")) . "]";
1283 }
1284
1285 if ($use_object_id) {
1286 $result_array[$row["obj_fi"]] = array(
1287 'qpl_id' => $row['obj_fi'],
1288 'qpl_title' => $row['title'],
1289 "title" => $title,
1290 "count" => $row["questioncount"]
1291 );
1292 } else {
1293 $result_array[$ref_id] = array(
1294 'qpl_id' => $row['obj_fi'],
1295 'qpl_title' => $row['title'],
1296 "title" => $title,
1297 "count" => $row["questioncount"]
1298 );
1299 }
1300 }
1301 }
1302 }
1303 return $result_array;
1304 }
1305
1306 public function &getQplQuestions(): array
1307 {
1308 global $DIC;
1309 $ilDB = $DIC['ilDB'];
1310
1311 $questions = array();
1312 $result = $ilDB->queryF(
1313 "SELECT qpl_questions.question_id FROM qpl_questions WHERE qpl_questions.original_id IS NULL AND qpl_questions.tstamp > 0 AND qpl_questions.obj_fi = %s",
1314 array('integer'),
1315 array($this->getId())
1316 );
1317 while ($row = $ilDB->fetchAssoc($result)) {
1318 array_push($questions, $row["question_id"]);
1319 }
1320 return $questions;
1321 }
1322
1328 public function cloneObject(int $a_target_id, int $a_copy_id = 0, bool $a_omit_tree = false): ?ilObject
1329 {
1330 $newObj = parent::cloneObject($a_target_id, $a_copy_id, $a_omit_tree);
1331
1332 $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
1333 $newObj->setOnline($this->getOnline());
1334 if ($cp_options->isRootNode($this->getRefId())) {
1335 $newObj->setOnline(0);
1336 }
1337
1338 $newObj->setSkillServiceEnabled($this->isSkillServiceEnabled());
1339 $newObj->setShowTaxonomies($this->getShowTaxonomies());
1340 $newObj->saveToDb();
1341
1342 // clone the questions in the question pool
1343 $questions = &$this->getQplQuestions();
1344 $questionIdsMap = array();
1345 foreach ($questions as $question_id) {
1346 $newQuestionId = $newObj->copyQuestion($question_id, $newObj->getId());
1347 $questionIdsMap[$question_id] = $newQuestionId;
1348 }
1349
1350 // clone meta data
1351 include_once "./Services/MetaData/classes/class.ilMD.php";
1352 $md = new ilMD($this->getId(), 0, $this->getType());
1353 $md->cloneMD($newObj->getId(), 0, $newObj->getType());
1354
1355 // update the metadata with the new title of the question pool
1356 $newObj->updateMetaData();
1357
1358 require_once 'Modules/TestQuestionPool/classes/class.ilQuestionPoolTaxonomiesDuplicator.php';
1359 $duplicator = new ilQuestionPoolTaxonomiesDuplicator();
1360 $duplicator->setSourceObjId($this->getId());
1361 $duplicator->setSourceObjType($this->getType());
1362 $duplicator->setTargetObjId($newObj->getId());
1363 $duplicator->setTargetObjType($newObj->getType());
1364 $duplicator->setQuestionIdMapping($questionIdsMap);
1365 $duplicator->duplicate($duplicator->getAllTaxonomiesForSourceObject());
1366
1367 $duplicatedTaxKeyMap = $duplicator->getDuplicatedTaxonomiesKeysMap();
1368 $newObj->setNavTaxonomyId($duplicatedTaxKeyMap->getMappedTaxonomyId($this->getNavTaxonomyId()));
1369 $newObj->saveToDb();
1370
1371 return $newObj;
1372 }
1373
1374 public function getQuestionTypes($all_tags = false, $fixOrder = false, $withDeprecatedTypes = true): array
1375 {
1376 return self::_getQuestionTypes($all_tags, $fixOrder, $withDeprecatedTypes);
1377 }
1378
1379 public static function _getQuestionTypes($all_tags = false, $fixOrder = false, $withDeprecatedTypes = true): array
1380 {
1381 global $DIC;
1382 $ilDB = $DIC['ilDB'];
1383 $lng = $DIC['lng'];
1384
1385 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
1387 $lng->loadLanguageModule("assessment");
1388 $result = $ilDB->query("SELECT * FROM qpl_qst_type");
1389 $types = array();
1390 while ($row = $ilDB->fetchAssoc($result)) {
1391 if ($all_tags || (!in_array($row["question_type_id"], $forbidden_types))) {
1392 $ilLog = $DIC['ilLog'];
1393
1394 if ($row["plugin"] == 0) {
1395 $types[$lng->txt($row["type_tag"])] = $row;
1396 } else {
1397 $component_factory = $DIC['component.factory'];
1398 //$plugins = $component_repository->getPluginSlotById("qst")->getActivePlugins();
1399 foreach ($component_factory->getActivePluginsInSlot("qst") as $pl) {
1400 if (strcmp($pl->getQuestionType(), $row["type_tag"]) == 0) {
1401 $types[$pl->getQuestionTypeTranslation()] = $row;
1402 }
1403 }
1404 }
1405 }
1406 }
1407
1408 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionTypeOrderer.php';
1410 $orderer = new ilAssQuestionTypeOrderer($types, $orderMode);
1411 $types = $orderer->getOrderedTypes($withDeprecatedTypes);
1412
1413 return $types;
1414 }
1415
1416 public static function getQuestionTypeByTypeId($type_id)
1417 {
1418 global $DIC;
1419 $ilDB = $DIC['ilDB'];
1420
1421 $query = "SELECT type_tag FROM qpl_qst_type WHERE question_type_id = %s";
1422 $types = array('integer');
1423 $values = array($type_id);
1424 $result = $ilDB->queryF($query, $types, $values);
1425
1426 if ($row = $ilDB->fetchAssoc($result)) {
1427 return $row['type_tag'];
1428 }
1429 return null;
1430 }
1431
1432 public static function getQuestionTypeTranslations(): array
1433 {
1434 global $DIC;
1435 $ilDB = $DIC['ilDB'];
1436 $lng = $DIC['lng'];
1437 $ilLog = $DIC['ilLog'];
1438 $component_factory = $DIC['component.factory'];
1439
1440 $lng->loadLanguageModule("assessment");
1441 $result = $ilDB->query("SELECT * FROM qpl_qst_type");
1442 $types = array();
1443 while ($row = $ilDB->fetchAssoc($result)) {
1444 if ($row["plugin"] == 0) {
1445 $types[$row['type_tag']] = $lng->txt($row["type_tag"]);
1446 } else {
1447 foreach ($component_factory->getActivePluginsInSlot("qst") as $pl) {
1448 if (strcmp($pl->getQuestionType(), $row["type_tag"]) == 0) {
1449 $types[$row['type_tag']] = $pl->getQuestionTypeTranslation();
1450 }
1451 }
1452 }
1453 }
1454 ksort($types);
1455 return $types;
1456 }
1457
1463 public static function &_getSelfAssessmentQuestionTypes($all_tags = false): array
1464 {
1465 /* $allowed_types = array(
1466 "assSingleChoice" => 1,
1467 "assMultipleChoice" => 2,
1468 "assClozeTest" => 3,
1469 "assMatchingQuestion" => 4,
1470 "assOrderingQuestion" => 5,
1471 "assOrderingHorizontal" => 6,
1472 "assImagemapQuestion" => 7,
1473 "assTextQuestion" => 8,
1474 "assTextSubset" => 9,
1475 "assErrorText" => 10
1476 );*/
1477 $allowed_types = array(
1478 "assSingleChoice" => 1,
1479 "assMultipleChoice" => 2,
1480 "assKprimChoice" => 3,
1481 "assClozeTest" => 4,
1482 "assMatchingQuestion" => 5,
1483 "assOrderingQuestion" => 6,
1484 "assOrderingHorizontal" => 7,
1485 "assImagemapQuestion" => 8,
1486 "assTextSubset" => 9,
1487 "assErrorText" => 10,
1488 "assLongMenu" => 11
1489 );
1490 $satypes = array();
1491 $qtypes = ilObjQuestionPool::_getQuestionTypes($all_tags);
1492 foreach ($qtypes as $k => $t) {
1493 //if (in_array($t["type_tag"], $allowed_types))
1494 if (isset($allowed_types[$t["type_tag"]])) {
1495 $t["order"] = $allowed_types[$t["type_tag"]];
1496 $satypes[$k] = $t;
1497 }
1498 }
1499 return $satypes;
1500 }
1501
1502
1503 public function &getQuestionList(): array
1504 {
1505 global $DIC;
1506 $ilDB = $DIC['ilDB'];
1507
1508 $questions = array();
1509 $result = $ilDB->queryF(
1510 "SELECT qpl_questions.*, qpl_qst_type.* FROM qpl_questions, qpl_qst_type WHERE qpl_questions.original_id IS NULL AND qpl_questions.obj_fi = %s AND qpl_questions.tstamp > 0 AND qpl_questions.question_type_fi = qpl_qst_type.question_type_id",
1511 array('integer'),
1512 array($this->getId())
1513 );
1514 while ($row = $ilDB->fetchAssoc($result)) {
1515 array_push($questions, $row);
1516 }
1517 return $questions;
1518 }
1519
1526 public static function _updateQuestionCount($object_id): void
1527 {
1528 global $DIC;
1529 $ilDB = $DIC['ilDB'];
1530 $result = $ilDB->manipulateF(
1531 "UPDATE qpl_questionpool SET questioncount = %s, tstamp = %s WHERE obj_fi = %s",
1532 array('integer','integer','integer'),
1533 array(ilObjQuestionPool::_getQuestionCount($object_id, true), time(), $object_id)
1534 );
1535 }
1536
1543 public function isPluginActive($questionType): bool
1544 {
1545 global $DIC;
1547 $component_repository = $DIC['component.repository'];
1548
1549 if (!$component_repository->getComponentByTypeAndName(
1551 'TestQuestionPool'
1552 )->getPluginSlotById('qst')->hasPluginName($questionType)) {
1553 return false;
1554 }
1555
1556 return $component_repository
1557 ->getComponentByTypeAndName(
1559 'TestQuestionPool'
1560 )
1561 ->getPluginSlotById(
1562 'qst'
1563 )
1564 ->getPluginByName(
1565 $questionType
1566 )->isActive();
1567 }
1568
1569 /*
1570 * Remove all questions with owner = 0
1571 */
1572 public function purgeQuestions(): void
1573 {
1574 global $DIC;
1575 $ilDB = $DIC['ilDB'];
1576 $ilUser = $DIC['ilUser'];
1577
1578 require_once 'Modules/TestQuestionPool/classes/class.ilAssIncompleteQuestionPurger.php';
1579 $incompleteQuestionPurger = new ilAssIncompleteQuestionPurger($ilDB);
1580 $incompleteQuestionPurger->setOwnerId($ilUser->getId());
1581 $incompleteQuestionPurger->purge();
1582 }
1583
1589 public function getTaxonomyIds(): array
1590 {
1591 require_once 'Services/Taxonomy/classes/class.ilObjTaxonomy.php';
1592 return ilObjTaxonomy::getUsageOfObject($this->getId());
1593 }
1594
1598 public function isSkillServiceEnabled(): bool
1599 {
1601 }
1602
1607 {
1608 $this->skillServiceEnabled = $skillServiceEnabled;
1609 }
1610
1612
1613 public static function isSkillManagementGloballyActivated(): ?bool
1614 {
1615 if (self::$isSkillManagementGloballyActivated === null) {
1616 $skmgSet = new ilSkillManagementSettings();
1617
1618 self::$isSkillManagementGloballyActivated = $skmgSet->isActivated();
1619 }
1620
1622 }
1623
1624 public function fromXML($xmlFile): void
1625 {
1626 require_once 'Modules/TestQuestionPool/classes/class.ilObjQuestionPoolXMLParser.php';
1627 $parser = new ilObjQuestionPoolXMLParser($this, $xmlFile);
1628 $parser->startParsing();
1629 }
1630} // END class.ilObjQuestionPool
raiseError(string $a_msg, int $a_err_obj)
wrapper for downward compability
static instantiateQuestionGUI(int $a_question_id)
static _includeClass(string $question_type, int $gui=0)
static _isUsedInRandomTest(int $question_id)
static instantiateQuestion(int $question_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const ORDER_MODE_FIX
order mode with fixed priority for ordering
const ORDER_MODE_ALPHA
order mode that orders by alphanumerical priority
static _getInstance(int $a_copy_id)
static _getExportDirectory(int $a_obj_id, string $a_type="xml", string $a_obj_type="", string $a_entity="")
Get export directory for an repository object.
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
static makeDir(string $a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static getDataDir()
get data directory (outside webspace)
loadLanguageModule(string $a_module)
Load language module.
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
static _getForbiddenQuestionTypes()
Returns the forbidden questiontypes for ILIAS.
Class ilObjFile.
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
static _getQuestionCount($questionpool_id, $complete_questions_only=false)
Returns the number of questions in a question pool.
static _lookupOnline($a_obj_id, $is_reference=false)
static _getQuestionTypes($all_tags=false, $fixOrder=false, $withDeprecatedTypes=true)
getExportDirectory($type="")
get export directory of questionpool
getImportMapping()
get array of (two) new created questions for import id
deleteQuestion($question_id)
Deletes a question from the question pool.
cleanupClipboard($deletedQuestionId)
static _isWriteable($object_id, $user_id)
Returns true, if the question pool is writeable by a given user.
& getQuestionDetails($question_ids)
Returns an array containing the qpl_question and qpl_qst_type fields for an array of question ids.
& getDeleteableQuestionDetails($question_ids)
Returns an array containing the qpl_question and qpl_qst_type fields of deleteable questions for an a...
moveToClipboard($question_id)
Moves a question to the clipboard.
getTaxonomyIds()
get ids of all taxonomies corresponding to current pool
setOnline($a_online_status)
Sets the questionpool online status.
exportFileItems($target_dir, &$expLog)
export files of file itmes
modifyExportIdentifier($a_tag, $a_param, $a_value)
getPrintviewQuestions()
Calculates the data for the print view of the questionpool.
setShowTaxonomies($showTaxonomies)
read($a_force_db=false)
read object data from db into object
static _createImportDirectory()
creates data directory for import files (data_dir/qpl_data/qpl_<id>/import, depending on data directo...
static _getImportDirectory()
get import directory of lm
createReference()
Creates a database reference id for the object (saves the object to the database and creates a refere...
loadFromDb()
Loads a ilObjQuestionpool object from a database.
questionsToXML($questions)
Returns a QTI xml representation of a list of questions.
_getFullPathToQpl($ref_id)
Retrieves the full path to a question pool with a given reference id.
static & _getSelfAssessmentQuestionTypes($all_tags=false)
Get all self assessment question types.
copyQuestion($question_id, $questionpool_to)
Copies a question into another question pool.
create($a_upload=false)
create questionpool object
objectToXmlWriter(ilXmlWriter &$a_xml_writer, $a_inst, $a_target_dir, &$expLog, $questions)
export pages of test to xml (see ilias_co.dtd)
exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
createExportDirectory()
creates data directory for export files (data_dir/qpl_data/qpl_<id>/export, depending on data directo...
setNavTaxonomyId($navTaxonomyId)
duplicateQuestion($question_id)
Duplicates a question for a questionpool.
static _setImportDirectory($a_import_dir=null)
set import directory
exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog, $questions)
export page objects to xml (see ilias_co.dtd)
static _hasEqualPoints($a_obj_id, $is_reference=false)
Checks a question pool for questions with the same maximum points.
createQuestion($question_type, $question_id=-1)
setSkillServiceEnabled($skillServiceEnabled)
static getQuestionTypeByTypeId($type_id)
exportXMLMetaData(&$a_xml_writer)
export content objects meta data to xml (see ilias_co.dtd)
isInUse($question_id)
Checks whether the question is in use or not.
__construct($a_id=0, $a_call_by_reference=true)
Constructor @access public.
update()
update object data
saveToDb()
Saves a ilObjQuestionpool object to a database.
copyToClipboard($question_id)
Copies a question to the clipboard.
static _getAvailableQuestionpools($use_object_id=false, $equal_points=false, $could_be_offline=false, $showPath=false, $with_questioncount=false, $permission="read", $usr_id="")
Returns the available question pools for the active user.
static _updateQuestionCount($object_id)
Updates the number of available questions for a question pool in the database.
cloneObject(int $a_target_id, int $a_copy_id=0, bool $a_omit_tree=false)
Creates a 1:1 copy of the object and places the copy in a given repository.
pasteFromClipboard()
Copies/Moves a question from the clipboard.
& getAllQuestions()
Retrieve an array containing all question ids of the questionpool.
populateQuestionSkillAssignmentsXml(ilXmlWriter &$a_xml_writer, $questions)
getQuestionTypes($all_tags=false, $fixOrder=false, $withDeprecatedTypes=true)
static getUsageOfObject(int $a_obj_id, bool $a_include_titles=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
string $title
static _hasUntrashedReference(int $obj_id)
checks whether an object has at least one reference that is not in trash
static _getAllReferences(int $id)
get all reference ids for object ID
ilLanguage $lng
ilTree $tree
static _prepareCloneSelection(array $ref_ids, string $new_type, bool $show_path=true)
Prepare copy wizard object selection.
string $type
ILIAS $ilias
static _lookupObjId(int $ref_id)
static collectFileItems(ilPageObject $a_page, DOMDocument $a_domdoc)
Get all file items that are used within the page.
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...
static subStr(string $a_str, int $a_start, ?int $a_length=null)
Definition: class.ilStr.php:24
static strLen(string $a_string)
Definition: class.ilStr.php:63
getPathFull(int $a_endnode_id, int $a_startnode_id=0)
get path from a given startnode to a given endnode if startnode is not given the rootnode is startnod...
static insertInstIntoID(string $a_value)
inserts installation id into ILIAS id
static _getObjectsByOperations( $a_obj_type, string $a_operation, int $a_usr_id=0, int $limit=0)
Get all objects of a specific type and check access This function is not recursive,...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
xmlEndTag(string $tag)
Writes an endtag.
xmlStartTag(string $tag, ?array $attrs=null, bool $empty=false, bool $encode=true, bool $escape=true)
Writes a starttag.
const CLIENT_WEB_DIR
Definition: constants.php:47
const IL_INST_ID
Definition: constants.php:40
global $DIC
Definition: feed.php:28
$ilUser
Definition: imgupload.php:34
$path
Definition: ltiservices.php:32
$xml
Definition: metadata.php:351
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
string $key
Consumer key/client ID value.
Definition: System.php:193
header include for all ilias files.
$query
$rows
Definition: xhr_table.php:10