ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
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(
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 }
Registry for resources required by rendered output like Javascript or CSS.
getTemplatePath($name)
Get the path to the template of this component.
addTriggererOnLoadCode(Triggerer $triggerer)
Add onload-code for triggerer.
checkComponent(Component $component)
Check if a given component fits this renderer and throw if that is not the case. ...
Class ChatMainBarProvider .
An entity that renders components to a string output.
trait JavaScriptBindable
Trait for components implementing JavaScriptBindable providing standard implementation.
Some Components need to resolve pathes to image-files.
toJS($key)
Add language var to client side (il.Language)
bindOnloadCode(JavaScriptBindable $component)
Bind the JavaScript onload-code.
getComponentInterfaceName()
Get the name of the component-interface this renderer is supposed to render.
if($format !==null) $name
Definition: metadata.php:230
__construct(Factory $ui_factory, TemplateFactory $tpl_factory, \ilLanguage $lng, JavaScriptBinding $js_binding, \ILIAS\Refinery\Factory $refinery, ImagePathResolver $image_path_resolver)
This is how the factory for UI elements looks.
Definition: Factory.php:17
getOnLoadCode()
Get the currently bound on load code.
Provides methods to interface with javascript.
withAdditionalOnLoadCode(\Closure $binder)
Add some onload-code to the component instead of replacing the existing one.
getTriggeredSignals()
Get all triggered signals of this component.
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
Interface for a factory that provides templates.
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.