ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
SimpleDC.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
32 
33 class SimpleDC implements SimpleDCInterface
34 {
35  protected PathFactory $path_factory;
36  protected NavigatorFactoryInterface $navigator_factory;
37  protected DataFactory $data_factory;
38  protected CopyrightHandlerInterface $copyright_handler;
39  protected LinkGeneratorInterface $link_generator;
40 
41  public function __construct(
42  PathFactory $path_factory,
43  NavigatorFactoryInterface $navigator_factory,
44  DataFactory $data_factory,
45  CopyrightHandlerInterface $copyright_handler,
46  LinkGeneratorInterface $link_generator
47  ) {
48  $this->path_factory = $path_factory;
49  $this->navigator_factory = $navigator_factory;
50  $this->data_factory = $data_factory;
51  $this->copyright_handler = $copyright_handler;
52  $this->link_generator = $link_generator;
53  }
54 
55  public function write(
56  SetInterface $set,
57  int $object_ref_id
58  ): \SimpleXMLElement {
59  $xml = new \SimpleXMLElement(<<<XML
60  <oai_dc:dc
61  xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/"
62  xmlns:dc="http://purl.org/dc/elements/1.1/"
63  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
64  xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd">
65  </oai_dc:dc>
66  XML);
67 
68  $this->addTitleToXML($xml, $set);
69  $this->addCreatorsPublishersAndContributorsToXML($xml, $set);
70  $this->addSubjectsToXML($xml, $set);
71  $this->addDescriptionsToXML($xml, $set);
72  $this->addDateToXML($xml, $set);
73  $this->addTypesToXML($xml, $set);
74  $this->addFormatsToXML($xml, $set);
75  $this->addIdentifierToXML($xml, $set, $object_ref_id);
76  $this->addSourcesAndRelationsToXML($xml, $set);
77  $this->addLanguagesToXML($xml, $set);
78  $this->addCoveragesToXML($xml, $set);
79  $this->addRightsToXML($xml, $set);
80 
81  return $xml;
82  }
83 
84  protected function addTitleToXML(\SimpleXMLElement $xml, SetInterface $set): void
85  {
86  $title_path = $this->path_factory
87  ->custom()
88  ->withNextStep('general')
89  ->withNextStep('title')
90  ->get();
91 
92  $this->addLangStringsToXML($xml, $set, 'title', $title_path);
93  }
94 
95  protected function addCreatorsPublishersAndContributorsToXML(\SimpleXMLElement $xml, SetInterface $set): void
96  {
97  $creator_path = $this->path_factory
98  ->custom()
99  ->withNextStep('lifeCycle')
100  ->withNextStep('contribute')
101  ->withNextStep('role')
102  ->withNextStep('value')
103  ->withAdditionalFilterAtCurrentStep(FilterType::DATA, 'author')
104  ->withNextStepToSuperElement()
105  ->withNextStepToSuperElement()
106  ->withNextStep('entity')
107  ->get();
108 
109  $publisher_path = $this->path_factory
110  ->custom()
111  ->withNextStep('lifeCycle')
112  ->withNextStep('contribute')
113  ->withNextStep('role')
114  ->withNextStep('value')
115  ->withAdditionalFilterAtCurrentStep(FilterType::DATA, 'publisher')
116  ->withNextStepToSuperElement()
117  ->withNextStepToSuperElement()
118  ->withNextStep('entity')
119  ->get();
120 
121  $any_contributor_path = $this->path_factory
122  ->custom()
123  ->withNextStep('lifeCycle')
124  ->withNextStep('contribute')
125  ->withNextStep('entity')
126  ->get();
127 
128  $path_from_entity_to_role = $this->path_factory
129  ->custom()
130  ->withRelative(true)
131  ->withNextStepToSuperElement()
132  ->withNextStep('role')
133  ->withNextStep('value')
134  ->get();
135 
136  $creators = [];
137  $creator_navigator = $this->navigator_factory->navigator($creator_path, $set->getRoot());
138  foreach ($creator_navigator->elementsAtFinalStep() as $creator) {
139  $creators[] = $creator;
140  $this->addNamespacedChildToXML(
141  $xml,
142  'creator',
143  $creator->getData()->value()
144  );
145  }
146 
147  $publishers = [];
148  $publisher_navigator = $this->navigator_factory->navigator($publisher_path, $set->getRoot());
149  foreach ($publisher_navigator->elementsAtFinalStep() as $publisher) {
150  $publishers[] = $publisher;
151  $this->addNamespacedChildToXML(
152  $xml,
153  'publisher',
154  $publisher->getData()->value()
155  );
156  }
157 
158  $any_contributor_navigator = $this->navigator_factory->navigator($any_contributor_path, $set->getRoot());
159  foreach ($any_contributor_navigator->elementsAtFinalStep() as $any_contributor) {
160  if (
161  in_array($any_contributor, $creators, true) ||
162  in_array($any_contributor, $publishers, true)
163  ) {
164  continue;
165  }
166 
167  $role = $this->navigator_factory
168  ->navigator($path_from_entity_to_role, $any_contributor)
169  ->lastElementAtFinalStep()?->getData()?->value() ?? '';
170  $contributor = $any_contributor->getData()->value();
171  if ($role !== '') {
172  $contributor .= ' (' . $role . ')';
173  }
174  $this->addNamespacedChildToXML(
175  $xml,
176  'contributor',
177  $contributor
178  );
179  }
180  }
181 
182  protected function addSubjectsToXML(\SimpleXMLElement $xml, SetInterface $set): void
183  {
184  $keyword_path = $this->path_factory
185  ->custom()
186  ->withNextStep('general')
187  ->withNextStep('keyword')
188  ->get();
189 
190  $this->addLangStringsToXML($xml, $set, 'subject', $keyword_path);
191 
192  $taxon_entry_string_path = $this->path_factory
193  ->custom()
194  ->withNextStep('classification')
195  ->withNextStep('purpose')
196  ->withNextStep('value')
197  ->withAdditionalFilterAtCurrentStep(FilterType::DATA, 'discipline')
198  ->withNextStepToSuperElement()
199  ->withNextStepToSuperElement()
200  ->withNextStep('taxonPath')
201  ->withNextStep('taxon')
202  ->withNextStep('entry')
203  ->withNextStep('string')
204  ->get();
205 
206  $navigator = $this->navigator_factory->navigator($taxon_entry_string_path, $set->getRoot());
207  $strings = [];
208  $current_taxon_path = null;
209 
210  foreach ($navigator->elementsAtFinalStep() as $entry_string) {
211  $taxon_path = $entry_string->getSuperElement()->getSuperElement()->getSuperElement();
212  if ($current_taxon_path !== $taxon_path) {
213  if (!empty($strings)) {
214  $this->addNamespacedChildToXML($xml, 'subject', implode(': ', $strings));
215  }
216 
217  $current_taxon_path = $taxon_path;
218  $strings = [];
219  }
220 
221  if ($entry_string->getData()->value() !== '') {
222  $strings[] = $entry_string->getData()->value();
223  }
224  }
225 
226  if (!empty($strings)) {
227  $this->addNamespacedChildToXML($xml, 'subject', implode(': ', $strings));
228  }
229  }
230 
231  protected function addDescriptionsToXML(\SimpleXMLElement $xml, SetInterface $set): void
232  {
233  $description_path = $this->path_factory
234  ->custom()
235  ->withNextStep('general')
236  ->withNextStep('description')
237  ->get();
238 
239  $this->addLangStringsToXML($xml, $set, 'description', $description_path);
240  }
241 
242  protected function addDateToXML(\SimpleXMLElement $xml, SetInterface $set): void
243  {
244  $date_path = $this->path_factory
245  ->custom()
246  ->withNextStep('lifeCycle')
247  ->withNextStep('contribute')
248  ->withNextStep('date')
249  ->withAdditionalFilterAtCurrentStep(FilterType::INDEX, '0')
250  ->withNextStep('dateTime')
251  ->get();
252 
253  foreach ($this->getDataValuesFromPath($set, $date_path) as $value) {
254  $this->addNamespacedChildToXML($xml, 'date', $value);
255  }
256  }
257 
258  protected function addTypesToXML(\SimpleXMLElement $xml, SetInterface $set): void
259  {
260  $type_path = $this->path_factory
261  ->custom()
262  ->withNextStep('educational')
263  ->withNextStep('learningResourceType')
264  ->withNextStep('value')
265  ->get();
266 
267  foreach ($this->getDataValuesFromPath($set, $type_path) as $value) {
268  $this->addNamespacedChildToXML($xml, 'type', $value);
269  }
270  }
271 
272  protected function addFormatsToXML(\SimpleXMLElement $xml, SetInterface $set): void
273  {
274  $format_path = $this->path_factory
275  ->custom()
276  ->withNextStep('technical')
277  ->withNextStep('format')
278  ->get();
279 
280  foreach ($this->getDataValuesFromPath($set, $format_path) as $value) {
281  $this->addNamespacedChildToXML($xml, 'format', $value);
282  }
283  }
284 
285  protected function addIdentifierToXML(
286  \SimpleXMLElement $xml,
287  SetInterface $set,
288  int $object_ref_id
289  ): void {
290  $type = $set->getRessourceID()->type();
291  if ($type === '') {
292  return;
293  }
294 
295  $link = $this->link_generator->generateLinkForReference($object_ref_id, $type);
296  $this->addNamespacedChildToXML($xml, 'identifier', (string) $link);
297 
298  if (!$this->link_generator->doesReferenceHavePublicAccessExport($object_ref_id)) {
299  return;
300  }
301  $download_link = $this->link_generator->generateLinkForPublicAccessExportOfReference($object_ref_id);
302  $this->addNamespacedChildToXML($xml, 'identifier', (string) $download_link);
303  }
304 
305  protected function addLanguagesToXML(\SimpleXMLElement $xml, SetInterface $set): void
306  {
307  $language_path = $this->path_factory
308  ->custom()
309  ->withNextStep('general')
310  ->withNextStep('language')
311  ->get();
312 
313  foreach ($this->getDataValuesFromPath($set, $language_path) as $value) {
314  $this->addNamespacedChildToXML(
315  $xml,
316  'language',
317  $value === 'xx' ? 'none' : $value
318  );
319  }
320  }
321 
322  protected function addSourcesAndRelationsToXML(\SimpleXMLElement $xml, SetInterface $set): void
323  {
324  $source_path = $this->path_factory
325  ->custom()
326  ->withNextStep('relation')
327  ->withNextStep('kind')
328  ->withNextStep('value')
329  ->withAdditionalFilterAtCurrentStep(FilterType::DATA, 'isbasedon')
330  ->withNextStepToSuperElement()
331  ->withNextStepToSuperElement()
332  ->withNextStep('resource')
333  ->withNextStep('identifier')
334  ->withNextStep('entry')
335  ->get();
336 
337  $any_entry_path = $this->path_factory
338  ->custom()
339  ->withNextStep('relation')
340  ->withNextStep('resource')
341  ->withNextStep('identifier')
342  ->withNextStep('entry')
343  ->get();
344 
345  $sources = [];
346  $source_navigator = $this->navigator_factory->navigator($source_path, $set->getRoot());
347  foreach ($source_navigator->elementsAtFinalStep() as $source) {
348  $sources[] = $source;
349  $this->addNamespacedChildToXML(
350  $xml,
351  'source',
352  $source->getData()->value()
353  );
354  }
355 
356  $any_entry_navigator = $this->navigator_factory->navigator($any_entry_path, $set->getRoot());
357  foreach ($any_entry_navigator->elementsAtFinalStep() as $any_entry) {
358  if (in_array($any_entry, $sources, true)) {
359  continue;
360  }
361 
362  $this->addNamespacedChildToXML(
363  $xml,
364  'relation',
365  $any_entry->getData()->value()
366  );
367  }
368  }
369 
370  protected function addCoveragesToXML(\SimpleXMLElement $xml, SetInterface $set): void
371  {
372  $coverage_path = $this->path_factory
373  ->custom()
374  ->withNextStep('general')
375  ->withNextStep('coverage')
376  ->get();
377 
378  $this->addLangStringsToXML($xml, $set, 'coverage', $coverage_path);
379  }
380 
381  protected function addRightsToXML(\SimpleXMLElement $xml, SetInterface $set): void
382  {
383  $description_path = $this->path_factory
384  ->custom()
385  ->withNextStep('rights')
386  ->withNextStep('description')
387  ->withNextStep('string')
388  ->get();
389 
390  foreach ($this->getDataValuesFromPath($set, $description_path) as $value) {
391  $this->addNamespacedChildToXML(
392  $xml,
393  'rights',
394  $this->copyright_handler->copyrightAsString($value)
395  );
396  }
397  }
398 
399  protected function addLangStringsToXML(
400  \SimpleXMLElement $xml,
401  SetInterface $set,
402  string $name,
403  PathInterface $path
404  ): void {
405  $navigator = $this->navigator_factory->navigator($path, $set->getRoot());
406  foreach ($navigator->elementsAtFinalStep() as $element) {
407  $string_element = null;
408  $lang_element = null;
409  foreach ($element->getSubElements() as $sub_element) {
410  if ($sub_element->getDefinition()->name() === 'string') {
411  $string_element = $sub_element;
412  }
413  if ($sub_element->getDefinition()->name() === 'language') {
414  $lang_element = $sub_element;
415  }
416  }
417 
418  if (is_null($string_element)) {
419  continue;
420  }
421  $string_xml = $this->addNamespacedChildToXML(
422  $xml,
423  $name,
424  $string_element->getData()->value()
425  );
426  if (!is_null($lang_element) && !is_null($string_xml)) {
427  $string_xml->addAttribute(
428  'xml:lang',
429  $lang_element->getData()->value(),
430  'xml'
431  );
432  }
433  }
434  }
435 
439  protected function getDataValuesFromPath(SetInterface $set, PathInterface $path): \Generator
440  {
441  $navigator = $this->navigator_factory->navigator($path, $set->getRoot());
442  foreach ($navigator->elementsAtFinalStep() as $element) {
443  yield $element->getData()->value();
444  }
445  }
446 
447  protected function addNamespacedChildToXML(
448  \SimpleXMLElement $xml,
449  string $name,
450  string $value
451  ): ?\SimpleXMLElement {
452  if ($value === '') {
453  return null;
454  }
455  $child_xml = $xml->addChild($name, null, "http://purl.org/dc/elements/1.1/");
456  $child_xml[0] = $value;
457  return $child_xml;
458  }
459 }
FilterType
Values should always be all lowercase.
Definition: FilterType.php:26
$path
Definition: ltiservices.php:30
__construct()
Constructor setup ILIAS global object public.
Definition: class.ilias.php:76
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...