ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilDataSet.php
Go to the documentation of this file.
1 <?php
2 
20 
38 abstract class ilDataSet
39 {
40  public const DATASET_NS = 'http://www.ilias.de/Services/DataSet/ds/4_3';
41  public const DATASET_NS_PREFIX = 'ds';
42 
43  public const EXPORT_NO_INST_ID = 1;
44  public const EXPORT_ID_ILIAS_LOCAL = 2;
46  public const EXPORT_ID_ILIAS_REMOTE = 4;
48  public const EXPORT_ID = 6;
49  public const EXPORT_ID_INVALID = 7;
50  protected \ILIAS\ResourceStorage\Services $irss;
51 
52  public int $dircnt = 0;
53  protected string $current_installation_id = "";
54  protected array $data = [];
55  protected ilDBInterface $db;
56  protected ilLogger $ds_log;
57  protected string $import_directory = "";
58  protected string $entity = "";
59  protected string $schema_version = "";
60  protected string $relative_export_dir = "";
61  protected string $absolute_export_dir = "";
62  protected string $ds_prefix = "ds";
63  protected string $version = "";
65 
66  public function __construct()
67  {
68  global $DIC;
69 
70  $this->db = $DIC->database();
71  $this->ds_log = ilLoggerFactory::getLogger('ds');
72  $this->irss = $DIC->resourceStorage();
73  }
74 
87  final public function init(string $a_entity, string $a_schema_version): void
88  {
89  $this->entity = $a_entity;
90  $this->schema_version = $a_schema_version;
91  $this->data = array();
92  }
93 
94  abstract public function getSupportedVersions(): array;
95 
103  abstract protected function getTypes(string $a_entity, string $a_version): array;
104 
105  abstract protected function getXmlNamespace(string $a_entity, string $a_schema_version): string;
106 
111  abstract public function readData(
112  string $a_entity,
113  string $a_version,
114  array $a_ids
115  ): void;
116 
117  public function setExportDirectories(string $a_relative, string $a_absolute): void
118  {
119  $this->relative_export_dir = $a_relative;
120  $this->absolute_export_dir = $a_absolute;
121  }
122 
123  public function setImportDirectory(string $a_val): void
124  {
125  $this->import_directory = $a_val;
126  }
127 
128  public function getImportDirectory(): string
129  {
131  }
132 
133  public function setDSPrefix(string $a_val): void
134  {
135  $this->ds_prefix = $a_val;
136  }
137 
138  public function getDSPrefix(): string
139  {
140  return $this->ds_prefix;
141  }
142 
143  public function getDSPrefixString(): string
144  {
145  if ($this->getDSPrefix() !== "") {
146  return $this->getDSPrefix() . ":";
147  }
148  return "";
149  }
150 
155  public function getDirectDataFromQuery(
156  string $a_query,
157  bool $a_convert_to_leading_upper = true,
158  bool $a_set = true
159  ): array {
160  $ilDB = $this->db;
161 
162  $set = $ilDB->query($a_query);
163  $this->data = array();
164  $ret = [];
165  while ($rec = $ilDB->fetchAssoc($set)) {
166  if ($a_convert_to_leading_upper) {
167  $tmp = array();
168  foreach ($rec as $k => $v) {
169  $tmp[$this->convertToLeadingUpper($k)]
170  = $v;
171  }
172  $rec = $tmp;
173  }
174 
175  if ($a_set) {
176  $this->data[] = $rec;
177  }
178  $ret[] = $rec;
179  }
180  return $ret;
181  }
182 
186  public function convertToLeadingUpper(string $a_str): string
187  {
188  $a_str = strtoupper(substr($a_str, 0, 1)) . substr($a_str, 1);
189  while (($pos = strpos($a_str, "_")) !== false) {
190  $a_str = substr($a_str, 0, $pos) .
191  strtoupper(substr($a_str, $pos + 1, 1)) .
192  substr($a_str, $pos + 2);
193  }
194  return $a_str;
195  }
196 
197 
219  final public function getXmlRepresentation(
220  string $a_entity,
221  string $a_schema_version,
222  ?array $a_ids,
223  string $a_field = "",
224  bool $a_omit_header = false,
225  bool $a_omit_types = false
226  ): string {
227  $this->dircnt = 1;
228 
229  // init writer
230  $writer = new ilXmlWriter();
231  if (!$a_omit_header) {
232  $writer->xmlHeader();
233  }
234 
235  // collect namespaces
236  $namespaces = $prefixes = array();
237  $this->getNamespaces($namespaces, $a_entity, $a_schema_version);
238  $atts = array("InstallationId" => IL_INST_ID,
239  "InstallationUrl" => ILIAS_HTTP_PATH, "TopEntity" => $a_entity);
240  $cnt = 1;
241  foreach ($namespaces as $entity => $ns) {
242  $prefix = "ns" . $cnt;
243  $prefixes[$entity] = $prefix;
244  // $atts["xmlns:".$prefix] = $ns;
245  $cnt++;
246  }
247  $this->ds_log->debug("Start writing Dataset, entity: " . $a_entity . ", schema version: " . $a_schema_version .
248  ", ids: " . print_r($a_ids, true));
249 
250  if ($this->getDSPrefix() !== '') {
251  $atts['xmlns:' . $this->getDSPrefix()] = self::DATASET_NS;
252  } else {
253  $atts['xmlns'] = self::DATASET_NS;
254  }
255  $writer->xmlStartTag($this->getDSPrefixString() . 'DataSet', $atts);
256  // add types
257  if (!$a_omit_types) {
258  $this->ds_log->debug("...write types");
259  $this->addTypesXml($writer, $a_entity, $a_schema_version);
260  }
261  // add records
262  $this->ds_log->debug("...write records");
263  $this->addRecordsXml($writer, $prefixes, $a_entity, $a_schema_version, $a_ids, $a_field);
264 
265  $writer->xmlEndTag($this->getDSPrefixString() . "DataSet");
266 
267  return $writer->xmlDumpMem(false);
268  }
269 
270 
271  public function addRecordsXml(
272  ilXmlWriter $a_writer,
273  array $a_prefixes,
274  string $a_entity,
275  string $a_schema_version,
276  array $a_ids,
277  ?string $a_field = ""
278  ): void {
279  $types = $this->getXmlTypes($a_entity, $a_schema_version);
280 
281  $this->ds_log->debug("...read data");
282  $this->readData($a_entity, $a_schema_version, $a_ids);
283  $this->ds_log->debug("...data: " . print_r($this->data, true));
284  foreach ($this->data as $d) {
285  $a_writer->xmlStartTag(
286  $this->getDSPrefixString() . "Rec",
287  array("Entity" => $this->getXMLEntityName($a_entity, $a_schema_version))
288  );
289  $a_writer->xmlStartTag($this->getXMLEntityTag($a_entity, ''));
290  $rec = $this->getXmlRecord($a_entity, $a_schema_version, $d);
291  foreach ($rec as $f => $c) {
292  if ($this->absolute_export_dir !== "" && $this->relative_export_dir !== "") {
293  if (($types[$f] ?? "") === "directory") {
294  ilFileUtils::makeDirParents($this->absolute_export_dir . "/dsDir_" . $this->dircnt);
295  $sdir = realpath($c);
296  $tdir = realpath($this->absolute_export_dir . "/dsDir_" . $this->dircnt);
297  try {
298  ilFileUtils::rCopy($sdir, $tdir);
299  } catch (\ILIAS\Filesystem\Exception\FileNotFoundException $e) {
300  $this->ds_log->error($e->getMessage());
301  }
302  $c = $this->relative_export_dir . "/dsDir_" . $this->dircnt;
303  $this->dircnt++;
304  }
305  if (($types[$f] ?? "") === "rscollection") {
306  $tdir = $this->absolute_export_dir . "/dsDir_" . $this->dircnt;
308  $tdir = realpath($tdir);
309  if ($collection = $this->getCollection($rec, $a_entity, $a_schema_version, $f, $c)) {
310  foreach ($collection->getResourceIdentifications() as $rid) {
311  $info = $this->irss->manage()->getResource($rid)
312  ->getCurrentRevision()
313  ->getInformation();
314  $stream = $this->irss->consume()->stream($rid);
315  $name = $tdir . "/" . $info->getTitle();
316  file_put_contents($name, $stream->getStream()->getContents());
317  }
318  }
319  $c = $this->relative_export_dir . "/dsDir_" . $this->dircnt;
320  $this->dircnt++;
321  }
322  }
323  // this changes schema/dtd
324  //$a_writer->xmlElement($a_prefixes[$a_entity].":".$f,
325  // array(), $c);
326  $a_writer->xmlElement($f, array(), $c);
327  }
328 
329  $a_writer->xmlEndTag($this->getXMLEntityTag($a_entity, ''));
330 
331  $a_writer->xmlEndTag($this->getDSPrefixString() . "Rec");
332 
333  $this->afterXmlRecordWriting($a_entity, $a_schema_version, $d);
334 
335  // foreach record records of dependent entities
336  $this->ds_log->debug("...get dependencies");
337  $deps = $this->getDependencies($a_entity, $a_schema_version, $rec, $a_ids);
338  $this->ds_log->debug("...dependencies: " . print_r($deps, true));
339  foreach ($deps as $dp => $par) {
340  $ids = !is_array($par["ids"])
341  ? [$par["ids"]]
342  : $par["ids"];
343  $this->addRecordsXml($a_writer, $a_prefixes, $dp, $a_schema_version, $ids, $par["field"] ?? null);
344  }
345  }
346  }
347 
348  protected function getDependencies(
349  string $a_entity,
350  string $a_version,
351  ?array $a_rec = null,
352  ?array $a_ids = null
353  ): array {
354  return [];
355  }
356 
357  // After xml record writing hook record
358  public function afterXmlRecordWriting(string $a_entity, string $a_version, array $a_set): void
359  {
360  }
361 
362  // Add types to xml writer
363  private function addTypesXml(ilXmlWriter $a_writer, string $a_entity, string $a_schema_version): void
364  {
365  $types = $this->getXmlTypes($a_entity, $a_schema_version);
366 
367  // add types of current entity
368  if (count($types) > 0) {
369  $a_writer->xmlStartTag(
370  $this->getDSPrefixString() . "Types",
371  array("Entity" => $this->getXMLEntityName($a_entity, $a_schema_version),
372  "SchemaVersion" => $a_schema_version)
373  );
374  foreach ($this->getXmlTypes($a_entity, $a_schema_version) as $f => $t) {
375  $a_writer->xmlElement(
376  $this->getDSPrefixString() . 'FieldType',
377  array("Name" => $f, "Type" => $t)
378  );
379  }
380  $a_writer->xmlEndTag($this->getDSPrefixString() . "Types");
381  }
382 
383  // add types of dependent entities
384  $deps = $this->getDependencies($a_entity, $a_schema_version, null, null);
385  foreach ($deps as $dp => $w) {
386  $this->addTypesXml($a_writer, $dp, $a_schema_version);
387  }
388  }
389 
390  // Get xml namespaces
391  public function getNamespaces(array &$namespaces, string $a_entity, string $a_schema_version): void
392  {
393  $ns = $this->getXmlNamespace($a_entity, $a_schema_version);
394  if ($ns !== "") {
395  $namespaces[$a_entity] = $ns;
396  }
397  // add types of dependent entities
398  $deps = $this->getDependencies($a_entity, $a_schema_version, null, null);
399  foreach ($deps as $dp => $w) {
400  $this->getNamespaces($namespaces, $dp, $a_schema_version);
401  }
402  }
403 
408  public function getXmlRecord(string $a_entity, string $a_version, array $a_set): array
409  {
410  return $a_set;
411  }
412 
417  public function getXmlTypes(string $a_entity, string $a_version): array
418  {
419  return $this->getTypes($a_entity, $a_version);
420  }
421 
426  public function getXMLEntityName(string $a_entity, string $a_version): string
427  {
428  return $a_entity;
429  }
430 
434  public function getXMLEntityTag(string $a_entity, string $a_schema_version): string
435  {
436  return $this->convertToLeadingUpper($a_entity);
437  }
438 
439  public function setImport(ilSurveyImporter $a_val): void
440  {
441  $this->import = $a_val;
442  }
443 
444  public function getImport(): ilSurveyImporter
445  {
446  return $this->import;
447  }
448 
449  public function setCurrentInstallationId(string $a_val): void
450  {
451  $this->current_installation_id = $a_val;
452  }
453 
454  public function getCurrentInstallationId(): string
455  {
457  }
458 
462  protected function createObjectExportId(string $a_type, string $a_id): string
463  {
464  return "il_" . IL_INST_ID . "_" . $a_type . "_" . $a_id;
465  }
466 
471  protected function parseObjectExportId(string $a_id, ?string $a_fallback_id = null): array
472  {
473  // ilias export id?
474  if (strpos($a_id, "il_") === 0) {
475  $parts = explode("_", $a_id);
476  if (count($parts) !== 4) {
477  throw new ilException("Invalid import ID '" . $a_id . "'.");
478  }
479  $inst_id = $parts[1];
480  $type = $parts[2];
481  $id = $parts[3];
482 
483  // missing installation ids?
484  if (($inst_id == 0 || IL_INST_ID === "0") && !DEVMODE) {
485  return array("type" => self::EXPORT_NO_INST_ID, "id" => $a_fallback_id);
486  }
487 
488  // same installation?
489  if ($inst_id == IL_INST_ID) {
490  // still existing?
491  if (ilObject::_lookupType($id) === $type) {
492  return array("type" => self::EXPORT_ID_ILIAS_LOCAL, "id" => $id);
493  }
494  // not found
495  else {
496  return array("type" => self::EXPORT_ID_ILIAS_LOCAL_INVALID, "id" => $a_fallback_id);
497  }
498  }
499  // different installation
500  else {
502  // matching type?
503  if ($id && ilObject::_lookupType($id) === $type) {
504  return array("type" => self::EXPORT_ID_ILIAS_REMOTE, "id" => $id);
505  }
506  // not found
507  else {
508  return array("type" => self::EXPORT_ID_ILIAS_REMOTE_INVALID, "id" => $a_fallback_id);
509  }
510  }
511  } else {
512  // external id
514  if ($id) {
515  return array("type" => self::EXPORT_ID, "id" => $id);
516  } else {
517  return array("type" => self::EXPORT_ID_INVALID, "id" => $a_fallback_id);
518  }
519  }
520  }
521 
525  public function importRecord(
526  string $a_entity,
527  array $a_types,
528  array $a_rec,
529  ilImportMapping $a_mapping,
530  string $a_schema_version
531  ): void {
532  }
533 
534  public function getCollection(
535  array $record,
536  string $entity,
537  string $schema_version,
538  string $field,
539  string $value
540  ): ?ResourceCollection {
541  return null;
542  }
543 
544  protected function stripTags(array $rec, array $omit_keys = []): array
545  {
546  $ret_rec = [];
547  foreach ($rec as $k => $v) {
548  if (in_array($k, $omit_keys, true)) {
549  $ret_rec[$k] = $v;
550  } else {
551  $ret_rec[$k] = ilUtil::stripSlashes($v);
552  }
553  }
554  return $ret_rec;
555  }
556 }
ilLogger $ds_log
getXMLEntityName(string $a_entity, string $a_version)
Get entity name for xml (may be overwritten)
readData(string $a_entity, string $a_version, array $a_ids)
Read data from DB.
const EXPORT_ID_ILIAS_REMOTE
init(string $a_entity, string $a_schema_version)
Init.
const DATASET_NS_PREFIX
string $import_directory
getCollection(array $record, string $entity, string $schema_version, string $field, string $value)
convertToLeadingUpper(string $a_str)
Make xyz_abc a XyzAbc string.
const IL_INST_ID
Definition: constants.php:40
getXmlRecord(string $a_entity, string $a_version, array $a_set)
Get xml record for version.
setCurrentInstallationId(string $a_val)
static getLogger(string $a_component_id)
Get component logger.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setImportDirectory(string $a_val)
getNamespaces(array &$namespaces, string $a_entity, string $a_schema_version)
string $relative_export_dir
string $schema_version
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:64
Class ChatMainBarProvider .
getXmlNamespace(string $a_entity, string $a_schema_version)
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="")
getXmlTypes(string $a_entity, string $a_version)
Get xml types.
const EXPORT_ID_ILIAS_LOCAL_INVALID
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
string $absolute_export_dir
parseObjectExportId(string $a_id, ?string $a_fallback_id=null)
Parse export id.
static rCopy(string $a_sdir, string $a_tdir, bool $preserveTimeAttributes=false)
Copies content of a directory $a_sdir recursively to a directory $a_tdir.
string $ds_prefix
const EXPORT_NO_INST_ID
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
addRecordsXml(ilXmlWriter $a_writer, array $a_prefixes, string $a_entity, string $a_schema_version, array $a_ids, ?string $a_field="")
static _getIdForImportId(string $import_id)
xmlEndTag(string $tag)
Writes an endtag.
const EXPORT_ID_INVALID
global $DIC
Definition: feed.php:28
const EXPORT_ID_ILIAS_REMOTE_INVALID
setExportDirectories(string $a_relative, string $a_absolute)
createObjectExportId(string $a_type, string $a_id)
Build ilias export id.
ilDBInterface $db
const EXPORT_ID_ILIAS_LOCAL
getSupportedVersions()
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...
ILIAS ResourceStorage Services $irss
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.
afterXmlRecordWriting(string $a_entity, string $a_version, array $a_set)
const DATASET_NS
getCurrentInstallationId()
getDependencies(string $a_entity, string $a_version, ?array $a_rec=null, ?array $a_ids=null)
addTypesXml(ilXmlWriter $a_writer, string $a_entity, string $a_schema_version)
getXMLEntityTag(string $a_entity, string $a_schema_version)
Get entity tag.
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 ...
ilSurveyImporter $import
string $version
getTypes(string $a_entity, string $a_version)
Get (abstract) types for (abstract) field names.
setImport(ilSurveyImporter $a_val)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
xmlStartTag(string $tag, ?array $attrs=null, bool $empty=false, bool $encode=true, bool $escape=true)
Writes a starttag.
string $entity
string $current_installation_id
xmlElement(string $tag, $attrs=null, $data=null, $encode=true, $escape=true)
Writes a basic element (no children, just textual content)
stripTags(array $rec, array $omit_keys=[])
static _lookupType(int $id, bool $reference=false)
setDSPrefix(string $a_val)