ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
Export.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
21 namespace ILIAS\Test\ExportImport;
22 
28 
40 abstract class Export implements Exporter
41 {
42  private string $export_dir;
43  private string $subdir;
44  private string $qti_filename;
45  private string $filename;
46  private string $resultsfile;
47 
48  private ?\ilXmlWriter $xml = null;
49 
50  protected bool $result_exporting_enabled = false;
51 
53 
54  protected string $inst_id;
55 
56  public function __construct(
57  protected readonly Language $lng,
58  protected readonly \ilDBInterface $db,
59  protected readonly \ilBenchmark $bench,
60  protected readonly TestLogger $logger,
61  protected readonly \ilTree $tree,
62  protected readonly \ilComponentRepository $component_repository,
63  protected readonly GeneralQuestionPropertiesRepository $questionrepository,
64  protected readonly FileDeliveryServices $file_delivery,
65  protected readonly \ilObjTest $test_obj,
66  protected readonly ResourceStorage $irss
67  ) {
68  $this->inst_id = (string) IL_INST_ID;
69  $this->export_dir = $test_obj->getExportDirectory();
70 
71  $date = time();
72  $this->export_dir = $test_obj->getExportDirectory();
73  $this->subdir = "{$date}__{$this->inst_id}__tst_{$this->test_obj->getId()}";
74  $this->filename = $this->subdir . '.xml';
75  $this->resultsfile = "{$date}__{$this->inst_id}__results_{$this->test_obj->getId()}.xml";
76  $this->qti_filename = "{$date}__{$this->inst_id}__qti_{$this->test_obj->getId()}.xml";
77  }
78 
79  abstract protected function initXmlExport();
80  abstract protected function getQuestionIds();
81  abstract protected function populateQuestionSetConfigXml(\ilXmlWriter $xmlWriter);
82  abstract protected function getQuestionsQtiXml();
83 
84  private function isResultExportingEnabled(): bool
85  {
87  }
88 
89  public function withResultExportingEnabled(bool $enable): self
90  {
91  $clone = clone $this;
92  $clone->result_exporting_enabled = $enable;
93  return $clone;
94  }
95 
96  public function withExportDirInfo(string $export_dir): self
97  {
98  $clone = clone $this;
99  $clone->subdir = basename($export_dir);
100  $clone->filename = $clone->subdir . '.xml';
101  $path_array = explode('__', $clone->subdir);
102  $clone->resultsfile = "{$path_array[0]}__{$path_array[1]}__results_{$this->test_obj->getId()}.xml";
103  $clone->qti_filename = "{$path_array[0]}__{$path_array[1]}__qti_{$this->test_obj->getId()}.xml";
104  return $clone;
105  }
106 
107  public function write(): ?string
108  {
109  $this->bench->start('TestExport', 'write');
110 
111  $this->initXmlExport();
112 
113  $this->xml = new \ilXmlWriter();
114 
115  // set dtd definition
116  $this->xml->xmlSetDtdDef('<!DOCTYPE Test SYSTEM "http://www.ilias.uni-koeln.de/download/dtd/ilias_co.dtd">');
117 
118  // set generated comment
119  $this->xml->xmlSetGenCmt('Export of ILIAS Test '
120  . "{$this->test_obj->getId()} of installation {$this->inst_id}");
121 
122  // set xml header
123  $this->xml->xmlHeader();
124 
125  $this->xml->xmlStartTag('ContentObject', ['Type' => 'Test']);
126 
127  // create directories
128  $this->test_obj->createExportDirectory();
129  \ilFileUtils::makeDir($this->export_dir . '/' . $this->subdir);
130  \ilFileUtils::makeDir($this->export_dir . '/' . $this->subdir . '/objects');
131 
132  $exp_log = new \ilLog(
133  $this->test_obj->getExportDirectory(),
134  'export.log'
135  );
136  $exp_log->delete();
137  $exp_log->setLogFormat('');
138  $exp_log->write(date('[y-m-d H:i:s] ') . 'Start Export');
139 
140  // write qti file
141  $qti_file = fopen($this->export_dir . '/' . $this->subdir . '/' . $this->qti_filename, 'wb');
142  fwrite($qti_file, $this->getQtiXml());
143  fclose($qti_file);
144 
145  // get xml content
146  $this->bench->start('TestExport', 'write_getXML');
147  $this->test_obj->exportPagesXML(
148  $this->xml,
149  $this->inst_id,
150  $this->export_dir . '/' . $this->subdir,
151  $exp_log
152  );
153  $this->bench->stop('TestExport', 'write_getXML');
154 
155  $this->populateQuestionSetConfigXml($this->xml);
156 
157  $assignment_list = $this->buildQuestionSkillAssignmentList();
158  $this->populateQuestionSkillAssignmentsXml($this->xml, $assignment_list, $this->getQuestionIds());
159  $this->populateSkillLevelThresholdsXml($this->xml, $assignment_list);
160 
161  $this->xml->xmlEndTag('ContentObject');
162 
163  $this->bench->start('TestExport', 'write_dumpToFile');
164  $this->xml->xmlDumpFile($this->export_dir . '/' . $this->subdir . '/' . $this->filename, false);
165  $this->bench->stop('TestExport', 'write_dumpToFile');
166 
167  if ($this->isResultExportingEnabled()) {
168  $resultwriter = new \ilTestResultsToXML(
169  $this->test_obj->getTestId(),
170  $this->db,
171  $this->irss,
172  $this->export_dir . "/" . $this->subdir . "/objects",
173  $this->test_obj->getAnonymity()
174  );
175  $resultwriter->setIncludeRandomTestQuestionsEnabled($this->test_obj->isRandomTest());
176  $this->bench->start('TestExport', 'write_results');
177  $resultwriter->xmlDumpFile($this->export_dir . '/' . $this->subdir . '/' . $this->resultsfile, false);
178  $this->bench->stop('TestExport', 'write_results');
179  }
180 
181  // add media objects which were added with tiny mce
182  $this->bench->start('QuestionpoolExport', 'write_saveAdditionalMobs');
183  $this->exportXHTMLMediaObjects($this->export_dir . '/' . $this->subdir);
184  $this->bench->stop('QuestionpoolExport', 'write_saveAdditionalMobs');
185 
186  // zip the file
187  $this->bench->start('TestExport', 'write_zipFile');
189  $this->export_dir . '/' . $this->subdir,
190  $this->export_dir . '/' . $this->subdir . '.zip'
191  );
192  $this->bench->stop('TestExport', 'write_zipFile');
193 
194  // destroy writer object
195  $this->xml = null;
196 
197  $exp_log->write(date('[y-m-d H:i:s] ') . 'Finished Export');
198  $this->bench->stop('TestExport', 'write');
199 
200  unlink($this->export_dir . '/' . $this->subdir . '.zip');
201 
202  return $this->export_dir . '/' . $this->subdir . '.zip';
203  }
204 
205  public function deliver(): void
206  {
207  if (($path = $this->write()) === null) {
208  return;
209  }
210  $this->file_delivery->legacyDelivery()->attached(
211  $path,
212  null,
213  null,
214  true
215  );
216  }
217 
218  protected function getQtiXml()
219  {
220  $tst_qti_xml = $this->test_obj->toXML();
221  $qst_qti_xml = $this->getQuestionsQtiXml();
222 
223  if (strpos($tst_qti_xml, '</section>') !== false) {
224  $qti_xml = str_replace('</section>', "{$qst_qti_xml}</section>", $tst_qti_xml);
225  } else {
226  $qti_xml = str_replace("<section ident=\"1\"/>", "<section ident=\"1\">\n{$qst_qti_xml}</section>", $tst_qti_xml);
227  }
228 
229  return $qti_xml;
230  }
231 
232  protected function getQuestionQtiXml(int $question_id): string
233  {
234  $question_obj = \assQuestion::instantiateQuestion($question_id);
235  $xml = $question_obj->toXML(false);
236 
237  // still neccessary? there is an include header flag!?
238  $xml = preg_replace('/<questestinterop>/', '', $xml);
239  $xml = preg_replace('/<\/questestinterop>/', '', $xml);
240 
241  return $xml;
242  }
243 
244  public function exportXHTMLMediaObjects($a_export_dir): void
245  {
246  $mobs = \ilObjMediaObject::_getMobsOfObject('tst:html', $this->test_obj->getId());
247 
248  foreach ($mobs as $mob) {
249  if (\ilObjMediaObject::_exists($mob)) {
250  $mob_obj = new \ilObjMediaObject($mob);
251  $mob_obj->exportFiles($a_export_dir);
252  unset($mob_obj);
253  }
254  }
255  foreach ($this->getQuestionIds() as $question_id) {
256  $mobs = \ilObjMediaObject::_getMobsOfObject('qpl:html', $question_id);
257  foreach ($mobs as $mob) {
258  if (\ilObjMediaObject::_exists($mob)) {
259  $mob_obj = new \ilObjMediaObject($mob);
260  $mob_obj->exportFiles($a_export_dir);
261  unset($mob_obj);
262  }
263  }
264  }
265  }
266 
268  \ilXmlWriter $a_xml_writer,
269  \ilAssQuestionSkillAssignmentList $assignment_list,
270  array $questions
271  ) {
272  $skill_question_assignment_exporter = new \ilAssQuestionSkillAssignmentExporter();
273  $skill_question_assignment_exporter->setXmlWriter($a_xml_writer);
274  $skill_question_assignment_exporter->setQuestionIds($questions);
275  $skill_question_assignment_exporter->setAssignmentList($assignment_list);
276  $skill_question_assignment_exporter->export();
277  }
278 
280  \ilXmlWriter $a_xml_writer,
281  \ilAssQuestionSkillAssignmentList $assignment_list
282  ) {
283  $threshold_list = new \ilTestSkillLevelThresholdList($this->db);
284  $threshold_list->setTestId($this->test_obj->getTestId());
285  $threshold_list->loadFromDb();
286 
287  $skill_level_threshold_exporter = new \ilTestSkillLevelThresholdExporter();
288  $skill_level_threshold_exporter->setXmlWriter($a_xml_writer);
289  $skill_level_threshold_exporter->setAssignmentList($assignment_list);
290  $skill_level_threshold_exporter->setThresholdList($threshold_list);
291  $skill_level_threshold_exporter->export();
292  }
293 
295  {
296  $assignment_list = new \ilAssQuestionSkillAssignmentList($this->db);
297  $assignment_list->setParentObjId($this->test_obj->getId());
298  $assignment_list->loadFromDb();
299  $assignment_list->loadAdditionalSkillData();
300 
301  return $assignment_list;
302  }
303 }
getQuestionQtiXml(int $question_id)
Definition: Export.php:232
Readable part of repository interface to ilComponentDataDB.
const IL_INST_ID
Definition: constants.php:40
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
populateSkillLevelThresholdsXml(\ilXmlWriter $a_xml_writer, \ilAssQuestionSkillAssignmentList $assignment_list)
Definition: Export.php:279
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
withResultExportingEnabled(bool $enable)
Definition: Export.php:89
__construct(protected readonly Language $lng, protected readonly \ilDBInterface $db, protected readonly \ilBenchmark $bench, protected readonly TestLogger $logger, protected readonly \ilTree $tree, protected readonly \ilComponentRepository $component_repository, protected readonly GeneralQuestionPropertiesRepository $questionrepository, protected readonly FileDeliveryServices $file_delivery, protected readonly \ilObjTest $test_obj, protected readonly ResourceStorage $irss)
Definition: Export.php:56
$path
Definition: ltiservices.php:29
populateQuestionSkillAssignmentsXml(\ilXmlWriter $a_xml_writer, \ilAssQuestionSkillAssignmentList $assignment_list, array $questions)
Definition: Export.php:267
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
ilTestParticipantList $forced_access_filtered_participant_list
Definition: Export.php:52
static instantiateQuestion(int $question_id)
Export class for tests.
Definition: Export.php:40
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _exists(int $id, bool $reference=false, ?string $type=null)
static _getMobsOfObject(string $a_type, int $a_id, int $a_usage_hist_nr=0, string $a_lang="-")
withExportDirInfo(string $export_dir)
Definition: Export.php:96
exportXHTMLMediaObjects($a_export_dir)
Definition: Export.php:244
global $lng
Definition: privfeed.php:31
$file_delivery
Definition: deliver.php:29
static zip(string $a_dir, string $a_file, bool $compress_content=false)
Class ilBenchmark.
populateQuestionSetConfigXml(\ilXmlWriter $xmlWriter)
static makeDir(string $a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...