ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
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  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,
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,
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 
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 
280  protected function renderTriggerButtonsAndSlates(
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  {
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 }
renderMetabar(MetaBar $component, RendererInterface $default_renderer)
Definition: Renderer.php:216
Class Factory.
This describes the MainBar.
Definition: MainBar.php:15
if(isset($_FILES['img_file']['size']) && $_FILES['img_file']['size'] > 0) $tpl
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 .
renderMainbar(MainBar $component, RendererInterface $default_renderer)
Definition: Renderer.php:159
renderToolEntry(Slate $entry, string $entry_id, string $mb_id, MainBar $component, UITemplateWrapper $tpl, RendererInterface $default_renderer)
Definition: Renderer.php:67
getEntryClickSignal()
The Signal is triggered when any Entry is being clicked.
renderFooter(Footer $component, RendererInterface $default_renderer)
Definition: Renderer.php:361
getDisengageAllSignal()
This signal disengages all slates when triggered.
renderModeInfo(ModeInfo $component, RendererInterface $default_renderer)
Definition: Renderer.php:266
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:394
$query
withAdditionalEntry(string $id, $entry)
Append an entry.
getToolsButton()
Returns the button of the tools-trigger.
getMoreButton()
Returns the button for further entries.
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
This describes the MetaBar.
Definition: MetaBar.php:14
renderMainbarEntry(array $entries, string $block, MainBar $component, UITemplateWrapper $tpl, RendererInterface $default_renderer)
Definition: Renderer.php:102
render(Component\Component $component, RendererInterface $default_renderer)
Definition: Renderer.php:32
getToggleToolsSignal()
Signal to toggle the tools-section.
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:11
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.