ILIAS  trunk Revision v12.0_alpha-377-g3641b37b9db
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 \ilLanguage $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 protected readonly \ilObjUser $user
68 ) {
69 $this->inst_id = (string) IL_INST_ID;
70 $this->export_dir = $test_obj->getExportDirectory();
71
72 $date = time();
73 $this->export_dir = $test_obj->getExportDirectory();
74 $this->subdir = "{$date}__{$this->inst_id}__tst_{$this->test_obj->getId()}";
75 $this->filename = $this->subdir . '.xml';
76 $this->resultsfile = "{$date}__{$this->inst_id}__results_{$this->test_obj->getId()}.xml";
77 $this->qti_filename = "{$date}__{$this->inst_id}__qti_{$this->test_obj->getId()}.xml";
78 }
79
80 abstract protected function initXmlExport();
81 abstract protected function getQuestionIds();
82 abstract protected function populateQuestionSetConfigXml(\ilXmlWriter $xmlWriter);
83 abstract protected function getQuestionsQtiXml();
84
85 private function isResultExportingEnabled(): bool
86 {
88 }
89
90 public function withResultExportingEnabled(bool $enable): self
91 {
92 $clone = clone $this;
93 $clone->result_exporting_enabled = $enable;
94 return $clone;
95 }
96
97 public function withExportDirInfo(string $export_dir): self
98 {
99 $clone = clone $this;
100 $clone->subdir = basename($export_dir);
101 $clone->filename = $clone->subdir . '.xml';
102 $path_array = explode('__', $clone->subdir);
103 $clone->resultsfile = "{$path_array[0]}__{$path_array[1]}__results_{$this->test_obj->getId()}.xml";
104 $clone->qti_filename = "{$path_array[0]}__{$path_array[1]}__qti_{$this->test_obj->getId()}.xml";
105 return $clone;
106 }
107
108 public function write(): ?string
109 {
110 $this->bench->start('TestExport', 'write');
111
112 $this->initXmlExport();
113
114 $this->xml = new \ilXmlWriter();
115
116 // set dtd definition
117 $this->xml->xmlSetDtdDef('<!DOCTYPE Test SYSTEM "http://www.ilias.uni-koeln.de/download/dtd/ilias_co.dtd">');
118
119 // set generated comment
120 $this->xml->xmlSetGenCmt('Export of ILIAS Test '
121 . "{$this->test_obj->getId()} of installation {$this->inst_id}");
122
123 // set xml header
124 $this->xml->xmlHeader();
125
126 $this->xml->xmlStartTag('ContentObject', ['Type' => 'Test']);
127
128 // create directories
129 $this->test_obj->createExportDirectory();
130 \ilFileUtils::makeDir($this->export_dir . '/' . $this->subdir);
131 \ilFileUtils::makeDir($this->export_dir . '/' . $this->subdir . '/objects');
132
133 $exp_log = new \ilLog(
134 $this->test_obj->getExportDirectory(),
135 'export.log'
136 );
137 $exp_log->delete();
138 $exp_log->setLogFormat('');
139 $exp_log->write(date('[y-m-d H:i:s] ') . 'Start Export');
140
141 // write qti file
142 $qti_file = fopen($this->export_dir . '/' . $this->subdir . '/' . $this->qti_filename, 'wb');
143 fwrite($qti_file, $this->getQtiXml());
144 fclose($qti_file);
145
146 // get xml content
147 $this->bench->start('TestExport', 'write_getXML');
148 $this->test_obj->exportPagesXML(
149 $this->xml,
150 $this->inst_id,
151 $this->export_dir . '/' . $this->subdir,
152 $exp_log
153 );
154 $this->bench->stop('TestExport', 'write_getXML');
155
156 $this->populateQuestionSetConfigXml($this->xml);
157
158 $assignment_list = $this->buildQuestionSkillAssignmentList();
159 $this->populateQuestionSkillAssignmentsXml($this->xml, $assignment_list, $this->getQuestionIds());
160 $this->populateSkillLevelThresholdsXml($this->xml, $assignment_list);
161
162 $this->xml->xmlEndTag('ContentObject');
163
164 $this->bench->start('TestExport', 'write_dumpToFile');
165 $this->xml->xmlDumpFile($this->export_dir . '/' . $this->subdir . '/' . $this->filename, false);
166 $this->bench->stop('TestExport', 'write_dumpToFile');
167
168 if ($this->isResultExportingEnabled()) {
169 $resultwriter = new \ilTestResultsToXML(
170 $this->test_obj,
171 $this->db,
172 $this->irss,
173 $this->user,
174 $this->lng,
175 "{$this->export_dir}/{$this->subdir}/objects"
176 );
177 $resultwriter->setIncludeRandomTestQuestionsEnabled($this->test_obj->isRandomTest());
178 $this->bench->start('TestExport', 'write_results');
179 $resultwriter->xmlDumpFile($this->export_dir . '/' . $this->subdir . '/' . $this->resultsfile, false);
180 $this->bench->stop('TestExport', 'write_results');
181 }
182
183 // add media objects which were added with tiny mce
184 $this->bench->start('QuestionpoolExport', 'write_saveAdditionalMobs');
185 $this->exportXHTMLMediaObjects($this->export_dir . '/' . $this->subdir);
186 $this->bench->stop('QuestionpoolExport', 'write_saveAdditionalMobs');
187
188 // zip the file
189 $this->bench->start('TestExport', 'write_zipFile');
191 $this->export_dir . '/' . $this->subdir,
192 $this->export_dir . '/' . $this->subdir . '.zip'
193 );
194 $this->bench->stop('TestExport', 'write_zipFile');
195
196 // destroy writer object
197 $this->xml = null;
198
199 $exp_log->write(date('[y-m-d H:i:s] ') . 'Finished Export');
200 $this->bench->stop('TestExport', 'write');
201
202 unlink($this->export_dir . '/' . $this->subdir . '.zip');
203
204 return $this->export_dir . '/' . $this->subdir . '.zip';
205 }
206
207 public function deliver(): void
208 {
209 if (($path = $this->write()) === null) {
210 return;
211 }
212 $this->file_delivery->legacyDelivery()->attached(
213 $path,
214 null,
215 null,
216 true
217 );
218 }
219
220 protected function getQtiXml()
221 {
222 $tst_qti_xml = $this->test_obj->toXML();
223 $qst_qti_xml = $this->getQuestionsQtiXml();
224
225 if (strpos($tst_qti_xml, '</section>') !== false) {
226 $qti_xml = str_replace('</section>', "{$qst_qti_xml}</section>", $tst_qti_xml);
227 } else {
228 $qti_xml = str_replace("<section ident=\"1\"/>", "<section ident=\"1\">\n{$qst_qti_xml}</section>", $tst_qti_xml);
229 }
230
231 return $qti_xml;
232 }
233
234 protected function getQuestionQtiXml(int $question_id): string
235 {
236 $question_obj = \assQuestion::instantiateQuestion($question_id);
237 $xml = $question_obj->toXML(false);
238
239 // still neccessary? there is an include header flag!?
240 $xml = preg_replace('/<questestinterop>/', '', $xml);
241 $xml = preg_replace('/<\/questestinterop>/', '', $xml);
242
243 return $xml;
244 }
245
246 public function exportXHTMLMediaObjects($a_export_dir): void
247 {
248 $mobs = \ilObjMediaObject::_getMobsOfObject('tst:html', $this->test_obj->getId());
249
250 foreach ($mobs as $mob) {
251 if (\ilObjMediaObject::_exists($mob)) {
252 $mob_obj = new \ilObjMediaObject($mob);
253 $mob_obj->exportFiles($a_export_dir);
254 unset($mob_obj);
255 }
256 }
257 foreach ($this->getQuestionIds() as $question_id) {
258 $mobs = \ilObjMediaObject::_getMobsOfObject('qpl:html', $question_id);
259 foreach ($mobs as $mob) {
260 if (\ilObjMediaObject::_exists($mob)) {
261 $mob_obj = new \ilObjMediaObject($mob);
262 $mob_obj->exportFiles($a_export_dir);
263 unset($mob_obj);
264 }
265 }
266 }
267 }
268
270 \ilXmlWriter $a_xml_writer,
271 \ilAssQuestionSkillAssignmentList $assignment_list,
272 array $questions
273 ) {
274 $skill_question_assignment_exporter = new \ilAssQuestionSkillAssignmentExporter();
275 $skill_question_assignment_exporter->setXmlWriter($a_xml_writer);
276 $skill_question_assignment_exporter->setQuestionIds($questions);
277 $skill_question_assignment_exporter->setAssignmentList($assignment_list);
278 $skill_question_assignment_exporter->export();
279 }
280
282 \ilXmlWriter $a_xml_writer,
283 \ilAssQuestionSkillAssignmentList $assignment_list
284 ) {
285 $threshold_list = new \ilTestSkillLevelThresholdList($this->db);
286 $threshold_list->setTestId($this->test_obj->getTestId());
287 $threshold_list->loadFromDb();
288
289 $skill_level_threshold_exporter = new \ilTestSkillLevelThresholdExporter();
290 $skill_level_threshold_exporter->setXmlWriter($a_xml_writer);
291 $skill_level_threshold_exporter->setAssignmentList($assignment_list);
292 $skill_level_threshold_exporter->setThresholdList($threshold_list);
293 $skill_level_threshold_exporter->export();
294 }
295
297 {
298 $assignment_list = new \ilAssQuestionSkillAssignmentList($this->db);
299 $assignment_list->setParentObjId($this->test_obj->getId());
300 $assignment_list->loadFromDb();
301 $assignment_list->loadAdditionalSkillData();
302
303 return $assignment_list;
304 }
305}
Export class for tests.
Definition: Export.php:41
withResultExportingEnabled(bool $enable)
Definition: Export.php:90
exportXHTMLMediaObjects($a_export_dir)
Definition: Export.php:246
populateSkillLevelThresholdsXml(\ilXmlWriter $a_xml_writer, \ilAssQuestionSkillAssignmentList $assignment_list)
Definition: Export.php:281
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:269
__construct(protected readonly \ilLanguage $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, protected readonly \ilObjUser $user)
Definition: Export.php:56
withExportDirInfo(string $export_dir)
Definition: Export.php:97
getQuestionQtiXml(int $question_id)
Definition: Export.php:234
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 ...
language handling
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|false $a_usage_hist_nr=0, string $a_lang="-")
User class.
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