ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilObjQuestionPool.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
5 
17 {
23  public $online;
24 
30  private $showTaxonomies = null;
31 
37  private $navTaxonomyId = null;
38 
43 
48  private $import_dir;
49 
56  public function __construct($a_id = 0, $a_call_by_reference = true)
57  {
58  $this->type = "qpl";
59  parent::__construct($a_id, $a_call_by_reference);
60  $this->setOnline(0);
61 
62  $this->skillServiceEnabled = false;
63  }
64 
68  public function create($a_upload = false)
69  {
70  parent::create();
71 
72  // meta data will be created by
73  // import parser
74  if (!$a_upload) {
75  $this->createMetaData();
76  }
77  }
78 
85  public function createReference()
86  {
87  $result = parent::createReference();
88  $this->saveToDb();
89  return $result;
90  }
91 
98  public function update()
99  {
100  $this->updateMetaData();
101  if (!parent::update()) {
102  return false;
103  }
104 
105  // put here object specific stuff
106 
107  return true;
108  }
109 
110  public function updateMetaData()
111  {
112  global $DIC;
113  $ilUser = $DIC['ilUser'];
114  include_once "./Services/MetaData/classes/class.ilMD.php";
115  $md = new ilMD($this->getId(), 0, $this->getType());
116  $md_gen = &$md->getGeneral();
117  if ($md_gen == false) {
118  include_once "./Services/MetaData/classes/class.ilMDCreator.php";
119  $md_creator = new ilMDCreator($this->getId(), 0, $this->getType());
120  $md_creator->setTitle($this->getTitle());
121  $md_creator->setTitleLanguage($ilUser->getPref('language'));
122  $md_creator->create();
123  }
124  parent::updateMetaData();
125  }
126 
132  public function read($a_force_db = false)
133  {
134  parent::read($a_force_db);
135  $this->loadFromDb();
136  }
137 
138 
145  public function delete()
146  {
147  // always call parent delete function first!!
148  if (!parent::delete()) {
149  return false;
150  }
151 
152  // delete meta data
153  $this->deleteMetaData();
154 
155  //put here your module specific stuff
156  $this->deleteQuestionpool();
157 
158  require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssQuestionSkillAssignmentImportFails.php';
159  $qsaImportFails = new ilAssQuestionSkillAssignmentImportFails($this->getId());
160  $qsaImportFails->deleteRegisteredImportFails();
161 
162  return true;
163  }
164 
165  public function deleteQuestionpool()
166  {
167  $questions = &$this->getAllQuestions();
168 
169  if (count($questions)) {
170  foreach ($questions as $question_id) {
171  $this->deleteQuestion($question_id);
172  }
173  }
174 
175  // delete export files
176  include_once "./Services/Utilities/classes/class.ilUtil.php";
177  $qpl_data_dir = ilUtil::getDataDir() . "/qpl_data";
178  $directory = $qpl_data_dir . "/qpl_" . $this->getId();
179  if (is_dir($directory)) {
180  include_once "./Services/Utilities/classes/class.ilUtil.php";
181  ilUtil::delDir($directory);
182  }
183  }
184 
191  public function deleteQuestion($question_id)
192  {
193  include_once "./Modules/Test/classes/class.ilObjTest.php";
194  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
195 
196  $question = assQuestion::_instanciateQuestion($question_id);
197  $this->addQuestionChangeListeners($question);
198  $question->delete($question_id);
199  }
200 
204  public function addQuestionChangeListeners(assQuestion $question)
205  {
206  global $DIC;
207  $ilDB = $DIC['ilDB'];
208 
209  foreach (ilObjTest::getPoolQuestionChangeListeners($ilDB, $this->getId()) as $listener) {
210  $question->addQuestionChangeListener($listener);
211  }
212  }
213 
219  public function loadFromDb()
220  {
221  global $DIC;
222  $ilDB = $DIC['ilDB'];
223 
224  $result = $ilDB->queryF(
225  "SELECT * FROM qpl_questionpool WHERE obj_fi = %s",
226  array('integer'),
227  array($this->getId())
228  );
229  if ($result->numRows() == 1) {
230  $row = $ilDB->fetchAssoc($result);
231  $this->setOnline($row['isonline']);
232  $this->setShowTaxonomies($row['show_taxonomies']);
233  $this->setNavTaxonomyId($row['nav_taxonomy']);
234  $this->setSkillServiceEnabled($row['skill_service']);
235  }
236  }
237 
243  public function saveToDb()
244  {
245  global $DIC;
246  $ilDB = $DIC['ilDB'];
247 
248  $result = $ilDB->queryF(
249  "SELECT id_questionpool FROM qpl_questionpool WHERE obj_fi = %s",
250  array('integer'),
251  array($this->getId())
252  );
253 
254  if ($result->numRows() == 1) {
255  $result = $ilDB->update(
256  'qpl_questionpool',
257  array(
258  'isonline' => array('text', $this->getOnline()),
259  'show_taxonomies' => array('integer', (int) $this->getShowTaxonomies()),
260  'nav_taxonomy' => array('integer', (int) $this->getNavTaxonomyId()),
261  'skill_service' => array('integer', (int) $this->isSkillServiceEnabled()),
262  'tstamp' => array('integer', time())
263  ),
264  array(
265  'obj_fi' => array('integer', $this->getId())
266  )
267  );
268  } else {
269  $next_id = $ilDB->nextId('qpl_questionpool');
270 
271  $result = $ilDB->insert('qpl_questionpool', array(
272  'id_questionpool' => array('integer', $next_id),
273  'isonline' => array('text', $this->getOnline()),
274  'show_taxonomies' => array('integer', (int) $this->getShowTaxonomies()),
275  'nav_taxonomy' => array('integer', (int) $this->getNavTaxonomyId()),
276  'skill_service' => array('integer', (int) $this->isSkillServiceEnabled()),
277  'tstamp' => array('integer', time()),
278  'obj_fi' => array('integer', $this->getId())
279  ));
280  }
281  }
282 
290  public function getQuestiontype($question_id)
291  {
292  global $DIC;
293  $ilDB = $DIC['ilDB'];
294 
295  if ($question_id < 1) {
296  return;
297  }
298 
299  $result = $ilDB->queryF(
300  "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",
301  array('integer'),
302  array($question_id)
303  );
304  if ($result->numRows() == 1) {
305  $data = $ilDB->fetchAssoc($result);
306  return $data["type_tag"];
307  } else {
308  return;
309  }
310  }
311 
317  public function getDescription()
318  {
319  return parent::getDescription();
320  }
321 
325  public function setDescription($a_description)
326  {
327  parent::setDescription($a_description);
328  }
329 
335  public function getTitle()
336  {
337  return parent::getTitle();
338  }
339 
343  public function setTitle($a_title)
344  {
345  parent::setTitle($a_title);
346  }
347 
355  public function isInUse($question_id)
356  {
357  global $DIC;
358  $ilDB = $DIC['ilDB'];
359 
360  $result = $ilDB->queryF(
361  "SELECT COUNT(solution_id) solution_count FROM tst_solutions WHERE question_fi = %s",
362  array('integer'),
363  array($question_id)
364  );
365  $row = $ilDB->fetchAssoc($result);
366  return $row["solution_count"];
367  }
368 
369  public function &createQuestion($question_type, $question_id = -1)
370  {
371  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
372  if ($question_id > 0) {
373  return assQuestion::_instanciateQuestionGUI($question_id);
374  }
375  assQuestion::_includeClass($question_type, 1);
376  $question_type_gui = $question_type . "GUI";
377  $question_gui = new $question_type_gui();
378  return $question_gui;
379  }
380 
387  public function duplicateQuestion($question_id)
388  {
389  $question = &$this->createQuestion("", $question_id);
390  $newtitle = $question->object->getTitle();
391  if ($question->object->questionTitleExists($this->getId(), $question->object->getTitle())) {
392  $counter = 2;
393  while ($question->object->questionTitleExists($this->getId(), $question->object->getTitle() . " ($counter)")) {
394  $counter++;
395  }
396  $newtitle = $question->object->getTitle() . " ($counter)";
397  }
398  $new_id = $question->object->duplicate(false, $newtitle);
399  // update question count of question pool
401  return $new_id;
402  }
403 
411  public function copyQuestion($question_id, $questionpool_to)
412  {
413  $question_gui = &$this->createQuestion("", $question_id);
414  if ($question_gui->object->getObjId() == $questionpool_to) {
415  // the question is copied into the same question pool
416  return $this->duplicateQuestion($question_id);
417  } else {
418  // the question is copied into another question pool
419  $newtitle = $question_gui->object->getTitle();
420  if ($question_gui->object->questionTitleExists($this->getId(), $question_gui->object->getTitle())) {
421  $counter = 2;
422  while ($question_gui->object->questionTitleExists($this->getId(), $question_gui->object->getTitle() . " ($counter)")) {
423  $counter++;
424  }
425  $newtitle = $question_gui->object->getTitle() . " ($counter)";
426  }
427  return $question_gui->object->copyObject($this->getId(), $newtitle);
428  }
429  }
430 
436  public function getPrintviewQuestions()
437  {
438  global $DIC;
439  $ilDB = $DIC['ilDB'];
440 
441  $query_result = $ilDB->queryF(
442  "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",
443  array('integer'),
444  array($this->getId())
445  );
446  $rows = array();
447  $types = $this->getQuestionTypeTranslations();
448  if ($query_result->numRows()) {
449  while ($row = $ilDB->fetchAssoc($query_result)) {
450  $row['ttype'] = $types[$row['type_tag']];
451  if ($row["plugin"]) {
452  if ($this->isPluginActive($row["type_tag"])) {
453  array_push($rows, $row);
454  }
455  } else {
456  array_push($rows, $row);
457  }
458  }
459  }
460  return $rows;
461  }
462 
466  private function exportXMLSettings($xmlWriter)
467  {
468  $xmlWriter->xmlStartTag('Settings');
469 
470  $xmlWriter->xmlElement('ShowTaxonomies', null, (int) $this->getShowTaxonomies());
471  $xmlWriter->xmlElement('NavTaxonomy', null, (int) $this->getNavTaxonomyId());
472  $xmlWriter->xmlElement('SkillService', null, (int) $this->isSkillServiceEnabled());
473 
474  $xmlWriter->xmlEndTag('Settings');
475  }
476 
483  public function objectToXmlWriter(ilXmlWriter &$a_xml_writer, $a_inst, $a_target_dir, &$expLog, $questions)
484  {
485  global $DIC;
486  $ilBench = $DIC['ilBench'];
487 
488  $this->mob_ids = array();
489  $this->file_ids = array();
490 
491  $attrs = array();
492  $attrs["Type"] = "Questionpool_Test";
493  $a_xml_writer->xmlStartTag("ContentObject", $attrs);
494 
495  // MetaData
496  $this->exportXMLMetaData($a_xml_writer);
497 
498  // Settings
499  $this->exportXMLSettings($a_xml_writer);
500 
501  // PageObjects
502  $expLog->write(date("[y-m-d H:i:s] ") . "Start Export Page Objects");
503  $ilBench->start("ContentObjectExport", "exportPageObjects");
504  $this->exportXMLPageObjects($a_xml_writer, $a_inst, $expLog, $questions);
505  $ilBench->stop("ContentObjectExport", "exportPageObjects");
506  $expLog->write(date("[y-m-d H:i:s] ") . "Finished Export Page Objects");
507 
508  // MediaObjects
509  $expLog->write(date("[y-m-d H:i:s] ") . "Start Export Media Objects");
510  $ilBench->start("ContentObjectExport", "exportMediaObjects");
511  $this->exportXMLMediaObjects($a_xml_writer, $a_inst, $a_target_dir, $expLog);
512  $ilBench->stop("ContentObjectExport", "exportMediaObjects");
513  $expLog->write(date("[y-m-d H:i:s] ") . "Finished Export Media Objects");
514 
515  // FileItems
516  $expLog->write(date("[y-m-d H:i:s] ") . "Start Export File Items");
517  $ilBench->start("ContentObjectExport", "exportFileItems");
518  $this->exportFileItems($a_target_dir, $expLog);
519  $ilBench->stop("ContentObjectExport", "exportFileItems");
520  $expLog->write(date("[y-m-d H:i:s] ") . "Finished Export File Items");
521 
522  // skill assignments
523  $this->populateQuestionSkillAssignmentsXml($a_xml_writer, $questions);
524 
525  $a_xml_writer->xmlEndTag("ContentObject");
526  }
527 
532  protected function populateQuestionSkillAssignmentsXml(ilXmlWriter &$a_xml_writer, $questions)
533  {
534  global $DIC;
535  $ilDB = $DIC['ilDB'];
536 
537  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php';
538  $assignmentList = new ilAssQuestionSkillAssignmentList($ilDB);
539  $assignmentList->setParentObjId($this->getId());
540  $assignmentList->loadFromDb();
541  $assignmentList->loadAdditionalSkillData();
542 
543  require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssQuestionSkillAssignmentExporter.php';
544  $skillQuestionAssignmentExporter = new ilAssQuestionSkillAssignmentExporter();
545  $skillQuestionAssignmentExporter->setXmlWriter($a_xml_writer);
546  $skillQuestionAssignmentExporter->setQuestionIds($questions);
547  $skillQuestionAssignmentExporter->setAssignmentList($assignmentList);
548  $skillQuestionAssignmentExporter->export();
549  }
550 
557  public function exportXMLMetaData(&$a_xml_writer)
558  {
559  include_once("Services/MetaData/classes/class.ilMD2XML.php");
560  $md2xml = new ilMD2XML($this->getId(), 0, $this->getType());
561  $md2xml->setExportMode(true);
562  $md2xml->startExport();
563  $a_xml_writer->appendXML($md2xml->getXML());
564  }
565 
566  public function modifyExportIdentifier($a_tag, $a_param, $a_value)
567  {
568  if ($a_tag == "Identifier" && $a_param == "Entry") {
569  include_once "./Services/Utilities/classes/class.ilUtil.php";
570  $a_value = ilUtil::insertInstIntoID($a_value);
571  }
572 
573  return $a_value;
574  }
575 
576 
583  public function exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog, $questions)
584  {
585  global $DIC;
586  $ilBench = $DIC['ilBench'];
587 
588  include_once "./Modules/LearningModule/classes/class.ilLMPageObject.php";
589 
590  foreach ($questions as $question_id) {
591  $ilBench->start("ContentObjectExport", "exportPageObject");
592  $expLog->write(date("[y-m-d H:i:s] ") . "Page Object " . $question_id);
593 
594  $attrs = array();
595  $a_xml_writer->xmlStartTag("PageObject", $attrs);
596 
597 
598  // export xml to writer object
599  $ilBench->start("ContentObjectExport", "exportPageObject_XML");
600  include_once("./Modules/TestQuestionPool/classes/class.ilAssQuestionPage.php");
601  $page_object = new ilAssQuestionPage($question_id);
602  $page_object->buildDom();
603  $page_object->insertInstIntoIDs($a_inst);
604  $mob_ids = $page_object->collectMediaObjects(false);
605  require_once 'Services/COPage/classes/class.ilPCFileList.php';
606  $file_ids = ilPCFileList::collectFileItems($page_object, $page_object->getDomDoc());
607  $xml = $page_object->getXMLFromDom(false, false, false, "", true);
608  $xml = str_replace("&", "&amp;", $xml);
609  $a_xml_writer->appendXML($xml);
610  $page_object->freeDom();
611  unset($page_object);
612 
613  $ilBench->stop("ContentObjectExport", "exportPageObject_XML");
614 
615  // collect media objects
616  $ilBench->start("ContentObjectExport", "exportPageObject_CollectMedia");
617  //$mob_ids = $page_obj->getMediaObjectIDs();
618  foreach ($mob_ids as $mob_id) {
619  $this->mob_ids[$mob_id] = $mob_id;
620  }
621  $ilBench->stop("ContentObjectExport", "exportPageObject_CollectMedia");
622 
623  // collect all file items
624  $ilBench->start("ContentObjectExport", "exportPageObject_CollectFileItems");
625  //$file_ids = $page_obj->getFileItemIds();
626  foreach ($file_ids as $file_id) {
627  $this->file_ids[$file_id] = $file_id;
628  }
629  $ilBench->stop("ContentObjectExport", "exportPageObject_CollectFileItems");
630 
631  $a_xml_writer->xmlEndTag("PageObject");
632  //unset($page_obj);
633 
634  $ilBench->stop("ContentObjectExport", "exportPageObject");
635  }
636  }
637 
644  public function exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
645  {
646  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
647 
648  foreach ($this->mob_ids as $mob_id) {
649  $expLog->write(date("[y-m-d H:i:s] ") . "Media Object " . $mob_id);
650  if (ilObjMediaObject::_exists($mob_id)) {
651  $media_obj = new ilObjMediaObject($mob_id);
652  $media_obj->exportXML($a_xml_writer, $a_inst);
653  $media_obj->exportFiles($a_target_dir);
654  unset($media_obj);
655  }
656  }
657  }
658 
663  public function exportFileItems($a_target_dir, &$expLog)
664  {
665  include_once("./Modules/File/classes/class.ilObjFile.php");
666 
667  foreach ($this->file_ids as $file_id) {
668  $expLog->write(date("[y-m-d H:i:s] ") . "File Item " . $file_id);
669  $file_obj = new ilObjFile($file_id, false);
670  $file_obj->export($a_target_dir);
671  unset($file_obj);
672  }
673  }
674 
680  public function createExportDirectory()
681  {
682  include_once "./Services/Utilities/classes/class.ilUtil.php";
683  $qpl_data_dir = ilUtil::getDataDir() . "/qpl_data";
684  ilUtil::makeDir($qpl_data_dir);
685  if (!is_writable($qpl_data_dir)) {
686  $this->ilias->raiseError("Questionpool Data Directory (" . $qpl_data_dir
687  . ") not writeable.", $this->ilias->error_obj->FATAL);
688  }
689 
690  // create learning module directory (data_dir/lm_data/lm_<id>)
691  $qpl_dir = $qpl_data_dir . "/qpl_" . $this->getId();
692  ilUtil::makeDir($qpl_dir);
693  if (!@is_dir($qpl_dir)) {
694  $this->ilias->raiseError("Creation of Questionpool Directory failed.", $this->ilias->error_obj->FATAL);
695  }
696  // create Export subdirectory (data_dir/lm_data/lm_<id>/Export)
697  ilUtil::makeDir($this->getExportDirectory('xls'));
698  if (!@is_dir($this->getExportDirectory('xls'))) {
699  $this->ilias->raiseError("Creation of Export Directory failed.", $this->ilias->error_obj->FATAL);
700  }
701  ilUtil::makeDir($this->getExportDirectory('zip'));
702  if (!@is_dir($this->getExportDirectory('zip'))) {
703  $this->ilias->raiseError("Creation of Export Directory failed.", $this->ilias->error_obj->FATAL);
704  }
705  }
706 
710  public function getExportDirectory($type = "")
711  {
712  include_once "./Services/Utilities/classes/class.ilUtil.php";
713  switch ($type) {
714  case 'xml':
715  include_once("./Services/Export/classes/class.ilExport.php");
716  $export_dir = ilExport::_getExportDirectory($this->getId(), $type, $this->getType());
717  break;
718  case 'xls':
719  case 'zip':
720  $export_dir = ilUtil::getDataDir() . "/qpl_data" . "/qpl_" . $this->getId() . "/export_$type";
721  break;
722  default:
723  $export_dir = ilUtil::getDataDir() . "/qpl_data" . "/qpl_" . $this->getId() . "/export";
724  break;
725  }
726  return $export_dir;
727  }
728 
734  public static function _createImportDirectory()
735  {
736  global $DIC;
737  $ilias = $DIC['ilias'];
738 
739  include_once "./Services/Utilities/classes/class.ilUtil.php";
740  $qpl_data_dir = ilUtil::getDataDir() . "/qpl_data";
741  ilUtil::makeDir($qpl_data_dir);
742 
743  if (!is_writable($qpl_data_dir)) {
744  $ilias->raiseError("Questionpool Data Directory (" . $qpl_data_dir
745  . ") not writeable.", $ilias->error_obj->FATAL);
746  }
747 
748  // create questionpool directory (data_dir/qpl_data/qpl_import)
749  $qpl_dir = $qpl_data_dir . "/qpl_import";
750  ilUtil::makeDir($qpl_dir);
751  if (!@is_dir($qpl_dir)) {
752  $ilias->raiseError("Creation of Questionpool Directory failed.", $ilias->error_obj->FATAL);
753  }
754  return $qpl_dir;
755  }
756 
760  public static function _setImportDirectory($a_import_dir = null)
761  {
762  if (strlen($a_import_dir)) {
763  $_SESSION["qpl_import_dir"] = $a_import_dir;
764  } else {
765  unset($_SESSION["qpl_import_dir"]);
766  }
767  }
768 
772  public static function _getImportDirectory()
773  {
774  if (strlen($_SESSION["qpl_import_dir"])) {
775  return $_SESSION["qpl_import_dir"];
776  }
777  return null;
778  }
779 
780  public function getImportDirectory()
781  {
783  }
784 
790  public function &getAllQuestions()
791  {
792  global $DIC;
793  $ilDB = $DIC['ilDB'];
794 
795  $result = $ilDB->queryF(
796  "SELECT question_id FROM qpl_questions WHERE obj_fi = %s AND qpl_questions.tstamp > 0 AND original_id IS NULL",
797  array('integer'),
798  array($this->getId())
799  );
800  $questions = array();
801  while ($row = $ilDB->fetchAssoc($result)) {
802  array_push($questions, $row["question_id"]);
803  }
804  return $questions;
805  }
806 
807  public function &getAllQuestionIds()
808  {
809  global $DIC;
810  $ilDB = $DIC['ilDB'];
811 
812  $query_result = $ilDB->queryF(
813  "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",
814  array('integer','text'),
815  array($this->getId(), 1)
816  );
817  $questions = array();
818  if ($query_result->numRows()) {
819  while ($row = $ilDB->fetchAssoc($query_result)) {
820  if ($row["plugin"]) {
821  if ($this->isPluginActive($row["type_tag"])) {
822  array_push($questions, $row["question_id"]);
823  }
824  } else {
825  array_push($questions, $row["question_id"]);
826  }
827  }
828  }
829  return $questions;
830  }
831 
832  public function checkQuestionParent($questionId)
833  {
834  global $DIC; /* @var ILIAS\DI\Container $DIC */
835 
836  $row = $DIC->database()->fetchAssoc($DIC->database()->queryF(
837  "SELECT COUNT(question_id) cnt FROM qpl_questions WHERE question_id = %s AND obj_fi = %s",
838  array('integer', 'integer'),
839  array($questionId, $this->getId())
840  ));
841 
842  return (bool) $row['cnt'];
843  }
844 
849  public function getImportMapping()
850  {
851  if (!is_array($this->import_mapping)) {
852  return array();
853  } else {
854  return $this->import_mapping;
855  }
856  }
857 
865  public function questionsToXML($questions)
866  {
867  $xml = "";
868  // export button was pressed
869  if (count($questions) > 0) {
870  foreach ($questions as $key => $value) {
871  $question = &$this->createQuestion("", $value);
872  $xml .= $question->object->toXML();
873  }
874  if (count($questions) > 1) {
875  $xml = preg_replace("/<\/questestinterop>\s*<.xml.*?>\s*<questestinterop>/", "", $xml);
876  }
877  }
878  $xml = preg_replace("/(<\?xml[^>]*?>)/", "\\1" . "<!DOCTYPE questestinterop SYSTEM \"ims_qtiasiv1p2p1.dtd\">", $xml);
879  return $xml;
880  }
881 
890  public static function _getQuestionCount($questionpool_id, $complete_questions_only = false)
891  {
892  global $DIC;
893  $ilDB = $DIC['ilDB'];
894  if ($complete_questions_only) {
895  $result = $ilDB->queryF(
896  "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",
897  array('integer', 'text'),
898  array($questionpool_id, 1)
899  );
900  } else {
901  $result = $ilDB->queryF(
902  "SELECT COUNT(question_id) question_count FROM qpl_questions WHERE obj_fi = %s AND qpl_questions.tstamp > 0 AND original_id IS NULL",
903  array('integer'),
904  array($questionpool_id)
905  );
906  }
907  $row = $ilDB->fetchAssoc($result);
908  return $row["question_count"];
909  }
910 
918  public function setOnline($a_online_status)
919  {
920  switch ($a_online_status) {
921  case 0:
922  case 1:
923  $this->online = $a_online_status;
924  break;
925  default:
926  $this->online = 0;
927  break;
928  }
929  }
930 
931  public function getOnline()
932  {
933  if (strcmp($this->online, "") == 0) {
934  $this->online = "0";
935  }
936  return $this->online;
937  }
938 
940  {
941  $this->showTaxonomies = $showTaxonomies;
942  }
943 
944  public function getShowTaxonomies()
945  {
946  return $this->showTaxonomies;
947  }
948 
950  {
951  $this->navTaxonomyId = $navTaxonomyId;
952  }
953 
954  public function getNavTaxonomyId()
955  {
956  return $this->navTaxonomyId;
957  }
958 
959  public function isNavTaxonomyActive()
960  {
961  return $this->getShowTaxonomies() && (int) $this->getNavTaxonomyId();
962  }
963 
964  public static function _lookupOnline($a_obj_id, $is_reference = false)
965  {
966  global $DIC;
967  $ilDB = $DIC['ilDB'];
968 
969  if ($is_reference) {
970  $result = $ilDB->queryF(
971  "SELECT qpl_questionpool.isonline FROM qpl_questionpool,object_reference WHERE object_reference.ref_id = %s AND object_reference.obj_id = qpl_questionpool.obj_fi",
972  array('integer'),
973  array($a_obj_id)
974  );
975  } else {
976  $result = $ilDB->queryF(
977  "SELECT isonline FROM qpl_questionpool WHERE obj_fi = %s",
978  array('integer'),
979  array($a_obj_id)
980  );
981  }
982  if ($result->numRows() == 1) {
983  $row = $ilDB->fetchAssoc($result);
984  return $row["isonline"];
985  }
986  return 0;
987  }
988 
995  public static function _hasEqualPoints($a_obj_id, $is_reference = false)
996  {
997  global $DIC;
998  $ilDB = $DIC['ilDB'];
999 
1000  if ($is_reference) {
1001  $result = $ilDB->queryF(
1002  "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",
1003  array('integer'),
1004  array($a_obj_id)
1005  );
1006  } else {
1007  $result = $ilDB->queryF(
1008  "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",
1009  array('integer'),
1010  array($a_obj_id)
1011  );
1012  }
1013  if ($result->numRows() == 1) {
1014  $row = $ilDB->fetchAssoc($result);
1015  if ($row["equal_points"] == 1) {
1016  return 1;
1017  } else {
1018  return 0;
1019  }
1020  }
1021  return 0;
1022  }
1023 
1029  public function pasteFromClipboard()
1030  {
1031  global $DIC;
1032  $ilDB = $DIC['ilDB'];
1033 
1034  $success = false;
1035  if (array_key_exists("qpl_clipboard", $_SESSION)) {
1036  $success = true;
1037  foreach ($_SESSION["qpl_clipboard"] as $question_object) {
1038  if (strcmp($question_object["action"], "move") == 0) {
1039  $result = $ilDB->queryF(
1040  "SELECT obj_fi FROM qpl_questions WHERE question_id = %s",
1041  array('integer'),
1042  array($question_object["question_id"])
1043  );
1044  if ($result->numRows() == 1) {
1045  $row = $ilDB->fetchAssoc($result);
1046  $source_questionpool = $row["obj_fi"];
1047  // change the questionpool id in the qpl_questions table
1048  $affectedRows = $ilDB->manipulateF(
1049  "UPDATE qpl_questions SET obj_fi = %s WHERE question_id = %s",
1050  array('integer','integer'),
1051  array($this->getId(), $question_object["question_id"])
1052  );
1053  if (!$affectedRows) {
1054  $success = false;
1055  }
1056 
1057  // move question data to the new target directory
1058  $source_path = CLIENT_WEB_DIR . "/assessment/" . $source_questionpool . "/" . $question_object["question_id"] . "/";
1059  if (@is_dir($source_path)) {
1060  $target_path = CLIENT_WEB_DIR . "/assessment/" . $this->getId() . "/";
1061  if (!@is_dir($target_path)) {
1062  include_once "./Services/Utilities/classes/class.ilUtil.php";
1063  ilUtil::makeDirParents($target_path);
1064  }
1065  rename($source_path, $target_path . $question_object["question_id"]);
1066  }
1067  // update question count of source question pool
1068  ilObjQuestionPool::_updateQuestionCount($source_questionpool);
1069  }
1070  } else {
1071  $new_question_id = $this->copyQuestion($question_object["question_id"], $this->getId());
1072  if (!$new_question_id) {
1073  $success = false;
1074  }
1075  }
1076  }
1077  }
1078  // update question count of question pool
1080  unset($_SESSION["qpl_clipboard"]);
1081 
1082  return (bool) $success;
1083  }
1084 
1091  public function copyToClipboard($question_id)
1092  {
1093  if (!array_key_exists("qpl_clipboard", $_SESSION)) {
1094  $_SESSION["qpl_clipboard"] = array();
1095  }
1096  $_SESSION["qpl_clipboard"][$question_id] = array("question_id" => $question_id, "action" => "copy");
1097  }
1098 
1105  public function moveToClipboard($question_id)
1106  {
1107  if (!array_key_exists("qpl_clipboard", $_SESSION)) {
1108  $_SESSION["qpl_clipboard"] = array();
1109  }
1110  $_SESSION["qpl_clipboard"][$question_id] = array("question_id" => $question_id, "action" => "move");
1111  }
1112 
1113  public function cleanupClipboard($deletedQuestionId)
1114  {
1115  if (!isset($_SESSION['qpl_clipboard'])) {
1116  return;
1117  }
1118 
1119  if (!isset($_SESSION['qpl_clipboard'][$deletedQuestionId])) {
1120  return;
1121  }
1122 
1123  unset($_SESSION['qpl_clipboard'][$deletedQuestionId]);
1124 
1125  if (!count($_SESSION['qpl_clipboard'])) {
1126  unset($_SESSION['qpl_clipboard']);
1127  }
1128  }
1129 
1137  public static function _isWriteable($object_id, $user_id)
1138  {
1139  global $DIC;
1140  $rbacsystem = $DIC['rbacsystem'];
1141 
1142  include_once "./Services/Object/classes/class.ilObject.php";
1143  $refs = ilObject::_getAllReferences($object_id);
1144  if (count($refs)) {
1145  foreach ($refs as $ref_id) {
1146  if ($rbacsystem->checkAccess("write", $ref_id) && (ilObject::_hasUntrashedReference($object_id))) {
1147  return true;
1148  }
1149  }
1150  }
1151  return false;
1152  }
1153 
1161  public function &getQuestionDetails($question_ids)
1162  {
1163  global $DIC;
1164  $ilDB = $DIC['ilDB'];
1165 
1166  $result = array();
1167  $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");
1168  if ($query_result->numRows()) {
1169  while ($row = $ilDB->fetchAssoc($query_result)) {
1170  array_push($result, $row);
1171  }
1172  }
1173  return $result;
1174  }
1175 
1184  public function &getDeleteableQuestionDetails($question_ids)
1185  {
1186  global $DIC;
1187  $ilDB = $DIC['ilDB'];
1188  $ilLog = $DIC['ilLog'];
1189 
1190  $result = array();
1191  $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");
1192  if ($query_result->numRows()) {
1193  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1194  while ($row = $ilDB->fetchAssoc($query_result)) {
1195  if (!assQuestion::_isUsedInRandomTest($row["question_id"])) {
1196  array_push($result, $row);
1197  } else {
1198  // the question was used in a random test prior to ILIAS 3.7 so it was inserted
1199  // as a reference to the original question pool object and not as a copy. To allow
1200  // the deletion of the question pool object, a copy must be created and all database references
1201  // of the original question must changed with the reference of the copy
1202 
1203  // 1. Create a copy of the original question
1204  $question = &$this->createQuestion("", $row["question_id"]);
1205  $duplicate_id = $question->object->duplicate(true);
1206  if ($duplicate_id > 0) {
1207  // 2. replace the question id in the solutions
1208  $affectedRows = $ilDB->manipulateF(
1209  "UPDATE tst_solutions SET question_fi = %s WHERE question_fi = %s",
1210  array('integer','integer'),
1211  array($duplicate_id, $row["question_id"])
1212  );
1213 
1214  // 3. replace the question id in the question list of random tests
1215  $affectedRows = $ilDB->manipulateF(
1216  "UPDATE tst_test_rnd_qst SET question_fi = %s WHERE question_fi = %s",
1217  array('integer','integer'),
1218  array($duplicate_id, $row["question_id"])
1219  );
1220 
1221  // 4. replace the question id in the test results
1222  $affectedRows = $ilDB->manipulateF(
1223  "UPDATE tst_test_result SET question_fi = %s WHERE question_fi = %s",
1224  array('integer','integer'),
1225  array($duplicate_id, $row["question_id"])
1226  );
1227 
1228  // 5. replace the question id in the test&assessment log
1229  $affectedRows = $ilDB->manipulateF(
1230  "UPDATE ass_log SET question_fi = %s WHERE question_fi = %s",
1231  array('integer','integer'),
1232  array($duplicate_id, $row["question_id"])
1233  );
1234 
1235  // 6. The original question can be deleted, so add it to the list of questions
1236  array_push($result, $row);
1237  }
1238  }
1239  }
1240  }
1241  return $result;
1242  }
1243 
1250  public function _getFullPathToQpl($ref_id)
1251  {
1252  global $DIC;
1253  $tree = $DIC['tree'];
1254  $path = $tree->getPathFull($ref_id);
1255  $items = array();
1256  $counter = 0;
1257  foreach ($path as $item) {
1258  if (($counter > 0) && ($counter < count($path) - 1)) {
1259  array_push($items, $item["title"]);
1260  }
1261  $counter++;
1262  }
1263  $fullpath = join(" > ", $items);
1264  include_once "./Services/Utilities/classes/class.ilStr.php";
1265  if (strlen($fullpath) > 60) {
1266  $fullpath = ilStr::subStr($fullpath, 0, 30) . "..." . ilStr::subStr($fullpath, ilStr::strLen($fullpath) - 30, 30);
1267  }
1268  return $fullpath;
1269  }
1270 
1277  public static function _getAvailableQuestionpools($use_object_id = false, $equal_points = false, $could_be_offline = false, $showPath = false, $with_questioncount = false, $permission = "read", $usr_id = "")
1278  {
1279  global $DIC;
1280  $ilUser = $DIC['ilUser'];
1281  $ilDB = $DIC['ilDB'];
1282  $lng = $DIC['lng'];
1283 
1284  $result_array = array();
1285  $permission = (strlen($permission) == 0) ? "read" : $permission;
1286  $qpls = ilUtil::_getObjectsByOperations("qpl", $permission, (strlen($usr_id)) ? $usr_id : $ilUser->getId(), -1);
1287  $obj_ids = array();
1288  foreach ($qpls as $ref_id) {
1289  $obj_id = ilObject::_lookupObjId($ref_id);
1290  $obj_ids[$ref_id] = $obj_id;
1291  }
1292  $titles = ilObject::_prepareCloneSelection($qpls, "qpl");
1293  if (count($obj_ids)) {
1294  $in = $ilDB->in('object_data.obj_id', $obj_ids, false, 'integer');
1295  if ($could_be_offline) {
1296  $result = $ilDB->query("SELECT qpl_questionpool.*, object_data.title FROM qpl_questionpool, object_data WHERE " .
1297  "qpl_questionpool.obj_fi = object_data.obj_id AND $in ORDER BY object_data.title");
1298  } else {
1299  $result = $ilDB->queryF(
1300  "SELECT qpl_questionpool.*, object_data.title FROM qpl_questionpool, object_data WHERE " .
1301  "qpl_questionpool.obj_fi = object_data.obj_id AND $in AND qpl_questionpool.isonline = %s " .
1302  "ORDER BY object_data.title",
1303  array('text'),
1304  array(1)
1305  );
1306  }
1307  while ($row = $ilDB->fetchAssoc($result)) {
1308  $add = true;
1309  if ($equal_points) {
1310  if (!ilObjQuestionPool::_hasEqualPoints($row["obj_fi"])) {
1311  $add = false;
1312  }
1313  }
1314  if ($add) {
1315  $ref_id = array_search($row["obj_fi"], $obj_ids);
1316  $title = (($showPath) ? $titles[$ref_id] : $row["title"]);
1317  if ($with_questioncount) {
1318  $title .= " [" . $row["questioncount"] . " " . ($row["questioncount"] == 1 ? $lng->txt("ass_question") : $lng->txt("assQuestions")) . "]";
1319  }
1320 
1321  if ($use_object_id) {
1322  $result_array[$row["obj_fi"]] = array(
1323  'qpl_id' => $row['obj_fi'],
1324  'qpl_title' => $row['title'],
1325  "title" => $title,
1326  "count" => $row["questioncount"]
1327  );
1328  } else {
1329  $result_array[$ref_id] = array(
1330  'qpl_id' => $row['obj_fi'],
1331  'qpl_title' => $row['title'],
1332  "title" => $title,
1333  "count" => $row["questioncount"]
1334  );
1335  }
1336  }
1337  }
1338  }
1339  return $result_array;
1340  }
1341 
1342  public function &getQplQuestions()
1343  {
1344  global $DIC;
1345  $ilDB = $DIC['ilDB'];
1346 
1347  $questions = array();
1348  $result = $ilDB->queryF(
1349  "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",
1350  array('integer'),
1351  array($this->getId())
1352  );
1353  while ($row = $ilDB->fetchAssoc($result)) {
1354  array_push($questions, $row["question_id"]);
1355  }
1356  return $questions;
1357  }
1358 
1364  public function cloneObject($a_target_id, $a_copy_id = 0, $a_omit_tree = false)
1365  {
1366  global $DIC;
1367  $ilLog = $DIC['ilLog'];
1368 
1369  $newObj = parent::cloneObject($a_target_id, $a_copy_id, $a_omit_tree);
1370 
1371  //copy online status if object is not the root copy object
1372  $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
1373 
1374  if (!$cp_options->isRootNode($this->getRefId())) {
1375  $newObj->setOnline($this->getOnline());
1376  }
1377 
1378  $newObj->setSkillServiceEnabled($this->isSkillServiceEnabled());
1379  $newObj->setShowTaxonomies($this->getShowTaxonomies());
1380  $newObj->saveToDb();
1381 
1382  // clone the questions in the question pool
1383  $questions = &$this->getQplQuestions();
1384  $questionIdsMap = array();
1385  foreach ($questions as $question_id) {
1386  $newQuestionId = $newObj->copyQuestion($question_id, $newObj->getId());
1387  $questionIdsMap[$question_id] = $newQuestionId;
1388  }
1389 
1390  // clone meta data
1391  include_once "./Services/MetaData/classes/class.ilMD.php";
1392  $md = new ilMD($this->getId(), 0, $this->getType());
1393  $new_md = &$md->cloneMD($newObj->getId(), 0, $newObj->getType());
1394 
1395  // update the metadata with the new title of the question pool
1396  $newObj->updateMetaData();
1397 
1398  require_once 'Modules/TestQuestionPool/classes/class.ilQuestionPoolTaxonomiesDuplicator.php';
1399  $duplicator = new ilQuestionPoolTaxonomiesDuplicator();
1400  $duplicator->setSourceObjId($this->getId());
1401  $duplicator->setSourceObjType($this->getType());
1402  $duplicator->setTargetObjId($newObj->getId());
1403  $duplicator->setTargetObjType($newObj->getType());
1404  $duplicator->setQuestionIdMapping($questionIdsMap);
1405  $duplicator->duplicate($duplicator->getAllTaxonomiesForSourceObject());
1406 
1407  $duplicatedTaxKeyMap = $duplicator->getDuplicatedTaxonomiesKeysMap();
1408  $newObj->setNavTaxonomyId($duplicatedTaxKeyMap->getMappedTaxonomyId($this->getNavTaxonomyId()));
1409  $newObj->saveToDb();
1410 
1411  return $newObj;
1412  }
1413 
1414  public function getQuestionTypes($all_tags = false, $fixOrder = false, $withDeprecatedTypes = true)
1415  {
1416  return self::_getQuestionTypes($all_tags, $fixOrder, $withDeprecatedTypes);
1417  }
1418 
1419  public static function _getQuestionTypes($all_tags = false, $fixOrder = false, $withDeprecatedTypes = true)
1420  {
1421  global $DIC;
1422  $ilDB = $DIC['ilDB'];
1423  $lng = $DIC['lng'];
1424 
1425  include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php";
1427  $lng->loadLanguageModule("assessment");
1428  $result = $ilDB->query("SELECT * FROM qpl_qst_type");
1429  $types = array();
1430  while ($row = $ilDB->fetchAssoc($result)) {
1431  if ($all_tags || (!in_array($row["question_type_id"], $forbidden_types))) {
1432  global $DIC;
1433  $ilLog = $DIC['ilLog'];
1434 
1435  if ($row["plugin"] == 0) {
1436  $types[$lng->txt($row["type_tag"])] = $row;
1437  } else {
1438  global $DIC;
1439  $ilPluginAdmin = $DIC['ilPluginAdmin'];
1440  $pl_names = $ilPluginAdmin->getActivePluginsForSlot(IL_COMP_MODULE, "TestQuestionPool", "qst");
1441  foreach ($pl_names as $pl_name) {
1442  $pl = ilPlugin::getPluginObject(IL_COMP_MODULE, "TestQuestionPool", "qst", $pl_name);
1443  if (strcmp($pl->getQuestionType(), $row["type_tag"]) == 0) {
1444  $types[$pl->getQuestionTypeTranslation()] = $row;
1445  }
1446  }
1447  }
1448  }
1449  }
1450 
1451  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionTypeOrderer.php';
1453  $orderer = new ilAssQuestionTypeOrderer($types, $orderMode);
1454  $types = $orderer->getOrderedTypes($withDeprecatedTypes);
1455 
1456  return $types;
1457  }
1458 
1459  public static function getQuestionTypeByTypeId($type_id)
1460  {
1461  global $DIC;
1462  $ilDB = $DIC['ilDB'];
1463 
1464  $query = "SELECT type_tag FROM qpl_qst_type WHERE question_type_id = %s";
1465  $types = array('integer');
1466  $values = array($type_id);
1467  $result = $ilDB->queryF($query, $types, $values);
1468 
1469  if ($row = $ilDB->fetchAssoc($result)) {
1470  return $row['type_tag'];
1471  }
1472  }
1473 
1474  public static function getQuestionTypeTranslations()
1475  {
1476  global $DIC;
1477  $ilDB = $DIC['ilDB'];
1478  $lng = $DIC['lng'];
1479  $ilLog = $DIC['ilLog'];
1480  $ilPluginAdmin = $DIC['ilPluginAdmin'];
1481 
1482  $lng->loadLanguageModule("assessment");
1483  $result = $ilDB->query("SELECT * FROM qpl_qst_type");
1484  $types = array();
1485  while ($row = $ilDB->fetchAssoc($result)) {
1486  if ($row["plugin"] == 0) {
1487  $types[$row['type_tag']] = $lng->txt($row["type_tag"]);
1488  } else {
1489  $pl_names = $ilPluginAdmin->getActivePluginsForSlot(IL_COMP_MODULE, "TestQuestionPool", "qst");
1490  foreach ($pl_names as $pl_name) {
1491  $pl = ilPlugin::getPluginObject(IL_COMP_MODULE, "TestQuestionPool", "qst", $pl_name);
1492  if (strcmp($pl->getQuestionType(), $row["type_tag"]) == 0) {
1493  $types[$row['type_tag']] = $pl->getQuestionTypeTranslation();
1494  }
1495  }
1496  }
1497  }
1498  ksort($types);
1499  return $types;
1500  }
1501 
1507  public static function &_getSelfAssessmentQuestionTypes($all_tags = false)
1508  {
1509  /* $allowed_types = array(
1510  "assSingleChoice" => 1,
1511  "assMultipleChoice" => 2,
1512  "assClozeTest" => 3,
1513  "assMatchingQuestion" => 4,
1514  "assOrderingQuestion" => 5,
1515  "assOrderingHorizontal" => 6,
1516  "assImagemapQuestion" => 7,
1517  "assTextQuestion" => 8,
1518  "assTextSubset" => 9,
1519  "assErrorText" => 10
1520  );*/
1521  $allowed_types = array(
1522  "assSingleChoice" => 1,
1523  "assMultipleChoice" => 2,
1524  "assKprimChoice" => 3,
1525  "assClozeTest" => 4,
1526  "assMatchingQuestion" => 5,
1527  "assOrderingQuestion" => 6,
1528  "assOrderingHorizontal" => 7,
1529  "assImagemapQuestion" => 8,
1530  "assTextSubset" => 9,
1531  "assErrorText" => 10,
1532  "assLongMenu" => 11
1533  );
1534  $satypes = array();
1535  $qtypes = ilObjQuestionPool::_getQuestionTypes($all_tags);
1536  foreach ($qtypes as $k => $t) {
1537  //if (in_array($t["type_tag"], $allowed_types))
1538  if (isset($allowed_types[$t["type_tag"]])) {
1539  $t["order"] = $allowed_types[$t["type_tag"]];
1540  $satypes[$k] = $t;
1541  }
1542  }
1543  return $satypes;
1544  }
1545 
1546 
1547  public function &getQuestionList()
1548  {
1549  global $DIC;
1550  $ilDB = $DIC['ilDB'];
1551 
1552  $questions = array();
1553  $result = $ilDB->queryF(
1554  "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",
1555  array('integer'),
1556  array($this->getId())
1557  );
1558  while ($row = $ilDB->fetchAssoc($result)) {
1559  array_push($questions, $row);
1560  }
1561  return $questions;
1562  }
1563 
1570  public static function _updateQuestionCount($object_id)
1571  {
1572  global $DIC;
1573  $ilDB = $DIC['ilDB'];
1574  $result = $ilDB->manipulateF(
1575  "UPDATE qpl_questionpool SET questioncount = %s, tstamp = %s WHERE obj_fi = %s",
1576  array('integer','integer','integer'),
1577  array(ilObjQuestionPool::_getQuestionCount($object_id, true), time(), $object_id)
1578  );
1579  }
1580 
1587  public function isPluginActive($questionType)
1588  {
1589  /* @var ilPluginAdmin $ilPluginAdmin */
1590  global $DIC;
1591  $ilPluginAdmin = $DIC['ilPluginAdmin'];
1592 
1593  $plugins = $ilPluginAdmin->getActivePluginsForSlot(IL_COMP_MODULE, "TestQuestionPool", "qst");
1594  foreach ($plugins as $pluginName) {
1595  if ($pluginName == $questionType) { // plugins having pname == qtype
1596  return true;
1597  }
1598 
1599  /* @var ilQuestionsPlugin $plugin */
1600  $plugin = ilPlugin::getPluginObject(IL_COMP_MODULE, "TestQuestionPool", "qst", $pluginName);
1601 
1602  if ($plugin->getQuestionType() == $questionType) { // plugins havin an independent name
1603  return true;
1604  }
1605  }
1606 
1607  return false;
1608  }
1609 
1610  /*
1611  * Remove all questions with owner = 0
1612  */
1613  public function purgeQuestions()
1614  {
1615  global $DIC;
1616  $ilDB = $DIC['ilDB'];
1617  $ilUser = $DIC['ilUser'];
1618 
1619  require_once 'Modules/TestQuestionPool/classes/class.ilAssIncompleteQuestionPurger.php';
1620  $incompleteQuestionPurger = new ilAssIncompleteQuestionPurger($ilDB);
1621  $incompleteQuestionPurger->setOwnerId($ilUser->getId());
1622  $incompleteQuestionPurger->purge();
1623  }
1624 
1630  public function getTaxonomyIds()
1631  {
1632  require_once 'Services/Taxonomy/classes/class.ilObjTaxonomy.php';
1633  return ilObjTaxonomy::getUsageOfObject($this->getId());
1634  }
1635 
1639  public function isSkillServiceEnabled()
1640  {
1642  }
1643 
1648  {
1649  $this->skillServiceEnabled = $skillServiceEnabled;
1650  }
1651 
1653 
1654  public static function isSkillManagementGloballyActivated()
1655  {
1656  if (self::$isSkillManagementGloballyActivated === null) {
1657  include_once 'Services/Skill/classes/class.ilSkillManagementSettings.php';
1658  $skmgSet = new ilSkillManagementSettings();
1659 
1660  self::$isSkillManagementGloballyActivated = $skmgSet->isActivated();
1661  }
1662 
1663  return self::$isSkillManagementGloballyActivated;
1664  }
1665 
1666  public function fromXML($xmlFile)
1667  {
1668  require_once 'Modules/TestQuestionPool/classes/class.ilObjQuestionPoolXMLParser.php';
1669  $parser = new ilObjQuestionPoolXMLParser($this, $xmlFile);
1670  $parser->startParsing();
1671  }
1672 } // END class.ilObjQuestionPool
static makeDirParents($a_dir)
Create a new directory and all parent directories.
const ORDER_MODE_FIX
order mode with fixed priority for ordering
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 getPoolQuestionChangeListeners(ilDBInterface $db, $poolObjId)
exportXMLMetaData(&$a_xml_writer)
export content objects meta data to xml (see ilias_co.dtd)
setTitle($a_title)
set title of glossary object
$path
Definition: aliased.php:25
static _instanciateQuestion($question_id)
Creates an instance of a question with a given question id.
static getPluginObject(string $a_ctype, string $a_cname, string $a_slot_id, string $a_pname)
xmlStartTag($tag, $attrs=null, $empty=false, $encode=true, $escape=true)
Writes a starttag.
exportXMLPageObjects(&$a_xml_writer, $a_inst, &$expLog, $questions)
export page objects to xml (see ilias_co.dtd)
static _includeClass($question_type, $gui=0)
Include the php class file for a given question type.
static _hasUntrashedReference($a_obj_id)
checks wether an object has at least one reference that is not in trash
static strLen($a_string)
Definition: class.ilStr.php:78
static _isWriteable($object_id, $user_id)
Returns true, if the question pool is writeable by a given user.
populateQuestionSkillAssignmentsXml(ilXmlWriter &$a_xml_writer, $questions)
const ORDER_MODE_ALPHA
order mode that orders by alphanumerical priority
exportFileItems($a_target_dir, &$expLog)
export files of file itmes
moveToClipboard($question_id)
Moves a question to the clipboard.
exportXMLMediaObjects(&$a_xml_writer, $a_inst, $a_target_dir, &$expLog)
export media objects to xml (see ilias_co.dtd)
static _prepareCloneSelection($a_ref_ids, $new_type, $show_path=true)
Prepare copy wizard object selection.
$_SESSION["AccountId"]
$result
static getUsageOfObject($a_obj_id, $a_include_titles=false)
Get usage of object.
addQuestionChangeListeners(assQuestion $question)
static _isUsedInRandomTest($question_id="")
Checks whether the question is used in a random test or not.
global $DIC
Definition: saml.php:7
getQuestiontype($question_id)
Returns the question type of a question with a given id.
setNavTaxonomyId($navTaxonomyId)
static _lookupOnline($a_obj_id, $is_reference=false)
pasteFromClipboard()
Copies/Moves a question from the clipboard.
Abstract basic class which is to be extended by the concrete assessment question type classes...
objectToXmlWriter(ilXmlWriter &$a_xml_writer, $a_inst, $a_target_dir, &$expLog, $questions)
export pages of test to xml (see ilias_co.dtd)
static getQuestionTypeByTypeId($type_id)
static & _instanciateQuestionGUI($question_id)
Creates an instance of a question gui with a given question id.
static _getObjectsByOperations($a_obj_type, $a_operation, $a_usr_id=0, $limit=0)
Get all objects of a specific type and check access This function is not recursive, instead it parses the serialized rbac_pa entries.
getExportDirectory($type="")
get export directory of questionpool
getDescription()
get description of content object
deleteQuestion($question_id)
Deletes a question from the question pool.
createReference()
Creates a database reference id for the object (saves the object to the database and creates a refere...
createMetaData()
create meta data entry
_getFullPathToQpl($ref_id)
Retrieves the full path to a question pool with a given reference id.
XML writer class.
Question page object.
getPrintviewQuestions()
Calculates the data for the print view of the questionpool.
& getQuestionDetails($question_ids)
Returns an array containing the qpl_question and qpl_qst_type fields for an array of question ids...
copyQuestion($question_id, $questionpool_to)
Copies a question into another question pool.
getImportMapping()
get array of (two) new created questions for import id
static subStr($a_str, $a_start, $a_length=null)
Definition: class.ilStr.php:15
saveToDb()
Saves a ilObjQuestionpool object to a database.
static _getAllReferences($a_id)
get all reference ids of object
xmlEndTag($tag)
Writes an endtag.
setOnline($a_online_status)
Sets the questionpool online status.
setSkillServiceEnabled($skillServiceEnabled)
modifyExportIdentifier($a_tag, $a_param, $a_value)
static _hasEqualPoints($a_obj_id, $is_reference=false)
Checks a question pool for questions with the same maximum points.
getQuestionTypes($all_tags=false, $fixOrder=false, $withDeprecatedTypes=true)
static & _getSelfAssessmentQuestionTypes($all_tags=false)
Get all self assessment question types.
duplicateQuestion($question_id)
Duplicates a question for a questionpool.
setShowTaxonomies($showTaxonomies)
questionsToXML($questions)
Returns a QTI xml representation of a list of questions.
static _getInstance($a_copy_id)
Get instance of copy wizard options.
static _updateQuestionCount($object_id)
Updates the number of available questions for a question pool in the database.
$success
Definition: Utf8Test.php:86
getId()
get object id public
$values
static _lookupObjId($a_id)
__construct($a_id=0, $a_call_by_reference=true)
Constructor public.
static collectFileItems($a_page, $a_domdoc)
Get all file items that are used within the page.
static _getForbiddenQuestionTypes()
Returns the forbidden questiontypes for ILIAS.
cleanupClipboard($deletedQuestionId)
static _setImportDirectory($a_import_dir=null)
set import directory
const IL_COMP_MODULE
$ilUser
Definition: imgupload.php:18
redirection script todo: (a better solution should control the processing via a xml file) ...
update()
update object data
createExportDirectory()
creates data directory for export files (data_dir/qpl_data/qpl_<id>/export, depending on data directo...
& createQuestion($question_type, $question_id=-1)
Class ilObjMediaObject.
$query
copyToClipboard($question_id)
Copies a question to the clipboard.
read($a_force_db=false)
read object data from db into object
getType()
get object type public
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
$row
if(php_sapi_name() !='cli') $in
Definition: Utf8Test.php:37
$rows
Definition: xhr_table.php:10
update($pash, $contents, Config $config)
getTitle()
get title of glossary object
isPluginActive($questionType)
Checks wheather or not a question plugin with a given name is active.
& getAllQuestions()
Retrieve an array containing all question ids of the questionpool.
$parser
Definition: BPMN2Parser.php:23
static getDataDir()
get data directory (outside webspace)
static _getQuestionCount($questionpool_id, $complete_questions_only=false)
Returns the number of questions in a question pool.
global $ilBench
Definition: ilias.php:18
global $ilDB
getTaxonomyIds()
get ids of all taxonomies corresponding to current pool
loadFromDb()
Loads a ilObjQuestionpool object from a database.
cloneObject($a_target_id, $a_copy_id=0, $a_omit_tree=false)
Creates a 1:1 copy of the object and places the copy in a given repository.
static _getExportDirectory($a_obj_id, $a_type="xml", $a_obj_type="", $a_entity="")
Get export directory for an repository object.
static insertInstIntoID($a_value)
inserts installation id into ILIAS id
deleteMetaData()
delete meta data entry
static _getImportDirectory()
get import directory of lm
addQuestionChangeListener(ilQuestionChangeListener $listener)
static _exists($a_id, $a_reference=false, $a_type=null)
checks wether a lm content object with specified id exists or not
static _createImportDirectory()
creates data directory for import files (data_dir/qpl_data/qpl_<id>/import, depending on data directo...
static delDir($a_dir, $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
$key
Definition: croninfo.php:18
setDescription($a_description)
set description of content object
create($a_upload=false)
create questionpool object
isInUse($question_id)
Checks whether the question is in use or not.
& getDeleteableQuestionDetails($question_ids)
Returns an array containing the qpl_question and qpl_qst_type fields of deleteable questions for an a...
static _getQuestionTypes($all_tags=false, $fixOrder=false, $withDeprecatedTypes=true)
$data
Definition: bench.php:6