ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
Renderer.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (c) 2018 Nils Haagen <nils.haagen@concepts.and-training.de> Extended GPL, see docs/LICENSE */
4
6
8use ILIAS\UI\Renderer as RendererInterface;
17use ILIAS\UI\Implementation\Render\Template as UITemplateWrapper;
19
21{
22 const BLOCK_MAINBAR_ENTRIES = 'trigger_item';
23 const BLOCK_MAINBAR_TOOLS = 'tool_trigger_item';
24 const BLOCK_METABAR_ENTRIES = 'meta_element';
25
26 private $signals_for_tools = [];
27 private $trigger_signals = [];
28
32 public function render(Component\Component $component, RendererInterface $default_renderer)
33 {
34 $this->checkComponent($component);
35
36 if ($component instanceof MainBar) {
37 return $this->renderMainbar($component, $default_renderer);
38 }
39 if ($component instanceof MetaBar) {
40 return $this->renderMetabar($component, $default_renderer);
41 }
42 if ($component instanceof Footer) {
43 return $this->renderFooter($component, $default_renderer);
44 }
45 if ($component instanceof ModeInfo) {
46 return $this->renderModeInfo($component, $default_renderer);
47 }
48 }
49
50 protected function calculateMainBarTreePosition($pos, $slate)
51 {
52 if (!$slate instanceof Slate && !$slate instanceof MainBar) {
53 return $slate;
54 }
55 return $slate
56 ->withMainBarTreePosition($pos)
57 ->withMappedSubNodes(
58 function ($num, $slate, $is_tool = false) use ($pos) {
59 if ($is_tool) {
60 $pos = 'T';
61 }
62 return $this->calculateMainBarTreePosition("$pos:$num", $slate);
63 }
64 );
65 }
66
67 protected function renderToolEntry(
68 Slate $entry,
69 string $entry_id,
70 string $mb_id,
71 MainBar $component,
72 UITemplateWrapper $tpl,
73 RendererInterface $default_renderer
74 ) : string {
75 $hidden = $component->getInitiallyHiddenToolIds();
76 $close_buttons = $component->getCloseButtons();
77
78 $is_removeable = array_key_exists($entry_id, $close_buttons);
79 $is_hidden = in_array($entry_id, $hidden);
80
81 if ($is_removeable) {
82 $trigger_signal = $component->getTriggerSignal($mb_id, $component::ENTRY_ACTION_REMOVE);
83 $this->trigger_signals[] = $trigger_signal;
84 $btn_removetool = $close_buttons[$entry_id]
85 ->withAdditionalOnloadCode(
86 function ($id) use ($mb_id) {
87 return "il.UI.maincontrols.mainbar.addPartIdAndEntry('{$mb_id}', 'remover', '{$id}', true);";
88 }
89 )
90 ->withOnClick($trigger_signal);
91
92 $tpl->setCurrentBlock("tool_removal");
93 $tpl->setVariable("REMOVE_TOOL", $default_renderer->render($btn_removetool));
94 $tpl->parseCurrentBlock();
95 }
96
97 $is_removeable = $is_removeable ? 'true':'false';
98 $is_hidden = $is_hidden ? 'true':'false';
99 return "il.UI.maincontrols.mainbar.addToolEntry('{$mb_id}', {$is_removeable}, {$is_hidden}, '{$entry_id}');";
100 }
101
102 protected function renderMainbarEntry(
103 array $entries,
104 string $block,
105 MainBar $component,
106 UITemplateWrapper $tpl,
107 RendererInterface $default_renderer
108 ) {
109 $f = $this->getUIFactory();
110 foreach ($entries as $k => $entry) {
111 $button = $entry;
112 $slate = null;
113 $js = '';
114
115 if ($entry instanceof Slate) {
116 $slate = $entry;
117 $mb_id = $entry->getMainBarTreePosition();
118 $is_tool = $block === static::BLOCK_MAINBAR_TOOLS;
119 if ($is_tool) {
120 $js = $this->renderToolEntry($entry, $k, $mb_id, $component, $tpl, $default_renderer);
121 }
122
123 $trigger_signal = $component->getTriggerSignal($mb_id, $component::ENTRY_ACTION_TRIGGER);
124 $this->trigger_signals[] = $trigger_signal;
125 $button = $f->button()->bulky($entry->getSymbol(), $entry->getName(), '#')
126 ->withAriaRole(IBulky::MENUITEM)
127 ->withOnClick($trigger_signal);
128 } else {
129 //add Links/Buttons as toplevel entries
130 $pos = array_search($k, array_keys($entries));
131 $mb_id = '0:' . $pos;
132 $is_tool = false;
133 }
134
135 $button = $button->withAdditionalOnLoadCode(
136 function ($id) use ($js, $mb_id, $k, $is_tool) {
137 $add_as_tool = $is_tool ? 'true':'false';
138 $js .= "
139 il.UI.maincontrols.mainbar.addPartIdAndEntry('{$mb_id}', 'triggerer', '{$id}', {$add_as_tool});
140 il.UI.maincontrols.mainbar.addMapping('{$k}','{$mb_id}');
141 ";
142 return $js;
143 }
144 );
145 $tpl->setCurrentBlock($block);
146 $tpl->setVariable("BUTTON", $default_renderer->render($button));
147 $tpl->parseCurrentBlock();
148
149 if ($slate) {
150 $entry = $entry->withAriaRole(ISlate::MENU);
151
152 $tpl->setCurrentBlock("slate_item");
153 $tpl->setVariable("SLATE", $default_renderer->render($entry));
154 $tpl->parseCurrentBlock();
155 }
156 }
157 }
158
159 protected function renderMainbar(MainBar $component, RendererInterface $default_renderer)
160 {
161 $f = $this->getUIFactory();
162 $tpl = $this->getTemplate("tpl.mainbar.html", true, true);
163
164 $tpl->setVariable("ARIA_LABEL", $this->txt('mainbar_aria_label'));
165
166 //add "more"-slate
167 $more_slate = $f->maincontrols()->slate()->combined(
168 $component->getMoreButton()->getLabel(),
169 $f->symbol()->glyph()->more()
170 )->withAriaRole(ISlate::MENU);
171 $component = $component->withAdditionalEntry(
172 '_mb_more_entry',
173 $more_slate
174 );
175
176 $component = $this->calculateMainBarTreePosition("0", $component);
177
178 $mb_entries = [
179 static::BLOCK_MAINBAR_ENTRIES => $component->getEntries(),
180 static::BLOCK_MAINBAR_TOOLS => $component->getToolEntries()
181 ];
182
183 foreach ($mb_entries as $block => $entries) {
184 $this->renderMainbarEntry(
185 $entries,
186 $block,
187 $component,
188 $tpl,
189 $default_renderer
190 );
191 }
192
193 //tools-section trigger
194 if (count($component->getToolEntries()) > 0) {
195 $btn_tools = $component->getToolsButton()
196 ->withOnClick($component->getToggleToolsSignal())
197 ->withAriaRole(IBulky::MENUITEM);
198
199 $tpl->setCurrentBlock("tools_trigger");
200 $tpl->setVariable("BUTTON", $default_renderer->render($btn_tools));
201 $tpl->parseCurrentBlock();
202 }
203
204 //disengage all, close slates
205 $btn_disengage = $f->button()->bulky($f->symbol()->glyph()->back("#"), "close", "#")
206 ->withOnClick($component->getDisengageAllSignal());
207 $tpl->setVariable("CLOSE_SLATES", $default_renderer->render($btn_disengage));
208
209
210 $id = $this->bindMainbarJS($component);
211 $tpl->setVariable('ID', $id);
212
213 return $tpl->get();
214 }
215
216 protected function renderMetabar(MetaBar $component, RendererInterface $default_renderer)
217 {
218 $f = $this->getUIFactory();
219 $tpl = $this->getTemplate("tpl.metabar.html", true, true);
220 $active = '';
221 $signals = [
222 'entry' => $component->getEntryClickSignal(),
223 'close_slates' => $component->getDisengageAllSignal()
224 ];
225 $entries = $component->getEntries();
226
227 $more_label = 'more';
228 $more_symbol = $f->symbol()->glyph()->disclosure()
229 ->withCounter($f->counter()->novelty(0))
230 ->withCounter($f->counter()->status(0));
231 $more_slate = $f->maincontrols()->slate()->combined($more_label, $more_symbol, $f->legacy(''))
232 ->withAriaRole(ISlate::MENU);
233 $entries[] = $more_slate;
234
235 $this->renderTriggerButtonsAndSlates(
236 $tpl,
237 $default_renderer,
238 $signals['entry'],
239 static::BLOCK_METABAR_ENTRIES,
240 $entries,
241 $active
242 );
243
244 $component = $component->withOnLoadCode(
245 function ($id) use ($signals) {
246 $entry_signal = $signals['entry'];
247 $close_slates_signal = $signals['close_slates'];
248 return "
249 il.UI.maincontrols.metabar.registerSignals(
250 '{$id}',
251 '{$entry_signal}',
252 '{$close_slates_signal}',
253 );
254 il.UI.maincontrols.metabar.init();
255 $(window).resize(il.UI.maincontrols.metabar.init);
256 ";
257 }
258 );
259 $tpl->setVariable('ARIA_LABEL', $this->txt('metabar_aria_label'));
260
261 $id = $this->bindJavaScript($component);
262 $tpl->setVariable('ID', $id);
263 return $tpl->get();
264 }
265
266 protected function renderModeInfo(ModeInfo $component, RendererInterface $default_renderer)
267 {
268 $tpl = $this->getTemplate("tpl.mode_info.html", true, true);
269 $tpl->setVariable('MODE_TITLE', $component->getModeTitle());
270 $base_URI = $component->getCloseAction()->getBaseURI();
271 $query = $component->getCloseAction()->getQuery();
272 $action = $base_URI . '?' . $query;
273 $close = $this->getUIFactory()->symbol()->glyph()->close($action);
274 $tpl->setVariable('CLOSE_GLYPH', $default_renderer->render($close));
275
276 return $tpl->get();
277 }
278
279
281 UITemplateWrapper $tpl,
282 RendererInterface $default_renderer,
283 Signal $entry_signal,
284 string $block,
285 array $entries,
286 string $active = null,
287 array $initially_hidden_ids = [],
288 array $close_buttons = [],
289 Signal $tool_removal_signal = null
290 ) {
291 foreach ($entries as $id => $entry) {
292 $use_block = $block;
293 $engaged = (string) $id === $active;
294
295 if ($entry instanceof Slate) {
296 $f = $this->getUIFactory();
297 $secondary_signal = $entry->getToggleSignal();
298 $button = $f->button()->bulky($entry->getSymbol(), $entry->getName(), '#')
299 ->withOnClick($entry_signal)
300 ->appendOnClick($secondary_signal)
301 ->withEngagedState($engaged)
302 ->withAriaRole(IBulky::MENUITEM);
303
304 $slate = $entry;
305 } else {
306 $button = $entry;
307 $slate = null;
308 }
309
310 $button_html = $default_renderer->render($button);
311
312 $tpl->setCurrentBlock($use_block);
313 $tpl->setVariable("BUTTON", $button_html);
314 $tpl->parseCurrentBlock();
315
316 if ($slate) {
317 $slate = $slate->withAriaRole(ISlate::MENU);
318
319 $tpl->setCurrentBlock("slate_item");
320 $tpl->setVariable("SLATE", $default_renderer->render($slate));
321 $tpl->parseCurrentBlock();
322 }
323 }
324 }
325
326 protected function bindMainbarJS(MainBar $component) : string
327 {
328 $trigger_signals = $this->trigger_signals;
329
330 $inititally_active = $component->getActive();
331
332 $component = $component->withOnLoadCode(
333 function ($id) use ($component, $trigger_signals, $inititally_active) {
334 $disengage_all_signal = $component->getDisengageAllSignal();
335 $tools_toggle_signal = $component->getToggleToolsSignal();
336
337 $js = "il.UI.maincontrols.mainbar.addTriggerSignal('{$disengage_all_signal}');";
338 $js .= "il.UI.maincontrols.mainbar.addTriggerSignal('{$tools_toggle_signal}');";
339
340 foreach ($trigger_signals as $signal) {
341 $js .= "il.UI.maincontrols.mainbar.addTriggerSignal('{$signal}');";
342 }
343
344 foreach ($component->getToolEntries() as $k => $tool) {
345 $signal = $component->getEngageToolSignal($k);
346 $js .= "il.UI.maincontrols.mainbar.addTriggerSignal('{$signal}');";
347 }
348
349 $js .= "
350 $(window).resize(il.UI.maincontrols.mainbar.adjustToScreenSize);
351 il.UI.maincontrols.mainbar.init('{$inititally_active}');
352 ";
353 return $js;
354 }
355 );
356
357 $id = $this->bindJavaScript($component);
358 return $id;
359 }
360
361 protected function renderFooter(Footer $component, RendererInterface $default_renderer)
362 {
363 $tpl = $this->getTemplate("tpl.footer.html", true, true);
364 $links = $component->getLinks();
365 if ($links) {
366 $link_list = $this->getUIFactory()->listing()->unordered($links);
367 $tpl->setVariable('LINKS', $default_renderer->render($link_list));
368 }
369
370 $tpl->setVariable('TEXT', $component->getText());
371
372 $perm_url = $component->getPermanentURL();
373 if ($perm_url instanceof URI) {
374 // Since URI::__toString() is only available in ILIAS >= 7 we have to do that on our own...
375 $uri = $perm_url->getBaseURI();
376 $query = $perm_url->getQuery();
377 if ($query) {
378 $uri .= '?' . $query;
379 }
380 $fragment = $perm_url->getFragment();
381 if ($fragment) {
382 $uri .= '#' . $fragment;
383 }
384
385 $tpl->setVariable('PERMA_LINK_LABEL', $this->txt('perma_link'));
386 $tpl->setVariable('PERMANENT_URL', $uri);
387 }
388 return $tpl->get();
389 }
390
394 public function registerResources(\ILIAS\UI\Implementation\Render\ResourceRegistry $registry)
395 {
396 parent::registerResources($registry);
397 $registry->register('./src/UI/templates/js/MainControls/mainbar.js');
398 $registry->register('./src/UI/templates/js/MainControls/metabar.js');
399 $registry->register('./src/GlobalScreen/Client/dist/GS.js');
400 $registry->register('./src/UI/templates/js/MainControls/footer.js');
401 }
402
406 protected function getComponentInterfaceName()
407 {
408 return array(
409 MetaBar::class,
410 MainBar::class,
411 Footer::class,
412 ModeInfo::class
413 );
414 }
415}
An exception for terminatinating execution or to throw for unit testing.
The scope of this class is split ilias-conform URI's into components.
Definition: URI.php:18
getComponentInterfaceName()
Get the name of the component-interface this renderer is supposed to render.ATTENTION: Fully qualifie...
Definition: Renderer.php:406
renderTriggerButtonsAndSlates(UITemplateWrapper $tpl, RendererInterface $default_renderer, Signal $entry_signal, string $block, array $entries, string $active=null, array $initially_hidden_ids=[], array $close_buttons=[], Signal $tool_removal_signal=null)
Definition: Renderer.php:280
registerResources(\ILIAS\UI\Implementation\Render\ResourceRegistry $registry)
Definition: Renderer.php:394
renderFooter(Footer $component, RendererInterface $default_renderer)
Definition: Renderer.php:361
renderModeInfo(ModeInfo $component, RendererInterface $default_renderer)
Definition: Renderer.php:266
renderMetabar(MetaBar $component, RendererInterface $default_renderer)
Definition: Renderer.php:216
renderMainbarEntry(array $entries, string $block, MainBar $component, UITemplateWrapper $tpl, RendererInterface $default_renderer)
Definition: Renderer.php:102
renderMainbar(MainBar $component, RendererInterface $default_renderer)
Definition: Renderer.php:159
render(Component\Component $component, RendererInterface $default_renderer)
Definition: Renderer.php:32
renderToolEntry(Slate $entry, string $entry_id, string $mb_id, MainBar $component, UITemplateWrapper $tpl, RendererInterface $default_renderer)
Definition: Renderer.php:67
checkComponent(Component $component)
Check if a given component fits this renderer and throw \LogicError if that is not the case.
A component is the most general form of an entity in the UI.
Definition: Component.php:14
This describes the Footer.
Definition: Footer.php:12
This describes the MainBar.
Definition: MainBar.php:16
getCloseButtons()
Buttons to close tools; maybe configure with callback.
getToolsButton()
Returns the button of the tools-trigger.
withAdditionalEntry(string $id, $entry)
Append an entry.
getToggleToolsSignal()
Signal to toggle the tools-section.
getMoreButton()
Returns the button for further entries.
getDisengageAllSignal()
This signal disengages all slates when triggered.
This describes the MetaBar.
Definition: MetaBar.php:15
getDisengageAllSignal()
This signal disengages all slates when triggered.
getEntryClickSignal()
The Signal is triggered when any Entry is being clicked.
getSymbol()
Get the Symbol of the slate.
getToggleSignal()
Signal that toggles the slate when triggered.
getName()
Get the name of this slate.
Interface to templating as it is used in the UI framework.
Definition: Template.php:14
An entity that renders components to a string output.
Definition: Renderer.php:15
Class ChatMainBarProvider \MainMenu\Provider.
Class Factory.
$query
if(isset($_FILES['img_file']['size']) && $_FILES['img_file']['size'] > 0) $tpl