ILIAS  release_8 Revision v8.24
AbstractComponentRenderer.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
23use ILIAS\Data\Factory as DataFactory;
28use ilLanguage;
29use InvalidArgumentException;
30use LogicException;
31
40{
45 private static array $component_storage = [];
46 private \ILIAS\Refinery\Factory $refinery;
48 private DataFactory $data_factory;
49
50
51 final public function __construct(
56 \ILIAS\Refinery\Factory $refinery,
58 DataFactory $data_factory
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 $this->image_path_resolver = $image_path_resolver;
66 $this->data_factory = $data_factory;
67 }
68
72 public function registerResources(ResourceRegistry $registry): void
73 {
74 $registry->register('./src/UI/templates/js/Core/dist/core.js');
75 }
76
82 final protected function getUIFactory(): Factory
83 {
84 return $this->ui_factory;
85 }
86
87 final protected function getDataFactory(): DataFactory
88 {
90 }
91
92 final protected function getRefinery(): \ILIAS\Refinery\Factory
93 {
94 return $this->refinery;
95 }
96
100 final public function txt(string $id): string
101 {
102 return $this->lng->txt($id);
103 }
104
109 final public function toJS($key): void
110 {
111 $this->lng->toJS($key);
112 }
113
117 public function getLangKey(): string
118 {
119 return $this->lng->getLangKey();
120 }
121
122 final protected function getJavascriptBinding(): JavaScriptBinding
123 {
124 return $this->js_binding;
125 }
126
135 final protected function getTemplate(string $name, bool $purge_unfilled_vars, bool $purge_unused_blocks): Template
136 {
137 $path = $this->getTemplatePath($name);
138 return $this->tpl_factory->getTemplate($path, $purge_unfilled_vars, $purge_unused_blocks);
139 }
140
144 protected function getTemplatePath(string $name): string
145 {
146 $component = $this->getMyComponent();
147 return "src/UI/templates/default/$component/$name";
148 }
149
156 final protected function bindJavaScript(JavaScriptBindable $component): ?string
157 {
158 if ($component instanceof Triggerer) {
159 $component = $this->addTriggererOnLoadCode($component);
160 }
161 return $this->bindOnloadCode($component);
162 }
163
176 final protected function createId(): string
177 {
178 return $this->js_binding->createId();
179 }
180
184 private function bindOnloadCode(JavaScriptBindable $component): ?string
185 {
186 $binder = $component->getOnLoadCode();
187 if ($binder === null) {
188 return null;
189 }
190
191 $id = $this->js_binding->createId();
192 $on_load_code = $binder($id);
193 if (!is_string($on_load_code)) {
194 throw new LogicException(
195 "Expected JavaScript binder to return string" .
196 " (used component: " . get_class($component) . ")"
197 );
198 }
199 $this->js_binding->addOnLoadCode($on_load_code);
200 return $id;
201 }
202
207 {
208 $triggered_signals = $triggerer->getTriggeredSignals();
209 if (count($triggered_signals) == 0) {
210 return $triggerer;
211 }
212 return $triggerer->withAdditionalOnLoadCode(function ($id) use ($triggered_signals): string {
213 $code = "";
214 foreach ($triggered_signals as $triggered_signal) {
215 $signal = $triggered_signal->getSignal();
216 $event = $triggered_signal->getEvent();
217 $options = json_encode($signal->getOptions());
218 //Note this switch is necessary since $(#...).on('load', ...) could be fired before the binding of the event.
219 //Same seems true fro ready, see: #27456
220 if ($event == 'load' || $event == 'ready') {
221 $code .=
222 "$(document).trigger('$signal',
223 {
224 'id' : '$signal', 'event' : '$event',
225 'triggerer' : $('#$id'),
226 'options' : JSON.parse('$options')
227 }
228 );";
229 } else {
230 $code .=
231 "$('#$id').on('$event', function(event) {
232 $(this).trigger('$signal',
233 {
234 'id' : '$signal', 'event' : '$event',
235 'triggerer' : $(this),
236 'options' : JSON.parse('$options')
237 }
238 );
239 return false;
240 });";
241 }
242 }
243 return $code;
244 });
245 }
246
253 final protected function checkComponent(Component $component): void
254 {
255 $interfaces = $this->getComponentInterfaceName();
256 if (!is_array($interfaces)) {
257 throw new LogicException(
258 "Expected array, found '" . (string) (null) . "' when rendering."
259 );
260 }
261
262 foreach ($interfaces as $interface) {
263 if ($component instanceof $interface) {
264 return;
265 }
266 }
267 $ifs = implode(", ", $interfaces);
268 throw new LogicException(
269 "Expected $ifs, found '" . get_class($component) . "' when rendering."
270 );
271 }
272
280 abstract protected function getComponentInterfaceName(): array;
281
285 private function getMyComponent()
286 {
287 $class = get_class($this);
288 if (isset(self::$component_storage[$class])) {
289 return self::$component_storage[$class];
290 }
291 $matches = array();
292 // Extract component
293 $re = "%ILIAS\\\\UI\\\\Implementation\\\\Component\\\\(\\w+)\\\\(\\w+)%";
294 preg_match($re, $class, $matches);
295 if (preg_match($re, $class, $matches) !== 1) {
296 throw new LogicException("The Renderer needs to be located in ILIAS\\UI\\Implementation\\Component\\*.");
297 }
298 self::$component_storage[$class] = $matches[1];
299
300 return self::$component_storage[$class];
301 }
302
304 {
306 }
307
308 protected function convertSpecialCharacters(string $value): string
309 {
310 return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'utf-8');
311 }
312}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
Builds data types.
Definition: Factory.php:21
registerResources(ResourceRegistry $registry)
Announce resources this renderer requires.
__construct(Factory $ui_factory, TemplateFactory $tpl_factory, ilLanguage $lng, JavaScriptBinding $js_binding, \ILIAS\Refinery\Factory $refinery, ImagePathResolver $image_path_resolver, DataFactory $data_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.
getTemplatePath(string $name)
Get the path to the template of this component.
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.
getTemplate(string $name, bool $purge_unfilled_vars, bool $purge_unused_blocks)
Get template of component this renderer is made for.
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:28
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:38
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.
register(string $name)
Add a dependency.
Interface for a factory that provides templates.
Interface to templating as it is used in the UI framework.
Definition: Template.php:29
$path
Definition: ltiservices.php:32
if($format !==null) $name
Definition: metadata.php:247
string $key
Consumer key/client ID value.
Definition: System.php:193
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
trait JavaScriptBindable
Trait for components implementing JavaScriptBindable providing standard implementation.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ChatMainBarProvider \MainMenu\Provider.