ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
MainMenuMainCollector.php
Go to the documentation of this file.
2
18
29{
30
34 private static $constructed = false;
38 private static $items = [];
42 private static $topitems = [];
50 private $information;
54 protected $providers;
58 private $loaded = false;
59
60
69 public function __construct(array $providers, ItemInformation $information = null)
70 {
71 if (self::$constructed === true) {
72 throw new \LogicException("only one Instance of MainMenuMainCollector Collector is possible");
73 }
74 self::$constructed = true;
75 $this->information = $information;
76 $this->providers = $providers;
77 $this->type_information_collection = new TypeInformationCollection();
78 $this->load();
79 }
80
81
91 public function getStackedTopItemsForPresentation() : array
92 {
93 return $this->getStackedTopItems();
94 }
95
96
101 private function getStackedTopItems() : array
102 {
103 $this->load();
104 $top_items = [];
105 foreach (self::$topitems as $top_item) {
106 if (!$this->checkAvailability($top_item)) {
107 continue;
108 }
109 if ($top_item instanceof isTopItem && $this->information) {
110 if ($top_item instanceof isParent) {
111 $has_always_available_item = false;
112 $children = [];
117 foreach ($top_item->getChildren() as $child) {
118 $child = $this->applyTypeHandler($child);
119 if (!$this->checkAvailability($child)) {
120 continue;
121 }
122 $position_of_sub_item = $this->information->getPositionOfSubItem($child);
123 if (isset($children[$position_of_sub_item])) {
124 $position_of_sub_item = max(array_keys($children)) + 1;
125 }
126 $children[$position_of_sub_item] = $child;
127 if ($child->isAlwaysAvailable() === true) {
128 $has_always_available_item = true;
129 }
130 }
131 ksort($children);
132 $children = $this->handleDoubleDividers($children);
133 // bugfix mantis 25577
134 $children = $this->handleSolitaryDividers($children, $top_item);
135
136 // https://mantis.ilias.de/view.php?id=24061
137 if (count($children) === 0) {
138 unset($top_item);
139 continue;
140 }
141
142 $top_item = $top_item->withChildren($children);
143 if ($has_always_available_item === true) {
144 $top_item = $top_item->withAlwaysAvailable(true);
145 }
146 }
147 $top_item = $this->applyTypeHandler($top_item);
148 $position_of_top_item = $this->information->getPositionOfTopItem($top_item);
149 if (isset($top_items[$position_of_top_item])) {
150 $position_of_top_item = max(array_keys($top_items)) + 1;
151 }
152 $top_items[$position_of_top_item] = $top_item;
153 }
154 }
155 ksort($top_items);
156
157 return $top_items;
158 }
159
160
167 private function checkAvailability(isItem $item) : bool
168 {
169 $is_visible = $item->isVisible();
170 $is_item_active = $this->information->isItemActive($item);
171 $is_always_available = $item->isAlwaysAvailable();
172
173 return !(!$is_visible || !$is_item_active && !$is_always_available);
174 }
175
176
183 public function getSingleItem(IdentificationInterface $identification) : isItem
184 {
185 $this->load();
186 try {
187 return self::$items[$identification->serialize()];
188 } catch (\Throwable $e) {
189 return $this->getLostItem($identification);
190 }
191 }
192
193
199 private function getLostItem(IdentificationInterface $identification) : Lost
200 {
201 global $DIC;
202
203 return $DIC->globalScreen()->mainmenu()->custom(Lost::class, new NullIdentification($identification))
204 ->withAlwaysAvailable(true)
205 ->setTypeInformation($this->type_information_collection->get(Lost::class))
206 ->withNonAvailableReason($DIC->ui()->factory()->legacy("{$DIC->language()->txt('mme_lost_item_reason')}"))
207 ->withVisibilityCallable(
208 function () use ($DIC) {
209 return (bool) ($DIC->rbac()->system()->checkAccess("visible", SYSTEM_FOLDER_ID));
210 }
211 )->withTitle($DIC->language()->txt("mme_lost_item_title"));
212 }
213
214
219 private function load() : bool
220 {
221 if ($this->loaded === false || $this->loaded === null) {
227 try {
228 $this->loaded = true;
229 $this->loadTypeInformation();
230 $this->loadTopItems();
231 $this->loadSubItems();
232 } catch (\Throwable $e) {
233 throw $e;
234 }
235 }
236
237 return $this->loaded;
238 }
239
240
241 private function loadTopItems()
242 {
243 foreach ($this->providers as $provider) {
244 foreach ($provider->getStaticTopItems() as $top_item) {
245 if ($top_item instanceof hasTitle && $this->information) {
246 $top_item = $this->information->translateItemForUser($top_item);
247 }
248 $this->addItemToMap($top_item);
249 }
250 }
251 }
252
253
254 private function loadSubItems()
255 {
256 foreach ($this->providers as $provider) {
257 foreach ($provider->getStaticSubItems() as $sub_item) {
258 if ($sub_item instanceof hasTitle && $this->information) {
259 $sub_item = $this->information->translateItemForUser($sub_item);
260 }
261 if ($sub_item instanceof isChild && $sub_item->hasParent()) {
262 $new_parent_identification = $this->information->getParent($sub_item);
263 $parent_item = $this->getSingleItem($new_parent_identification);
264 if ($parent_item->getProviderIdentification() instanceof NullIdentification) {
265 $this->addItemToMap($parent_item);
266 // self::$items[$parent_item->getProviderIdentification()->serialize()] = $parent_item;
267 // self::$topitems[$parent_item->getProviderIdentification()->serialize()] = $parent_item;
268 $sub_item->overrideParent($parent_item->getProviderIdentification());
269 } else {
270 $sub_item->overrideParent($new_parent_identification);
271 }
272 if ($this->itemExistsInMap($sub_item->getParent()) && $this->getItemFromMap($sub_item->getParent()) instanceof isParent) {
273 $this->getItemFromMap($sub_item->getParent())->appendChild($sub_item);
274 // self::$topitems[$sub_item->getParent()->serialize()]->appendChild($sub_item);
275 if ($sub_item->isAlwaysAvailable()) {
276 $parent = $this->getItemFromMap($sub_item->getParent())->withAlwaysAvailable(true);
277 $this->addItemToMap($parent);
278 // self::$topitems[$sub_item->getParent()->serialize()] = self::$topitems[$sub_item->getParent()->serialize()]->withAlwaysAvailable(true);
279 }
280 }
281 }
282 $this->addItemToMap($sub_item);
283 // self::$items[$sub_item->getProviderIdentification()->serialize()] = $sub_item; // register them always since they could be lost
284 }
285 }
286 }
287
288
294 private function applyTypeHandler(isItem $item) : isItem
295 {
296 $item = $this->getHandlerForItem($item)->enrichItem($item);
297
298 return $item;
299 }
300
301
307 public function getHandlerForItem(isItem $item) : TypeHandler
308 {
312 $type = get_class($item);
313 $type_information = $this->type_information_collection->get($type);
314 if (is_null($type_information)) {
315 return new BaseTypeHandler();
316 }
317 $handler = $type_information->getTypeHandler();
318
319 return $handler;
320 }
321
322
328 private function handleDoubleDividers($children) : array
329 {
330 $separators = 0;
331 foreach ($children as $position => $child) {
332 if ($child instanceof Separator) {
333 $separators++;
334 } else {
335 $separators = 0;
336 }
337 if ($separators > 1) {
338 unset($children[$position]);
339 }
340 }
341
342 return $children;
343 }
344
345
354 private function handleSolitaryDividers($children, $top_item) : array
355 {
356 foreach ($children as $position => $child) {
357 if ($child instanceof Separator) {
358 // remove dividers that are the only item of the item-list and remove their top-item as well
359 if (count($children) === 1) {
360 unset($children[$position]);
361 unset($top_item);
362 continue;
363 }
364 // remove dividers that stand alone at the beginning of the item-list
365 if ($position == min(array_keys($children))) {
366 unset($children[$position]);
367 continue;
368 }
369 // remove dividers that stand alone at the end of the item-list
370 if ($position == max(array_keys($children))) {
371 unset($children[$position]);
372 continue;
373 }
374 }
375 }
376
377 return $children;
378 }
379
380
385 {
387 }
388
389
390 private function loadTypeInformation()
391 {
392 foreach ($this->providers as $provider) {
393 if ($provider instanceof StaticMainMenuProvider) {
394 $this->type_information_collection->append($provider->provideTypeInformation());
395 }
396 }
397 }
398
399
403 private function addItemToMap(isItem $item)
404 {
405 if ($item instanceof isItem) {
406 $item->setTypeInformation($this->type_information_collection->get(get_class($item)));
407 }
408
409 if ($item instanceof isTopItem) {
410 self::$topitems[$item->getProviderIdentification()->serialize()] = $item;
411 }
412 self::$items[$item->getProviderIdentification()->serialize()] = $item;
413 }
414
415
421 private function itemExistsInMap(IdentificationInterface $identification) : bool
422 {
423 return isset(self::$items[$identification->serialize()]);
424 }
425
426
432 private function getItemFromMap(IdentificationInterface $identification)
433 {
434 if (!$this->itemExistsInMap($identification)) {
435 // Exception?
436 }
437
438 return self::$items[$identification->serialize()];
439 }
440}
An exception for terminatinating execution or to throw for unit testing.
__construct(array $providers, ItemInformation $information=null)
MainMenuMainCollector constructor.
handleSolitaryDividers($children, $top_item)
bugfix mantis 25577: prevent solitary dividers from being shown
getStackedTopItemsForPresentation()
This will return all available topitems, stacked based on the configuration in "Administration" and f...
setTypeInformation(TypeInformation $information)
$type
$handler
global $DIC
Definition: saml.php:7