19declare(strict_types=1);
41use ILIAS\UI\Implementation\Component\ComponentHelper;
99 case ($component instanceof
F\
Section):
105 case ($component instanceof
F\
Link):
108 case ($component instanceof
F\
Group):
109 return $default_renderer->render($component->getInputs());
111 case ($component instanceof
F\
Text):
114 case ($component instanceof
F\
Numeric):
120 case ($component instanceof
F\
Tag):
126 case ($component instanceof
F\
Select):
130 return $this->renderMarkdownField($component, $default_renderer);
133 return $this->renderTextareaField($component, $default_renderer);
135 case ($component instanceof
F\
Radio):
144 case ($component instanceof
F\
Image):
147 case ($component instanceof
F\
File):
150 case ($component instanceof
F\
Url):
153 case ($component instanceof
F\
Hidden):
159 case ($component instanceof
F\
Rating):
177 ?
string $id_for_label =
null,
178 ?
string $dependant_group_html =
null
182 $tpl->setVariable(
"LABEL", $label);
183 $tpl->setVariable(
"INPUT", $input_html);
185 $tpl->setVariable(
"INPUT_NAME", $component->getName());
189 $tpl->setVariable(
"BINDING_ID", $binding_id);
193 $tpl->setCurrentBlock(
'for');
194 $tpl->setVariable(
"ID", $id_for_label);
195 $tpl->parseCurrentBlock();
197 $tpl->touchBlock(
'tabindex');
202 $tpl->setVariable(
"BYLINE", $byline);
207 $tpl->setCurrentBlock(
'required');
208 $tpl->setVariable(
"REQUIRED_ARIA", $this->
txt(
'required_field'));
209 $tpl->parseCurrentBlock();
213 $tpl->touchBlock(
"disabled");
216 $error = $component->getError();
219 $tpl->setVariable(
"ERROR_LABEL", $this->
txt(
"ui_error"));
220 $tpl->setVariable(
"ERROR_ID", $error_id);
221 $tpl->setVariable(
"ERROR",
$error);
223 $tpl->setVariable(
"ERROR_FOR_ID", $id_for_label);
227 if ($dependant_group_html) {
228 $tpl->setVariable(
"DEPENDANT_GROUP", $dependant_group_html);
235 $name = $component->getName();
242 $id = $this->bindJavaScript($component) ?? $this->createId();
258 if (!is_null($escape)) {
259 $value = $escape($value);
261 if (isset($value) && $value !==
'') {
268 return function ($v) {
272 return htmlspecialchars((
string) $v, ENT_QUOTES,
'utf-8',
false);
278 return function ($v) {
282 return htmlentities((
string) $v, ENT_QUOTES,
'utf-8',
false);
288 $input_html = $default_renderer->render($component->getInputs());
289 return $this->wrapInFormContext(
291 $component->getLabel(),
298 $tpl = $this->getTemplate(
"tpl.text.html",
true,
true);
299 $this->applyName($component, $tpl);
301 if ($component->getMaxLength()) {
302 $tpl->setVariable(
"MAX_LENGTH", $component->getMaxLength());
305 $this->applyValue($component, $tpl, $this->escapeSpecialChars());
307 $label_id = $this->createId();
308 $tpl->setVariable(
'ID', $label_id);
309 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
314 $tpl = $this->getTemplate(
"tpl.numeric.html",
true,
true);
315 $this->applyName($component, $tpl);
316 $this->applyValue($component, $tpl, $this->escapeSpecialChars());
318 $tpl->setVariable(
"STEPSIZE", $component->getStepSize());
320 $label_id = $this->createId();
321 $tpl->setVariable(
'ID', $label_id);
322 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
327 $tpl = $this->getTemplate(
"tpl.checkbox.html",
true,
true);
328 $this->applyName($component, $tpl);
330 if ($component->getValue()) {
331 $tpl->touchBlock(
"value");
334 $label_id = $this->createId();
335 $tpl->setVariable(
'ID', $label_id);
336 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
341 $tpl = $this->getTemplate(
"tpl.optionalgroup_label.html",
true,
true);
342 $tpl->setVariable(
'LABEL', $component->getLabel());
343 $tpl->setVariable(
"NAME", $component->getName());
344 if ($component->getValue()) {
345 $tpl->setVariable(
"CHECKED",
'checked="checked"');
348 $label_id = $this->createId();
349 $tpl->setVariable(
'ID', $label_id);
351 $label = $tpl->get();
352 $input_html = $default_renderer->render($component->getInputs());
354 return $this->wrapInFormContext($component, $label, $input_html, $label_id);
360 if ($component->getValue() !==
null) {
361 list($value, ) = $component->getValue();
365 foreach ($component->getInputs() as $key => $group) {
366 $tpl = $this->getTemplate(
"tpl.switchablegroup_label.html",
true,
true);
367 $tpl->setVariable(
'LABEL', $group->getLabel());
368 $tpl->setVariable(
"NAME", $component->getName());
369 $tpl->setVariable(
"VALUE", $key);
371 $label_id = $this->createId();
372 $tpl->setVariable(
'ID', $label_id);
374 if ($key == $value) {
375 $tpl->setVariable(
"CHECKED",
'checked="checked"');
378 $input_html .= $this->wrapInFormContext(
381 $default_renderer->render($group),
387 return $this->wrapInFormContext(
389 $component->getLabel(),
396 $tpl = $this->getTemplate(
"tpl.tag_input.html",
true,
true);
397 $this->applyName($component, $tpl);
399 $configuration = $component->getConfiguration();
400 $value = $component->getValue();
405 return [
'value' => rawurlencode($v),
'display' => $v];
411 $autocomplete_endpoint =
'undefined';
412 $autocomplete_token =
'undefined';
413 if ($component->getAsyncAutocompleteEndpoint() !==
null) {
414 $autocomplete_endpoint = $component->getAsyncAutocompleteEndpoint()
415 ->renderObject([$component->getAsyncAutocompleteToken()]);
416 $autocomplete_token = $component->getAsyncAutocompleteToken()->render();
419 $component = $component->withAdditionalOnLoadCode(
420 function (
$id) use ($configuration, $value, $autocomplete_endpoint, $autocomplete_token) {
421 $encoded = json_encode($configuration);
422 $value = json_encode($value);
423 return 'il.UI.Input.tagInput.init(document.querySelector('
424 .
"'#{$id} .c-field-tag'), {$encoded}, {$value},"
425 .
" {$autocomplete_endpoint}, "
426 .
" {$autocomplete_token}"
431 if ($component->isDisabled()) {
432 $tpl->setVariable(
"DISABLED",
"disabled");
433 $tpl->setVariable(
"READONLY",
"readonly");
436 $label_id = $this->createId();
437 $tpl->setVariable(
'ID', $label_id);
438 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
443 $tpl = $this->getTemplate(
"tpl.password.html",
true,
true);
444 $this->applyName($component, $tpl);
446 if ($component->getRevelation()) {
447 $component = $component->withResetSignals();
448 $sig_reveal = $component->getRevealSignal();
449 $sig_mask = $component->getMaskSignal();
450 $component = $component->withAdditionalOnLoadCode(
function (
$id) use ($sig_reveal, $sig_mask) {
452 "$(document).on('$sig_reveal', function() {
453 const fieldContainer = document.querySelector('#$id .c-input__field .c-field-password');
454 fieldContainer.classList.add('revealed');
455 fieldContainer.getElementsByTagName('input').item(0).type='text';
457 "$(document).on('$sig_mask', function() {
458 const fieldContainer = document.querySelector('#$id .c-input__field .c-field-password');
459 fieldContainer.classList.remove('revealed');
460 fieldContainer.getElementsByTagName('input').item(0).type='password';
464 $f = $this->getUIFactory();
465 $glyph_reveal =
$f->symbol()->glyph()->eyeopen(
"#")
466 ->withOnClick($sig_reveal);
467 $glyph_mask =
$f->symbol()->glyph()->eyeclosed(
"#")
468 ->withOnClick($sig_mask);
470 $tpl->setVariable(
'PASSWORD_REVEAL', $default_renderer->render($glyph_reveal));
471 $tpl->setVariable(
'PASSWORD_MASK', $default_renderer->render($glyph_mask));
474 $this->applyValue($component, $tpl, $this->escapeSpecialChars());
476 $label_id = $this->createId();
477 $tpl->setVariable(
'ID', $label_id);
478 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
483 $tpl = $this->getTemplate(
"tpl.select.html",
true,
true);
484 $this->applyName($component, $tpl);
486 $value = $component->getValue();
488 $tpl->setCurrentBlock(
"options");
490 $tpl->setVariable(
"SELECTED",
'selected="selected"');
492 if ($component->isRequired() && !$value) {
493 $tpl->setVariable(
"DISABLED_OPTION",
"disabled");
494 $tpl->setVariable(
"HIDDEN",
"hidden");
497 if (!($value && $component->isRequired())) {
498 $tpl->setVariable(
"VALUE",
null);
499 $tpl->setVariable(
"VALUE_STR", $component->isRequired() ? $this->txt(
'ui_select_dropdown_label') :
'-');
500 $tpl->parseCurrentBlock();
503 foreach ($component->getOptions() as $option_key => $option_value) {
504 $tpl->setCurrentBlock(
"options");
505 if ($value == $option_key) {
506 $tpl->setVariable(
"SELECTED",
'selected="selected"');
508 $tpl->setVariable(
"VALUE", $option_key);
509 $tpl->setVariable(
"VALUE_STR", $option_value);
510 $tpl->parseCurrentBlock();
513 $label_id = $this->createId();
514 $tpl->setVariable(
'ID', $label_id);
515 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
518 protected function renderMarkdownField(
F\
Markdown $component, RendererInterface $default_renderer): string
521 $component = $component->withAdditionalOnLoadCode(
522 static function (
$id) use ($component):
string {
524 const id = document.querySelector('#$id .c-input__field textarea')?.id;
525 il.UI.Input.markdown.init(
527 '{$component->getMarkdownRenderer()->getAsyncUrl()}',
528 '{$component->getMarkdownRenderer()->getParameterName()}'
534 $textarea_id = $this->createId();
535 $textarea_tpl = $this->getPreparedTextareaTemplate($component);
536 $textarea_tpl->setVariable(
'ID', $textarea_id);
538 $markdown_tpl = $this->getTemplate(
"tpl.markdown.html",
true,
true);
539 $markdown_tpl->setVariable(
'TEXTAREA', $textarea_tpl->get());
541 $markdown_tpl->setVariable(
543 $component->getMarkdownRenderer()->render(
544 $this->htmlEntities()($component->getValue() ??
'')
548 $markdown_tpl->setVariable(
550 $default_renderer->render(
551 $this->getUIFactory()->viewControl()->mode([
552 $this->txt(
'ui_md_input_edit') =>
'#',
553 $this->txt(
'ui_md_input_view') =>
'#',
559 $markdown_actions_glyphs = [
560 'ACTION_HEADING' => $this->getUIFactory()->symbol()->glyph()->header(),
561 'ACTION_LINK' => $this->getUIFactory()->symbol()->glyph()->link(),
562 'ACTION_BOLD' => $this->getUIFactory()->symbol()->glyph()->bold(),
563 'ACTION_ITALIC' => $this->getUIFactory()->symbol()->glyph()->italic(),
564 'ACTION_ORDERED_LIST' => $this->getUIFactory()->symbol()->glyph()->numberedlist(),
565 'ACTION_UNORDERED_LIST' => $this->getUIFactory()->symbol()->glyph()->bulletlist()
568 foreach ($markdown_actions_glyphs as $tpl_variable => $glyph) {
569 if ($component->isDisabled()) {
570 $glyph = $glyph->withUnavailableAction();
573 $action = $this->getUIFactory()->button()->standard(
'',
'#')->withSymbol($glyph);
575 if ($component->isDisabled()) {
576 $action = $action->withUnavailableAction();
579 $markdown_tpl->setVariable($tpl_variable, $default_renderer->render($action));
582 return $this->wrapInFormContext($component, $component->getLabel(), $markdown_tpl->get());
585 protected function renderTextareaField(
F\Textarea $component, RendererInterface $default_renderer): string
588 $component = $component->withAdditionalOnLoadCode(
589 static function (
$id):
string {
591 taId = document.querySelector('#$id .c-input__field textarea')?.id;
592 il.UI.Input.textarea.init(taId);
597 $tpl = $this->getPreparedTextareaTemplate($component);
599 $label_id = $this->createId();
600 $tpl->setVariable(
'ID', $label_id);
601 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
606 $tpl = $this->getTemplate(
"tpl.textarea.html",
true,
true);
608 if (0 < $component->getMaxLimit()) {
609 $tpl->setVariable(
'REMAINDER_TEXT', $this->txt(
'ui_chars_remaining'));
610 $tpl->setVariable(
'REMAINDER', $component->getMaxLimit() - strlen($component->getValue() ??
''));
611 $tpl->setVariable(
'MAX_LIMIT', $component->getMaxLimit());
614 if (
null !== $component->getMinLimit()) {
615 $tpl->setVariable(
'MIN_LIMIT', $component->getMinLimit());
618 $this->applyName($component, $tpl);
619 $this->applyValue($component, $tpl, $this->htmlEntities());
625 $tpl = $this->getTemplate(
"tpl.radio.html",
true,
true);
626 $id = $this->createId();
628 foreach ($component->getOptions() as $value => $label) {
629 $opt_id =
$id .
'_' . $value .
'_opt';
631 $tpl->setCurrentBlock(
'optionblock');
632 $tpl->setVariable(
"NAME", $component->getName());
633 $tpl->setVariable(
"OPTIONID", $opt_id);
634 $tpl->setVariable(
"VALUE", $value);
635 $tpl->setVariable(
"LABEL", $label);
637 if ($component->getValue() !==
null && $component->getValue() == $value) {
638 $tpl->setVariable(
"CHECKED",
'checked="checked"');
640 if ($component->isDisabled()) {
641 $tpl->setVariable(
"DISABLED",
'disabled="disabled"');
644 $byline = $component->getBylineFor((
string) $value);
645 if (!empty($byline)) {
646 $tpl->setVariable(
"BYLINE", $byline);
649 $tpl->parseCurrentBlock();
652 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get());
657 $tpl = $this->getTemplate(
"tpl.multiselect.html",
true,
true);
659 $options = $component->getOptions();
660 if (count($options) > 0) {
661 $value = $component->getValue();
662 $name = $this->applyName($component, $tpl);
663 foreach ($options as $opt_value => $opt_label) {
664 $tpl->setCurrentBlock(
"option");
665 $tpl->setVariable(
"NAME", $name);
666 $tpl->setVariable(
"VALUE", $opt_value);
667 $tpl->setVariable(
"LABEL", $opt_label);
669 if ($value && in_array($opt_value, $value)) {
670 $tpl->setVariable(
"CHECKED",
'checked="checked"');
672 $tpl->parseCurrentBlock();
675 $tpl->touchBlock(
"no_options");
678 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get());
683 list($component, $tpl) = $this->internalRenderDateTimeField($component, $default_renderer);
684 $label_id = $this->createId();
685 $tpl->setVariable(
'ID', $label_id);
686 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
694 $tpl = $this->getTemplate(
"tpl.datetime.html",
true,
true);
695 $this->applyName($component, $tpl);
697 if ($component->getTimeOnly() ===
true) {
698 $format = $component::TIME_FORMAT;
699 $dt_type = self::TYPE_TIME;
701 $dt_type = self::TYPE_DATE;
702 $format = $this->getTransformedDateFormat(
703 $component->getFormat(),
704 self::DATEPICKER_FORMAT_MAPPING
707 if ($component->getUseTime() ===
true) {
708 $format .=
' ' . $component::TIME_FORMAT;
709 $dt_type = self::TYPE_DATETIME;
713 $tpl->setVariable(
"DTTYPE", $dt_type);
715 $min_max_format = self::DATE_DATEPICKER_MINMAX_FORMAT;
716 if ($dt_type === self::TYPE_DATETIME) {
717 $min_max_format = self::DATETIME_DATEPICKER_MINMAX_FORMAT;
720 $min_date = $component->getMinValue();
721 if (!is_null($min_date)) {
722 $tpl->setVariable(
"MIN_DATE", date_format($min_date, $min_max_format));
724 $max_date = $component->getMaxValue();
725 if (!is_null($max_date)) {
726 $tpl->setVariable(
"MAX_DATE", date_format($max_date, $min_max_format));
729 $this->applyValue($component, $tpl,
function (?
string $value) use ($dt_type) {
730 if ($value !==
null) {
731 $value = new \DateTimeImmutable($value);
732 return $value->format(match ($dt_type) {
733 self::TYPE_DATETIME => self::HTML5_NATIVE_DATETIME_FORMAT,
734 self::TYPE_DATE => self::HTML5_NATIVE_DATE_FORMAT,
735 self::TYPE_TIME => self::HTML5_NATIVE_TIME_FORMAT,
740 return [$component, $tpl];
745 $inputs = $component->getInputs();
748 list($input, $tpl) = $this->internalRenderDateTimeField($input, $default_renderer);
750 $from_input_id = $this->createId();
751 $tpl->setVariable(
'ID', $from_input_id);
752 $input_html = $this->wrapInFormContext($input, $input->getLabel(), $tpl->get(), $from_input_id);
755 ->withAdditionalPickerconfig([
'useCurrent' =>
false]);
756 list($input, $tpl) = $this->internalRenderDateTimeField($input, $default_renderer);
757 $until_input_id = $this->createId();
758 $tpl->setVariable(
'ID', $until_input_id);
759 $input_html .= $this->wrapInFormContext($input, $input->getLabel(), $tpl->get(), $until_input_id);
761 $tpl = $this->getTemplate(
"tpl.duration.html",
true,
true);
762 $tpl->setVariable(
'DURATION', $input_html);
763 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get());
768 $inputs_html = $default_renderer->render($section->getInputs());
770 $headline_tpl = $this->getTemplate(
"tpl.headlines.html",
true,
true);
771 $headline_tpl->setVariable(
"HEADLINE", $section->getLabel());
772 $nesting_level = $section->getNestingLevel() + 2;
773 if ($nesting_level > 6) {
776 $headline_tpl->setVariable(
"LEVEL", $nesting_level);
778 $headline_html = $headline_tpl->get();
780 return $this->wrapInFormContext($section, $headline_html, $inputs_html);
785 $tpl = $this->getTemplate(
"tpl.url.html",
true,
true);
786 $this->applyName($component, $tpl);
787 $this->applyValue($component, $tpl, $this->escapeSpecialChars());
789 $label_id = $this->createId();
790 $tpl->setVariable(
'ID', $label_id);
791 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
796 return $this->renderFileField($input, $default_renderer);
801 $template = $this->getTemplate(
'tpl.file.html',
true,
true);
802 foreach ($input->getGeneratedDynamicInputs() as $metadata_input) {
804 if (
null !== (
$data = $metadata_input->getValue())) {
805 $file_id = (!$input->hasMetadataInputs()) ?
$data :
$data[0] ??
null;
807 if (
null !== $file_id) {
808 $file_info = $input->getUploadHandler()->getInfoResult($file_id);
812 $template = $this->renderFilePreview(
821 $file_preview_template = $this->getTemplate(
'tpl.file.html',
true,
true);
822 $file_preview_template = $this->renderFilePreview(
824 $input->getTemplateForDynamicInputs(),
827 $file_preview_template
830 $template->setVariable(
'FILE_PREVIEW_TEMPLATE', $file_preview_template->get(
'block_file_preview'));
832 $this->setHelpBlockForFileField($template, $input);
834 $input = $this->initClientsideFileInput($input);
837 $template->setVariable(
'ACTION_BUTTON', $default_renderer->render(
838 $this->getUIFactory()->button()->shy(
839 $this->txt(
'select_files_from_computer'),
844 return $this->wrapInFormContext(
853 $template = $this->getTemplate(
'tpl.hidden.html',
true,
true);
854 $this->applyName($input, $template);
855 $this->applyValue($input, $template, $this->escapeSpecialChars());
856 if ($input->isDisabled()) {
857 $template->setVariable(
"DISABLED",
'disabled="disabled"');
859 $this->bindJSandApplyId($input, $template);
860 return $template->get();
868 parent::registerResources($registry);
869 $registry->
register(
'assets/css/tagify.css');
870 $registry->
register(
'assets/js/tagInput.js');
872 $registry->
register(
'assets/js/dropzone.min.js');
873 $registry->
register(
'assets/js/dropzone.js');
874 $registry->
register(
'assets/js/input.js');
875 $registry->
register(
'assets/js/core.js');
876 $registry->
register(
'assets/js/file.js');
878 $registry->
register(
'assets/js/drilldown.min.js');
879 $registry->
register(
'assets/js/input.factory.min.js');
889 foreach ($input->getTriggeredSignals() as $s) {
891 "signal_id" => $s->getSignal()->getId(),
892 "event" => $s->getEvent(),
893 "options" => $s->getSignal()->getOptions()
896 if ($signals !==
null) {
897 $signals = json_encode($signals);
899 $input = $input->withAdditionalOnLoadCode(
function (
$id) use ($signals) {
900 $code =
"il.UI.input.setSignalsForId('$id', $signals);";
904 $input = $input->withAdditionalOnLoadCode($input->getUpdateOnLoadCode());
920 foreach ($origin->toArray() as $element) {
921 if (array_key_exists($element, $mapping)) {
922 $ret .= $mapping[$element];
933 RendererInterface $default_renderer,
937 $template->setCurrentBlock(
'block_file_preview');
938 $template->
setVariable(
'REMOVAL_GLYPH', $default_renderer->render(
939 $this->getUIFactory()->symbol()->glyph()->close()->withAction(
"#")
942 if (
null !== $file_info) {
952 if ($file_input->hasMetadataInputs()) {
953 $template->
setVariable(
'EXPAND_GLYPH', $default_renderer->render(
954 $this->getUIFactory()->symbol()->glyph()->expand()->withAction(
"#")
956 $template->
setVariable(
'COLLAPSE_GLYPH', $default_renderer->render(
957 $this->getUIFactory()->symbol()->glyph()->collapse()->withAction(
"#")
961 $template->
setVariable(
'METADATA_INPUTS', $default_renderer->render($metadata_input));
971 function (
$id) use ($input) {
972 $current_file_count = count($input->getGeneratedDynamicInputs());
973 $translations = json_encode($input->getTranslations());
974 $is_disabled = ($input->isDisabled()) ?
'true' :
'false';
975 $php_upload_limit = $this->getUploadLimitResolver()->getPhpUploadLimitInBytes();
976 $should_upload_be_chunked = ($input->getMaxFileSize() > $php_upload_limit) ?
'true' :
'false';
977 $chunk_size = (
int) floor($php_upload_limit * self::FILE_UPLOAD_CHUNK_SIZE_FACTOR);
979 $(document).ready(function () {
980 il.UI.Input.File.init(
982 '{$input->getUploadHandler()->getUploadURL()}',
983 '{$input->getUploadHandler()->getFileRemovalURL()}',
984 '{$input->getUploadHandler()->getFileIdentifierParameterName()}',
986 {$input->getMaxFiles()},
987 {$input->getMaxFileSize()},
988 '{$this->prepareDropzoneJsMimeTypes($input->getAcceptedMimeTypes())}',
991 $should_upload_be_chunked,
1007 $mime_type_string =
'';
1008 foreach ($mime_types as $index => $mime_type) {
1009 $mime_type_string .= (isset($mime_types[$index + 1])) ?
"$mime_type," : $mime_type;
1012 return $mime_type_string;
1017 $tpl = $this->getTemplate(
"tpl.color_select.html",
true,
true);
1018 $this->applyName($component, $tpl);
1019 $tpl->setVariable(
'VALUE', $component->getValue());
1021 $label_id = $this->createId();
1022 $tpl->setVariable(
'ID', $label_id);
1023 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get(), $label_id);
1028 $tpl = $this->getTemplate(
"tpl.rating.html",
true,
true);
1029 $id = $this->createId();
1030 $aria_description_id =
$id .
'_desc';
1031 $tpl->setVariable(
'DESCRIPTION_SRC_ID', $aria_description_id);
1033 $option_count = count(FiveStarRatingScale::cases()) - 1;
1035 foreach (range($option_count, 1, -1) as $option) {
1036 $tpl->setCurrentBlock(
'scaleoption');
1037 $tpl->setVariable(
'ARIALABEL', $this->txt($option .
'stars'));
1038 $tpl->setVariable(
'OPT_VALUE', (
string) $option);
1039 $tpl->setVariable(
'OPT_ID',
$id .
'-' . $option);
1040 $tpl->setVariable(
'NAME', $component->getName());
1041 $tpl->setVariable(
'DESCRIPTION_ID', $aria_description_id);
1044 $tpl->setVariable(
"SELECTED",
' checked="checked"');
1046 if ($component->isDisabled()) {
1047 $tpl->setVariable(
"DISABLED",
'disabled="disabled"');
1049 $tpl->parseCurrentBlock();
1052 if (!$component->isRequired()) {
1053 $tpl->setVariable(
'NEUTRAL_ID',
$id .
'-0');
1054 $tpl->setVariable(
'NEUTRAL_NAME', $component->getName());
1055 $tpl->setVariable(
'NEUTRAL_LABEL', $this->txt(
'reset_stars'));
1056 $tpl->setVariable(
'NEUTRAL_DESCRIPTION_ID', $aria_description_id);
1058 if ($component->getValue() === FiveStarRatingScale::NONE || is_null($component->getValue())) {
1059 $tpl->setVariable(
'NEUTRAL_SELECTED',
' checked="checked"');
1063 if (
$txt = $component->getAdditionalText()) {
1064 $tpl->setVariable(
'TEXT',
$txt);
1067 if ($component->isDisabled()) {
1068 $tpl->touchBlock(
'disabled');
1070 if ($average = $component->getCurrentAverage()) {
1071 $average_title = sprintf($this->txt(
'rating_average'), $average);
1072 $tpl->setVariable(
'AVERAGE_VALUE', $average_title);
1073 $tpl->setVariable(
'AVERAGE_VALUE_PERCENT', $average / $option_count * self::CENTUM);
1076 return $this->wrapInFormContext($component, $component->getLabel(), $tpl->get());
1081 $template = $this->prepareTreeSelectTemplate($component, $default_renderer);
1083 if ($component->canSelectChildNodes()) {
1084 $select_child_nodes =
'true';
1086 $select_child_nodes =
'false';
1089 $enriched_component = $component->withAdditionalOnLoadCode(
1090 static fn(
$id) =>
"il.UI.Input.treeSelect.initTreeMultiSelect('$id', $select_child_nodes);"
1093 $id = $this->bindJSandApplyId($enriched_component, $template);
1095 return $this->wrapInFormContext($component, $component->getLabel(), $template->
get(),
$id);
1100 $template = $this->prepareTreeSelectTemplate($component, $default_renderer);
1102 $enriched_component = $component->withAdditionalOnLoadCode(
1103 static fn(
$id) =>
"il.UI.Input.treeSelect.initTreeSelect('$id');"
1106 $id = $this->bindJSandApplyId($enriched_component, $template);
1108 return $this->wrapInFormContext($component, $component->getLabel(), $template->
get(),
$id);
1111 protected function prepareTreeSelectTemplate(
1113 RendererInterface $default_renderer,
1115 $template = $this->getTemplate(
'tpl.tree_select.html',
true,
true);
1121 $template->
setVariable(
'SELECT_LABEL', $this->txt(
'select'));
1122 $template->
setVariable(
'CLOSE_LABEL', $this->txt(
'close'));
1125 $template->
setVariable(
'INPUT_TEMPLATE', $default_renderer->render(
1128 $template->
setVariable(
'BREADCRUMB_TEMPLATE', $default_renderer->render(
1129 $this->getUIFactory()->breadcrumbs([$this->getUIFactory()->link()->standard(
'label',
'#')])
1131 $template->
setVariable(
'BREADCRUMBS', $default_renderer->render(
1132 $this->getUIFactory()->breadcrumbs([])
1135 $node_factory = $this->getUIFactory()->input()->field()->node();
1138 $this->getUIFactory()->
symbol()->icon(),
1142 foreach ($node_generator as $node) {
1144 $this->checkArgInstanceOf(
'node', $node,
Component\
Input\Field\Node\Node::class);
1148 $template->
setVariable(
'DRILLDOWN', $default_renderer->render(
1149 $this->getUIFactory()->menu()->drilldown($component->
getLabel(), $nodes)
1156 $this->getUIFactory()->input()->field()->node(),
1157 $this->getUIFactory()->symbol()->icon(),
1161 $lockstep_iterator = $this->iterateGeneratorsInLockstep($leaf_generator, $dynamic_inputs_generator);
1163 foreach ($lockstep_iterator as [$leaf, $dynamic_input]) {
1166 $this->checkArgInstanceOf(
'leaf', $leaf, Node\Leaf::class);
1168 $value_template = $this->getTemplate(
'tpl.tree_select.html',
true,
true);
1169 $value_template->setCurrentBlock(
'with_value_template');
1170 $value_template->setVariable(
'NODE_ID', (
string) ($leaf->getId()));
1171 $value_template->setVariable(
'NODE_NAME', $leaf->getName());
1172 $value_template->setVariable(
'INPUT_TEMPLATE', $default_renderer->render($dynamic_input));
1173 $value_template->setVariable(
'UNSELECT_NODE_LABEL', sprintf($this->txt(
'unselect_node'), $leaf->getName()));
1174 $value_template->parseCurrentBlock();
1177 $template->
setVariable(
'VALUE', $value_template->get(
'with_value_template'));
1181 $this->toJS(
'unselect_node');
1182 $this->toJS(
'select_node');
1196 while (
$a->valid() &&
$b->valid()) {
1197 yield [
$a->current(),
$b->current()];
1201 if (
$a->valid() ||
$b->valid()) {
1202 throw new LogicException(
'Generators do not have equal lenghts.');
1211 $template->
setVariable(
'FILE_SIZE_LABEL', $this->txt(
'file_notice'));
1212 $template->
setVariable(
'FILE_SIZE_VALUE',
new DataSize($input->getMaxFileSize(), DataSize::Byte));
1216 $template->
setVariable(
'FILES_LABEL', $this->txt(
'ui_file_upload_max_nr'));
1217 $template->
setVariable(
'FILES_VALUE', $input->getMaxFiles());
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
This class provides the data size with additional information to remove the work to calculate the siz...
A Link is the often used combination of a label and an URL.
A password is used as part of credentials for authentication.
The scope of this class is split ilias-conform URI's into components.
FiveStarRatingScale
This is the scale for the Rating Input.
This implements the text input.
This implements the textarea input.
Base class for all component renderers.
cannotHandleComponent(Component $component)
This method MUST be called by derived component renderers, if.
txt(string $id)
Get a text from the language file.
createId()
Get a fresh unique id.
bindJavaScript(JavaScriptBindable $component)
Bind the component to JavaScript.
getComponentCanonicalNameAttribute(Component $component)
getTemplate(string $name, bool $purge_unfilled_vars, bool $purge_unused_blocks)
Get template of component this renderer is made for.
Interface FileInfoResult.
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.
Registry for resources required by rendered output like Javascript or CSS.
register(string $name)
Add a dependency.
Interface to templating as it is used in the UI framework.
setVariable(string $name, $value)
Set a variable in the current block.
get(?string $block=null)
Get the rendered template or a specific block.
setCurrentBlock(string $name)
Set the block to work on.
parseCurrentBlock()
Parse the block that is currently worked on.
An entity that renders components to a string output.
trait JavaScriptBindable
Trait for components implementing JavaScriptBindable providing standard implementation.
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples