ComponentsTwigExtension.php

Same filename in other branches
  1. 10 core/lib/Drupal/Core/Template/ComponentsTwigExtension.php

Namespace

Drupal\Core\Template

File

core/lib/Drupal/Core/Template/ComponentsTwigExtension.php

View source
<?php

namespace Drupal\Core\Template;

use Drupal\Core\Plugin\Component;
use Drupal\Core\Render\Component\Exception\ComponentNotFoundException;
use Drupal\Core\Render\Component\Exception\InvalidComponentException;
use Drupal\Core\Theme\Component\ComponentValidator;
use Drupal\Core\Theme\ComponentPluginManager;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

/**
 * The twig extension so Drupal can recognize the new code.
 *
 * @internal
 */
final class ComponentsTwigExtension extends AbstractExtension {
    
    /**
     * Creates TwigExtension.
     *
     * @param \Drupal\Core\Theme\ComponentPluginManager $pluginManager
     *   The component plugin manager.
     * @param \Drupal\Core\Theme\Component\ComponentValidator $componentValidator
     *   The component validator.
     */
    public function __construct(ComponentPluginManager $pluginManager, ComponentValidator $componentValidator) {
    }
    
    /**
     * {@inheritdoc}
     */
    public function getNodeVisitors() : array {
        return [
            new ComponentNodeVisitor($this->pluginManager),
        ];
    }
    
    /**
     * {@inheritdoc}
     */
    public function getFunctions() : array {
        return [
            new TwigFunction('add_component_context', [
                $this,
                'addAdditionalContext',
            ], [
                'needs_context' => TRUE,
            ]),
            new TwigFunction('validate_component_props', [
                $this,
                'validateProps',
            ], [
                'needs_context' => TRUE,
            ]),
        ];
    }
    
    /**
     * Appends additional context to the template based on the template id.
     *
     * @param array &$context
     *   The context.
     * @param string $component_id
     *   The component ID.
     *
     * @throws \Drupal\Core\Render\Component\Exception\ComponentNotFoundException
     */
    public function addAdditionalContext(array &$context, string $component_id) : void {
        $context = $this->mergeAdditionalRenderContext($this->pluginManager
            ->find($component_id), $context);
    }
    
    /**
     * Calculates additional context for this template.
     *
     * @param \Drupal\Core\Plugin\Component $component
     *   The component.
     * @param array $context
     *   The context to update.
     *
     * @return array
     *   The additional context to inject to component templates.
     */
    protected function mergeAdditionalRenderContext(Component $component, array $context) : array {
        $context['componentMetadata'] = $component->metadata
            ->normalize();
        $component_attributes = [
            'data-component-id' => $component->getPluginId(),
        ];
        if (!isset($context['attributes'])) {
            $context['attributes'] = new Attribute($component_attributes);
        }
        elseif ($context['attributes'] instanceof Attribute) {
            $context['attributes']->merge(new Attribute($component_attributes));
        }
        return $context;
    }
    
    /**
     * Validates the props in development environments.
     *
     * @param array $context
     *   The context provided to the component.
     * @param string $component_id
     *   The component ID.
     *
     * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
     */
    public function validateProps(array &$context, string $component_id) : void {
        assert($this->doValidateProps($context, $component_id));
    }
    
    /**
     * Performs the actual validation of the schema for the props.
     *
     * @param array $context
     *   The context provided to the component.
     * @param string $component_id
     *   The component ID.
     *
     * @return bool
     *   TRUE if it's valid.
     *
     * @throws \Drupal\Core\Render\Component\Exception\InvalidComponentException
     */
    protected function doValidateProps(array $context, string $component_id) : bool {
        try {
            return $this->componentValidator
                ->validateProps($context, $this->pluginManager
                ->find($component_id));
        } catch (ComponentNotFoundException $e) {
            throw new InvalidComponentException($e->getMessage(), $e->getCode(), $e);
        }
    }

}

Classes

Title Deprecated Summary
ComponentsTwigExtension The twig extension so Drupal can recognize the new code.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.