Loading src/Element/ComponentElement.php +96 −5 Original line number Diff line number Diff line Loading @@ -2,7 +2,12 @@ namespace Drupal\cl_components\Element; use Drupal\cl_components\Component\Component; use Drupal\cl_components\Component\ComponentDiscovery; use Drupal\Component\Serialization\Json; use Drupal\Component\Utility\Xss; use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Render\Element\RenderElement; /** Loading Loading @@ -41,18 +46,104 @@ class ComponentElement extends RenderElement { */ public static function preRenderComponent(array $element): array { $variant = $element['#variant'] ?? ''; $component = \Drupal::service(ComponentDiscovery::class)->find($element['#component']); $id = $component->getId(); $embed_id = $variant ? $id . '--' . $variant : $id; $inline_template = '{% include "' . $embed_id . '" %}'; $context_alter_callback = $element['#context_alter_callback'] ?? NULL; $blocks_alter_callback = $element['#blocks_alter_callback'] ?? NULL; $discovery = \Drupal::service(ComponentDiscovery::class); assert($discovery instanceof ComponentDiscovery); $component = $discovery->find($element['#component']); $context = $element['#context'] ?? []; $bubbleable_metadata = new BubbleableMetadata(); $twig_blocks = $element['#twig_blocks'] ?? []; $trusted_blocks = $element['#trusted_blocks'] ?? FALSE; $inline_template = static::generateComponentTemplate( $component, $variant, $twig_blocks, $context, $context_alter_callback, $blocks_alter_callback, $bubbleable_metadata, $trusted_blocks, ); $element['inline-template'] = [ '#type' => 'inline_template', '#template' => $inline_template, '#context' => $element['#context'] ?? [], '#context' => $context, ]; $bubbleable_metadata->applyTo($element['inline-template']); return $element; } /** * Generates the template to render the component. * * @param \Drupal\cl_components\Component\Component $component * The component. * @param mixed $variant * The variant. * @param array $twig_blocks * The contents of any potential embed blocks. * @param array $context * The context data. * @param callable|null $context_alter_callback * The potential callable for altering context. * @param \Drupal\Core\Cache\CacheableMetadata $bubbleable_metadata * The cacheable metadata. * @param bool $trusted_blocks * Set to TRUE to render the twig blocks verbatim instead of filtering them. * * @return string * The template. */ private static function generateComponentTemplate( Component $component, string $variant, array $twig_blocks, array $context, mixed $context_alter_callback, mixed $blocks_alter_callback, CacheableMetadata $bubbleable_metadata, bool $trusted_blocks = FALSE, ): string { $id = $component->getId(); $embed_id = $variant ? $id . '--' . $variant : $id; $template = '{# This template was dynamically generated by cl_block #}' . PHP_EOL; // If there is a context alter callback, execute it here. if (is_callable($context_alter_callback)) { $context = call_user_func($context_alter_callback, $context, $bubbleable_metadata); } $template .= empty($context) ? sprintf('{%% embed \'%s\' %%}', $embed_id) : sprintf('{%% embed \'%s\' with %s %%}', $embed_id, Json::encode($context)); $template .= PHP_EOL; foreach ($twig_blocks as $block_name => $block_value) { $bl_val = is_callable($blocks_alter_callback) ? call_user_func($blocks_alter_callback, $block_value, $bubbleable_metadata) : $block_value; $block_build = $trusted_blocks ? ['#markup' => Xss::filterAdmin($bl_val)] : [ '#type' => 'processed_text', '#text' => $bl_val, '#format' => is_array($block_value) ? $block_value['format'] : NULL, ]; try { $value = \Drupal::service('renderer')->render($block_build); } catch (\Exception $e) { $value = $bl_val; } // Save the collected attachments before we do the stringification. $twig_block_metadata = BubbleableMetadata::createFromRenderArray($block_build); $bubbleable_metadata = $bubbleable_metadata->merge($twig_block_metadata); $template .= " {% block $block_name %}" . PHP_EOL . " $value" . PHP_EOL . " {% endblock %}" . PHP_EOL; } $template .= '{% endembed %}' . PHP_EOL; return $template; } /** * {@inheritdoc} */ Loading Loading
src/Element/ComponentElement.php +96 −5 Original line number Diff line number Diff line Loading @@ -2,7 +2,12 @@ namespace Drupal\cl_components\Element; use Drupal\cl_components\Component\Component; use Drupal\cl_components\Component\ComponentDiscovery; use Drupal\Component\Serialization\Json; use Drupal\Component\Utility\Xss; use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Render\Element\RenderElement; /** Loading Loading @@ -41,18 +46,104 @@ class ComponentElement extends RenderElement { */ public static function preRenderComponent(array $element): array { $variant = $element['#variant'] ?? ''; $component = \Drupal::service(ComponentDiscovery::class)->find($element['#component']); $id = $component->getId(); $embed_id = $variant ? $id . '--' . $variant : $id; $inline_template = '{% include "' . $embed_id . '" %}'; $context_alter_callback = $element['#context_alter_callback'] ?? NULL; $blocks_alter_callback = $element['#blocks_alter_callback'] ?? NULL; $discovery = \Drupal::service(ComponentDiscovery::class); assert($discovery instanceof ComponentDiscovery); $component = $discovery->find($element['#component']); $context = $element['#context'] ?? []; $bubbleable_metadata = new BubbleableMetadata(); $twig_blocks = $element['#twig_blocks'] ?? []; $trusted_blocks = $element['#trusted_blocks'] ?? FALSE; $inline_template = static::generateComponentTemplate( $component, $variant, $twig_blocks, $context, $context_alter_callback, $blocks_alter_callback, $bubbleable_metadata, $trusted_blocks, ); $element['inline-template'] = [ '#type' => 'inline_template', '#template' => $inline_template, '#context' => $element['#context'] ?? [], '#context' => $context, ]; $bubbleable_metadata->applyTo($element['inline-template']); return $element; } /** * Generates the template to render the component. * * @param \Drupal\cl_components\Component\Component $component * The component. * @param mixed $variant * The variant. * @param array $twig_blocks * The contents of any potential embed blocks. * @param array $context * The context data. * @param callable|null $context_alter_callback * The potential callable for altering context. * @param \Drupal\Core\Cache\CacheableMetadata $bubbleable_metadata * The cacheable metadata. * @param bool $trusted_blocks * Set to TRUE to render the twig blocks verbatim instead of filtering them. * * @return string * The template. */ private static function generateComponentTemplate( Component $component, string $variant, array $twig_blocks, array $context, mixed $context_alter_callback, mixed $blocks_alter_callback, CacheableMetadata $bubbleable_metadata, bool $trusted_blocks = FALSE, ): string { $id = $component->getId(); $embed_id = $variant ? $id . '--' . $variant : $id; $template = '{# This template was dynamically generated by cl_block #}' . PHP_EOL; // If there is a context alter callback, execute it here. if (is_callable($context_alter_callback)) { $context = call_user_func($context_alter_callback, $context, $bubbleable_metadata); } $template .= empty($context) ? sprintf('{%% embed \'%s\' %%}', $embed_id) : sprintf('{%% embed \'%s\' with %s %%}', $embed_id, Json::encode($context)); $template .= PHP_EOL; foreach ($twig_blocks as $block_name => $block_value) { $bl_val = is_callable($blocks_alter_callback) ? call_user_func($blocks_alter_callback, $block_value, $bubbleable_metadata) : $block_value; $block_build = $trusted_blocks ? ['#markup' => Xss::filterAdmin($bl_val)] : [ '#type' => 'processed_text', '#text' => $bl_val, '#format' => is_array($block_value) ? $block_value['format'] : NULL, ]; try { $value = \Drupal::service('renderer')->render($block_build); } catch (\Exception $e) { $value = $bl_val; } // Save the collected attachments before we do the stringification. $twig_block_metadata = BubbleableMetadata::createFromRenderArray($block_build); $bubbleable_metadata = $bubbleable_metadata->merge($twig_block_metadata); $template .= " {% block $block_name %}" . PHP_EOL . " $value" . PHP_EOL . " {% endblock %}" . PHP_EOL; } $template .= '{% endembed %}' . PHP_EOL; return $template; } /** * {@inheritdoc} */ Loading