ILIAS  release_7 Revision v7.30-3-g800a261c036
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
54
55
56 final public function __construct(
61 \ILIAS\Refinery\Factory $refinery,
63 ) {
64 $this->ui_factory = $ui_factory;
65 $this->tpl_factory = $tpl_factory;
66 $this->lng = $lng;
67 $this->js_binding = $js_binding;
68 $this->refinery = $refinery;
69 $this->image_path_resolver = $image_path_resolver;
70 }
71
75 public function registerResources(ResourceRegistry $registry)
76 {
77 $registry->register('./src/UI/templates/js/Core/ui.js');
78 }
79
87 final protected function getUIFactory()
88 {
89 return $this->ui_factory;
90 }
91
95 final protected function getRefinery() : \ILIAS\Refinery\Factory
96 {
97 return $this->refinery;
98 }
99
106 final public function txt($id)
107 {
108 return $this->lng->txt($id);
109 }
110
115 final public function toJS($key)
116 {
117 $this->lng->toJS($key);
118 }
119
125 public function getLangKey()
126 {
127 return $this->lng->getLangKey();
128 }
129
130
134 final protected function getJavascriptBinding()
135 {
136 return $this->js_binding;
137 }
138
151 final protected function getTemplate($name, $purge_unfilled_vars, $purge_unused_blocks)
152 {
153 $path = $this->getTemplatePath($name);
154 return $this->tpl_factory->getTemplate($path, $purge_unfilled_vars, $purge_unused_blocks);
155 }
156
163 protected function getTemplatePath($name)
164 {
165 $component = $this->getMyComponent();
166 return "src/UI/templates/default/$component/$name";
167 }
168
178 final protected function bindJavaScript(JavaScriptBindable $component)
179 {
180 if ($component instanceof Triggerer) {
181 $component = $this->addTriggererOnLoadCode($component);
182 }
183 return $this->bindOnloadCode($component);
184 }
185
198 final protected function createId() : string
199 {
200 return $this->js_binding->createId();
201 }
202
209 private function bindOnloadCode(JavaScriptBindable $component)
210 {
211 $binder = $component->getOnLoadCode();
212 if ($binder === null) {
213 return null;
214 }
215
216 $id = $this->js_binding->createId();
217 $on_load_code = $binder($id);
218 if (!is_string($on_load_code)) {
219 throw new \LogicException(
220 "Expected JavaScript binder to return string" .
221 " (used component: " . get_class($component) . ")"
222 );
223 }
224 $this->js_binding->addOnLoadCode($on_load_code);
225 return $id;
226 }
227
234 private function addTriggererOnLoadCode(Triggerer $triggerer)
235 {
236 $triggered_signals = $triggerer->getTriggeredSignals();
237 if (count($triggered_signals) == 0) {
238 return $triggerer;
239 }
240 return $triggerer->withAdditionalOnLoadCode(function ($id) use ($triggered_signals) {
241 $code = "";
242 foreach ($triggered_signals as $triggered_signal) {
243 $signal = $triggered_signal->getSignal();
244 $event = $triggered_signal->getEvent();
245 $options = json_encode($signal->getOptions());
246 //Note this switch is necessary since $(#...).on('load', ...) could be fired before the binding of the event.
247 //Same seems true fro ready, see: #27456
248 if ($event == 'load' || $event == 'ready') {
249 $code .=
250 "$(document).trigger('{$signal}',
251 {
252 'id' : '{$signal}', 'event' : '{$event}',
253 'triggerer' : $('#{$id}'),
254 'options' : JSON.parse('{$options}')
255 }
256 );";
257 } else {
258 $code .=
259 "$('#{$id}').on('{$event}', function(event) {
260 $(this).trigger('{$signal}',
261 {
262 'id' : '{$signal}', 'event' : '{$event}',
263 'triggerer' : $(this),
264 'options' : JSON.parse('{$options}')
265 }
266 );
267 return false;
268 });";
269 }
270 }
271 return $code;
272 });
273 }
274
283 final protected function checkComponent(Component $component)
284 {
285 $interfaces = $this->getComponentInterfaceName();
286 if (!is_array($interfaces)) {
287 throw new \LogicException(
288 "Expected array, found '" . (string) (null) . "' when rendering."
289 );
290 }
291
292 foreach ($interfaces as $interface) {
293 if ($component instanceof $interface) {
294 return;
295 }
296 }
297 $ifs = implode(", ", $interfaces);
298 throw new \LogicException(
299 "Expected $ifs, found '" . get_class($component) . "' when rendering."
300 );
301 }
302
310 abstract protected function getComponentInterfaceName();
311
312
313 private function getMyComponent()
314 {
315 $class = get_class($this);
316 if (isset(self::$component_storage[$class])) {
317 return self::$component_storage[$class];
318 }
319 $matches = array();
320 // Extract component
321 $re = "%ILIAS\\\\UI\\\\Implementation\\\\Component\\\\(\\w+)\\\\(\\w+)%";
322 preg_match($re, $class, $matches);
323 if (preg_match($re, $class, $matches) !== 1) {
324 throw new \LogicException("The Renderer needs to be located in ILIAS\\UI\\Implementation\\Component\\*.");
325 }
326 self::$component_storage[$class] = $matches[1];
327
328 return self::$component_storage[$class];
329 }
330
332 {
334 }
335}
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.
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.
__construct(Factory $ui_factory, TemplateFactory $tpl_factory, \ilLanguage $lng, JavaScriptBinding $js_binding, \ILIAS\Refinery\Factory $refinery, ImagePathResolver $image_path_resolver)
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.
Some Components need to resolve pathes to image-files.
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.