ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
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
7use ILIAS\UI\Renderer as RendererInterface;
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 $button = $f->button()->standard($label, $action)->withAriaLabel($label);
59 if ($activate_first_item) {
60 $button = $button->withEngagedState(true)->withUnavailableAction();
61 $activate_first_item = false;
62 } elseif ($active == $label) {
63 $button = $button->withEngagedState(true)->withUnavailableAction();
64 } else {
65 $button = $button->withEngagedState(false);
66 }
67 $tpl->setVariable("BUTTON", $default_renderer->render($button));
68 $tpl->parseCurrentBlock();
69 }
70
71 return $tpl->get();
72 }
73
74 protected function renderSection(Component\ViewControl\Section $component, RendererInterface $default_renderer)
75 {
76 $f = $this->getUIFactory();
77
78 $tpl = $this->getTemplate("tpl.section.html", true, true);
79
80 // render middle button
81 $tpl->setVariable("BUTTON", $default_renderer->render($component->getSelectorButton()));
82
83 // previous button
84 $this->renderSectionButton($component->getPreviousActions(), $tpl, "prev");
85
86 // next button
87 $this->renderSectionButton($component->getNextActions(), $tpl, "next");
88
89 return $tpl->get();
90 }
91
97 protected function renderSectionButton(Component\Button\Button $component, $tpl, $type)
98 {
99 $uptype = strtoupper($type);
100
101 $action = $component->getAction();
102 $tpl->setVariable($uptype . "_ACTION", $action);
103 $label = ($type == "next")
104 ? $this->txt("next")
105 : $this->txt("previous");
106 $tpl->setVariable($uptype . "_LABEL", $label);
107 if ($component->isActive()) {
108 $tpl->setCurrentBlock($type . "_with_href");
109 $tpl->setVariable($uptype . "_HREF", $action);
110 $tpl->parseCurrentBlock();
111 } else {
112 $tpl->touchBlock($type . "_disabled");
113 }
114 $this->maybeRenderId($component, $tpl, $type . "_with_id", $uptype . "_ID");
115 }
116
117
118 protected function renderSortation(Component\ViewControl\Sortation $component, RendererInterface $default_renderer)
119 {
120 $f = $this->getUIFactory();
121
122 $tpl = $this->getTemplate("tpl.sortation.html", true, true);
123
124 $component = $component->withResetSignals();
125 $triggeredSignals = $component->getTriggeredSignals();
126 if ($triggeredSignals) {
127 $internal_signal = $component->getSelectSignal();
128 $signal = $triggeredSignals[0]->getSignal();
129 $options = json_encode($signal->getOptions());
130
131 $component = $component->withOnLoadCode(function ($id) use ($internal_signal, $signal) {
132 return "$(document).on('{$internal_signal}', function(event, signalData) {
133 il.UI.viewcontrol.sortation.onInternalSelect(event, signalData, '{$signal}', '{$id}');
134 return false;
135 })";
136 });
137
138 //maybeRenderId does not return id
139 $id = $this->bindJavaScript($component);
140 $tpl->setVariable('ID', $id);
141 }
142
143 //setup entries
144 $options = $component->getOptions();
145 $init_label = $component->getLabel();
146 $items = array();
147 foreach ($options as $val => $label) {
148 if ($triggeredSignals) {
149 $shy = $f->button()->shy($label, $val)->withOnClick($internal_signal);
150 } else {
151 $url = $component->getTargetURL();
152 $url .= (strpos($url, '?') === false) ? '?' : '&';
153 $url .= $component->getParameterName() . '=' . $val;
154 $shy = $f->button()->shy($label, $url);
155 }
156 $items[] = $shy;
157 }
158
159 $dd = $f->dropdown()->standard($items)
160 ->withLabel($init_label);
161
162 $tpl->setVariable('SORTATION_DROPDOWN', $default_renderer->render($dd));
163 return $tpl->get();
164 }
165
166
167
168 protected function renderPagination(Component\ViewControl\Pagination $component, RendererInterface $default_renderer)
169 {
170 $tpl = $this->getTemplate("tpl.pagination.html", true, true);
171
172 $component = $component->withResetSignals();
173 $triggeredSignals = $component->getTriggeredSignals();
174 if ($triggeredSignals) {
175 $internal_signal = $component->getInternalSignal();
176 $signal = $triggeredSignals[0]->getSignal();
177 $component = $component->withOnLoadCode(function ($id) use ($internal_signal, $signal) {
178 return "$(document).on('{$internal_signal}', function(event, signalData) {
179 il.UI.viewcontrol.pagination.onInternalSelect(event, signalData, '{$signal}', '{$id}');
180 return false;
181 })";
182 });
183
184 $id = $this->bindJavaScript($component);
185 $tpl->setVariable('ID', $id);
186 }
187
188 $range = $this->getPaginationRange($component);
189 $chunk_options = array();
190 foreach ($range as $entry) {
191 $shy = $this->getPaginationShyButton($entry, $component);
192 if ((int) $entry === $component->getCurrentPage()) {
193 $shy = $shy->withUnavailableAction();
194 }
195 $chunk_options[] = $shy;
196 }
197
198 if ($component->getDropdownAt() == null ||
199 $component->getDropdownAt() > $component->getNumberOfPages()) {
200 foreach ($chunk_options as $entry) {
201 $tpl->setCurrentBlock("entry");
202 $tpl->setVariable('BUTTON', $default_renderer->render($entry));
203 $tpl->parseCurrentBlock();
204 }
205 } else {
206 //if threshold is reached, render as dropdown
207 $f = $this->getUIFactory();
208
209 $dd_label_template = $component->getDropdownLabel();
210 if ($dd_label_template === $component->getDefaultDropdownLabel()) {
211 $dd_label_template = $this->txt($dd_label_template);
212 }
213 $dd_label = sprintf(
214 $dd_label_template,
215 $component->getCurrentPage() + 1,
216 $component->getNumberOfPages()
217 );
218
219 $dd = $f->dropdown()->standard($chunk_options)->withLabel($dd_label);
220 $tpl->setCurrentBlock("entry");
221 $tpl->setVariable('BUTTON', $default_renderer->render($dd));
222 $tpl->parseCurrentBlock();
223 }
224
225 if ($component->getMaxPaginationButtons()) {
226 $this->setPaginationFirstLast($component, $range, $default_renderer, $tpl);
227 }
228
229 $this->setPaginationBrowseControls($component, $default_renderer, $tpl);
230 return $tpl->get();
231 }
232
240 protected function getPaginationRange(Component\ViewControl\Pagination $component)
241 {
242 if (!$component->getMaxPaginationButtons()) {
243 $start = 0;
244 $stop = max($component->getNumberOfPages() - 1, 0);
245 } else {
246 //current page should be in the middle, so start is half the amount of max entries:
247 $start = (int) ($component->getCurrentPage() - floor($component->getMaxPaginationButtons() / 2));
248 $start = max($start, 0); //0, if negative
249 //stop is (calculated) start plus number of entries:
250 $stop = $start + $component->getMaxPaginationButtons() - 1;
251 //if stop exceeds max pages, recalculate both:
252 if ($stop > $component->getNumberOfPages() - 1) {
253 $stop = max($component->getNumberOfPages() - 1, 0); //0, if negative
254 $start = $stop - $component->getMaxPaginationButtons();
255 $start = max($start, 0); //0, if negative
256 }
257 }
258 return range($start, $stop);
259 }
260
261
269 protected function getPaginationShyButton($val, Component\ViewControl\Pagination $component, $label = '')
270 {
271 $f = $this->getUIFactory();
272
273 if ($label === '') {
274 $label = (string) ($val + 1);
275 }
276
277 if ($component->getTriggeredSignals()) {
278 $shy = $f->button()->shy($label, (string) $val)->withOnClick($component->getInternalSignal());
279 } else {
280 $url = $component->getTargetURL();
281 if (strpos($url, '?') === false) {
282 $url .= '?' . $component->getParameterName() . '=' . $val;
283 } else {
284 $base = substr($url, 0, strpos($url, '?') + 1);
285 $query = parse_url($url, PHP_URL_QUERY);
286 parse_str($query, $params);
287 $params[$component->getParameterName()] = $val;
288 $url = $base . http_build_query($params);
289 }
290 $shy = $f->button()->shy($label, $url);
291 }
292 return $shy;
293 }
294
304 protected function setPaginationBrowseControls(Component\ViewControl\Pagination $component, RendererInterface $default_renderer, &$tpl)
305 {
306 $prev = max(0, $component->getCurrentPage() - 1);
307 $next = $component->getCurrentPage() + 1;
308
309 $f = $this->getUIFactory();
310
311 if ($component->getTriggeredSignals()) {
312 $back = $f->symbol()->glyph()->back('')->withOnClick($component->getInternalSignal());
313 $forward = $f->symbol()->glyph()->next('')->withOnClick($component->getInternalSignal());
314 } else {
315 $url = $component->getTargetURL();
316 if (strpos($url, '?') === false) {
317 $url_prev = $url . '?' . $component->getParameterName() . '=' . $prev;
318 $url_next = $url . '?' . $component->getParameterName() . '=' . $next;
319 } else {
320 $base = substr($url, 0, strpos($url, '?') + 1);
321 $query = parse_url($url, PHP_URL_QUERY);
322 parse_str($query, $params);
323
324 $params[$component->getParameterName()] = $prev;
325 $url_prev = $base . http_build_query($params);
326 $params[$component->getParameterName()] = $next;
327 $url_next = $base . http_build_query($params);
328 }
329
330 $back = $f->symbol()->glyph()->back($url_prev);
331 $forward = $f->symbol()->glyph()->next($url_next);
332 }
333
334 if ($component->getCurrentPage() === 0) {
335 $back = $back->withUnavailableAction();
336 }
337 if ($component->getCurrentPage() >= $component->getNumberOfPages() - 1) {
338 $forward = $forward->withUnavailableAction();
339 }
340
341 $tpl->setVariable('PREVIOUS', $default_renderer->render($back));
342 $tpl->setVariable('NEXT', $default_renderer->render($forward));
343 }
344
355 protected function setPaginationFirstLast(Component\ViewControl\Pagination $component, $range, RendererInterface $default_renderer, &$tpl)
356 {
357 if (!in_array(0, $range)) {
358 $shy = $this->getPaginationShyButton(0, $component);
359 $tpl->setVariable('FIRST', $default_renderer->render($shy));
360 }
361 $last = max($component->getNumberOfPages() - 1, 0);
362 if (!in_array($last, $range)) {
363 $shy = $this->getPaginationShyButton($component->getNumberOfPages() - 1, $component);
364 $tpl->setVariable('LAST', $default_renderer->render($shy));
365 }
366 }
367
368
372 public function registerResources(\ILIAS\UI\Implementation\Render\ResourceRegistry $registry)
373 {
374 parent::registerResources($registry);
375 $registry->register('./src/UI/templates/js/ViewControl/sortation.js');
376 $registry->register('./src/UI/templates/js/ViewControl/pagination.js');
377 }
378
379
380 protected function maybeRenderId(Component\Component $component, $tpl, $block, $template_var)
381 {
382 $id = $this->bindJavaScript($component);
383 if ($id !== null) {
384 $tpl->setCurrentBlock($block);
385 $tpl->setVariable($template_var, $id);
386 $tpl->parseCurrentBlock();
387 }
388 }
389
393 protected function getComponentInterfaceName()
394 {
395 return array(
396 Component\ViewControl\Mode::class,
397 Component\ViewControl\Section::class,
398 Component\ViewControl\Sortation::class,
399 Component\ViewControl\Pagination::class
400 );
401 }
402}
An exception for terminatinating execution or to throw for unit testing.
renderMode(Component\ViewControl\Mode $component, RendererInterface $default_renderer)
Definition: Renderer.php:40
renderPagination(Component\ViewControl\Pagination $component, RendererInterface $default_renderer)
Definition: Renderer.php:168
setPaginationFirstLast(Component\ViewControl\Pagination $component, $range, RendererInterface $default_renderer, &$tpl)
Add quick-access to first/last pages in pagination.
Definition: Renderer.php:355
getComponentInterfaceName()
Get the name of the component-interface this renderer is supposed to render.ATTENTION: Fully qualifie...
Definition: Renderer.php:393
renderSortation(Component\ViewControl\Sortation $component, RendererInterface $default_renderer)
Definition: Renderer.php:118
render(Component\Component $component, RendererInterface $default_renderer)
@inheritdocs
Definition: Renderer.php:22
maybeRenderId(Component\Component $component, $tpl, $block, $template_var)
Definition: Renderer.php:380
renderSectionButton(Component\Button\Button $component, $tpl, $type)
Definition: Renderer.php:97
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:304
getPaginationShyButton($val, Component\ViewControl\Pagination $component, $label='')
Definition: Renderer.php:269
getPaginationRange(Component\ViewControl\Pagination $component)
Get the range of pagination-buttons to show.
Definition: Renderer.php:240
registerResources(\ILIAS\UI\Implementation\Render\ResourceRegistry $registry)
Definition: Renderer.php:372
renderSection(Component\ViewControl\Section $component, RendererInterface $default_renderer)
Definition: Renderer.php:74
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.
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
An entity that renders components to a string output.
Definition: Renderer.php:15
$base
Definition: index.php:4
Class ChatMainBarProvider \MainMenu\Provider.
Class Factory.
$query
$type
$url
if(isset($_FILES['img_file']['size']) && $_FILES['img_file']['size'] > 0) $tpl