ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Renderer.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 2017 Jesús López <lopez@leifos.de> Extended GPL, see docs/LICENSE */
3 
5 
9 
15 {
16  const MODE_ROLE = "group";
17 
22  public function render(Component\Component $component, RendererInterface $default_renderer)
23  {
24  $this->checkComponent($component);
25 
26  if ($component instanceof Component\ViewControl\Mode) {
27  return $this->renderMode($component, $default_renderer);
28  }
29  if ($component instanceof Component\ViewControl\Section) {
30  return $this->renderSection($component, $default_renderer);
31  }
32  if ($component instanceof Component\ViewControl\Sortation) {
33  return $this->renderSortation($component, $default_renderer);
34  }
35  if ($component instanceof Component\ViewControl\Pagination) {
36  return $this->renderPagination($component, $default_renderer);
37  }
38  }
39 
40  protected function renderMode(Component\ViewControl\Mode $component, RendererInterface $default_renderer)
41  {
42  $f = $this->getUIFactory();
43 
44  $tpl = $this->getTemplate("tpl.mode.html", true, true);
45 
46  $active = $component->getActive();
47  if ($active == "") {
48  $activate_first_item = true;
49  }
50 
51  foreach ($component->getLabelledActions() as $label => $action) {
52  $tpl->setVariable("ARIA", $this->txt($component->getAriaLabel()));
53  $tpl->setVariable("ROLE", self::MODE_ROLE);
54 
55  $tpl->setCurrentBlock("view_control");
56 
57  //At this point we don't have an specific text for the button aria label. component->getAriaLabel gets the main viewcontrol aria label.
58  if ($activate_first_item) {
59  $tpl->setVariable("BUTTON", $default_renderer->render($f->button()->standard($label, $action)->WithUnavailableAction()->withAriaLabel($label)->withAriaChecked()));
60  $activate_first_item = false;
61  } elseif ($active == $label) {
62  $tpl->setVariable("BUTTON", $default_renderer->render($f->button()->standard($label, $action)->withUnavailableAction()->withAriaLabel($label)->withAriaChecked()));
63  } else {
64  $tpl->setVariable("BUTTON", $default_renderer->render($f->button()->standard($label, $action)->withAriaLabel($label)));
65  }
66  $tpl->parseCurrentBlock();
67  }
68 
69  return $tpl->get();
70  }
71 
72  protected function renderSection(Component\ViewControl\Section $component, RendererInterface $default_renderer)
73  {
74  $f = $this->getUIFactory();
75 
76  $tpl = $this->getTemplate("tpl.section.html", true, true);
77 
78  // render middle button
79  $tpl->setVariable("BUTTON", $default_renderer->render($component->getSelectorButton()));
80 
81  // previous button
82  $this->renderSectionButton($component->getPreviousActions(), $tpl, "prev");
83 
84  // next button
85  $this->renderSectionButton($component->getNextActions(), $tpl, "next");
86 
87  return $tpl->get();
88  }
89 
95  protected function renderSectionButton(Component\Button\Button $component, $tpl, $type)
96  {
97  $uptype = strtoupper($type);
98 
99  $action = $component->getAction();
100  $tpl->setVariable($uptype . "_ACTION", $action);
101  if ($component->isActive()) {
102  $tpl->setCurrentBlock($type . "_with_href");
103  $tpl->setVariable($uptype . "_HREF", $action);
104  $tpl->parseCurrentBlock();
105  } else {
106  $tpl->touchBlock($type . "_disabled");
107  }
108  $this->maybeRenderId($component, $tpl, $type . "_with_id", $uptype . "_ID");
109  }
110 
111 
112  protected function renderSortation(Component\ViewControl\Sortation $component, RendererInterface $default_renderer)
113  {
114  $f = $this->getUIFactory();
115 
116  $tpl = $this->getTemplate("tpl.sortation.html", true, true);
117 
118  $component = $component->withResetSignals();
119  $triggeredSignals = $component->getTriggeredSignals();
120  if ($triggeredSignals) {
121  $internal_signal = $component->getSelectSignal();
122  $signal = $triggeredSignals[0]->getSignal();
123  $options = json_encode($signal->getOptions());
124 
125  $component = $component->withOnLoadCode(function ($id) use ($internal_signal, $signal) {
126  return "$(document).on('{$internal_signal}', function(event, signalData) {
127  il.UI.viewcontrol.sortation.onInternalSelect(event, signalData, '{$signal}', '{$id}');
128  return false;
129  })";
130  });
131 
132  //maybeRenderId does not return id
133  $id = $this->bindJavaScript($component);
134  $tpl->setVariable('ID', $id);
135  }
136 
137  //setup entries
138  $options = $component->getOptions();
139  $init_label = $component->getLabel();
140  $items = array();
141  foreach ($options as $val => $label) {
142  if ($triggeredSignals) {
143  $shy = $f->button()->shy($label, $val)->withOnClick($internal_signal);
144  } else {
145  $url = $component->getTargetURL();
146  $url .= (strpos($url, '?') === false) ? '?' : '&';
147  $url .= $component->getParameterName() . '=' . $val;
148  $shy = $f->button()->shy($label, $url);
149  }
150  $items[] = $shy;
151  }
152 
153  $dd = $f->dropdown()->standard($items)
154  ->withLabel($init_label);
155 
156  $tpl->setVariable('SORTATION_DROPDOWN', $default_renderer->render($dd));
157  return $tpl->get();
158  }
159 
160 
161 
162  protected function renderPagination(Component\ViewControl\Pagination $component, RendererInterface $default_renderer)
163  {
164  $tpl = $this->getTemplate("tpl.pagination.html", true, true);
165 
166  $component = $component->withResetSignals();
167  $triggeredSignals = $component->getTriggeredSignals();
168  if ($triggeredSignals) {
169  $internal_signal = $component->getInternalSignal();
170  $signal = $triggeredSignals[0]->getSignal();
171  $component = $component->withOnLoadCode(function ($id) use ($internal_signal, $signal) {
172  return "$(document).on('{$internal_signal}', function(event, signalData) {
173  il.UI.viewcontrol.pagination.onInternalSelect(event, signalData, '{$signal}', '{$id}');
174  return false;
175  })";
176  });
177 
178  $id = $this->bindJavaScript($component);
179  $tpl->setVariable('ID', $id);
180  }
181 
182  $range = $this->getPaginationRange($component);
183  $chunk_options = array();
184  foreach ($range as $entry) {
185  $shy = $this->getPaginationShyButton($entry, $component);
186  if ((int) $entry === $component->getCurrentPage()) {
187  $shy = $shy->withUnavailableAction();
188  }
189  $chunk_options[] = $shy;
190  }
191 
192  if ($component->getDropdownAt() == null ||
193  $component->getDropdownAt() > $component->getNumberOfPages()) {
194  foreach ($chunk_options as $entry) {
195  $tpl->setCurrentBlock("entry");
196  $tpl->setVariable('BUTTON', $default_renderer->render($entry));
197  $tpl->parseCurrentBlock();
198  }
199  } else {
200  //if threshold is reached, render as dropdown
201  $f = $this->getUIFactory();
202  $dd = $f->dropdown()->standard($chunk_options)->withLabel(
203  (string) ($component->getCurrentPage() + 1)
204  );
205  $tpl->setCurrentBlock("entry");
206  $tpl->setVariable('BUTTON', $default_renderer->render($dd));
207  $tpl->parseCurrentBlock();
208  }
209 
210  if ($component->getMaxPaginationButtons()) {
211  $this->setPaginationFirstLast($component, $range, $default_renderer, $tpl);
212  }
213 
214  $this->setPaginationBrowseControls($component, $default_renderer, $tpl);
215  return $tpl->get();
216  }
217 
225  protected function getPaginationRange(Component\ViewControl\Pagination $component)
226  {
227  if (!$component->getMaxPaginationButtons()) {
228  $start = 0;
229  $stop = max($component->getNumberOfPages() - 1, 0);
230  } else {
231  //current page should be in the middle, so start is half the amount of max entries:
232  $start = (int) ($component->getCurrentPage() - floor($component->getMaxPaginationButtons() / 2));
233  $start = max($start, 0); //0, if negative
234  //stop is (calculated) start plus number of entries:
235  $stop = $start + $component->getMaxPaginationButtons() - 1;
236  //if stop exceeds max pages, recalculate both:
237  if ($stop > $component->getNumberOfPages() - 1) {
238  $stop = max($component->getNumberOfPages() - 1, 0); //0, if negative
239  $start = $stop - $component->getMaxPaginationButtons();
240  $start = max($start, 0); //0, if negative
241  }
242  }
243  return range($start, $stop);
244  }
245 
246 
254  protected function getPaginationShyButton($val, Component\ViewControl\Pagination $component, $label = '')
255  {
256  $f = $this->getUIFactory();
257 
258  if ($label === '') {
259  $label = (string) ($val + 1);
260  }
261 
262  if ($component->getTriggeredSignals()) {
263  $shy = $f->button()->shy($label, (string) $val)->withOnClick($component->getInternalSignal());
264  } else {
265  $url = $component->getTargetURL();
266  if (strpos($url, '?') === false) {
267  $url .= '?' . $component->getParameterName() . '=' . $val;
268  } else {
269  $base = substr($url, 0, strpos($url, '?') + 1);
270  $query = parse_url($url, PHP_URL_QUERY);
271  parse_str($query, $params);
272  $params[$component->getParameterName()] = $val;
273  $url = $base . http_build_query($params);
274  }
275  $shy = $f->button()->shy($label, $url);
276  }
277  return $shy;
278  }
279 
289  protected function setPaginationBrowseControls(Component\ViewControl\Pagination $component, RendererInterface $default_renderer, &$tpl)
290  {
291  $prev = max(0, $component->getCurrentPage() - 1);
292  $next = $component->getCurrentPage() + 1;
293 
294  $f = $this->getUIFactory();
295 
296  if ($component->getTriggeredSignals()) {
297  $back = $f->glyph()->back('')->withOnClick($component->getInternalSignal());
298  $forward = $f->glyph()->next('')->withOnClick($component->getInternalSignal());
299  } else {
300  $url = $component->getTargetURL();
301  if (strpos($url, '?') === false) {
302  $url_prev = $url . '?' . $component->getParameterName() . '=' . $prev;
303  $url_next = $url . '?' . $component->getParameterName() . '=' . $next;
304  } else {
305  $base = substr($url, 0, strpos($url, '?') + 1);
306  $query = parse_url($url, PHP_URL_QUERY);
307  parse_str($query, $params);
308 
309  $params[$component->getParameterName()] = $prev;
310  $url_prev = $base . http_build_query($params);
311  $params[$component->getParameterName()] = $next;
312  $url_next = $base . http_build_query($params);
313  }
314 
315  $back = $f->glyph()->back($url_prev);
316  $forward = $f->glyph()->next($url_next);
317  }
318 
319  if ($component->getCurrentPage() === 0) {
320  $back = $back->withUnavailableAction();
321  }
322  if ($component->getCurrentPage() >= $component->getNumberOfPages() - 1) {
323  $forward = $forward->withUnavailableAction();
324  }
325 
326  $tpl->setVariable('PREVIOUS', $default_renderer->render($back));
327  $tpl->setVariable('NEXT', $default_renderer->render($forward));
328  }
329 
340  protected function setPaginationFirstLast(Component\ViewControl\Pagination $component, $range, RendererInterface $default_renderer, &$tpl)
341  {
342  if (!in_array(0, $range)) {
343  $shy = $this->getPaginationShyButton(0, $component);
344  $tpl->setVariable('FIRST', $default_renderer->render($shy));
345  }
346  $last = max($component->getNumberOfPages() - 1, 0);
347  if (!in_array($last, $range)) {
348  $shy = $this->getPaginationShyButton($component->getNumberOfPages() - 1, $component);
349  $tpl->setVariable('LAST', $default_renderer->render($shy));
350  }
351  }
352 
353 
357  public function registerResources(\ILIAS\UI\Implementation\Render\ResourceRegistry $registry)
358  {
359  parent::registerResources($registry);
360  $registry->register('./src/UI/templates/js/ViewControl/sortation.js');
361  $registry->register('./src/UI/templates/js/ViewControl/pagination.js');
362  }
363 
364 
365  protected function maybeRenderId(Component\Component $component, $tpl, $block, $template_var)
366  {
367  $id = $this->bindJavaScript($component);
368  if ($id !== null) {
369  $tpl->setCurrentBlock($block);
370  $tpl->setVariable($template_var, $id);
371  $tpl->parseCurrentBlock();
372  }
373  }
374 
378  protected function getComponentInterfaceName()
379  {
380  return array(
381  Component\ViewControl\Mode::class,
382  Component\ViewControl\Section::class,
383  Component\ViewControl\Sortation::class,
384  Component\ViewControl\Pagination::class
385  );
386  }
387 }
renderSection(Component\ViewControl\Section $component, RendererInterface $default_renderer)
Definition: Renderer.php:72
renderSortation(Component\ViewControl\Sortation $component, RendererInterface $default_renderer)
Definition: Renderer.php:112
Class Factory.
render(Component\Component $component, RendererInterface $default_renderer)
Definition: Renderer.php:22
$action
checkComponent(Component $component)
Check if a given component fits this renderer and throw if that is not the case. ...
$type
$tpl
Definition: ilias.php:10
setPaginationBrowseControls(Component\ViewControl\Pagination $component, RendererInterface $default_renderer, &$tpl)
Add back/next-glyphs to the template for left/right browsing in pagination.
Definition: Renderer.php:289
Class BaseForm.
if(!array_key_exists('StateId', $_REQUEST)) $id
getPaginationShyButton($val, Component\ViewControl\Pagination $component, $label='')
Definition: Renderer.php:254
renderSectionButton(Component\Button\Button $component, $tpl, $type)
Definition: Renderer.php:95
$start
Definition: bench.php:8
$base
Definition: index.php:4
getPaginationRange(Component\ViewControl\Pagination $component)
Get the range of pagintaion-buttons to show.
Definition: Renderer.php:225
registerResources(\ILIAS\UI\Implementation\Render\ResourceRegistry $registry)
Definition: Renderer.php:357
renderMode(Component\ViewControl\Mode $component, RendererInterface $default_renderer)
Definition: Renderer.php:40
$query
maybeRenderId(Component\Component $component, $tpl, $block, $template_var)
Definition: Renderer.php:365
setPaginationFirstLast(Component\ViewControl\Pagination $component, $range, RendererInterface $default_renderer, &$tpl)
Add quick-access to first/last pages in pagination.
Definition: Renderer.php:340
renderPagination(Component\ViewControl\Pagination $component, RendererInterface $default_renderer)
Definition: Renderer.php:162
$url
getTemplate($name, $purge_unfilled_vars, $purge_unused_blocks)
Get template of component this renderer is made for.
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.