ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
DatabaseReader.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
26use ILIAS\MetaData\Elements\Factory as ElementFactory;
38use ILIAS\MetaData\Paths\FactoryInterface as PathFactoryInterface;
41
43{
44 protected ElementFactory $element_factory;
48 protected PathFactoryInterface $path_factory;
50 protected \ilLogger $logger;
51
52 public function __construct(
53 ElementFactory $element_factory,
57 PathFactoryInterface $path_factory,
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 = $this->readSubElements(
150 $depth + 1,
151 $sub,
152 $ressource_id,
153 $parent_id,
154 $row
155 );
156 if (!isset($tag) && $sub_elements->current() === null) {
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 $unchecked_structs = [$struct];
180 while ($unchecked_structs !== []) {
181 if ($depth > 20) {
182 throw new \ilMDStructureException('LOM Structure is nested to deep.');
183 }
184
185 $next_unchecked_structs = [];
186 foreach ($unchecked_structs as $unchecked_struct) {
187 $tag = $this->tag($unchecked_struct);
188 if (!is_null($tag) && $table !== $tag?->table()) {
189 continue;
190 }
191 if (!is_null($tag)) {
192 yield $tag;
193 }
194 $next_unchecked_structs = array_merge(
195 $next_unchecked_structs,
196 iterator_to_array($this->subElements($unchecked_struct))
197 );
198 }
199
200 $unchecked_structs = $next_unchecked_structs;
201 $depth++;
202 }
203 }
204
210 {
211 $depth = 0;
212 $super_step_depths = [];
213 foreach ($path->steps() as $step) {
214 if ($step->name() === StepToken::SUPER) {
215 $depth--;
216 $super_step_depths[] = $depth;
217 continue;
218 }
219 $depth++;
220 }
221
222 if (empty($super_step_depths)) {
223 return $path;
224 }
225
226 $cut_off = min($super_step_depths);
227 $depth = 0;
228 $path_builder = $this->path_factory->custom();
229 foreach ($path->steps() as $step) {
230 if ($depth === $cut_off) {
231 break;
232 }
233 $path_builder = $path_builder->withNextStepFromStep($step);
234 $depth++;
235 }
236 return $path_builder->get();
237 }
238
239 protected function definition(
242 if ($struct instanceof StructureNavigatorInterface) {
243 $struct = $struct->element();
244 }
245 return $struct->getDefinition();
246 }
247
251 protected function subElements(
253 ): \Generator {
254 if ($struct instanceof StructureElementInterface) {
255 yield from $struct->getSubElements();
256 return;
257 }
258 if ($next_struct = $struct->nextStep()) {
259 yield $next_struct;
260 } else {
261 yield from $struct->element()->getSubElements();
262 }
263 }
264
265 protected function tag(
267 ): ?TagInterface {
268 if ($struct instanceof StructureNavigatorInterface) {
269 $struct = $struct->element();
270 }
271 return $this->dictionary->tagForElement($struct);
272 }
273
274 protected function getSetWithRoot(
275 RessourceIDInterface $ressource_id,
276 Element ...$elements
277 ): SetInterface {
278 $root_definition = $this->structure->getRoot()->getDefinition();
279 return $this->element_factory->set(
280 $ressource_id,
281 $this->element_factory->root(
282 $root_definition,
283 ...$elements
284 )
285 );
286 }
287}
getMD(RessourceIDInterface $ressource_id)
definition(StructureElementInterface|StructureNavigatorInterface $struct,)
tag(StructureElementInterface|StructureNavigatorInterface $struct,)
collectTagsFromSameTable(int $depth, string $table, StructureElementInterface|StructureNavigatorInterface $struct)
readSubElements(int $depth, StructureElementInterface|StructureNavigatorInterface $struct, RessourceIDInterface $ressource_id, int $id_from_parent_table, ?RowInterface $result_row=null)
getMDOnPath(PathInterface $path, RessourceIDInterface $ressource_id)
subElements(StructureElementInterface|StructureNavigatorInterface $struct,)
getSetWithRoot(RessourceIDInterface $ressource_id, Element ... $elements)
shortenPath(PathInterface $path)
Cuts off the path at the highest starting point of sub-paths created with super steps.
__construct(ElementFactory $element_factory, StructureSetInterface $structure, DictionaryInterface $dictionary, NavigatorFactoryInterface $navigator_factory, PathFactoryInterface $path_factory, DatabaseQuerierInterface $querier, \ilLogger $logger)
Component logger with individual log levels by component id.
nextStep()
Returns null if there is no next step.
element()
Returns the element at the current step in the path.
$path
Definition: ltiservices.php:30
StepToken
The string representation of these tokens must not occur as names of metadata elements.
Definition: StepToken.php:28
if(!file_exists('../ilias.ini.php'))