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