ILIAS  release_8 Revision v8.24
class.ilContainerRenderer.php
Go to the documentation of this file.
1<?php
2
25{
26 protected const UNIQUE_SEPARATOR = "-";
27 protected bool $admin_panel;
28
29 protected ilLanguage $lng;
33
34 // switches
36 protected bool $enable_multi_download;
37 protected bool $active_block_ordering;
38
39 // properties
40 protected array $type_blocks = [];
41 protected array $custom_blocks = [];
42 protected array $items = [];
43 protected array $hidden_items = [];
44 protected array $block_items = [];
45 protected array $details = [];
46 protected array $item_ids = [];
47
48 // block (unique) ids
49 protected array $rendered_blocks = [];
50 protected int $bl_cnt = 0;
51
52 // ordering
53 protected array $block_pos = [];
54 protected array $block_custom_pos = [];
55 protected int $order_cnt = 0;
56
57 protected array $show_more = [];
58 protected int $view_mode;
59 protected \ILIAS\DI\UIServices $ui;
60 protected ilCtrl $ctrl;
61
62 public function __construct(
63 bool $a_enable_manage_select_all = false,
64 bool $a_enable_multi_download = false,
65 bool $a_active_block_ordering = false,
66 array $a_block_custom_positions = [],
67 ?ilContainerGUI $container_gui_obj = null,
69 bool $admin_panel = false
70 ) {
71 global $DIC;
72
73 $this->admin_panel = $admin_panel;
74 $this->lng = $DIC->language();
75 $this->settings = $DIC->settings();
76 $this->ui = $DIC->ui();
77 $this->obj_definition = $DIC["objDefinition"];
78 $this->enable_manage_select_all = $a_enable_manage_select_all;
79 $this->enable_multi_download = $a_enable_multi_download;
80 $this->active_block_ordering = $a_active_block_ordering;
81 $this->block_custom_pos = $a_block_custom_positions;
82 $this->view_mode = $a_view_mode;
84 $obj = $container_gui_obj;
85 $this->container_gui = $obj;
86 $this->ctrl = $DIC->ctrl();
87 }
88
89 protected function getViewMode(): int
90 {
91 return $this->view_mode;
92 }
93
94 //
95 // blocks
96 //
97
98 public function addTypeBlock(
99 string $a_type,
100 string $a_prefix = null,
101 string $a_postfix = null
102 ): bool {
103 if ($a_type !== "itgr" &&
104 !$this->hasTypeBlock($a_type)) {
105 $this->type_blocks[$a_type] = [
106 "prefix" => $a_prefix
107 ,"postfix" => $a_postfix
108 ];
109 return true;
110 }
111 return false;
112 }
113
114 public function hasTypeBlock(string $a_type): bool
115 {
116 return array_key_exists($a_type, $this->type_blocks);
117 }
118
123 public function addCustomBlock(
124 $a_id,
125 string $a_caption,
126 string $a_actions = null,
127 array $a_data = []
128 ): bool {
129 if (!$this->hasCustomBlock($a_id)) {
130 $this->custom_blocks[$a_id] = [
131 "caption" => $a_caption
132 ,"actions" => $a_actions
133 ,"data" => $a_data
134 ];
135 return true;
136 }
137 return false;
138 }
139
144 public function hasCustomBlock($a_id): bool
145 {
146 return array_key_exists($a_id, $this->custom_blocks);
147 }
148
153 public function isValidBlock($a_id): bool
154 {
155 return ($this->hasTypeBlock($a_id) ||
156 $this->hasCustomBlock($a_id));
157 }
158
159
160 //
161 // items
162 //
163
169 public function hideItem($a_id): void
170 {
171 // see hasItem();
172 $this->hidden_items[$a_id] = true;
173
174 // #16629 - do not remove hidden items from other blocks
175 // $this->removeItem($a_id);
176 }
177
182 public function removeItem($a_id): void
183 {
184 if (!$this->hasItem($a_id)) {
185 return;
186 }
187
188 unset($this->item_ids[$a_id], $this->hidden_items[$a_id]);
189
190 foreach (array_keys($this->items) as $item_id) {
191 $parts = explode(self::UNIQUE_SEPARATOR, $item_id);
192 if (array_pop($parts) == $a_id) {
193 unset($this->items[$item_id]);
194 }
195 }
196
197 foreach ($this->block_items as $block_id => $items) {
198 foreach ($items as $idx => $item_id) {
199 $parts = explode(self::UNIQUE_SEPARATOR, $item_id);
200 if (array_pop($parts) == $a_id) {
201 unset($this->block_items[$block_id][$idx]);
202 if (!count($this->block_items[$block_id])) {
203 unset($this->block_items[$block_id]);
204 }
205 break;
206 }
207 }
208 }
209 }
210
216 public function hasItem($a_id): bool
217 {
218 return (array_key_exists($a_id, $this->item_ids) ||
219 array_key_exists($a_id, $this->hidden_items));
220 }
221
229 public function addItemToBlock(
230 $a_block_id,
231 string $a_item_type,
232 $a_item_id,
233 $a_item_html,
234 bool $a_force = false
235 ): bool {
236 if ($a_item_type !== "itgr" &&
237 $this->isValidBlock($a_block_id) &&
238 (!$this->hasItem($a_item_id) || $a_force)) {
239 if (is_string($a_item_html) && trim($a_item_html) === "") {
240 return false;
241 }
242 if (!$a_item_html) {
243 return false;
244 }
245
246
247 // #16563 - item_id (== ref_id) is NOT unique, adding parent block id
248 $uniq_id = $a_block_id . self::UNIQUE_SEPARATOR . $a_item_id;
249
250 $this->items[$uniq_id] = [
251 "type" => $a_item_type
252 ,"html" => $a_item_html
253 ];
254
255 // #18326
256 $this->addItemId($a_item_id);
257
258 $this->block_items[$a_block_id][] = $uniq_id;
259 return true;
260 }
261 return false;
262 }
263
267 public function addItemId($a_item_id): void
268 {
269 $this->item_ids[$a_item_id] = true;
270 }
271
276 public function addShowMoreButton($a_block_id): void
277 {
278 $this->show_more[] = $a_block_id;
279 }
280
281 public function addDetailsLevel(
282 int $a_level,
283 string $a_url,
284 bool $a_active = false
285 ): void {
286 $this->details[$a_level] = [
287 "url" => $a_url
288 ,"active" => $a_active
289 ];
290 }
291
292 public function resetDetails(): void
293 {
294 $this->details = [];
295 }
296
297
298 //
299 // render
300 //
301
305 public function setBlockPosition(
306 $a_block_id,
307 int $a_pos
308 ): void {
309 if ($this->isValidBlock($a_block_id)) {
310 $this->block_pos[$a_block_id] = $a_pos;
311 }
312 }
313
314 public function getHTML(): string
315 {
316 $valid = false;
317
318 $block_tpl = $this->initBlockTemplate();
319
320 foreach ($this->processBlockPositions() as $block_id) {
321 if (array_key_exists($block_id, $this->custom_blocks) && $this->renderHelperCustomBlock(
322 $block_tpl,
323 $block_id
324 )) {
325 $this->addSeparatorRow($block_tpl);
326 $valid = true;
327 }
328 if (array_key_exists($block_id, $this->type_blocks) && $this->renderHelperTypeBlock(
329 $block_tpl,
330 $block_id
331 )) {
332 $this->addSeparatorRow($block_tpl);
333 $valid = true;
334 }
335 }
336
337 if ($valid) {
338 $this->renderDetails($block_tpl);
339
340 return $block_tpl->get();
341 }
342 return "";
343 }
344
345 public function renderSingleTypeBlock(string $a_type): string
346 {
347 $block_tpl = $this->initBlockTemplate();
348
349 if ($this->renderHelperTypeBlock($block_tpl, $a_type, true)) {
350 return $block_tpl->get();
351 }
352 return "";
353 }
354
358 public function renderSingleCustomBlock($a_id): string
359 {
360 $block_tpl = $this->initBlockTemplate();
361
362 if ($this->renderHelperCustomBlock($block_tpl, $a_id, true)) {
363 return $block_tpl->get();
364 }
365 return "";
366 }
367
368
369 //
370 // render (helper)
371 //
372
373 protected function processBlockPositions(): array
374 {
375 // manual order
376 if (is_array($this->block_custom_pos) && count($this->block_custom_pos)) {
377 $tmp = $this->block_pos;
378 $this->block_pos = [];
379 foreach ($this->block_custom_pos as $idx => $block_id) {
380 if ($this->isValidBlock($block_id)) {
381 $this->block_pos[$block_id] = $idx;
382 }
383 }
384
385 // at least some manual are valid
386 if (count($this->block_pos)) {
387 // append missing blocks from default order
388 $last = max($this->block_pos);
389 foreach (array_keys($tmp) as $block_id) {
390 if (!array_key_exists($block_id, $this->block_pos)) {
391 $this->block_pos[$block_id] = ++$last;
392 }
393 }
394 }
395 // all manual invalid, use default
396 else {
397 $this->block_pos = $tmp;
398 }
399 }
400
401 // add missing blocks to order
402 $last = count($this->block_pos)
403 ? max($this->block_pos)
404 : 0;
405 foreach (array_keys($this->custom_blocks) as $block_id) {
406 if (!array_key_exists($block_id, $this->block_pos)) {
407 $this->block_pos[$block_id] = ++$last;
408 }
409 }
410 foreach (array_keys($this->type_blocks) as $block_id) {
411 if (!array_key_exists($block_id, $this->block_pos)) {
412 $this->block_pos[$block_id] = ++$last;
413 }
414 }
415
416 asort($this->block_pos);
417 return array_keys($this->block_pos);
418 }
419
423 protected function renderHelperCustomBlock(
424 ilTemplate $a_block_tpl,
425 $a_block_id,
426 bool $a_is_single = false
427 ): bool {
428 if ($this->hasCustomBlock($a_block_id)) {
429 return $this->renderHelperGeneric($a_block_tpl, $a_block_id, $this->custom_blocks[$a_block_id], $a_is_single);
430 }
431 return false;
432 }
433
434 protected function renderHelperTypeBlock(
435 ilTemplate $a_block_tpl,
436 string $a_type,
437 bool $a_is_single = false
438 ): bool {
439 if ($this->hasTypeBlock($a_type)) {
440 $block = $this->type_blocks[$a_type];
441 $block["type"] = $a_type;
442 return $this->renderHelperGeneric($a_block_tpl, $a_type, $block, $a_is_single);
443 }
444 return false;
445 }
446
450 protected function renderHelperGeneric(
451 ilTemplate $a_block_tpl,
452 $a_block_id,
453 array $a_block,
454 bool $a_is_single = false
455 ): bool {
456 $ctrl = $this->ctrl;
457 if (!in_array($a_block_id, $this->rendered_blocks)) {
458 $this->rendered_blocks[] = $a_block_id;
459
460 $block_types = [];
461 if (isset($this->block_items[$a_block_id]) && is_array($this->block_items[$a_block_id])) {
462 foreach ($this->block_items[$a_block_id] as $item_id) {
463 if (isset($this->items[$item_id]["type"])) {
464 $block_types[] = $this->items[$item_id]["type"];
465 }
466 }
467 }
468
469 // determine view mode and tile size
470 $tile_size = ilContainer::TILE_SMALL;
471 $view_mode = $this->getViewMode();
472 if ($view_mode === ilContainerContentGUI::VIEW_MODE_TILE) {
473 $tile_size = ilContainer::_lookupContainerSetting($this->container_gui->getObject()->getId(), "tile_size");
474 }
475 if (is_numeric($a_block_id)) {
476 $item_group = new ilObjItemGroup($a_block_id);
477 if ($item_group->getListPresentation() !== "") {
478 $view_mode = ($item_group->getListPresentation() === "tile" && !$this->active_block_ordering && !$this->admin_panel)
481 $tile_size = $item_group->getTileSize();
482 }
483 }
484
485
486 // #14610 - manage empty item groups
487 if ((isset($this->block_items[$a_block_id]) && is_array($this->block_items[$a_block_id])) ||
488 is_numeric($a_block_id)) {
489 $cards = [];
490
491 $order_id = (!$a_is_single && $this->active_block_ordering)
492 ? $a_block_id
493 : "";
494 $this->addHeaderRow(
495 $a_block_tpl,
496 $a_block["type"] ?? '',
497 $a_block["caption"] ?? '',
498 array_unique($block_types),
499 $a_block["actions"] ?? '',
500 $order_id,
501 $a_block["data"] ?? []
502 );
503
504 if ($view_mode === ilContainerContentGUI::VIEW_MODE_LIST) {
505 if (isset($a_block["prefix"]) && $a_block["prefix"]) {
506 $this->addStandardRow($a_block_tpl, $a_block["prefix"]);
507 }
508 }
509
510 if (isset($this->block_items[$a_block_id])) {
511 foreach ($this->block_items[$a_block_id] as $item_id) {
512 if ($view_mode === ilContainerContentGUI::VIEW_MODE_LIST) {
513 $this->addStandardRow($a_block_tpl, $this->items[$item_id]["html"], (int) $item_id);
514 } else {
515 $cards[] = $this->items[$item_id]["html"];
516 }
517 }
518 }
519
520 if ($view_mode === ilContainerContentGUI::VIEW_MODE_LIST) {
521 if (isset($a_block["postfix"]) && $a_block["postfix"]) {
522 $this->addStandardRow($a_block_tpl, $a_block["postfix"]);
523 }
524 }
525
526 if ($view_mode === ilContainerContentGUI::VIEW_MODE_TILE) {
527 $f = $this->ui->factory();
528 $renderer = $this->ui->renderer();
529
530 //Create a deck with large cards
531 switch ($tile_size) {
533 $deck = $f->deck($cards)->withSmallCardsSize();
534 break;
535
537 $deck = $f->deck($cards)->withLargeCardsSize();
538 break;
539
541 $deck = $f->deck($cards)->withExtraLargeCardsSize();
542 break;
543
545 $deck = $f->deck($cards)->withFullSizedCardsSize();
546 break;
547
548 default:
549 $deck = $f->deck($cards)->withNormalCardsSize();
550 break;
551 }
552
553
554 $html = $renderer->render($deck);
555 $a_block_tpl->setCurrentBlock("tile_rows");
556 $a_block_tpl->setVariable("TILE_ROWS", $html);
557 $a_block_tpl->parseCurrentBlock();
558 }
559
560 // show more
561 if (in_array($a_block_id, $this->show_more)) {
562 $a_block_tpl->setCurrentBlock("show_more");
563
564 $ctrl->setParameter($this->container_gui, "type", $a_block_id);
565 $url = $ctrl->getLinkTarget($this->container_gui, "renderBlockAsynch", "", true);
566 $ctrl->setParameter($this->container_gui, "type", "");
567
568 $f = $this->ui->factory();
569 $renderer = $this->ui->renderer();
570 $button = $f->button()->standard($this->lng->txt("cont_show_more"), "")
571 ->withLoadingAnimationOnClick(true)
572 ->withOnLoadCode(function ($id) use ($a_block_id, $url) {
573 return "il.Container.initShowMore('$id', '$a_block_id', '" . $url . "');";
574 });
575 if ($ctrl->isAsynch()) {
576 $a_block_tpl->setVariable("SHOW_MORE_BUTTON", $renderer->renderAsync($button));
577 } else {
578 $a_block_tpl->setVariable("SHOW_MORE_BUTTON", $renderer->render($button));
579 }
580 $a_block_tpl->parseCurrentBlock();
581 $a_block_tpl->setCurrentBlock("show_more");
582 $a_block_tpl->parseCurrentBlock();
583 }
584
585 return true;
586 }
587 }
588
589 return false;
590 }
591
592 protected function initBlockTemplate(): ilTemplate
593 {
594 return new ilTemplate("tpl.container_list_block.html", true, true, "Services/Container");
595 }
596
602 protected function addHeaderRow(
603 ilTemplate $a_tpl,
604 string $a_type = "",
605 string $a_text = "",
606 array $a_types_in_block = null,
607 string $a_commands_html = "",
608 string $a_order_id = "",
609 array $a_data = []
610 ): void {
611 $lng = $this->lng;
613 $objDefinition = $this->obj_definition;
614
615 $a_tpl->setVariable("CB_ID", ' id="bl_cntr_' . (++$this->bl_cnt) . '"');
616
617 if ($this->enable_manage_select_all) {
618 $this->renderSelectAllBlock($a_tpl);
619 } elseif ($this->enable_multi_download) {
620 if ($a_type) {
621 $a_types_in_block = [$a_type];
622 }
623 foreach ($a_types_in_block as $type) {
624 if (in_array($type, $this->getDownloadableTypes(), true)) {
625 $this->renderSelectAllBlock($a_tpl);
626 break;
627 }
628 }
629 }
630
631 if ($a_text === "" && $a_type !== "") {
632 if (!$objDefinition->isPlugin($a_type)) {
633 $title = $lng->txt("objs_" . $a_type);
634 } else {
636 $title = $pl->txt("objs_" . $a_type);
637 }
638 } else {
639 $title = $a_text;
640 }
641
642 if (is_array($a_data)) {
643 foreach ($a_data as $k => $v) {
644 $a_tpl->setCurrentBlock("cb_data");
645 $a_tpl->setVariable("DATA_KEY", $k);
646 $a_tpl->setVariable("DATA_VALUE", $v);
647 $a_tpl->parseCurrentBlock();
648
649 if ($k === "behaviour" && $v == ilItemGroupBehaviour::EXPANDABLE_CLOSED) {
650 $a_tpl->touchBlock("container_items_hide");
651 }
652 }
653 }
654
655 if ($a_type !== "" && $ilSetting->get("icon_position_in_lists") !== "item_rows") {
656 $icon = ilUtil::getImagePath("icon_" . $a_type . ".svg");
657
658 $a_tpl->setCurrentBlock("container_header_row_image");
659 $a_tpl->setVariable("HEADER_IMG", $icon);
660 $a_tpl->setVariable("HEADER_ALT", $title);
661 } else {
662 $a_tpl->setCurrentBlock("container_header_row");
663 }
664
665 if ($a_order_id !== "") {
666 $a_tpl->setVariable("BLOCK_HEADER_ORDER_NAME", "position[blocks][" . $a_order_id . "]");
667 $a_tpl->setVariable("BLOCK_HEADER_ORDER_NUM", (++$this->order_cnt) * 10);
668 }
669
670 $presentation_title = $title;
671 $sr_only = "";
672 if (trim($title) === "") {
673 $presentation_title = $this->lng->txt("cont_no_title");
674 $sr_only = "sr-only";
675 }
676 $a_tpl->setVariable("BLOCK_HEADER_CONTENT", $presentation_title);
677 $a_tpl->setVariable("SR_ONLY", $sr_only);
678 $a_tpl->setVariable("CHR_COMMANDS", $a_commands_html);
679 $a_tpl->parseCurrentBlock();
680 }
681
682 protected function addStandardRow(
683 ilTemplate $a_tpl,
684 string $a_html,
685 int $a_ref_id = 0
686 ): void {
687 if ($a_ref_id > 0) {
688 $a_tpl->setCurrentBlock("row");
689 $a_tpl->setVariable("ROW_ID", 'id="item_row_' . $a_ref_id . '"');
690 $a_tpl->parseCurrentBlock();
691 } else {
692 $a_tpl->touchBlock("row");
693 }
694
695 $a_tpl->setCurrentBlock("container_standard_row");
696 $a_tpl->setVariable("BLOCK_ROW_CONTENT", $a_html);
697 $a_tpl->parseCurrentBlock();
698
699 $a_tpl->touchBlock("container_row");
700 }
701
705 protected function renderSelectAllBlock(ilTemplate $a_tpl): void
706 {
708
709 $a_tpl->setCurrentBlock("select_all_row");
710 $a_tpl->setVariable("CHECKBOXNAME", "bl_cb_" . $this->bl_cnt);
711 $a_tpl->setVariable("SEL_ALL_PARENT", "bl_cntr_" . $this->bl_cnt);
712 $a_tpl->setVariable("SEL_ALL_PARENT", "bl_cntr_" . $this->bl_cnt);
713 $a_tpl->setVariable("TXT_SELECT_ALL", $lng->txt("select_all"));
714 $a_tpl->parseCurrentBlock();
715 }
716
717 protected function addSeparatorRow(ilTemplate $a_tpl): void
718 {
719 $a_tpl->setCurrentBlock("container_block");
720 $a_tpl->parseCurrentBlock();
721 }
722
726 protected function getDownloadableTypes(): array
727 {
728 return ["fold", "file"];
729 }
730
731 public function renderDetails(ilTemplate $a_tpl): void
732 {
734
735 if (count($this->details)) {
736 $a_tpl->setCurrentBlock('container_details_row');
737 $a_tpl->setVariable('TXT_DETAILS', $lng->txt('details'));
738 $a_tpl->parseCurrentBlock();
739 }
740 }
741}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
setVariable($variable, $value='')
Sets a variable value.
Definition: IT.php:514
Class ilContainerGUI This is a base GUI class for all container objects in ILIAS: root folder,...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
addDetailsLevel(int $a_level, string $a_url, bool $a_active=false)
removeItem($a_id)
Remove item (from any block)
getDownloadableTypes()
Get downloadable repository object types.
addHeaderRow(ilTemplate $a_tpl, string $a_type="", string $a_text="", array $a_types_in_block=null, string $a_commands_html="", string $a_order_id="", array $a_data=[])
Render block header.
addItemToBlock( $a_block_id, string $a_item_type, $a_item_id, $a_item_html, bool $a_force=false)
Add item to existing block.
hideItem($a_id)
Mark item id as used, but do not render.
renderHelperTypeBlock(ilTemplate $a_block_tpl, string $a_type, bool $a_is_single=false)
setBlockPosition( $a_block_id, int $a_pos)
hasCustomBlock($a_id)
Custom block already exists?
addShowMoreButton($a_block_id)
Add show more button to a block.
renderHelperCustomBlock(ilTemplate $a_block_tpl, $a_block_id, bool $a_is_single=false)
hasItem($a_id)
Item with id exists?
renderSelectAllBlock(ilTemplate $a_tpl)
Render "select all".
addCustomBlock( $a_id, string $a_caption, string $a_actions=null, array $a_data=[])
Add custom block.
addSeparatorRow(ilTemplate $a_tpl)
renderHelperGeneric(ilTemplate $a_block_tpl, $a_block_id, array $a_block, bool $a_is_single=false)
addTypeBlock(string $a_type, string $a_prefix=null, string $a_postfix=null)
renderDetails(ilTemplate $a_tpl)
addStandardRow(ilTemplate $a_tpl, string $a_html, int $a_ref_id=0)
isValidBlock($a_id)
Any block with id exists?
ilObjectDefinition $obj_definition
static _lookupContainerSetting(int $a_id, string $a_keyword, string $a_default_value=null)
Class ilCtrl provides processing control methods.
language handling
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
parses the objects.xml it handles the xml-description of all ilias objects
static getPluginObjectByType(string $type)
Return either a repoObject plugin or a orgunit extension plugin or null if the type is not a plugin.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
special template class to simplify handling of ITX/PEAR
setCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
parseCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
touchBlock(string $block)
static getImagePath(string $img, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
if(!file_exists(getcwd() . '/ilias.ini.php'))
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: confirmReg.php:20
$valid
global $DIC
Definition: feed.php:28
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:64
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
array $settings
Setting values (LTI parameters, custom parameters and local parameters).
Definition: System.php:200
global $ilSetting
Definition: privfeed.php:17
$type
$url
$lng