ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilContainerRenderer.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3require_once('./Services/Repository/classes/class.ilObjectPlugin.php');
4
12{
16 protected $lng;
17
21 protected $settings;
22
26 protected $obj_definition;
27
28 // switches
29 protected $enable_manage_select_all; // [bool]
30 protected $enable_multi_download; // [bool]
31 protected $active_block_ordering; // [bool]
32
33 // properties
34 protected $type_blocks = array(); // [array]
35 protected $custom_blocks = array(); // [array]
36 protected $items = array(); // [array]
37 protected $hidden_items = array(); // [array]
38 protected $block_items = array(); // [array]
39 protected $details = array(); // [array]
40 protected $item_ids = array(); // [array]
41
42 // block (unique) ids
43 protected $rendered_blocks = array(); // [array]
44 protected $bl_cnt = 0; // [int]
45 protected $cur_row_type; // [string]
46
47 // ordering
48 protected $block_pos = array(); // [array]
49 protected $block_custom_pos = array(); // [array]
50 protected $order_cnt = 0; // [int]
51
55 protected $show_more = [];
56
57 const UNIQUE_SEPARATOR = "-";
58
62 protected $view_mode;
63
67 protected $ui;
68
72 protected $ctrl;
73
82 public function __construct($a_enable_manage_select_all = false, $a_enable_multi_download = false, $a_active_block_ordering = false, $a_block_custom_positions, $container_gui_obj, $a_view_mode =
84 {
85 global $DIC;
86
87 $this->lng = $DIC->language();
88 $this->settings = $DIC->settings();
89 $this->ui = $DIC->ui();
90 $this->obj_definition = $DIC["objDefinition"];
91 $this->enable_manage_select_all = (bool) $a_enable_manage_select_all;
92 $this->enable_multi_download = (bool) $a_enable_multi_download;
93 $this->active_block_ordering = (bool) $a_active_block_ordering;
94 $this->block_custom_pos = $a_block_custom_positions;
95 $this->view_mode = $a_view_mode;
96 $this->container_gui = $container_gui_obj;
97 $this->ctrl = $DIC->ctrl();
98 }
99
103 protected function getViewMode()
104 {
105 return $this->view_mode;
106 }
107
108 //
109 // blocks
110 //
111
120 public function addTypeBlock($a_type, $a_prefix = null, $a_postfix = null)
121 {
122 if ($a_type != "itgr" &&
123 !$this->hasTypeBlock($a_type)) {
124 $this->type_blocks[$a_type] = array(
125 "prefix" => $a_prefix
126 ,"postfix" => $a_postfix
127 );
128 return true;
129 }
130 return false;
131 }
132
139 public function hasTypeBlock($a_type)
140 {
141 return array_key_exists($a_type, $this->type_blocks);
142 }
143
152 public function addCustomBlock($a_id, $a_caption, $a_actions = null, $a_data = array())
153 {
154 if (!$this->hasCustomBlock($a_id)) {
155 $this->custom_blocks[$a_id] = array(
156 "caption" => $a_caption
157 ,"actions" => $a_actions
158 ,"data" => $a_data
159 );
160 return true;
161 }
162 return false;
163 }
164
171 public function hasCustomBlock($a_id)
172 {
173 return array_key_exists($a_id, $this->custom_blocks);
174 }
175
182 public function isValidBlock($a_id)
183 {
184 return ($this->hasTypeBlock($a_id) ||
185 $this->hasCustomBlock($a_id));
186 }
187
188
189 //
190 // items
191 //
192
198 public function hideItem($a_id)
199 {
200 // see hasItem();
201 $this->hidden_items[$a_id] = true;
202
203 // #16629 - do not remove hidden items from other blocks
204 // $this->removeItem($a_id);
205 }
206
212 public function removeItem($a_id)
213 {
214 if (!$this->hasItem($a_id)) {
215 return;
216 }
217
218 unset($this->item_ids[$a_id]);
219 unset($this->hidden_items[$a_id]);
220
221 foreach (array_keys($this->items) as $item_id) {
222 if (array_pop(explode(self::UNIQUE_SEPARATOR, $item_id)) == $a_id) {
223 unset($this->items[$item_id]);
224 }
225 }
226
227 foreach ($this->block_items as $block_id => $items) {
228 foreach ($items as $idx => $item_id) {
229 if (array_pop(explode(self::UNIQUE_SEPARATOR, $item_id)) == $a_id) {
230 unset($this->block_items[$block_id][$idx]);
231 if (!sizeof($this->block_items[$block_id])) {
232 unset($this->block_items[$block_id]);
233 }
234 break;
235 }
236 }
237 }
238 }
239
246 public function hasItem($a_id)
247 {
248 return (array_key_exists($a_id, $this->item_ids) ||
249 array_key_exists($a_id, $this->hidden_items));
250 }
251
262 public function addItemToBlock($a_block_id, $a_item_type, $a_item_id, $a_item_html, $a_force = false)
263 {
264 if ($this->isValidBlock($a_block_id) &&
265 $a_item_type != "itgr" &&
266 (!$this->hasItem($a_item_id) || $a_force)) {
267 if (is_string($a_item_html) && trim($a_item_html) == "") {
268 return false;
269 }
270 if (!$a_item_html) {
271 return false;
272 }
273
274
275 // #16563 - item_id (== ref_id) is NOT unique, adding parent block id
276 $uniq_id = $a_block_id . self::UNIQUE_SEPARATOR . $a_item_id;
277
278 $this->items[$uniq_id] = array(
279 "type" => $a_item_type
280 ,"html" => $a_item_html
281 );
282
283 // #18326
284 $this->item_ids[$a_item_id] = true;
285
286 $this->block_items[$a_block_id][] = $uniq_id;
287 return true;
288 }
289 return false;
290 }
291
295 public function addShowMoreButton($a_block_id)
296 {
297 $this->show_more[] = $a_block_id;
298 }
299
307 public function addDetailsLevel($a_level, $a_url, $a_active = false)
308 {
309 $this->details[$a_level] = array(
310 "url" => $a_url
311 ,"active" => (bool) $a_active
312 );
313 }
314
318 public function resetDetails()
319 {
320 $this->details = array();
321 }
322
323
324 //
325 // render
326 //
327
334 public function setBlockPosition($a_block_id, $a_pos)
335 {
336 if ($this->isValidBlock($a_block_id)) {
337 $this->block_pos[$a_block_id] = $a_pos;
338 }
339 }
340
346 public function getHTML()
347 {
348 $valid = false;
349
350 $block_tpl = $this->initBlockTemplate();
351
352 foreach ($this->processBlockPositions() as $block_id) {
353 if (array_key_exists($block_id, $this->custom_blocks)) {
354 if ($this->renderHelperCustomBlock($block_tpl, $block_id)) {
355 $this->addSeparatorRow($block_tpl);
356 $valid = true;
357 }
358 }
359 if (array_key_exists($block_id, $this->type_blocks)) {
360 if ($this->renderHelperTypeBlock($block_tpl, $block_id)) {
361 $this->addSeparatorRow($block_tpl);
362 $valid = true;
363 }
364 }
365 }
366
367 if ($valid) {
368 $this->renderDetails($block_tpl);
369
370 return $block_tpl->get();
371 }
372 }
373
381 {
382 $block_tpl = $this->initBlockTemplate();
383
384 if ($this->renderHelperTypeBlock($block_tpl, $a_type, true)) {
385 return $block_tpl->get();
386 }
387 }
388
395 public function renderSingleCustomBlock($a_id)
396 {
397 $block_tpl = $this->initBlockTemplate();
398
399 if ($this->renderHelperCustomBlock($block_tpl, $a_id, true)) {
400 return $block_tpl->get();
401 }
402 }
403
404
405 //
406 // render (helper)
407 //
408
414 protected function processBlockPositions()
415 {
416 // manual order
417 if (is_array($this->block_custom_pos) && sizeof($this->block_custom_pos)) {
418 $tmp = $this->block_pos;
419 $this->block_pos = array();
420 foreach ($this->block_custom_pos as $idx => $block_id) {
421 if ($this->isValidBlock($block_id)) {
422 $this->block_pos[$block_id] = $idx;
423 }
424 }
425
426 // at least some manual are valid
427 if (sizeof($this->block_pos)) {
428 // append missing blocks from default order
429 $last = max($this->block_pos);
430 foreach (array_keys($tmp) as $block_id) {
431 if (!array_key_exists($block_id, $this->block_pos)) {
432 $this->block_pos[$block_id] = ++$last;
433 }
434 }
435 }
436 // all manual invalid, use default
437 else {
438 $this->block_pos = $tmp;
439 }
440 }
441
442 // add missing blocks to order
443 $last = sizeof($this->block_pos)
444 ? max($this->block_pos)
445 : 0;
446 foreach (array_keys($this->custom_blocks) as $block_id) {
447 if (!array_key_exists($block_id, $this->block_pos)) {
448 $this->block_pos[$block_id] = ++$last;
449 }
450 }
451 foreach (array_keys($this->type_blocks) as $block_id) {
452 if (!array_key_exists($block_id, $this->block_pos)) {
453 $this->block_pos[$block_id] = ++$last;
454 }
455 }
456
457 asort($this->block_pos);
458
459 return array_keys($this->block_pos);
460 }
461
470 protected function renderHelperCustomBlock(ilTemplate $a_block_tpl, $a_block_id, $a_is_single = false)
471 {
472 if ($this->hasCustomBlock($a_block_id)) {
473 return $this->renderHelperGeneric($a_block_tpl, $a_block_id, $this->custom_blocks[$a_block_id], $a_is_single);
474 }
475 return false;
476 }
477
486 protected function renderHelperTypeBlock(ilTemplate $a_block_tpl, $a_type, $a_is_single = false)
487 {
488 if ($this->hasTypeBlock($a_type)) {
489 $block = $this->type_blocks[$a_type];
490 $block["type"] = $a_type;
491 return $this->renderHelperGeneric($a_block_tpl, $a_type, $block, $a_is_single);
492 }
493 return false;
494 }
495
505 protected function renderHelperGeneric(ilTemplate $a_block_tpl, $a_block_id, array $a_block, $a_is_single = false)
506 {
508 if (!in_array($a_block_id, $this->rendered_blocks)) {
509 $this->rendered_blocks[] = $a_block_id;
510
511 $block_types = array();
512 if (is_array($this->block_items[$a_block_id])) {
513 foreach ($this->block_items[$a_block_id] as $item_id) {
514 if (isset($this->items[$item_id]["type"])) {
515 $block_types[] = $this->items[$item_id]["type"];
516 }
517 }
518 }
519
520 // #14610 - manage empty item groups
521 if (is_array($this->block_items[$a_block_id]) ||
522 is_numeric($a_block_id)) {
523 $cards = [];
524
525 $order_id = (!$a_is_single && $this->active_block_ordering)
526 ? $a_block_id
527 : null;
528 $this->addHeaderRow($a_block_tpl, $a_block["type"], $a_block["caption"], array_unique($block_types), $a_block["actions"], $order_id, $a_block["data"]);
529
531 if ($a_block["prefix"]) {
532 $this->addStandardRow($a_block_tpl, $a_block["prefix"]);
533 }
534 }
535
536 if (is_array($this->block_items[$a_block_id])) {
537 foreach ($this->block_items[$a_block_id] as $item_id) {
539 $this->addStandardRow($a_block_tpl, $this->items[$item_id]["html"], $item_id);
540 } else {
541 $cards[] = $this->items[$item_id]["html"];
542 }
543 }
544 }
545
547 if ($a_block["postfix"]) {
548 $this->addStandardRow($a_block_tpl, $a_block["postfix"]);
549 }
550 }
551
553 $f = $this->ui->factory();
554 $renderer = $this->ui->renderer();
555
556 //Create a deck with large cards
557 $deck = $f->deck($cards)->withNormalCardsSize();
558 //$deck = $f->deck($cards)->withSmallCardsSize();
559
560
561 $html = $renderer->render($deck);
562 $a_block_tpl->setCurrentBlock("tile_rows");
563 $a_block_tpl->setVariable("TILE_ROWS", $html);
564 $a_block_tpl->parseCurrentBlock();
565 }
566
567 // show more
568 if (in_array($a_block_id, $this->show_more)) {
569 $a_block_tpl->setCurrentBlock("show_more");
570
571 $ctrl->setParameter($this->container_gui, "type", $a_block_id);
572 $url = $ctrl->getLinkTarget($this->container_gui, "renderBlockAsynch", "", true);
573 $ctrl->setParameter($this->container_gui, "type", "");
574
575 $f = $this->ui->factory();
576 $renderer = $this->ui->renderer();
577 $button = $f->button()->standard($this->lng->txt("cont_show_more"), "")
578 ->withLoadingAnimationOnClick(true)
579 ->withOnLoadCode(function ($id) use ($a_block_id, $url) {
580 return "il.Container.initShowMore('$id', '$a_block_id', '" . $url . "');";
581 });
582 if ($ctrl->isAsynch()) {
583 $a_block_tpl->setVariable("SHOW_MORE_BUTTON", $renderer->renderAsync($button));
584 } else {
585 $a_block_tpl->setVariable("SHOW_MORE_BUTTON", $renderer->render($button));
586 }
587 $a_block_tpl->parseCurrentBlock();
588 $a_block_tpl->setCurrentBlock("show_more");
589 $a_block_tpl->parseCurrentBlock();
590 }
591
592 return true;
593 }
594 }
595
596 return false;
597 }
598
604 protected function initBlockTemplate()
605 {
606 // :TODO: obsolete?
607 $this->cur_row_type = "row_type_1";
608
609 return new ilTemplate("tpl.container_list_block.html", true, true, "Services/Container");
610 }
611
622 protected function addHeaderRow(ilTemplate $a_tpl, $a_type = "", $a_text = "", array $a_types_in_block = null, $a_commands_html = null, $a_order_id = null, $a_data = array())
623 {
626 $objDefinition = $this->obj_definition;
627
628 $a_tpl->setVariable("CB_ID", ' id="bl_cntr_' . (++$this->bl_cnt) . '"');
629
630 if ($this->enable_manage_select_all) {
631 $this->renderSelectAllBlock($a_tpl);
632 } elseif ($this->enable_multi_download) {
633 if ($a_type) {
634 $a_types_in_block = array($a_type);
635 }
636 foreach ($a_types_in_block as $type) {
637 if (in_array($type, $this->getDownloadableTypes())) {
638 $this->renderSelectAllBlock($a_tpl);
639 break;
640 }
641 }
642 }
643
644 if ($a_text == "" && $a_type != "") {
645 if (!$objDefinition->isPlugin($a_type)) {
646 $title = $lng->txt("objs_" . $a_type);
647 } else {
648 include_once("./Services/Component/classes/class.ilPlugin.php");
650 $title = $pl->txt("objs_" . $a_type);
651 }
652 } else {
653 $title = $a_text;
654 }
655
656 include_once("./Modules/ItemGroup/classes/class.ilItemGroupBehaviour.php");
657 if (is_array($a_data)) {
658 foreach ($a_data as $k => $v) {
659 $a_tpl->setCurrentBlock("cb_data");
660 $a_tpl->setVariable("DATA_KEY", $k);
661 $a_tpl->setVariable("DATA_VALUE", $v);
662 $a_tpl->parseCurrentBlock();
663
664 if ($k == "behaviour" && $v == ilItemGroupBehaviour::EXPANDABLE_CLOSED) {
665 $a_tpl->touchBlock("container_items_hide");
666 }
667 }
668 }
669
670 if ($ilSetting->get("icon_position_in_lists") != "item_rows" &&
671 $a_type != "") {
672 $icon = ilUtil::getImagePath("icon_" . $a_type . ".svg");
673
674 $a_tpl->setCurrentBlock("container_header_row_image");
675 $a_tpl->setVariable("HEADER_IMG", $icon);
676 $a_tpl->setVariable("HEADER_ALT", $title);
677 } else {
678 $a_tpl->setCurrentBlock("container_header_row");
679 }
680
681 if ($a_order_id) {
682 $a_tpl->setVariable("BLOCK_HEADER_ORDER_NAME", "position[blocks][" . $a_order_id . "]");
683 $a_tpl->setVariable("BLOCK_HEADER_ORDER_NUM", (++$this->order_cnt) * 10);
684 }
685
686 $a_tpl->setVariable("BLOCK_HEADER_CONTENT", $title);
687 $a_tpl->setVariable("CHR_COMMANDS", $a_commands_html);
688 $a_tpl->parseCurrentBlock();
689
690 //$a_tpl->touchBlock("container_row");
691
692 $this->resetRowType();
693 }
694
702 protected function addStandardRow(ilTemplate $a_tpl, $a_html, $a_ref_id = 0)
703 {
704 // :TODO: obsolete?
705 $this->cur_row_type = ($this->cur_row_type == "row_type_1")
706 ? "row_type_2"
707 : "row_type_1";
708
709 if ($a_ref_id > 0) {
710 $a_tpl->setCurrentBlock($this->cur_row_type);
711 $a_tpl->setVariable("ROW_ID", 'id="item_row_' . $a_ref_id . '"');
712 $a_tpl->parseCurrentBlock();
713 } else {
714 $a_tpl->touchBlock($this->cur_row_type);
715 }
716
717 $a_tpl->setCurrentBlock("container_standard_row");
718 $a_tpl->setVariable("BLOCK_ROW_CONTENT", $a_html);
719 $a_tpl->parseCurrentBlock();
720
721 $a_tpl->touchBlock("container_row");
722 }
723
727 protected function renderSelectAllBlock(ilTemplate $a_tpl)
728 {
730
731 $a_tpl->setCurrentBlock("select_all_row");
732 $a_tpl->setVariable("CHECKBOXNAME", "bl_cb_" . $this->bl_cnt);
733 $a_tpl->setVariable("SEL_ALL_PARENT", "bl_cntr_" . $this->bl_cnt);
734 $a_tpl->setVariable("SEL_ALL_PARENT", "bl_cntr_" . $this->bl_cnt);
735 $a_tpl->setVariable("TXT_SELECT_ALL", $lng->txt("select_all"));
736 $a_tpl->parseCurrentBlock();
737 }
738
744 protected function addSeparatorRow(ilTemplate $a_tpl)
745 {
746 $a_tpl->setCurrentBlock("container_block");
747 $a_tpl->parseCurrentBlock();
748 }
749
753 protected function resetRowType()
754 {
755 // :TODO: obsolete?
756 $this->cur_row_type = "";
757 }
758
764 protected function getDownloadableTypes()
765 {
766 return array("fold", "file");
767 }
768
774 public function renderDetails(ilTemplate $a_tpl)
775 {
777
778 if (sizeof($this->details)) {
779 $a_tpl->setCurrentBlock('container_details_row');
780 $a_tpl->setVariable('TXT_DETAILS', $lng->txt('details'));
781 $a_tpl->parseCurrentBlock();
782 }
783 }
784}
An exception for terminatinating execution or to throw for unit testing.
setVariable($variable, $value='')
Sets a variable value.
Definition: IT.php:613
Class ilContainerRenderer.
removeItem($a_id)
Remove item (from any block)
getDownloadableTypes()
Get downloadable repository object types.
renderHelperGeneric(ilTemplate $a_block_tpl, $a_block_id, array $a_block, $a_is_single=false)
Render block.
renderHelperTypeBlock(ilTemplate $a_block_tpl, $a_type, $a_is_single=false)
Render type block.
resetRowType()
Reset internal row type.
addTypeBlock($a_type, $a_prefix=null, $a_postfix=null)
Add type block.
addItemToBlock($a_block_id, $a_item_type, $a_item_id, $a_item_html, $a_force=false)
Add item to existing block.
renderSingleCustomBlock($a_id)
Get rendered html of single custom block.
addDetailsLevel($a_level, $a_url, $a_active=false)
Add details level.
hideItem($a_id)
Mark item id as used, but do not render.
getHTML()
Get rendered html (of all blocks)
addHeaderRow(ilTemplate $a_tpl, $a_type="", $a_text="", array $a_types_in_block=null, $a_commands_html=null, $a_order_id=null, $a_data=array())
Render block header.
hasCustomBlock($a_id)
Custom block already exists?
hasTypeBlock($a_type)
Type block already exists?
renderHelperCustomBlock(ilTemplate $a_block_tpl, $a_block_id, $a_is_single=false)
Render custom block.
addStandardRow(ilTemplate $a_tpl, $a_html, $a_ref_id=0)
Render item row.
addShowMoreButton($a_block_id)
Add show more button to a block.
hasItem($a_id)
Item with id exists?
renderSingleTypeBlock($a_type)
Get rendered html of single type block.
renderSelectAllBlock(ilTemplate $a_tpl)
Render "select all".
setBlockPosition($a_block_id, $a_pos)
Set block position.
addSeparatorRow(ilTemplate $a_tpl)
Render separator row.
processBlockPositions()
Process block positions.
resetDetails()
Reset/remove all detail levels.
renderDetails(ilTemplate $a_tpl)
Render detail level.
isValidBlock($a_id)
Any block with id exists?
addCustomBlock($a_id, $a_caption, $a_actions=null, $a_data=array())
Add custom block.
__construct($a_enable_manage_select_all=false, $a_enable_multi_download=false, $a_active_block_ordering=false, $a_block_custom_positions, $container_gui_obj, $a_view_mode=ilContainerContentGUI::VIEW_MODE_LIST)
Constructor.
static getPluginObjectByType($type)
Return either a repoObject plugin or a orgunit extension plugin or null if the type is not a plugin.
special template class to simplify handling of ITX/PEAR
touchBlock($block)
overwrites ITX::touchBlock.
parseCurrentBlock($part="DEFAULT")
Überladene Funktion, die auf den aktuelle Block vorher noch ein replace ausführt @access public.
setCurrentBlock($part="DEFAULT")
Überladene Funktion, die sich hier lokal noch den aktuellen Block merkt.
static getImagePath($img, $module_path="", $mode="output", $offline=false)
get image path (for images located in a template directory)
$valid
$html
Definition: example_001.php:87
if(!array_key_exists('StateId', $_REQUEST)) $id
global $ilSetting
Definition: privfeed.php:17
$type
$url
global $DIC
Definition: saml.php:7
settings()
Definition: settings.php:2
$a_type
Definition: workflow.php:92