ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
AbstractComponentRenderer.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (c) 2016 Richard Klees <richard.klees@concepts-and-training.de> Extended GPL, see docs/LICENSE */
4
6
11
20{
24 private $ui_factory;
25
29 private $tpl_factory;
30
34 private $lng;
35
39 private $js_binding;
43 private static $component_storage = [];
44
48 private $refinery;
49
53 final public function __construct(
58 \ILIAS\Refinery\Factory $refinery
59 ) {
60 $this->ui_factory = $ui_factory;
61 $this->tpl_factory = $tpl_factory;
62 $this->lng = $lng;
63 $this->js_binding = $js_binding;
64 $this->refinery = $refinery;
65 }
66
70 public function registerResources(ResourceRegistry $registry)
71 {
72 $registry->register('./src/UI/templates/js/Core/ui.js');
73 }
74
82 final protected function getUIFactory()
83 {
84 return $this->ui_factory;
85 }
86
90 final protected function getRefinery() : \ILIAS\Refinery\Factory
91 {
92 return $this->refinery;
93 }
94
101 final public function txt($id)
102 {
103 return $this->lng->txt($id);
104 }
105
110 final public function toJS($key)
111 {
112 $this->lng->toJS($key);
113 }
114
120 public function getLangKey()
121 {
122 return $this->lng->getLangKey();
123 }
124
125
129 final protected function getJavascriptBinding()
130 {
131 return $this->js_binding;
132 }
133
146 final protected function getTemplate($name, $purge_unfilled_vars, $purge_unused_blocks)
147 {
148 $path = $this->getTemplatePath($name);
149 return $this->tpl_factory->getTemplate($path, $purge_unfilled_vars, $purge_unused_blocks);
150 }
151
158 protected function getTemplatePath($name)
159 {
160 $component = $this->getMyComponent();
161 return "src/UI/templates/default/$component/$name";
162 }
163
173 final protected function bindJavaScript(JavaScriptBindable $component)
174 {
175 if ($component instanceof Triggerer) {
176 $component = $this->addTriggererOnLoadCode($component);
177 }
178 return $this->bindOnloadCode($component);
179 }
180
193 final protected function createId() : string
194 {
195 return $this->js_binding->createId();
196 }
197
204 private function bindOnloadCode(JavaScriptBindable $component)
205 {
206 $binder = $component->getOnLoadCode();
207 if ($binder === null) {
208 return null;
209 }
210
211 $id = $this->js_binding->createId();
212 $on_load_code = $binder($id);
213 if (!is_string($on_load_code)) {
214 throw new \LogicException(
215 "Expected JavaScript binder to return string" .
216 " (used component: " . get_class($component) . ")"
217 );
218 }
219 $this->js_binding->addOnLoadCode($on_load_code);
220 return $id;
221 }
222
229 private function addTriggererOnLoadCode(Triggerer $triggerer)
230 {
231 $triggered_signals = $triggerer->getTriggeredSignals();
232 if (count($triggered_signals) == 0) {
233 return $triggerer;
234 }
235 return $triggerer->withAdditionalOnLoadCode(function ($id) use ($triggered_signals) {
236 $code = "";
237 foreach ($triggered_signals as $triggered_signal) {
238 $signal = $triggered_signal->getSignal();
239 $event = $triggered_signal->getEvent();
240 $options = json_encode($signal->getOptions());
241 //Note this switch is necessary since $(#...).on('load', ...) could be fired before the binding of the event.
242 //Same seems true fro ready, see: #27456
243 if ($event == 'load' || $event == 'ready') {
244 $code .=
245 "$(document).trigger('{$signal}',
246 {
247 'id' : '{$signal}', 'event' : '{$event}',
248 'triggerer' : $('#{$id}'),
249 'options' : JSON.parse('{$options}')
250 }
251 );";
252 } else {
253 $code .=
254 "$('#{$id}').on('{$event}', function(event) {
255 $(this).trigger('{$signal}',
256 {
257 'id' : '{$signal}', 'event' : '{$event}',
258 'triggerer' : $(this),
259 'options' : JSON.parse('{$options}')
260 }
261 );
262 return false;
263 });";
264 }
265 }
266 return $code;
267 });
268 }
269
278 final protected function checkComponent(Component $component)
279 {
280 $interfaces = $this->getComponentInterfaceName();
281 if (!is_array($interfaces)) {
282 throw new \LogicException(
283 "Expected array, found '" . (string) (null) . "' when rendering."
284 );
285 }
286
287 foreach ($interfaces as $interface) {
288 if ($component instanceof $interface) {
289 return;
290 }
291 }
292 $ifs = implode(", ", $interfaces);
293 throw new \LogicException(
294 "Expected $ifs, found '" . get_class($component) . "' when rendering."
295 );
296 }
297
305 abstract protected function getComponentInterfaceName();
306
307
308 private function getMyComponent()
309 {
310 $class = get_class($this);
311 if (isset(self::$component_storage[$class])) {
312 return self::$component_storage[$class];
313 }
314 $matches = array();
315 // Extract component
316 $re = "%ILIAS\\\\UI\\\\Implementation\\\\Component\\\\(\\w+)\\\\(\\w+)%";
317 preg_match($re, $class, $matches);
318 if (preg_match($re, $class, $matches) !== 1) {
319 throw new \LogicException("The Renderer needs to be located in ILIAS\\UI\\Implementation\\Component\\*.");
320 }
321 self::$component_storage[$class] = $matches[1];
322
323 return self::$component_storage[$class];
324 }
325}
An exception for terminatinating execution or to throw for unit testing.
getTemplate($name, $purge_unfilled_vars, $purge_unused_blocks)
Get template of component this renderer is made for.
registerResources(ResourceRegistry $registry)
Announce resources this renderer requires.null
getTemplatePath($name)
Get the path to the template of this component.
__construct(Factory $ui_factory, TemplateFactory $tpl_factory, \ilLanguage $lng, JavaScriptBinding $js_binding, \ILIAS\Refinery\Factory $refinery)
Component renderers must only depend on a UI-Factory and a Template Factory.
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.
addTriggererOnLoadCode(Triggerer $triggerer)
Add onload-code for triggerer.
toJS($key)
Add language var to client side (il.Language)
getComponentInterfaceName()
Get the name of the component-interface this renderer is supposed to render.
bindOnloadCode(JavaScriptBindable $component)
Bind the JavaScript onload-code.
language handling
A component is the most general form of an entity in the UI.
Definition: Component.php:14
Interface to be extended by components that have the possibility to bind to Javascript.
withAdditionalOnLoadCode(\Closure $binder)
Add some onload-code to the component instead of replacing the existing one.
getOnLoadCode()
Get the currently bound on load code.
getTriggeredSignals()
Get all triggered signals of this component.
This is how the factory for UI elements looks.
Definition: Factory.php:18
An entity that renders components to a string output.
Provides methods to interface with javascript.
Registry for resources required by rendered output like Javascript or CSS.
Interface for a factory that provides templates.
if($format !==null) $name
Definition: metadata.php:230
trait JavaScriptBindable
Trait for components implementing JavaScriptBindable providing standard implementation.
Class ChatMainBarProvider \MainMenu\Provider.