ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
AbstractComponentRenderer.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
23use ILIAS\Data\Factory as DataFactory;
31use InvalidArgumentException;
32use LogicException;
35
44{
45 private static array $component_storage;
46
47 final public function __construct(
48 private FactoryInternal $ui_factory,
49 private TemplateFactory $tpl_factory,
50 private Language $lng,
51 private JavaScriptBinding $js_binding,
52 private ImagePathResolver $image_path_resolver,
53 private DataFactory $data_factory,
54 private HelpTextRetriever $help_text_retriever,
55 private UploadLimitResolver $upload_limit_resolver,
56 ) {
57 }
58
62 public function registerResources(ResourceRegistry $registry): void
63 {
64 $registry->register('assets/js/core.js');
65 }
66
72 final protected function getUIFactory(): FactoryInternal
73 {
74 return $this->ui_factory;
75 }
76
77 final protected function getDataFactory(): DataFactory
78 {
79 return $this->data_factory;
80 }
81
82 final protected function getUploadLimitResolver(): UploadLimitResolver
83 {
84 return $this->upload_limit_resolver;
85 }
86
90 final public function txt(string $id): string
91 {
92 return $this->lng->txt($id);
93 }
94
99 final public function toJS($key): void
100 {
101 $this->lng->toJS($key);
102 }
103
107 public function getLangKey(): string
108 {
109 return $this->lng->getLangKey();
110 }
111
112 final protected function getJavascriptBinding(): JavaScriptBinding
113 {
114 return $this->js_binding;
115 }
116
125 final protected function getTemplate(string $name, bool $purge_unfilled_vars, bool $purge_unused_blocks): Template
126 {
127 $path = $this->getTemplatePath($name);
128 return $this->getTemplateRaw($path, $purge_unfilled_vars, $purge_unused_blocks);
129 }
130
134 protected function getTemplatePath(string $name): string
135 {
136 $component = $this->getMyComponent();
137 return "components/ILIAS/UI/src/templates/default/$component/$name";
138 }
139
143 private function getTemplateRaw(string $path, bool $purge_unfilled_vars, bool $purge_unused_blocks): Template
144 {
145 return $this->tpl_factory->getTemplate($path, $purge_unfilled_vars, $purge_unused_blocks);
146 }
147
154 final protected function bindJavaScript(JavaScriptBindable $component): ?string
155 {
156 if ($component instanceof Triggerer) {
157 $component = $this->addTriggererOnLoadCode($component);
158 }
159 return $this->bindOnloadCode($component);
160 }
161
174 final protected function createId(): string
175 {
176 return $this->js_binding->createId();
177 }
178
182 private function bindOnloadCode(JavaScriptBindable $component): ?string
183 {
184 $binder = $component->getOnLoadCode();
185 if ($binder === null) {
186 return null;
187 }
188
189 $id = $this->js_binding->createId();
190 $on_load_code = $binder($id);
191 if (!is_string($on_load_code)) {
192 throw new LogicException(
193 "Expected JavaScript binder to return string" .
194 " (used component: " . get_class($component) . ")"
195 );
196 }
197 $this->js_binding->addOnLoadCode($on_load_code);
198 return $id;
199 }
200
205 {
206 $triggered_signals = $triggerer->getTriggeredSignals();
207 if (count($triggered_signals) == 0) {
208 return $triggerer;
209 }
210 return $triggerer->withAdditionalOnLoadCode(function ($id) use ($triggered_signals): string {
211 $code = "";
212 foreach ($triggered_signals as $triggered_signal) {
213 $signal = $triggered_signal->getSignal();
214 $event = $triggered_signal->getEvent();
215 $options = json_encode($signal->getOptions());
216 //Note this switch is necessary since $(#...).on('load', ...) could be fired before the binding of the event.
217 //Same seems true fro ready, see: #27456
218 if ($event == 'load' || $event == 'ready') {
219 $code .=
220 "$(document).trigger('$signal',
221 {
222 'id' : '$signal', 'event' : '$event',
223 'triggerer' : $('#$id'),
224 'options' : JSON.parse('$options')
225 }
226 );";
227 } else {
228 $code .=
229 "$('#$id').on('$event', function(event) {
230 $(this).trigger('$signal',
231 {
232 'id' : '$signal', 'event' : '$event',
233 'triggerer' : $(this),
234 'options' : JSON.parse('$options')
235 }
236 );
237 return false;
238 });";
239 }
240 }
241 return $code;
242 });
243 }
244
249 final protected function cannotHandleComponent(Component $component): never
250 {
251 throw new LogicException(
252 sprintf(
253 "%s could not render component %s",
254 static::class,
255 get_class($component)
256 )
257 );
258 }
259
263 private function getMyComponent()
264 {
265 $class = get_class($this);
266 if (isset(self::$component_storage[$class])) {
267 return self::$component_storage[$class];
268 }
269 $matches = array();
270 // Extract component
271 $re = "%ILIAS\\\\UI\\\\Implementation\\\\Component\\\\(\\w+)\\\\(\\w+)%";
272 preg_match($re, $class, $matches);
273 if (preg_match($re, $class, $matches) !== 1) {
274 throw new LogicException("The Renderer needs to be located in ILIAS\\UI\\Implementation\\Component\\*.");
275 }
276 self::$component_storage[$class] = $matches[1];
277
278 return self::$component_storage[$class];
279 }
280
282 {
283 return $this->image_path_resolver;
284 }
285
286 public function getHelpText(Help\Purpose $purpose, Help\Topic ...$topics): array
287 {
288 return $this->help_text_retriever->getHelpText($purpose, ...$topics);
289 }
290
291 /*
292 * This is supposed to unify rendering of tooltips over all components.
293 */
295
297 {
298 if ($this->tooltip_renderer === null) {
299 $this->tooltip_renderer = new TooltipRenderer(
300 $this,
301 fn($path, $f1, $f2) => $this->getTemplateRaw($path, $f1, $f2)
302 );
303 }
305 }
306
307 protected function convertSpecialCharacters(string $value): string
308 {
309 return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'utf-8');
310 }
311
312 public function getComponentCanonicalNameAttribute(Component $component): string
313 {
314 return str_replace(' ', '-', strtolower($component->getCanonicalName()));
315 }
316}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
Builds data types.
Definition: Factory.php:36
A purpose describes the intended use for a certain help text.
Definition: Purpose.php:47
This is just a class that marks a string as a help topic.
Definition: Topic.php:27
cannotHandleComponent(Component $component)
This method MUST be called by derived component renderers, if.
registerResources(ResourceRegistry $registry)
Announce resources this renderer requires.
__construct(private FactoryInternal $ui_factory, private TemplateFactory $tpl_factory, private Language $lng, private JavaScriptBinding $js_binding, private ImagePathResolver $image_path_resolver, private DataFactory $data_factory, private HelpTextRetriever $help_text_retriever, private UploadLimitResolver $upload_limit_resolver,)
getHelpText(Help\Purpose $purpose, Help\Topic ... $topics)
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.
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)
getTemplateRaw(string $path, bool $purge_unfilled_vars, bool $purge_unused_blocks)
Get a template from any path.
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.
This class is supposed to unify rendering of tooltips over all components and should also be usable b...
A component is the most general form of an entity in the UI.
Definition: Component.php:28
getCanonicalName()
Get the canonical name of the component.
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 describes a facility that the UI framework can use to retrieve some help text.
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
An entity that renders components to a string output.
Definition: Renderer.php:31
$path
Definition: ltiservices.php:30
trait JavaScriptBindable
Trait for components implementing JavaScriptBindable providing standard implementation.
global $lng
Definition: privfeed.php:31