ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
Export.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
26use ILIAS\FileDelivery\Services as FileDeliveryServices;
27use ILIAS\ResourceStorage\Services as ResourceStorage;
28
40abstract 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}
Export class for tests.
Definition: Export.php:41
withResultExportingEnabled(bool $enable)
Definition: Export.php:89
exportXHTMLMediaObjects($a_export_dir)
Definition: Export.php:244
populateSkillLevelThresholdsXml(\ilXmlWriter $a_xml_writer, \ilAssQuestionSkillAssignmentList $assignment_list)
Definition: Export.php:279
populateQuestionSetConfigXml(\ilXmlWriter $xmlWriter)
ilTestParticipantList $forced_access_filtered_participant_list
Definition: Export.php:52
populateQuestionSkillAssignmentsXml(\ilXmlWriter $a_xml_writer, \ilAssQuestionSkillAssignmentList $assignment_list, array $questions)
Definition: Export.php:267
__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
withExportDirInfo(string $export_dir)
Definition: Export.php:96
getQuestionQtiXml(int $question_id)
Definition: Export.php:232
static instantiateQuestion(int $question_id)
Class ilBenchmark.
static zip(string $a_dir, string $a_file, bool $compress_content=false)
static makeDir(string $a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
static _getMobsOfObject(string $a_type, int $a_id, int $a_usage_hist_nr=0, string $a_lang="-")
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const IL_INST_ID
Definition: constants.php:40
$file_delivery
Definition: deliver.php:29
Readable part of repository interface to ilComponentDataDB.
Interface ilDBInterface.
$path
Definition: ltiservices.php:30
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $lng
Definition: privfeed.php:31