ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
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 
18 use ILIAS\Data\URI;
19 
21 {
22  public const BLOCK_MAINBAR_ENTRIES = 'trigger_item';
23  public const BLOCK_MAINBAR_TOOLS = 'tool_trigger_item';
24  public 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  if ($component instanceof Component\MainControls\SystemInfo) {
49  return $this->renderSystemInfo($component, $default_renderer);
50  }
51  }
52 
53  protected function calculateMainBarTreePosition($pos, $slate)
54  {
55  if (!$slate instanceof Slate && !$slate instanceof MainBar) {
56  return $slate;
57  }
58  return $slate
59  ->withMainBarTreePosition($pos)
60  ->withMappedSubNodes(
61  function ($num, $slate, $is_tool = false) use ($pos) {
62  if ($is_tool) {
63  $pos = 'T';
64  }
65  return $this->calculateMainBarTreePosition("$pos:$num", $slate);
66  }
67  );
68  }
69 
70  protected function renderToolEntry(
71  Slate $entry,
72  string $entry_id,
73  string $mb_id,
74  MainBar $component,
76  RendererInterface $default_renderer
77  ) : string {
78  $hidden = $component->getInitiallyHiddenToolIds();
79  $close_buttons = $component->getCloseButtons();
80 
81  $is_removeable = array_key_exists($entry_id, $close_buttons);
82  $is_hidden = in_array($entry_id, $hidden);
83 
84  if ($is_removeable) {
85  $trigger_signal = $component->getTriggerSignal($mb_id, $component::ENTRY_ACTION_REMOVE);
86  $this->trigger_signals[] = $trigger_signal;
87  $btn_removetool = $close_buttons[$entry_id]
88  ->withAdditionalOnloadCode(
89  function ($id) use ($mb_id) {
90  return "il.UI.maincontrols.mainbar.addPartIdAndEntry('{$mb_id}', 'remover', '{$id}', true);";
91  }
92  )
93  ->withOnClick($trigger_signal);
94 
95  $tpl->setCurrentBlock("tool_removal");
96  $tpl->setVariable("REMOVE_TOOL", $default_renderer->render($btn_removetool));
97  $tpl->parseCurrentBlock();
98  }
99 
100  $is_removeable = $is_removeable ? 'true':'false';
101  $is_hidden = $is_hidden ? 'true':'false';
102  return "il.UI.maincontrols.mainbar.addToolEntry('{$mb_id}', {$is_removeable}, {$is_hidden}, '{$entry_id}');";
103  }
104 
105  protected function renderMainbarEntry(
106  array $entries,
107  string $block,
108  MainBar $component,
110  RendererInterface $default_renderer
111  ) {
112  $f = $this->getUIFactory();
113  foreach ($entries as $k => $entry) {
114  $button = $entry;
115  $slate = null;
116  $js = '';
117 
118  if ($entry instanceof Slate) {
119  $slate = $entry;
120  $mb_id = $entry->getMainBarTreePosition();
121  $is_tool = $block === static::BLOCK_MAINBAR_TOOLS;
122  if ($is_tool) {
123  $js = $this->renderToolEntry($entry, $k, $mb_id, $component, $tpl, $default_renderer);
124  }
125 
126  $trigger_signal = $component->getTriggerSignal($mb_id, $component::ENTRY_ACTION_TRIGGER);
127  $this->trigger_signals[] = $trigger_signal;
128  $button = $f->button()->bulky($entry->getSymbol(), $entry->getName(), '#')
129  ->withOnClick($trigger_signal);
130  } else {
131  //add Links/Buttons as toplevel entries
132  $pos = array_search($k, array_keys($entries));
133  $mb_id = '0:' . $pos;
134  $is_tool = false;
135  }
136 
137  $button = $button->withAdditionalOnLoadCode(
138  function ($id) use ($js, $mb_id, $k, $is_tool) {
139  $add_as_tool = $is_tool ? 'true':'false';
140  $js .= "
141  il.UI.maincontrols.mainbar.addPartIdAndEntry('{$mb_id}', 'triggerer', '{$id}', {$add_as_tool});
142  il.UI.maincontrols.mainbar.addMapping('{$k}','{$mb_id}');
143  ";
144  return $js;
145  }
146  )->withAriaRole(IBulky::MENUITEM);
147 
148  $tpl->setCurrentBlock($block);
149  $tpl->setVariable("BUTTON", $default_renderer->render($button));
150  $tpl->parseCurrentBlock();
151 
152  if ($slate) {
153  $entry = $entry->withAriaRole(ISlate::MENU);
154 
155  $tpl->setCurrentBlock("slate_item");
156  $tpl->setVariable("SLATE", $default_renderer->render($entry));
157  $tpl->parseCurrentBlock();
158  }
159  }
160  }
161 
162  protected function renderMainbar(MainBar $component, RendererInterface $default_renderer)
163  {
164  $f = $this->getUIFactory();
165  $tpl = $this->getTemplate("tpl.mainbar.html", true, true);
166 
167  $tpl->setVariable("ARIA_LABEL", $this->txt('mainbar_aria_label'));
168  $more_btn_label = $this->txt('mainbar_more_label');
172  $more_slate = $f->mainControls()->slate()->combined(
173  $more_btn_label,
174  $f->symbol()->glyph()->more()
175  );
176  $more_slate = $more_slate->withAriaRole(ISlate::MENU);
177  $component = $component->withAdditionalEntry(
178  '_mb_more_entry',
179  $more_slate
180  );
181  $component = $this->calculateMainBarTreePosition("0", $component);
182 
183  $mb_entries = [
184  static::BLOCK_MAINBAR_ENTRIES => $component->getEntries(),
185  static::BLOCK_MAINBAR_TOOLS => $component->getToolEntries()
186  ];
187 
188  foreach ($mb_entries as $block => $entries) {
189  $this->renderMainbarEntry(
190  $entries,
191  $block,
192  $component,
193  $tpl,
194  $default_renderer
195  );
196  }
197 
198  //tools-section trigger
199  if (count($component->getToolEntries()) > 0) {
200  $btn_tools = $component->getToolsButton()
201  ->withOnClick($component->getToggleToolsSignal());
202 
203  $tpl->setCurrentBlock("tools_trigger");
204  $tpl->setVariable("BUTTON", $default_renderer->render($btn_tools));
205  $tpl->parseCurrentBlock();
206  }
207 
208  //disengage all, close slates
209  $btn_disengage = $f->button()->bulky($f->symbol()->glyph()->back("#"), "close", "#")
210  ->withOnClick($component->getDisengageAllSignal());
211  $tpl->setVariable("CLOSE_SLATES", $default_renderer->render($btn_disengage));
212 
213 
214  $id = $this->bindMainbarJS($component);
215  $tpl->setVariable('ID', $id);
216 
217  return $tpl->get();
218  }
219 
220  protected function renderMetabar(MetaBar $component, RendererInterface $default_renderer)
221  {
222  $f = $this->getUIFactory();
223  $tpl = $this->getTemplate("tpl.metabar.html", true, true);
224  $active = '';
225  $signals = [
226  'entry' => $component->getEntryClickSignal(),
227  'close_slates' => $component->getDisengageAllSignal()
228  ];
229  $entries = $component->getEntries();
230 
231  $more_label = 'more';
232  $more_symbol = $f->symbol()->glyph()->disclosure()
233  ->withCounter($f->counter()->novelty(0))
234  ->withCounter($f->counter()->status(0));
238  $more_slate = $f->mainControls()->slate()->combined($more_label, $more_symbol);
239  $more_slate = $more_slate->withAriaRole(ISlate::MENU);
240  $entries[] = $more_slate;
241 
243  $tpl,
244  $default_renderer,
245  $signals['entry'],
246  static::BLOCK_METABAR_ENTRIES,
247  $entries,
248  $active
249  );
250 
251  $component = $component->withOnLoadCode(
252  function ($id) use ($signals) {
253  $entry_signal = $signals['entry'];
254  $close_slates_signal = $signals['close_slates'];
255  return "
256  il.UI.maincontrols.metabar.registerSignals(
257  '{$id}',
258  '{$entry_signal}',
259  '{$close_slates_signal}',
260  );
261  il.UI.maincontrols.metabar.init();
262  $(window).resize(il.UI.maincontrols.metabar.init);
263  ";
264  }
265  );
266  $tpl->setVariable('ARIA_LABEL', $this->txt('metabar_aria_label'));
267 
268  $id = $this->bindJavaScript($component);
269  $tpl->setVariable('ID', $id);
270  return $tpl->get();
271  }
272 
273  protected function renderModeInfo(ModeInfo $component, RendererInterface $default_renderer)
274  {
275  $tpl = $this->getTemplate("tpl.mode_info.html", true, true);
276  $tpl->setVariable('MODE_TITLE', $component->getModeTitle());
277  $base_URI = $component->getCloseAction()->getBaseURI();
278  $query = $component->getCloseAction()->getQuery();
279  $action = $base_URI . '?' . $query;
280  $close = $this->getUIFactory()->symbol()->glyph()->close($action);
281  $tpl->setVariable('CLOSE_GLYPH', $default_renderer->render($close));
282 
283  return $tpl->get();
284  }
285 
286  protected function renderSystemInfo(Component\MainControls\SystemInfo $component, RendererInterface $default_renderer) : string
287  {
288  $tpl = $this->getTemplate("tpl.system_info.html", true, true);
289  $tpl->setVariable('HEADLINE', $component->getHeadLine());
290  $tpl->setVariable('BODY', $component->getInformationText());
291  $tpl->setVariable('DENOTATION', $component->getDenotation());
292  switch ($component->getDenotation()) {
295  $tpl->setVariable('LIVE', 'aria-live="polite"');
296  break;
298  $tpl->setVariable('ROLE', 'role="alert"');
299  break;
300  }
301  if ($component->isDismissable()) {
302  $close = $this->getUIFactory()->symbol()->glyph()->close("#");
303  $signal = $component->getCloseSignal();
304  $close = $close->withOnClick($signal);
305  $tpl->setVariable('CLOSE_BUTTON', $default_renderer->render($close));
306  $tpl->setVariable('CLOSE_URI', (string) $component->getDismissAction());
307  $component = $component->withAdditionalOnLoadCode(function ($id) use ($signal) {
308  return "$(document).on('{$signal}', function() { il.UI.maincontrols.system_info.close('{$id}'); });";
309  });
310  }
311 
312  $more = $this->getUIFactory()->symbol()->glyph()->more("#");
313  $tpl->setVariable('MORE_BUTTON', $default_renderer->render($more));
314 
315  $component = $component->withAdditionalOnLoadCode(function ($id) {
316  return "il.UI.maincontrols.system_info.init('{$id}')";
317  });
318 
319 
320  $id = $this->bindJavaScript($component);
321  $tpl->setVariable('ID', $id);
322 
323 
324  return $tpl->get();
325  }
326 
327 
328  protected function renderTriggerButtonsAndSlates(
330  RendererInterface $default_renderer,
331  Signal $entry_signal,
332  string $block,
333  array $entries,
334  string $active = null,
335  array $initially_hidden_ids = [],
336  array $close_buttons = [],
337  Signal $tool_removal_signal = null
338  ) {
339  foreach ($entries as $id => $entry) {
340  $use_block = $block;
341  $engaged = (string) $id === $active;
342 
343  if ($entry instanceof Slate) {
344  $f = $this->getUIFactory();
345  $secondary_signal = $entry->getToggleSignal();
346 
347  $clickable = $f->button()->bulky($entry->getSymbol(), $entry->getName(), '#')
348  ->withEngagedState($engaged)
349  ->withOnClick($entry_signal)
350  ->appendOnClick($secondary_signal)
351  ->withEngagedState($engaged)
352  ->withAriaRole(IBulky::MENUITEM);
353 
354  $slate = $entry;
355  } elseif ($entry instanceof IBulky) {
356  $clickable = $entry;
357  $clickable = $clickable->withAriaRole(IBulky::MENUITEM);
358  $slate = null;
359  } else {
360  $clickable = $entry;
361  }
362 
363  $clickable_html = $default_renderer->render($clickable);
364 
365  if ($slate) {
366  $tpl->setCurrentBlock("slate_item");
367  $tpl->setVariable("SLATE", $default_renderer->render($slate));
368  $tpl->parseCurrentBlock();
369  }
370 
371  $tpl->setCurrentBlock($use_block);
372  $tpl->setVariable("BUTTON", $clickable_html);
373  $tpl->parseCurrentBlock();
374  }
375  }
376 
377  protected function bindMainbarJS(MainBar $component) : string
378  {
380 
381  $inititally_active = $component->getActive();
382 
383  $component = $component->withOnLoadCode(
384  function ($id) use ($component, $trigger_signals, $inititally_active) {
385  $disengage_all_signal = $component->getDisengageAllSignal();
386  $tools_toggle_signal = $component->getToggleToolsSignal();
387 
388  $js = "il.UI.maincontrols.mainbar.addTriggerSignal('{$disengage_all_signal}');";
389  $js .= "il.UI.maincontrols.mainbar.addTriggerSignal('{$tools_toggle_signal}');";
390 
391  foreach ($trigger_signals as $signal) {
392  $js .= "il.UI.maincontrols.mainbar.addTriggerSignal('{$signal}');";
393  }
394 
395  foreach ($component->getToolEntries() as $k => $tool) {
396  $signal = $component->getEngageToolSignal($k);
397  $js .= "il.UI.maincontrols.mainbar.addTriggerSignal('{$signal}');";
398  }
399 
400  $js .= "
401  window.addEventListener('resize', il.UI.maincontrols.mainbar.adjustToScreenSize);
402  il.UI.maincontrols.mainbar.init('{$inititally_active}');
403  ";
404  return $js;
405  }
406  );
407 
408  $id = $this->bindJavaScript($component);
409  return $id;
410  }
411 
412  protected function renderFooter(Footer $component, RendererInterface $default_renderer)
413  {
414  $tpl = $this->getTemplate("tpl.footer.html", true, true);
415  $links = $component->getLinks();
416  $modalsWithTriggers = $component->getModals();
417  $links = array_merge($links, array_column($modalsWithTriggers, 1));
418 
419  if ($links) {
420  $link_list = $this->getUIFactory()->listing()->unordered($links);
421  $tpl->setVariable('LINKS', $default_renderer->render($link_list));
422  }
423 
424  if ($modalsWithTriggers !== []) {
425  $tpl->setVariable('MODALS', $default_renderer->render(
426  array_column($modalsWithTriggers, 0)
427  ));
428  }
429 
430  $tpl->setVariable('TEXT', $component->getText());
431 
432  $perm_url = $component->getPermanentURL();
433  if ($perm_url instanceof URI) {
434  $url = $perm_url->__toString();
435  $tpl->setVariable('PERMA_LINK_LABEL', $this->txt('perma_link'));
436  $tpl->setVariable('PERMANENT_URL', $url);
437  }
438  return $tpl->get();
439  }
440 
444  public function registerResources(\ILIAS\UI\Implementation\Render\ResourceRegistry $registry)
445  {
446  parent::registerResources($registry);
447  $registry->register('./src/UI/templates/js/MainControls/dist/mainbar.js');
448  $registry->register('./src/UI/templates/js/MainControls/metabar.js');
449  $registry->register('./src/GlobalScreen/Client/dist/GS.js');
450  $registry->register('./src/UI/templates/js/MainControls/footer.js');
451  $registry->register('./src/UI/templates/js/MainControls/system_info.js');
452  }
453 
457  protected function getComponentInterfaceName()
458  {
459  return array(
460  MetaBar::class,
461  MainBar::class,
462  Footer::class,
463  ModeInfo::class,
464  Component\MainControls\SystemInfo::class
465  );
466  }
467 }
Class Factory.
This describes the MainBar.
Definition: MainBar.php:16
checkComponent(Component $component)
Check if a given component fits this renderer and throw if that is not the case. ...
getDisengageAllSignal()
This signal disengages all slates when triggered.
getInitiallyHiddenToolIds()
There are tools that are rendered invisible before first activation.
Class ChatMainBarProvider .
renderToolEntry(Slate $entry, string $entry_id, string $mb_id, MainBar $component, UITemplateWrapper $tpl, RendererInterface $default_renderer)
Definition: Renderer.php:70
getEntryClickSignal()
The Signal is triggered when any Entry is being clicked.
renderFooter(Footer $component, RendererInterface $default_renderer)
Definition: Renderer.php:412
getDisengageAllSignal()
This signal disengages all slates when triggered.
renderSystemInfo(Component\MainControls\SystemInfo $component, RendererInterface $default_renderer)
Definition: Renderer.php:286
renderModeInfo(ModeInfo $component, RendererInterface $default_renderer)
Definition: Renderer.php:273
The scope of this class is split ilias-conform URI&#39;s into components.
Definition: URI.php:17
registerResources(\ILIAS\UI\Implementation\Render\ResourceRegistry $registry)
Definition: Renderer.php:444
$query
withAdditionalEntry(string $id, $entry)
Append an entry.
getToolsButton()
Returns the button of the tools-trigger.
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:328
This describes the MetaBar.
Definition: MetaBar.php:14
renderMainbarEntry(array $entries, string $block, MainBar $component, UITemplateWrapper $tpl, RendererInterface $default_renderer)
Definition: Renderer.php:105
render(Component\Component $component, RendererInterface $default_renderer)
Definition: Renderer.php:32
$url
getToggleToolsSignal()
Signal to toggle the tools-section.
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
getTemplate($name, $purge_unfilled_vars, $purge_unused_blocks)
Get template of component this renderer is made for.
getEngageToolSignal(string $tool_id)
Signal to engage a tool from outside the mainbar.
getCloseButtons()
Buttons to close tools; maybe configure with callback.
This describes the Footer.
Definition: Footer.php:15
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.