ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilDataSet.php
Go to the documentation of this file.
1<?php
2
24
42abstract class ilDataSet
43{
44 public const DATASET_NS = 'http://www.ilias.de/Services/DataSet/ds/4_3';
45 public const DATASET_NS_PREFIX = 'ds';
46
47 public const EXPORT_NO_INST_ID = 1;
48 public const EXPORT_ID_ILIAS_LOCAL = 2;
50 public const EXPORT_ID_ILIAS_REMOTE = 4;
52 public const EXPORT_ID = 6;
53 public const EXPORT_ID_INVALID = 7;
54 protected \ILIAS\ResourceStorage\Services $irss;
55
56 public int $dircnt = 0;
57 protected string $current_installation_id = "";
58 protected array $data = [];
59 protected ilDBInterface $db;
60 protected ilLogger $ds_log;
61 protected string $import_directory = "";
62 protected string $entity = "";
63 protected string $schema_version = "";
64 protected string $component_export_dir = "";
65 protected string $ds_prefix = "ds";
66 protected string $version = "";
68 protected ilExport $export;
69
70 public function __construct()
71 {
72 global $DIC;
73
74 $this->db = $DIC->database();
75 $this->ds_log = ilLoggerFactory::getLogger('ds');
76 $this->irss = $DIC->resourceStorage();
77 }
78
91 final public function init(string $a_entity, string $a_schema_version): void
92 {
93 $this->entity = $a_entity;
94 $this->schema_version = $a_schema_version;
95 $this->data = array();
96 }
97
98 abstract public function getSupportedVersions(): array;
99
107 abstract protected function getTypes(string $a_entity, string $a_version): array;
108
109 abstract protected function getXmlNamespace(string $a_entity, string $a_schema_version): string;
110
115 abstract public function readData(
116 string $a_entity,
117 string $a_version,
118 array $a_ids
119 ): void;
120
121 public function initByExporter(ilXmlExporter $xml_exporter): void
122 {
123 $this->export = $xml_exporter->getExport();
124 }
125
126 public function setImportDirectory(string $a_val): void
127 {
128 $this->import_directory = $a_val;
129 }
130
131 public function getImportDirectory(): string
132 {
134 }
135
136 public function setDSPrefix(string $a_val): void
137 {
138 $this->ds_prefix = $a_val;
139 }
140
141 public function getDSPrefix(): string
142 {
143 return $this->ds_prefix;
144 }
145
146 public function getDSPrefixString(): string
147 {
148 if ($this->getDSPrefix() !== "") {
149 return $this->getDSPrefix() . ":";
150 }
151 return "";
152 }
153
158 public function getDirectDataFromQuery(
159 string $a_query,
160 bool $a_convert_to_leading_upper = true,
161 bool $a_set = true
162 ): array {
163 $ilDB = $this->db;
164
165 $set = $ilDB->query($a_query);
166 $this->data = array();
167 $ret = [];
168 while ($rec = $ilDB->fetchAssoc($set)) {
169 if ($a_convert_to_leading_upper) {
170 $tmp = array();
171 foreach ($rec as $k => $v) {
172 $tmp[$this->convertToLeadingUpper($k)]
173 = $v;
174 }
175 $rec = $tmp;
176 }
177
178 if ($a_set) {
179 $this->data[] = $rec;
180 }
181 $ret[] = $rec;
182 }
183 return $ret;
184 }
185
189 public function convertToLeadingUpper(string $a_str): string
190 {
191 $a_str = strtoupper(substr($a_str, 0, 1)) . substr($a_str, 1);
192 while (($pos = strpos($a_str, "_")) !== false) {
193 $a_str = substr($a_str, 0, $pos) .
194 strtoupper(substr($a_str, $pos + 1, 1)) .
195 substr($a_str, $pos + 2);
196 }
197 return $a_str;
198 }
199
200
222 final public function getXmlRepresentation(
223 string $a_entity,
224 string $a_schema_version,
225 ?array $a_ids,
226 string $a_field = "",
227 bool $a_omit_header = false,
228 bool $a_omit_types = false
229 ): string {
230 $this->dircnt = 1;
231
232 // init writer
233 $writer = new ilXmlWriter();
234 if (!$a_omit_header) {
235 $writer->xmlHeader();
236 }
237
238 // collect namespaces
239 $namespaces = $prefixes = array();
240 $this->getNamespaces($namespaces, $a_entity, $a_schema_version);
241 $atts = array("InstallationId" => IL_INST_ID,
242 "InstallationUrl" => ILIAS_HTTP_PATH, "TopEntity" => $a_entity);
243 $cnt = 1;
244 foreach ($namespaces as $entity => $ns) {
245 $prefix = "ns" . $cnt;
246 $prefixes[$entity] = $prefix;
247 // $atts["xmlns:".$prefix] = $ns;
248 $cnt++;
249 }
250 $this->ds_log->debug("Start writing Dataset, entity: " . $a_entity . ", schema version: " . $a_schema_version .
251 ", ids: " . print_r($a_ids, true));
252
253 if ($this->getDSPrefix() !== '') {
254 $atts['xmlns:' . $this->getDSPrefix()] = self::DATASET_NS;
255 } else {
256 $atts['xmlns'] = self::DATASET_NS;
257 }
258 $writer->xmlStartTag($this->getDSPrefixString() . 'DataSet', $atts);
259 // add types
260 if (!$a_omit_types) {
261 $this->ds_log->debug("...write types");
262 $this->addTypesXml($writer, $a_entity, $a_schema_version);
263 }
264 // add records
265 $this->ds_log->debug("...write records");
266 $this->addRecordsXml($writer, $prefixes, $a_entity, $a_schema_version, $a_ids, $a_field);
267
268 $writer->xmlEndTag($this->getDSPrefixString() . "DataSet");
269
270 return $writer->xmlDumpMem(false);
271 }
272
273 protected function getExportDirInContainer(string $exp_dir): string
274 {
275 // note, the export returns in ILIAS 10 (Jan 2024) something like
276 // 1737382047__0__cat_436/components/ILIAS/Style/set_0/dsDir_1
277 // whereas ILIAS 9 returned
278 // Services/Style/set_1/expDir_1/dsDir_1
279 // thus we skip the 1737382047__0__cat_436/ part since it would be redundant
280 // an make import fail
281 if (str_contains($exp_dir, "components/")) {
282 $exp_dir = substr($exp_dir, strpos($exp_dir, "components/"));
283 }
284 return $exp_dir;
285 }
286
287 public function addRecordsXml(
288 ilXmlWriter $a_writer,
289 array $a_prefixes,
290 string $a_entity,
291 string $a_schema_version,
292 array $a_ids,
293 ?string $a_field = ""
294 ): void {
295 $types = $this->getXmlTypes($a_entity, $a_schema_version);
296 $this->ds_log->debug("...read data");
297 $this->readData($a_entity, $a_schema_version, $a_ids);
298 $this->ds_log->debug("...data: " . print_r($this->data, true));
299 foreach ($this->data as $d) {
300 $a_writer->xmlStartTag(
301 $this->getDSPrefixString() . "Rec",
302 array("Entity" => $this->getXMLEntityName($a_entity, $a_schema_version))
303 );
304 $a_writer->xmlStartTag($this->getXMLEntityTag($a_entity, ''));
305 $rec = $this->getXmlRecord($a_entity, $a_schema_version, $d);
306 foreach ($rec as $f => $c) {
307 if (isset($this->export) and ($types[$f] ?? "") === "directory") {
308 $sdir = realpath($c);
309 $path_in_container = $this->export->getPathToComponentExpDirInContainer() . "/dsDir_" . $this->dircnt;
310 $this->export->getExportWriter()->writeDirectory(
311 $sdir,
312 $path_in_container
313 );
314 $c = $this->getExportDirInContainer($path_in_container); // note: this corrects the path, see above
315 $this->dircnt++;
316 }
317 if (isset($this->export) and ($types[$f] ?? "") === "rscollection") {
318 $path_in_container = $this->export->getPathToComponentExpDirInContainer() . "/dsDir_" . $this->dircnt;
319 $collection = $this->getCollection($rec, $a_entity, $a_schema_version, $f, $c);
320 if (!is_null($collection)) {
321 $this->export->getExportWriter()->writeFilesByResourceCollection(
322 $collection,
323 $path_in_container
324 );
325 }
326
327 $c = $this->getExportDirInContainer($path_in_container); // note: this corrects the path, see above
328 $this->dircnt++;
329 }
330 if (isset($this->export) and ($types[$f] ?? "") === "rscontainer") {
331 $path_in_container = "/dsDir_" . $this->dircnt;
332 if ($this->export->isContainerExport()) { // note: this checks if the export is in a container context and adds the set number to the path accordingly
333 $path_in_container = $this->export->getPathToComponentExpDirInContainerWithLeadingSetNumber() . $path_in_container;
334 } else {
335 $path_in_container = $this->export->getPathToComponentExpDirInContainer() . $path_in_container;
336 }
337 if ($config = $this->getContainerExportConfig($rec, $a_entity, $a_schema_version, $f, $c)) {
338 $this->export->getExportWriter()->writeFilesByResourceContainer(
339 $this->getIRSSContainerExportConfig(
340 $config->getSourceContainer(),
341 $config->getSourcePath(),
342 $path_in_container
343 )
344 );
345 }
346 $c = $this->getExportDirInContainer($path_in_container); // note: this corrects the path, see above
347 $this->dircnt++;
348 }
349 // this changes schema/dtd
350 //$a_writer->xmlElement($a_prefixes[$a_entity].":".$f,
351 // array(), $c);
352 $a_writer->xmlElement($f, array(), $c);
353 }
354
355 $a_writer->xmlEndTag($this->getXMLEntityTag($a_entity, ''));
356
357 $a_writer->xmlEndTag($this->getDSPrefixString() . "Rec");
358
359 $this->afterXmlRecordWriting($a_entity, $a_schema_version, $d);
360
361 // foreach record records of dependent entities
362 $this->ds_log->debug("...get dependencies");
363 $deps = $this->getDependencies($a_entity, $a_schema_version, $rec, $a_ids);
364 $this->ds_log->debug("...dependencies: " . print_r($deps, true));
365 foreach ($deps as $dp => $par) {
366 $ids = !is_array($par["ids"])
367 ? [$par["ids"]]
368 : $par["ids"];
369 $this->addRecordsXml($a_writer, $a_prefixes, $dp, $a_schema_version, $ids, $par["field"] ?? null);
370 }
371 }
372 }
373
375 StorableResource $source_container,
376 string $source_path,
377 string $target_path = ""
380 $source_container,
381 $source_path,
382 $target_path
383 );
384 }
385
386 protected function getDependencies(
387 string $a_entity,
388 string $a_version,
389 ?array $a_rec = null,
390 ?array $a_ids = null
391 ): array {
392 return [];
393 }
394
395 // After xml record writing hook record
396 public function afterXmlRecordWriting(string $a_entity, string $a_version, array $a_set): void
397 {
398 }
399
400 // Add types to xml writer
401 private function addTypesXml(ilXmlWriter $a_writer, string $a_entity, string $a_schema_version): void
402 {
403 $types = $this->getXmlTypes($a_entity, $a_schema_version);
404
405 // add types of current entity
406 if (count($types) > 0) {
407 $a_writer->xmlStartTag(
408 $this->getDSPrefixString() . "Types",
409 array("Entity" => $this->getXMLEntityName($a_entity, $a_schema_version),
410 "SchemaVersion" => $a_schema_version)
411 );
412 foreach ($this->getXmlTypes($a_entity, $a_schema_version) as $f => $t) {
413 $a_writer->xmlElement(
414 $this->getDSPrefixString() . 'FieldType',
415 array("Name" => $f, "Type" => $t)
416 );
417 }
418 $a_writer->xmlEndTag($this->getDSPrefixString() . "Types");
419 }
420
421 // add types of dependent entities
422 $deps = $this->getDependencies($a_entity, $a_schema_version, null, null);
423 foreach ($deps as $dp => $w) {
424 $this->addTypesXml($a_writer, $dp, $a_schema_version);
425 }
426 }
427
428 // Get xml namespaces
429 public function getNamespaces(array &$namespaces, string $a_entity, string $a_schema_version): void
430 {
431 $ns = $this->getXmlNamespace($a_entity, $a_schema_version);
432 if ($ns !== "") {
433 $namespaces[$a_entity] = $ns;
434 }
435 // add types of dependent entities
436 $deps = $this->getDependencies($a_entity, $a_schema_version, null, null);
437 foreach ($deps as $dp => $w) {
438 $this->getNamespaces($namespaces, $dp, $a_schema_version);
439 }
440 }
441
446 public function getXmlRecord(string $a_entity, string $a_version, array $a_set): array
447 {
448 return $a_set;
449 }
450
455 public function getXmlTypes(string $a_entity, string $a_version): array
456 {
457 return $this->getTypes($a_entity, $a_version);
458 }
459
464 public function getXMLEntityName(string $a_entity, string $a_version): string
465 {
466 return $a_entity;
467 }
468
472 public function getXMLEntityTag(string $a_entity, string $a_schema_version): string
473 {
474 return $this->convertToLeadingUpper($a_entity);
475 }
476
477 public function setImport(ilSurveyImporter $a_val): void
478 {
479 $this->import = $a_val;
480 }
481
482 public function getImport(): ilSurveyImporter
483 {
484 return $this->import;
485 }
486
487 public function setCurrentInstallationId(string $a_val): void
488 {
489 $this->current_installation_id = $a_val;
490 }
491
492 public function getCurrentInstallationId(): string
493 {
494 return $this->current_installation_id;
495 }
496
500 protected function createObjectExportId(string $a_type, string $a_id): string
501 {
502 return "il_" . IL_INST_ID . "_" . $a_type . "_" . $a_id;
503 }
504
509 protected function parseObjectExportId(string $a_id, ?string $a_fallback_id = null): array
510 {
511 // ilias export id?
512 if (strpos($a_id, "il_") === 0) {
513 $parts = explode("_", $a_id);
514 if (count($parts) !== 4) {
515 throw new ilException("Invalid import ID '" . $a_id . "'.");
516 }
517 $inst_id = $parts[1];
518 $type = $parts[2];
519 $id = $parts[3];
520
521 // missing installation ids?
522 if (($inst_id == 0 || IL_INST_ID === "0") && !DEVMODE) {
523 return array("type" => self::EXPORT_NO_INST_ID, "id" => $a_fallback_id);
524 }
525
526 // same installation?
527 if ($inst_id == IL_INST_ID) {
528 // still existing?
529 if (ilObject::_lookupType($id) === $type) {
530 return array("type" => self::EXPORT_ID_ILIAS_LOCAL, "id" => $id);
531 }
532 // not found
533 else {
534 return array("type" => self::EXPORT_ID_ILIAS_LOCAL_INVALID, "id" => $a_fallback_id);
535 }
536 }
537 // different installation
538 else {
540 // matching type?
541 if ($id && ilObject::_lookupType($id) === $type) {
542 return array("type" => self::EXPORT_ID_ILIAS_REMOTE, "id" => $id);
543 }
544 // not found
545 else {
546 return array("type" => self::EXPORT_ID_ILIAS_REMOTE_INVALID, "id" => $a_fallback_id);
547 }
548 }
549 } else {
550 // external id
552 if ($id) {
553 return array("type" => self::EXPORT_ID, "id" => $id);
554 } else {
555 return array("type" => self::EXPORT_ID_INVALID, "id" => $a_fallback_id);
556 }
557 }
558 }
559
563 public function importRecord(
564 string $a_entity,
565 array $a_types,
566 array $a_rec,
567 ilImportMapping $a_mapping,
568 string $a_schema_version
569 ): void {
570 }
571
572 public function getCollection(
573 array $record,
574 string $entity,
575 string $schema_version,
576 string $field,
577 string $value
579 return null;
580 }
581
583 array $record,
584 string $entity,
585 string $schema_version,
586 string $field,
587 string $value
589 return null;
590 }
591
592 protected function stripTags(array $rec, array $omit_keys = []): array
593 {
594 $ret_rec = [];
595 foreach ($rec as $k => $v) {
596 if (in_array($k, $omit_keys, true)) {
597 $ret_rec[$k] = $v;
598 } else {
599 $ret_rec[$k] = ilUtil::stripSlashes($v);
600 }
601 }
602 return $ret_rec;
603 }
604}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
A dataset contains in data in a common structure that can be shared and transformed for different pur...
const EXPORT_ID_ILIAS_REMOTE_INVALID
getTypes(string $a_entity, string $a_version)
Get (abstract) types for (abstract) field names.
getXMLEntityName(string $a_entity, string $a_version)
Get entity name for xml (may be overwritten)
importRecord(string $a_entity, array $a_types, array $a_rec, ilImportMapping $a_mapping, string $a_schema_version)
Needs to be overwritten for import use case.
ILIAS ResourceStorage Services $irss
stripTags(array $rec, array $omit_keys=[])
getIRSSContainerExportConfig(StorableResource $source_container, string $source_path, string $target_path="")
convertToLeadingUpper(string $a_str)
Make xyz_abc a XyzAbc string.
addRecordsXml(ilXmlWriter $a_writer, array $a_prefixes, string $a_entity, string $a_schema_version, array $a_ids, ?string $a_field="")
getXmlTypes(string $a_entity, string $a_version)
Get xml types.
const EXPORT_ID_ILIAS_LOCAL_INVALID
getContainerExportConfig(array $record, string $entity, string $schema_version, string $field, string $value)
getNamespaces(array &$namespaces, string $a_entity, string $a_schema_version)
string $ds_prefix
string $current_installation_id
readData(string $a_entity, string $a_version, array $a_ids)
Read data from DB.
getDirectDataFromQuery(string $a_query, bool $a_convert_to_leading_upper=true, bool $a_set=true)
Get data from query.This is a standard procedure, all db field names are directly mapped to abstract ...
setDSPrefix(string $a_val)
init(string $a_entity, string $a_schema_version)
Init.
parseObjectExportId(string $a_id, ?string $a_fallback_id=null)
Parse export id.
const DATASET_NS
createObjectExportId(string $a_type, string $a_id)
Build ilias export id.
const EXPORT_ID_INVALID
addTypesXml(ilXmlWriter $a_writer, string $a_entity, string $a_schema_version)
getCurrentInstallationId()
string $component_export_dir
ilDBInterface $db
getXmlRepresentation(string $a_entity, string $a_schema_version, ?array $a_ids, string $a_field="", bool $a_omit_header=false, bool $a_omit_types=false)
Get xml representation <dataset install_id="123" install_url="..."> <types entity="table_name" versio...
string $schema_version
const EXPORT_NO_INST_ID
getDependencies(string $a_entity, string $a_version, ?array $a_rec=null, ?array $a_ids=null)
const EXPORT_ID_ILIAS_REMOTE
getXmlNamespace(string $a_entity, string $a_schema_version)
getXMLEntityTag(string $a_entity, string $a_schema_version)
Get entity tag.
getSupportedVersions()
string $version
ilLogger $ds_log
initByExporter(ilXmlExporter $xml_exporter)
const DATASET_NS_PREFIX
setImport(ilSurveyImporter $a_val)
afterXmlRecordWriting(string $a_entity, string $a_version, array $a_set)
setImportDirectory(string $a_val)
ilSurveyImporter $import
const EXPORT_ID_ILIAS_LOCAL
ilExport $export
setCurrentInstallationId(string $a_val)
string $entity
getXmlRecord(string $a_entity, string $a_version, array $a_set)
Get xml record for version.
getExportDirInContainer(string $exp_dir)
string $import_directory
Base class for ILIAS Exception handling.
static getLogger(string $a_component_id)
Get component logger.
Component logger with individual log levels by component id.
static _lookupType(int $id, bool $reference=false)
static _getIdForImportId(string $import_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
Xml Exporter class.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
xmlElement(string $tag, $attrs=null, $data=null, $encode=true, $escape=true)
Writes a basic element (no children, just textual content)
xmlEndTag(string $tag)
Writes an endtag.
xmlStartTag(string $tag, ?array $attrs=null, bool $empty=false, bool $encode=true, bool $escape=true)
Writes a starttag.
const IL_INST_ID
Definition: constants.php:40
$c
Definition: deliver.php:25
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Interface ilDBInterface.
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:61
global $DIC
Definition: shib_login.php:26