ILIAS  release_7 Revision v7.30-3-g800a261c036
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->addItemId($a_item_id);
285
286 $this->block_items[$a_block_id][] = $uniq_id;
287 return true;
288 }
289 return false;
290 }
291
292 public function addItemId($a_item_id)
293 {
294 $this->item_ids[$a_item_id] = true;
295 }
296
300 public function addShowMoreButton($a_block_id)
301 {
302 $this->show_more[] = $a_block_id;
303 }
304
312 public function addDetailsLevel($a_level, $a_url, $a_active = false)
313 {
314 $this->details[$a_level] = array(
315 "url" => $a_url
316 ,"active" => (bool) $a_active
317 );
318 }
319
323 public function resetDetails()
324 {
325 $this->details = array();
326 }
327
328
329 //
330 // render
331 //
332
339 public function setBlockPosition($a_block_id, $a_pos)
340 {
341 if ($this->isValidBlock($a_block_id)) {
342 $this->block_pos[$a_block_id] = $a_pos;
343 }
344 }
345
351 public function getHTML()
352 {
353 $valid = false;
354
355 $block_tpl = $this->initBlockTemplate();
356
357 foreach ($this->processBlockPositions() as $block_id) {
358 if (array_key_exists($block_id, $this->custom_blocks)) {
359 if ($this->renderHelperCustomBlock($block_tpl, $block_id)) {
360 $this->addSeparatorRow($block_tpl);
361 $valid = true;
362 }
363 }
364 if (array_key_exists($block_id, $this->type_blocks)) {
365 if ($this->renderHelperTypeBlock($block_tpl, $block_id)) {
366 $this->addSeparatorRow($block_tpl);
367 $valid = true;
368 }
369 }
370 }
371
372 if ($valid) {
373 $this->renderDetails($block_tpl);
374
375 return $block_tpl->get();
376 }
377 }
378
385 public function renderSingleTypeBlock($a_type)
386 {
387 $block_tpl = $this->initBlockTemplate();
388
389 if ($this->renderHelperTypeBlock($block_tpl, $a_type, true)) {
390 return $block_tpl->get();
391 }
392 }
393
400 public function renderSingleCustomBlock($a_id)
401 {
402 $block_tpl = $this->initBlockTemplate();
403
404 if ($this->renderHelperCustomBlock($block_tpl, $a_id, true)) {
405 return $block_tpl->get();
406 }
407 }
408
409
410 //
411 // render (helper)
412 //
413
419 protected function processBlockPositions()
420 {
421 // manual order
422 if (is_array($this->block_custom_pos) && sizeof($this->block_custom_pos)) {
423 $tmp = $this->block_pos;
424 $this->block_pos = array();
425 foreach ($this->block_custom_pos as $idx => $block_id) {
426 if ($this->isValidBlock($block_id)) {
427 $this->block_pos[$block_id] = $idx;
428 }
429 }
430
431 // at least some manual are valid
432 if (sizeof($this->block_pos)) {
433 // append missing blocks from default order
434 $last = max($this->block_pos);
435 foreach (array_keys($tmp) as $block_id) {
436 if (!array_key_exists($block_id, $this->block_pos)) {
437 $this->block_pos[$block_id] = ++$last;
438 }
439 }
440 }
441 // all manual invalid, use default
442 else {
443 $this->block_pos = $tmp;
444 }
445 }
446
447 // add missing blocks to order
448 $last = sizeof($this->block_pos)
449 ? max($this->block_pos)
450 : 0;
451 foreach (array_keys($this->custom_blocks) as $block_id) {
452 if (!array_key_exists($block_id, $this->block_pos)) {
453 $this->block_pos[$block_id] = ++$last;
454 }
455 }
456 foreach (array_keys($this->type_blocks) as $block_id) {
457 if (!array_key_exists($block_id, $this->block_pos)) {
458 $this->block_pos[$block_id] = ++$last;
459 }
460 }
461
462 asort($this->block_pos);
463
464 return array_keys($this->block_pos);
465 }
466
475 protected function renderHelperCustomBlock(ilTemplate $a_block_tpl, $a_block_id, $a_is_single = false)
476 {
477 if ($this->hasCustomBlock($a_block_id)) {
478 return $this->renderHelperGeneric($a_block_tpl, $a_block_id, $this->custom_blocks[$a_block_id], $a_is_single);
479 }
480 return false;
481 }
482
491 protected function renderHelperTypeBlock(ilTemplate $a_block_tpl, $a_type, $a_is_single = false)
492 {
493 if ($this->hasTypeBlock($a_type)) {
494 $block = $this->type_blocks[$a_type];
495 $block["type"] = $a_type;
496 return $this->renderHelperGeneric($a_block_tpl, $a_type, $block, $a_is_single);
497 }
498 return false;
499 }
500
510 protected function renderHelperGeneric(ilTemplate $a_block_tpl, $a_block_id, array $a_block, $a_is_single = false)
511 {
513 if (!in_array($a_block_id, $this->rendered_blocks)) {
514 $this->rendered_blocks[] = $a_block_id;
515
516 $block_types = array();
517 if (is_array($this->block_items[$a_block_id])) {
518 foreach ($this->block_items[$a_block_id] as $item_id) {
519 if (isset($this->items[$item_id]["type"])) {
520 $block_types[] = $this->items[$item_id]["type"];
521 }
522 }
523 }
524
525 // #14610 - manage empty item groups
526 if (is_array($this->block_items[$a_block_id]) ||
527 is_numeric($a_block_id)) {
528 $cards = [];
529
530 $order_id = (!$a_is_single && $this->active_block_ordering)
531 ? $a_block_id
532 : null;
533 $this->addHeaderRow($a_block_tpl, $a_block["type"], $a_block["caption"], array_unique($block_types), $a_block["actions"], $order_id, $a_block["data"]);
534
536 if ($a_block["prefix"]) {
537 $this->addStandardRow($a_block_tpl, $a_block["prefix"]);
538 }
539 }
540
541 if (is_array($this->block_items[$a_block_id])) {
542 foreach ($this->block_items[$a_block_id] as $item_id) {
544 $this->addStandardRow($a_block_tpl, $this->items[$item_id]["html"], $item_id);
545 } else {
546 $cards[] = $this->items[$item_id]["html"];
547 }
548 }
549 }
550
552 if ($a_block["postfix"]) {
553 $this->addStandardRow($a_block_tpl, $a_block["postfix"]);
554 }
555 }
556
558 $f = $this->ui->factory();
559 $renderer = $this->ui->renderer();
560
561 //Create a deck with large cards
562 $deck = $f->deck($cards)->withNormalCardsSize();
563 //$deck = $f->deck($cards)->withSmallCardsSize();
564
565
566 $html = $renderer->render($deck);
567 $a_block_tpl->setCurrentBlock("tile_rows");
568 $a_block_tpl->setVariable("TILE_ROWS", $html);
569 $a_block_tpl->parseCurrentBlock();
570 }
571
572 // show more
573 if (in_array($a_block_id, $this->show_more)) {
574 $a_block_tpl->setCurrentBlock("show_more");
575
576 $ctrl->setParameter($this->container_gui, "type", $a_block_id);
577 $url = $ctrl->getLinkTarget($this->container_gui, "renderBlockAsynch", "", true);
578 $ctrl->setParameter($this->container_gui, "type", "");
579
580 $f = $this->ui->factory();
581 $renderer = $this->ui->renderer();
582 $button = $f->button()->standard($this->lng->txt("cont_show_more"), "")
583 ->withLoadingAnimationOnClick(true)
584 ->withOnLoadCode(function ($id) use ($a_block_id, $url) {
585 return "il.Container.initShowMore('$id', '$a_block_id', '" . $url . "');";
586 });
587 if ($ctrl->isAsynch()) {
588 $a_block_tpl->setVariable("SHOW_MORE_BUTTON", $renderer->renderAsync($button));
589 } else {
590 $a_block_tpl->setVariable("SHOW_MORE_BUTTON", $renderer->render($button));
591 }
592 $a_block_tpl->parseCurrentBlock();
593 $a_block_tpl->setCurrentBlock("show_more");
594 $a_block_tpl->parseCurrentBlock();
595 }
596
597 return true;
598 }
599 }
600
601 return false;
602 }
603
609 protected function initBlockTemplate()
610 {
611 // :TODO: obsolete?
612 $this->cur_row_type = "row_type_1";
613
614 return new ilTemplate("tpl.container_list_block.html", true, true, "Services/Container");
615 }
616
627 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())
628 {
631 $objDefinition = $this->obj_definition;
632
633 $a_tpl->setVariable("CB_ID", ' id="bl_cntr_' . (++$this->bl_cnt) . '"');
634
635 if ($this->enable_manage_select_all) {
636 $this->renderSelectAllBlock($a_tpl);
637 } elseif ($this->enable_multi_download) {
638 if ($a_type) {
639 $a_types_in_block = array($a_type);
640 }
641 foreach ($a_types_in_block as $type) {
642 if (in_array($type, $this->getDownloadableTypes())) {
643 $this->renderSelectAllBlock($a_tpl);
644 break;
645 }
646 }
647 }
648
649 if ($a_text == "" && $a_type != "") {
650 if (!$objDefinition->isPlugin($a_type)) {
651 $title = $lng->txt("objs_" . $a_type);
652 } else {
653 include_once("./Services/Component/classes/class.ilPlugin.php");
655 $title = $pl->txt("objs_" . $a_type);
656 }
657 } else {
658 $title = $a_text;
659 }
660
661 include_once("./Modules/ItemGroup/classes/class.ilItemGroupBehaviour.php");
662 if (is_array($a_data)) {
663 foreach ($a_data as $k => $v) {
664 $a_tpl->setCurrentBlock("cb_data");
665 $a_tpl->setVariable("DATA_KEY", $k);
666 $a_tpl->setVariable("DATA_VALUE", $v);
667 $a_tpl->parseCurrentBlock();
668
669 if ($k == "behaviour" && $v == ilItemGroupBehaviour::EXPANDABLE_CLOSED) {
670 $a_tpl->touchBlock("container_items_hide");
671 }
672 }
673 }
674
675 if ($ilSetting->get("icon_position_in_lists") != "item_rows" &&
676 $a_type != "") {
677 $icon = ilUtil::getImagePath("icon_" . $a_type . ".svg");
678
679 $a_tpl->setCurrentBlock("container_header_row_image");
680 $a_tpl->setVariable("HEADER_IMG", $icon);
681 $a_tpl->setVariable("HEADER_ALT", $title);
682 } else {
683 $a_tpl->setCurrentBlock("container_header_row");
684 }
685
686 if ($a_order_id) {
687 $a_tpl->setVariable("BLOCK_HEADER_ORDER_NAME", "position[blocks][" . $a_order_id . "]");
688 $a_tpl->setVariable("BLOCK_HEADER_ORDER_NUM", (++$this->order_cnt) * 10);
689 }
690
691 $a_tpl->setVariable("BLOCK_HEADER_CONTENT", $title);
692 $a_tpl->setVariable("CHR_COMMANDS", $a_commands_html);
693 $a_tpl->parseCurrentBlock();
694
695 //$a_tpl->touchBlock("container_row");
696
697 $this->resetRowType();
698 }
699
707 protected function addStandardRow(ilTemplate $a_tpl, $a_html, $a_ref_id = 0)
708 {
709 // :TODO: obsolete?
710 $this->cur_row_type = ($this->cur_row_type == "row_type_1")
711 ? "row_type_2"
712 : "row_type_1";
713
714 if ($a_ref_id > 0) {
715 $a_tpl->setCurrentBlock($this->cur_row_type);
716 $a_tpl->setVariable("ROW_ID", 'id="item_row_' . $a_ref_id . '"');
717 $a_tpl->parseCurrentBlock();
718 } else {
719 $a_tpl->touchBlock($this->cur_row_type);
720 }
721
722 $a_tpl->setCurrentBlock("container_standard_row");
723 $a_tpl->setVariable("BLOCK_ROW_CONTENT", $a_html);
724 $a_tpl->parseCurrentBlock();
725
726 $a_tpl->touchBlock("container_row");
727 }
728
732 protected function renderSelectAllBlock(ilTemplate $a_tpl)
733 {
735
736 $a_tpl->setCurrentBlock("select_all_row");
737 $a_tpl->setVariable("CHECKBOXNAME", "bl_cb_" . $this->bl_cnt);
738 $a_tpl->setVariable("SEL_ALL_PARENT", "bl_cntr_" . $this->bl_cnt);
739 $a_tpl->setVariable("SEL_ALL_PARENT", "bl_cntr_" . $this->bl_cnt);
740 $a_tpl->setVariable("TXT_SELECT_ALL", $lng->txt("select_all"));
741 $a_tpl->parseCurrentBlock();
742 }
743
749 protected function addSeparatorRow(ilTemplate $a_tpl)
750 {
751 $a_tpl->setCurrentBlock("container_block");
752 $a_tpl->parseCurrentBlock();
753 }
754
758 protected function resetRowType()
759 {
760 // :TODO: obsolete?
761 $this->cur_row_type = "";
762 }
763
769 protected function getDownloadableTypes()
770 {
771 return array("fold", "file");
772 }
773
779 public function renderDetails(ilTemplate $a_tpl)
780 {
782
783 if (sizeof($this->details)) {
784 $a_tpl->setCurrentBlock('container_details_row');
785 $a_tpl->setVariable('TXT_DETAILS', $lng->txt('details'));
786 $a_tpl->parseCurrentBlock();
787 }
788 }
789}
An exception for terminatinating execution or to throw for unit testing.
setVariable($variable, $value='')
Sets a variable value.
Definition: IT.php:615
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
global $DIC
Definition: goto.php:24
global $ilSetting
Definition: privfeed.php:17
$type
$url
settings()
Definition: settings.php:2
ui()
Definition: ui.php:5