ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
DatabaseReader.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
26 use ILIAS\MetaData\Elements\Factory as ElementFactory;
41 
43 {
44  protected ElementFactory $element_factory;
50  protected \ilLogger $logger;
51 
52  public function __construct(
53  ElementFactory $element_factory,
54  StructureSetInterface $structure,
55  DictionaryInterface $dictionary,
56  NavigatorFactoryInterface $navigator_factory,
57  PathFactoryInterface $path_factory,
58  DatabaseQuerierInterface $querier,
59  \ilLogger $logger
60  ) {
61  $this->element_factory = $element_factory;
62  $this->structure = $structure;
63  $this->dictionary = $dictionary;
64  $this->navigator_factory = $navigator_factory;
65  $this->path_factory = $path_factory;
66  $this->querier = $querier;
67  $this->logger = $logger;
68  }
69 
70  public function getMD(RessourceIDInterface $ressource_id): SetInterface
71  {
72  return $this->getSetWithRoot(
73  $ressource_id,
74  ...$this->readSubElements(
75  0,
76  $this->structure->getRoot(),
77  $ressource_id,
78  0
79  )
80  );
81  }
82 
83  public function getMDOnPath(
85  RessourceIDInterface $ressource_id
86  ): SetInterface {
87  $path = $this->shortenPath($path);
88 
89  $navigator = $this->navigator_factory->structureNavigator(
90  $path,
91  $this->structure->getRoot()
92  );
93  return $this->getSetWithRoot(
94  $ressource_id,
95  ...$this->readSubElements(
96  0,
97  $navigator,
98  $ressource_id,
99  0
100  )
101  );
102  }
103 
107  protected function readSubElements(
108  int $depth,
110  RessourceIDInterface $ressource_id,
111  int $id_from_parent_table,
112  ?RowInterface $result_row = null
113  ): \Generator {
114  if ($depth > 20) {
115  throw new \ilMDStructureException('LOM Structure is nested to deep.');
116  }
117 
118  foreach ($this->subElements($struct) as $sub) {
119  $tag = $this->tag($sub);
120  $table = $tag?->table() ?? '';
121  $definition = $this->definition($sub);
122 
123  // Read out the next table, if required.
124  $parent_id = $id_from_parent_table;
125  $result_rows = [];
126  if (!is_null($result_row)) {
127  $result_rows = [$result_row];
128  }
129  if ($table && $result_row?->table() !== $table) {
130  $parent_id = $result_row?->id() ?? 0;
131  $result_rows = $this->querier->read(
132  $ressource_id,
133  $parent_id,
134  ...$this->collectTagsFromSameTable($depth, $table, $sub)
135  );
136  }
137 
138  foreach ($result_rows as $row) {
139  $value = $row->value($tag?->dataField() ?? '');
140 
141  if ($definition->dataType() !== Type::NULL && $value === '') {
142  continue;
143  }
144 
149  $sub_elements = iterator_to_array($this->readSubElements(
150  $depth + 1,
151  $sub,
152  $ressource_id,
153  $parent_id,
154  $row
155  ));
156  if (!isset($tag) && count($sub_elements) <= 0) {
157  continue;
158  }
159 
160  yield $this->element_factory->element(
161  $row->id(),
162  $definition,
163  $value,
165  ...$sub_elements
166  );
167  }
168  }
169  }
170 
174  protected function collectTagsFromSameTable(
175  int $depth,
176  string $table,
178  ): \Generator {
179  if ($depth > 20) {
180  throw new \ilMDStructureException('LOM Structure is nested to deep.');
181  }
182 
183  $tag = $this->tag($struct);
184  if (!is_null($tag) && $table !== $tag?->table()) {
185  return;
186  }
187  if (!is_null($tag)) {
188  yield $tag;
189  }
190 
191  foreach ($this->subElements($struct) as $sub) {
192  yield from $this->collectTagsFromSameTable(
193  $depth + 1,
194  $table,
195  $sub
196  );
197  }
198  }
199 
205  {
206  $depth = 0;
207  $super_step_depths = [];
208  foreach ($path->steps() as $step) {
209  if ($step->name() === StepToken::SUPER) {
210  $depth--;
211  $super_step_depths[] = $depth;
212  continue;
213  }
214  $depth++;
215  }
216 
217  if (empty($super_step_depths)) {
218  return $path;
219  }
220 
221  $cut_off = min($super_step_depths);
222  $depth = 0;
223  $path_builder = $this->path_factory->custom();
224  foreach ($path->steps() as $step) {
225  if ($depth === $cut_off) {
226  break;
227  }
228  $path_builder = $path_builder->withNextStepFromStep($step);
229  $depth++;
230  }
231  return $path_builder->get();
232  }
233 
234  protected function definition(
237  if ($struct instanceof StructureNavigatorInterface) {
238  $struct = $struct->element();
239  }
240  return $struct->getDefinition();
241  }
242 
246  protected function subElements(
248  ): \Generator {
249  if ($struct instanceof StructureElementInterface) {
250  yield from $struct->getSubElements();
251  return;
252  }
253  if ($next_struct = $struct->nextStep()) {
254  yield $next_struct;
255  } else {
256  yield from $struct->element()->getSubElements();
257  }
258  }
259 
260  protected function tag(
262  ): ?TagInterface {
263  if ($struct instanceof StructureNavigatorInterface) {
264  $struct = $struct->element();
265  }
266  return $this->dictionary->tagForElement($struct);
267  }
268 
269  protected function getSetWithRoot(
270  RessourceIDInterface $ressource_id,
271  Element ...$elements
272  ): SetInterface {
273  $root_definition = $this->structure->getRoot()->getDefinition();
274  return $this->element_factory->set(
275  $ressource_id,
276  $this->element_factory->root(
277  $root_definition,
278  ...$elements
279  )
280  );
281  }
282 }
nextStep()
Returns null if there is no next step.
steps()
Get all steps in the path.
__construct(ElementFactory $element_factory, StructureSetInterface $structure, DictionaryInterface $dictionary, NavigatorFactoryInterface $navigator_factory, PathFactoryInterface $path_factory, DatabaseQuerierInterface $querier, \ilLogger $logger)
getMD(RessourceIDInterface $ressource_id)
readSubElements(int $depth, StructureElementInterface|StructureNavigatorInterface $struct, RessourceIDInterface $ressource_id, int $id_from_parent_table, ?RowInterface $result_row=null)
getSetWithRoot(RessourceIDInterface $ressource_id, Element ... $elements)
element()
Returns the element at the current step in the path.
collectTagsFromSameTable(int $depth, string $table, StructureElementInterface|StructureNavigatorInterface $struct)
tag(StructureElementInterface|StructureNavigatorInterface $struct,)
$path
Definition: ltiservices.php:29
getRoot()
Returns the root element of the metadata set.
definition(StructureElementInterface|StructureNavigatorInterface $struct,)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
StepToken
The string representation of these tokens must not occur as names of metadata elements.
Definition: StepToken.php:27
getMDOnPath(PathInterface $path, RessourceIDInterface $ressource_id)
shortenPath(PathInterface $path)
Cuts off the path at the highest starting point of sub-paths created with super steps.
subElements(StructureElementInterface|StructureNavigatorInterface $struct,)