Unverified Commit 24a87045 authored by Mateu Aguiló Bosch's avatar Mateu Aguiló Bosch Committed by Mateu Aguiló Bosch
Browse files

Issue #3309297 by e0ipso: Support loading components via identifier instead of path

parent 03450efc
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -107,11 +107,11 @@ in [the documentation](https://git.drupalcode.org/project/cl_components/-/blob/1

#### With the traditional syntax: `include` or `embed`

Just provide the path to the template of the component. CL Components will check
if the template is for a components, and add the CSS & JS if it is. Example:
Just provide the ID of the component. CL Components will check if the template
is for a components, and add the CSS & JS if it is. Example:

```twig
{% include "@cl_components_examples/components/my-button/my-button--primary.twig" with {
{% include "my-button--primary" with {
  text: 'Click Me',
  iconType: 'external'
} %}
+2 −2
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ stories:
      header: I am a header!
      card_body: |
        <p>I am the <em>card</em> contents.</p>
        {% include '@cl_components_examples/components/my-button/my-button.twig' with { text: 'Learn more', iconType: 'external' } %}
        {% include 'my-button' with { text: 'Learn more', iconType: 'external' } %}
  - name: Light
    parameters:
      options:
@@ -14,4 +14,4 @@ stories:
      header: I am a header!
      card_body: |
        <p>I am the <em>card</em> contents.</p>
        {% include '@cl_components_examples/components/my-button/my-button.twig' with { text: 'Learn more', iconType: 'external' } %}
        {% include 'my-button' with { text: 'Learn more', iconType: 'external' } %}
+53 −1
Original line number Diff line number Diff line
@@ -181,7 +181,7 @@ class ComponentLoader extends FilesystemLoader {
   * @param string $name
   *   The template name as provided in the include/embed.
   *
   * @return array
   * @return array [string, string]
   *   The component ID and variant.
   *
   * @throws \Twig\Error\LoaderError
@@ -190,6 +190,25 @@ class ComponentLoader extends FilesystemLoader {
    if (isset($this->idVariantCache[$name])) {
      return $this->idVariantCache[$name];
    }
    $id_and_variant = $this->parseIdAndVariantByIdSyntax($name);
    if (!empty($id_and_variant)) {
      return $id_and_variant;
    }
    return $this->parseIdAndVariantByPath($name);
  }

  /**
   * Parses the ID and variant from the component path.
   *
   * @param string $name
   *   The template name.
   *
   * @return array [string, string]
   *   The component ID and variant.
   *
   * @throws \Twig\Error\LoaderError
   */
  private function parseIdAndVariantByPath(string $name): array {
    $path = parent::findTemplate($name);
    // Check if there is a metadata.json in the same directory.
    $dir = dirname($path);
@@ -227,4 +246,37 @@ class ComponentLoader extends FilesystemLoader {
    return [$id, $variant];
  }

  /**
   * Tries to load a component using the provided name as the component ID.
   *
   * @param string $name
   *   The template's name.
   *
   * @return array|null
   *   The ID and variant, or NULL if not found.
   */
  private function parseIdAndVariantByIdSyntax(string $name): ?array {
    // First check if we can parse the prefix and variant from the name.
    $id = $name;
    $variant = '';
    if (str_contains($name, '--')) {
      [$id, $variant] = explode('--', $id);
    }
    if (empty($id)) {
      return NULL;
    }
    try {
      $component = $this->componentDiscovery->find($id);
    }
    catch (ComponentNotFoundException $e) {
      return NULL;
    }
    $available_variants = $component->getVariants();
    if (!empty($variant) && !in_array($variant, $available_variants, TRUE)) {
      return NULL;
    }
    $this->idVariantCache[$name] = [$id, $variant];
    return [$id, $variant];
  }

}
+3 −3
Original line number Diff line number Diff line
@@ -38,13 +38,13 @@ class ComponentElement extends RenderElement {
   *   The form element.
   *
   * @throws \Drupal\cl_components\Exception\ComponentNotFoundException
   * @throws \Drupal\cl_components\Exception\TemplateNotFoundException
   */
  public static function preRenderComponent(array $element): array {
    $variant = $element['#variant'] ?? '';
    $component = \Drupal::service(ComponentDiscovery::class)->find($element['#component']);
    $template_path = $component->getMetadata()->getPath() . DIRECTORY_SEPARATOR . $component->getTemplateName($variant);
    $inline_template = '{% include "' . $template_path . '" %}';
    $id = $component->getId();
    $embed_id = $variant ? $id . '--' . $variant : $id;
    $inline_template = '{% include "' . $embed_id . '" %}';
    $element['inline-template'] = [
      '#type' => 'inline_template',
      '#template' => $inline_template,