ILIAS  trunk Revision v11.0_alpha-1715-g7fc467680fb
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
Renderer.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
32 
34 {
38  public function render(Component\Component $component, RendererInterface $default_renderer): string
39  {
40  if ($component instanceof Component\Button\Close) {
41  return $this->renderClose($component);
42  } elseif ($component instanceof Component\Button\Minimize) {
43  return $this->renderMinimize($component);
44  } elseif ($component instanceof Component\Button\Toggle) {
45  return $this->renderToggle($component);
46  } elseif ($component instanceof Component\Button\Month) {
47  return $this->renderMonth($component);
48  } elseif ($component instanceof Component\Button\Button) {
49  return $this->renderButton($component, $default_renderer);
50  }
51  $this->cannotHandleComponent($component);
52  }
53 
54  protected function renderButton(Component\Button\Button $component, RendererInterface $default_renderer): string
55  {
56  $tpl_name = "";
57  if ($component instanceof Component\Button\Primary) {
58  $tpl_name = "tpl.primary.html";
59  }
60  if ($component instanceof Component\Button\Standard) {
61  $tpl_name = "tpl.standard.html";
62  }
63  if ($component instanceof Component\Button\Shy) {
64  $tpl_name = "tpl.shy.html";
65  }
66  if ($component instanceof Component\Button\Tag) {
67  $tpl_name = "tpl.tag.html";
68  }
69  if ($component instanceof Component\Button\Bulky) {
70  $tpl_name = "tpl.bulky.html";
71  }
72 
73  $tpl = $this->getTemplate($tpl_name, true, true);
74 
75  $action = $component->getAction();
76  // The action is always put in the data-action attribute to have it available
77  // on the client side, even if it is not available on rendering.
78  if (is_string($action)) {
79  $tpl->setCurrentBlock("with_data_action");
80  $tpl->setVariable("ACTION", $action);
81  $tpl->parseCurrentBlock();
82  }
83 
84  $tpl->setVariable("LABEL", $component->getLabel());
85  $symbol = $component->getSymbol();
86  if ($symbol !== null) {
87  if ($component->getLabel() !== '') {
88  $symbol = $symbol->withLabel('');
89  }
90  $tpl->setVariable("SYMBOL", $default_renderer->render($symbol));
91  }
92 
93  if ($component->isActive()) {
94  // The actions might also be a list of signals, these will be appended by
95  // bindJavascript in maybeRenderId.
96  if (is_string($action) && $action != "") {
97  $component = $component->withAdditionalOnLoadCode(function ($id) use ($action) {
98  $action = str_replace("&amp;", "&", $action);
99 
100  return "$('#$id').on('click', function(event) {
101  window.location = '$action';
102  return false;
103  });";
104  });
105  }
106 
107  if ($component instanceof Component\Button\LoadingAnimationOnClick && $component->hasLoadingAnimationOnClick()) {
108  $component = $component->withAdditionalOnLoadCode(fn($id) => "$('#$id').click(function(e) { il.UI.button.activateLoadingAnimation('$id')});");
109  }
110  } else {
111  $tpl->touchBlock("disabled");
112  }
113  $aria_label = $component->getAriaLabel();
114  if ($aria_label != null) {
115  $tpl->setCurrentBlock("with_aria_label");
116  $tpl->setVariable("ARIA_LABEL", $aria_label);
117  $tpl->parseCurrentBlock();
118  }
119 
120  if ($component instanceof Component\Button\Engageable
121  && $component->isEngageable()
122  ) {
123  if ($component->isEngaged()) {
124  $tpl->touchBlock("engaged");
125  $aria_pressed = 'true';
126  } else {
127  $aria_pressed = 'false';
128  }
129 
130  //Note that Bulky Buttons need to handle aria_pressed seperatly due to possible aria_role conflicts
131  if (!($component instanceof Bulky)) {
132  $tpl->setCurrentBlock("with_aria_pressed");
133  $tpl->setVariable("ARIA_PRESSED", $aria_pressed);
134  $tpl->parseCurrentBlock();
135  }
136  }
137 
138  $tooltip_embedding = $this->getTooltipRenderer()->maybeGetTooltipEmbedding(...$component->getHelpTopics());
139  if ($tooltip_embedding) {
140  $component = $component->withAdditionalOnLoadCode($tooltip_embedding[1]);
141  }
142 
143  $this->maybeRenderId($component, $tpl);
144 
145  if ($component instanceof Component\Button\Tag) {
146  $this->additionalRenderTag($component, $tpl);
147  }
148 
149  if ($component instanceof Component\Button\Bulky) {
150  $this->additionalRenderBulky($component, $default_renderer, $tpl);
151  }
152 
153  if (!$tooltip_embedding) {
154  return $tpl->get();
155  }
156 
157  $tooltip_id = $this->createId();
158  $tpl->setCurrentBlock("with_aria_describedby");
159  $tpl->setVariable("ARIA_DESCRIBED_BY", $tooltip_id);
160  $tpl->parseCurrentBlock();
161 
162  return $tooltip_embedding[0]($tooltip_id, $tpl->get());
163  }
164 
168  public function registerResources(ResourceRegistry $registry): void
169  {
170  parent::registerResources($registry);
171  $registry->register('assets/js/button.js');
172  $registry->register("./assets/js/moment-with-locales.min.js");
173  $registry->register("./assets/js/bootstrap-datetimepicker.min.js");
174  }
175 
176  protected function renderClose(Component\Button\Close $component): string
177  {
178  $tpl = $this->getTemplate("tpl.close.html", true, true);
179  // This is required as the rendering seems to only create any output at all
180  // if any var was set or block was touched.
181  $tpl->setVariable("FORCE_RENDERING", "");
182  $tpl->setVariable("ARIA_LABEL", $this->txt("close"));
183  $this->maybeRenderId($component, $tpl);
184  return $tpl->get();
185  }
186 
187  protected function renderMinimize(Component\Button\Minimize $component): string
188  {
189  $tpl = $this->getTemplate("tpl.minimize.html", true, true);
190  $tpl->setVariable("ARIA_LABEL", $this->txt("minimize"));
191  $this->maybeRenderId($component, $tpl);
192  return $tpl->get();
193  }
194 
195  protected function renderToggle(Component\Button\Toggle $component): string
196  {
197  $tpl = $this->getTemplate("tpl.toggle.html", true, true);
198 
199  $on_action = $component->getActionOn();
200  $off_action = $component->getActionOff();
201 
202  $on_url = (is_string($on_action))
203  ? $on_action
204  : "";
205 
206  $off_url = (is_string($off_action))
207  ? $off_action
208  : "";
209 
210  $signals = [];
211 
212  foreach ($component->getTriggeredSignals() as $s) {
213  $signals[] = [
214  "signal_id" => $s->getSignal()->getId(),
215  "event" => $s->getEvent(),
216  "options" => $s->getSignal()->getOptions()
217  ];
218  }
219 
220  $signals = json_encode($signals);
221 
222  $button_status = 'off';
223  if ($component->isEngaged()) {
224  $button_status = 'on';
225  }
226 
227  if ($component->isActive()) {
228  $component = $component->withAdditionalOnLoadCode(
229  fn($id) =>
230  "$('#$id').on('click', function(event) {
231  il.UI.button.handleToggleClick(event, '$id', '$on_url', '$off_url', $signals);
232  return false; // stop event propagation
233  });"
234  );
235  $tpl->setCurrentBlock("with_on_off_label");
236  $tpl->setVariable("ON_LABEL", $this->txt("toggle_on"));
237  $tpl->setVariable("OFF_LABEL", $this->txt("toggle_off"));
238  $tpl->parseCurrentBlock();
239  } else {
240  $tpl->touchBlock("disabled");
241  $button_status = 'unavailable';
242  }
243 
244  $tpl->touchBlock($button_status);
245 
246  $label = $component->getLabel();
247  if (!empty($label)) {
248  $tpl->setCurrentBlock("with_label");
249  $tpl->setVariable("LABEL", $label);
250  $tpl->parseCurrentBlock();
251  }
252  $aria_label = $component->getAriaLabel();
253  if ($aria_label != null) {
254  $tpl->setCurrentBlock("with_aria_label");
255  $tpl->setVariable("ARIA_LABEL", $aria_label);
256  $tpl->parseCurrentBlock();
257  }
258 
259  $tooltip_embedding = $this->getTooltipRenderer()->maybeGetTooltipEmbedding(...$component->getHelpTopics());
260  if ($tooltip_embedding) {
261  $component = $component->withAdditionalOnLoadCode($tooltip_embedding[1]);
262  $tooltip_id = $this->createId();
263  $tpl->setCurrentBlock("with_aria_describedby");
264  $tpl->setVariable("ARIA_DESCRIBED_BY", $tooltip_id);
265  $tpl->parseCurrentBlock();
266 
267  $this->maybeRenderId($component, $tpl);
268  return $tooltip_embedding[0]($tooltip_id, $tpl->get());
269  }
270 
271  $this->maybeRenderId($component, $tpl);
272  return $tpl->get();
273  }
274 
275  protected function maybeRenderId(Component\JavaScriptBindable $component, Template $tpl): void
276  {
277  $id = $this->bindJavaScript($component);
278  if ($id !== null) {
279  $tpl->setCurrentBlock("with_id");
280  $tpl->setVariable("ID", $id);
281  $tpl->parseCurrentBlock();
282  }
283  }
284 
285  protected function renderMonth(Component\Button\Month $component): string
286  {
287  $tpl = $this->getTemplate("tpl.month.html", true, true);
288 
289  $component = $component->withAdditionalOnLoadCode(fn($id) => "il.UI.button.initMonth('$id');");
290  $id = $this->bindJavaScript($component);
291  $tpl->setVariable("ID", $id);
292 
293  $def = $component->getDefault();
294  $value = implode('-', array_reverse(explode("-", $def)));
295  $tpl->setVariable("DEFAULT", $value);
296 
297  return $tpl->get();
298  }
299 
300  protected function additionalRenderTag(Component\Button\Tag $component, Template $tpl): void
301  {
302  $tpl->touchBlock('rel_' . $component->getRelevance());
303 
304  $classes = trim(join(' ', $component->getClasses()));
305  if ($classes !== '') {
306  $tpl->setVariable("CLASSES", $classes);
307  }
308 
309  $bgcol = $component->getBackgroundColor();
310  if ($bgcol) {
311  $tpl->setVariable("BGCOL", $bgcol->asHex());
312  }
313  $forecol = $component->getForegroundColor();
314  if ($forecol) {
315  $tpl->setVariable("FORECOL", $forecol->asHex());
316  }
317  }
318 
319  protected function additionalRenderBulky(
320  Component\Button\Button $component,
321  RendererInterface $default_renderer,
322  Template $tpl
323  ): void {
324  $aria_role = $component->getAriaRole();
325  if ($aria_role != null) {
326  $tpl->setCurrentBlock("with_aria_role");
327  $tpl->setVariable("ARIA_ROLE", $aria_role);
328  $tpl->parseCurrentBlock();
329  }
330  if ($component->isEngageable()) {
331  if ($aria_role == Bulky::MENUITEM) {
332  $tpl->touchBlock("with_aria_haspopup");
333  } else {
334  //Note that aria-role='menuitems MUST-NOT have Aria-pressed to true;
335  $tpl->setCurrentBlock("with_aria_pressed");
336  if ($component->isEngaged()) {
337  $tpl->setVariable("ARIA_PRESSED", "true");
338  } else {
339  $tpl->setVariable("ARIA_PRESSED", "false");
340  }
341  $tpl->parseCurrentBlock();
342  }
343  }
344  }
345 }
Registry for resources required by rendered output like Javascript or CSS.
render(Component\Component $component, RendererInterface $default_renderer)
Definition: Renderer.php:38
renderMinimize(Component\Button\Minimize $component)
Definition: Renderer.php:187
renderMonth(Component\Button\Month $component)
Definition: Renderer.php:285
txt(string $id)
Get a text from the language file.
setCurrentBlock(string $name)
Set the block to work on.
setVariable(string $name, $value)
Set a variable in the current block.
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: Bulky.php:21
registerResources(ResourceRegistry $registry)
Announce resources this renderer requires.
Definition: Renderer.php:168
getTemplate(string $name, bool $purge_unfilled_vars, bool $purge_unused_blocks)
Get template of component this renderer is made for.
renderToggle(Component\Button\Toggle $component)
Definition: Renderer.php:195
additionalRenderTag(Component\Button\Tag $component, Template $tpl)
Definition: Renderer.php:300
renderButton(Component\Button\Button $component, RendererInterface $default_renderer)
Definition: Renderer.php:54
cannotHandleComponent(Component $component)
This method MUST be called by derived component renderers, if.
register(string $name)
Add a dependency.
renderClose(Component\Button\Close $component)
Definition: Renderer.php:176
parseCurrentBlock()
Parse the block that is currently worked on.
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
touchBlock(string $name)
Touch a block without working further on it.
additionalRenderBulky(Component\Button\Button $component, RendererInterface $default_renderer, Template $tpl)
Definition: Renderer.php:319
maybeRenderId(Component\JavaScriptBindable $component, Template $tpl)
Definition: Renderer.php:275
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.