ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
Renderer.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
22 
29 
34 {
38  public function render(Component\Component $component, RendererInterface $default_renderer): string
39  {
40  $this->checkComponent($component);
41 
42  // If the modal is rendered async, we just create a fake container which will be
43  // replaced by the modal upon successful ajax request
45  if ($component->getAsyncRenderUrl()) {
46  return $this->renderAsync($component);
47  }
48 
49  if ($component instanceof Component\Modal\Interruptive) {
50  return $this->renderInterruptive($component, $default_renderer);
51  } elseif ($component instanceof Component\Modal\RoundTrip) {
52  return $this->renderRoundTrip($component, $default_renderer);
53  } elseif ($component instanceof Component\Modal\Lightbox) {
54  return $this->renderLightbox($component, $default_renderer);
55  }
56  return '';
57  }
58 
62  public function registerResources(ResourceRegistry $registry): void
63  {
64  parent::registerResources($registry);
65  $registry->register('./src/UI/templates/js/Modal/modal.js');
66  }
67 
69  {
70  $show = $modal->getShowSignal();
71  $close = $modal->getCloseSignal();
72 
73  $replace = "";
74  if ($modal instanceof Component\Modal\RoundTrip) {
75  $replace = $modal->getReplaceSignal();
76  }
77 
78  $options = array(
79  'ajaxRenderUrl' => $modal->getAsyncRenderUrl(),
80  'keyboard' => $modal->getCloseWithKeyboard()
81  );
82  // ATTENTION, ATTENTION:
83  // with(Additional)OnLoadCode opens a wormhole into the future, where some unspecified
84  // entity magically created an id for the component that can be used to refer to it
85  // via javascript.
86  // This replaced a pattern, where an id was created manually and the java script
87  // code was manually inserted to the (now internal) js-binding of the
88  // AbstractComponentRenderer. (see commit 192144fd1f0e040cadc0149c3dc15fbc4b67858e).
89  // The wormhole solution is considered superior over the manual creation of ids because:
90  // * withAdditionalOnLoadCode introduces no new principles to the UI framework but reuses
91  // an existing one
92  // * withAdditionalOnLoadCode does not require it to expose internals (js-binding) from
93  // the AbstractComponentRenderer and thus does have less coupling
94  // * withAdditionalOnLoadCode allows the framework to decide, when ids are actually
95  // created
96  // * since withAdditionalOnLoadCode refers to some yet unknown future, it disencourages
97  // tempering with the id _here_.
98  return $modal->withAdditionalOnLoadCode(function ($id) use ($show, $close, $options, $replace): string {
99  $options["url"] = "#$id";
100  $options = json_encode($options);
101  $code =
102  "$(document).on('$show', function(event, signalData) { il.UI.modal.showModal('$id', $options, signalData);});" .
103  "$(document).on('$close', function() { il.UI.modal.closeModal('$id');});";
104  if ($replace != "") {
105  $code .= "$(document).on('$replace', function(event, signalData) { il.UI.modal.replaceFromSignal('$id', signalData);});";
106  }
107  return $code;
108  });
109  }
110 
111  protected function renderAsync(Component\Modal\Modal $modal): string
112  {
113  $modal = $this->registerSignals($modal);
114  $id = $this->bindJavaScript($modal);
115  return "<span id='$id'></span>";
116  }
117 
118  protected function renderInterruptive(
120  RendererInterface $default_renderer
121  ): string {
122  $tpl = $this->getTemplate('tpl.interruptive.html', true, true);
123  $modal = $this->registerSignals($modal);
124  $id = $this->bindJavaScript($modal);
125  $tpl->setVariable('ID', $id);
126  $value = $modal->getFormAction();
127  $tpl->setVariable('FORM_ACTION', $value);
128  $tpl->setVariable('TITLE', $modal->getTitle());
129  $tpl->setVariable('MESSAGE', $modal->getMessage());
130  if (count($modal->getAffectedItems())) {
131  $tpl->setCurrentBlock('with_items');
132  foreach ($modal->getAffectedItems() as $item) {
133  $tpl->setCurrentBlock('item');
134  $icon = ($item->getIcon()) ? $default_renderer->render($item->getIcon()) : '';
135  $desc = ($item->getDescription()) ? '<br>' . $item->getDescription() : '';
136  $tpl->setVariable('ITEM_ICON', $icon);
137  $tpl->setVariable('ITEM_ID', $item->getId());
138  $tpl->setVariable('ITEM_TITLE', $item->getTitle());
139  $tpl->setVariable('ITEM_DESCRIPTION', $desc);
140  $tpl->parseCurrentBlock();
141  }
142  }
143  $tpl->setVariable('ACTION_BUTTON_LABEL', $this->txt($modal->getActionButtonLabel()));
144  $tpl->setVariable('ACTION_BUTTON', $modal->getActionButtonLabel());
145  $tpl->setVariable('CANCEL_BUTTON_LABEL', $this->txt($modal->getCancelButtonLabel()));
146  $tpl->setVariable('CLOSE_LABEL', $this->txt($modal->getCancelButtonLabel()));
147 
148  return $tpl->get();
149  }
150 
151  protected function renderRoundTrip(Component\Modal\RoundTrip $modal, RendererInterface $default_renderer): string
152  {
153  $tpl = $this->getTemplate('tpl.roundtrip.html', true, true);
155  $modal = $this->registerSignals($modal);
156  $id = $this->bindJavaScript($modal);
157  $tpl->setVariable('ID', $id);
158  $tpl->setVariable('TITLE', $modal->getTitle());
159  $tpl->setVariable('CLOSE_LABEL', $this->txt('close'));
160 
161  foreach ($modal->getContent() as $content) {
162  $tpl->setCurrentBlock('with_content');
163  $tpl->setVariable('CONTENT', $default_renderer->render($content));
164  $tpl->parseCurrentBlock();
165  }
166  foreach ($modal->getActionButtons() as $button) {
167  $tpl->setCurrentBlock('with_buttons');
168  $tpl->setVariable('BUTTON', $default_renderer->render($button));
169  $tpl->parseCurrentBlock();
170  }
171 
172  // only render form if it contains any inputs (for now).
173  if (!empty($modal->getInputs())) {
174  // render form in modal body.
175  $tpl->setCurrentBlock('with_form');
176  $tpl->setVariable('FORM', $default_renderer->render($modal->getForm()));
177  $tpl->parseCurrentBlock();
178 
179  // render submit in modal footer.
180  $submit = $this->getUIFactory()->button()->standard(
181  $modal->getSubmitCaption(),
182  ''
183  )->withOnClick($modal->getForm()->getSubmitSignal());
184  $tpl->setCurrentBlock('with_submit');
185  $tpl->setVariable('SUBMIT_BUTTON', $default_renderer->render($submit));
186  $tpl->parseCurrentBlock();
187  }
188 
189  $tpl->setVariable('CANCEL_BUTTON_LABEL', $this->txt($modal->getCancelButtonLabel()));
190  return $tpl->get();
191  }
192 
193  protected function renderLightbox(Component\Modal\Lightbox $modal, RendererInterface $default_renderer): string
194  {
195  $tpl = $this->getTemplate('tpl.lightbox.html', true, true);
196  $modal = $this->registerSignals($modal);
197  $id = $this->bindJavaScript($modal);
198  $tpl->setVariable('ID', $id);
199  $id_carousel = "{$id}_carousel";
200  $pages = $modal->getPages();
201  $tpl->setVariable('TITLE', $pages[0]->getTitle());
202  $tpl->setVariable('ID_CAROUSEL', $id_carousel);
203  $tpl->setVariable('CLOSE_LABEL', $this->txt('close'));
204 
205  if (count($pages) > 1) {
206  $tpl->setCurrentBlock('has_indicators');
207  foreach ($pages as $index => $page) {
208  $tpl->setCurrentBlock('indicators');
209  $tpl->setVariable('INDEX', $index);
210  $tpl->setVariable('CLASS_ACTIVE', ($index == 0) ? 'active' : '');
211  $tpl->setVariable('ID_CAROUSEL2', $id_carousel);
212  $tpl->parseCurrentBlock();
213  }
214  }
215  foreach ($pages as $i => $page) {
216  if ($page instanceof LightboxTextPage) {
217  $tpl->setCurrentBlock('pages');
218  $tpl->touchBlock('page_type_text');
219  $tpl->parseCurrentBlock();
220  }
221  $tpl->setCurrentBlock('pages');
222  $tpl->setVariable('CLASS_ACTIVE', ($i == 0) ? ' active' : '');
223  $tpl->setVariable('TITLE2', htmlentities($page->getTitle(), ENT_QUOTES, 'UTF-8'));
224  $tpl->setVariable('CONTENT', $default_renderer->render($page->getComponent()));
225  if ($page instanceof LightboxDescriptionEnabledPage) {
226  $tpl->setVariable('DESCRIPTION', $page->getDescription());
227  }
228  $tpl->parseCurrentBlock();
229  }
230  if (count($pages) > 1) {
231  $tpl->setCurrentBlock('controls');
232  $tpl->setVariable('ID_CAROUSEL3', $id_carousel);
233  $tpl->parseCurrentBlock();
234  }
235  $tpl->setVariable('ID_CAROUSEL4', $id_carousel);
236  return $tpl->get();
237  }
238 
242  protected function getComponentInterfaceName(): array
243  {
244  return array(
245  Component\Modal\Interruptive::class,
246  Component\Modal\RoundTrip::class,
247  Component\Modal\Lightbox::class,
248  );
249  }
250 }
Registry for resources required by rendered output like Javascript or CSS.
checkComponent(Component $component)
Check if a given component fits this renderer and throw if that is not the case. ...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: Factory.php:21
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
txt(string $id)
Get a text from the language file.
$index
Definition: metadata.php:145
renderLightbox(Component\Modal\Lightbox $modal, RendererInterface $default_renderer)
Definition: Renderer.php:193
registerResources(ResourceRegistry $registry)
Announce resources this renderer requires.
Definition: Renderer.php:62
getTemplate(string $name, bool $purge_unfilled_vars, bool $purge_unused_blocks)
Get template of component this renderer is made for.
renderInterruptive(Component\Modal\Interruptive $modal, RendererInterface $default_renderer)
Definition: Renderer.php:118
register(string $name)
Add a dependency.
render(Component $component, Renderer $default_renderer)
Render the component if possible and delegate additional rendering to the default_renderer.
renderAsync(Component\Modal\Modal $modal)
Definition: Renderer.php:111
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
registerSignals(Component\Modal\Modal $modal)
Definition: Renderer.php:68
$i
Definition: metadata.php:41
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.