Problem/Motivation

The validate_component_props Twig function is added twice - for the main template and extended (internally in Twig). But the extended template should not be validated, since it will contain only limited information if the only keyword is used in combination with embed.

Steps to reproduce

You can see the simple example in the 3464-failtest branch. Calling the component ({% embed 'sdc_test:wrapper' with { text: 'Test' } only %}{% endembed %}) with an embed and only keywords leads to WSOD.

NOTICE: PHP message: Uncaught PHP Exception Drupal\Core\Render\Component\Exception\InvalidComponentException: "[text] The property text is required" at /var/www/html/core/lib/Drupal/Core/Theme/Component/ComponentValidator.php line 203
2024-07-30T15:19:02.149398187Z 192.168.192.7 -  30/Jul/2024:15:19:01 +0000 "GET /index.php" 500

But as you can see, the property has been passed.

The next part can be inaccurate.

When Twig renders {% embed 'foo' only %}{% endembed %}, it internally creates something like include 'foo' extends 'foo', which leads to the 'foo' template being processed twice. So the \Drupal\Core\Template\ComponentNodeVisitor will be called on that template twice, and both "templates" will receive a Twig function validate_component_props, which basically validates the component. However, the extended template only receives basic information, because of the only token, which leads to a validation error of the component schema.

Proposed resolution

\Drupal\Core\Template\ComponentNodeVisitor::leaveNode should leave the node if it is a child of another one. The problem "call" will contain parent element. Without it, the extended template will pass all the other checks, because the name will be a proper component plugin with a schema, but the context will be empty.

Issue fork drupal-3464719

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

Niklan created an issue. See original summary.

niklan’s picture

Issue summary: View changes
smustgrave’s picture

Status: Needs review » Active

@Niklan mean to open an MR?

niklan’s picture

I'm not sure what I should add/change in MR at this point. I can't understand where this bug comes from. It seems to me that it is potentially a bug in Twig itself. I'm not familiar with Twig's internal code, but I think I should try to find out where the template is compiled to find out why it compiles it with a wrong template reference which leads to a recursion.

I just don't know where to approach this task. It's definitely not a ComponentValidator problem. Everything hints and leads to Twig. Basically, that 'example:foo' component tried to be rendered twice, while it is a single call. And the second call comes from a wrong Twig compiled template, which is a little hard to follow and understand, so I want to try to find out where and how these templates are built in the first place.

Maybe I'll try to make a failtest later.

smustgrave’s picture

If you’re on slack #components or #ui_patterns someone may be able to help.

niklan’s picture

Added a failtest which highlights the issue as well: https://git.drupalcode.org/issue/drupal-3464719/-/jobs/2292129#L3250

pdureau’s picture

If you’re on slack #components or #ui_patterns someone may be able to help.

Not #ui_patterns but #ui-suite-initiative ;)

pdureau’s picture

If the issue is not specific to SDC (which is resolving template path from component ID: {% embed 'sdc_test:no-props' only %} ) and can be reproduce with normal Twig "embed" (calling directly a template path), the fix must be proposed directly at https://github.com/twigphp/Twig

niklan’s picture

Did a quick and dirty test with just Twig, and it works fine.

script.php:

<?php

use Twig\Environment;
use Twig\Loader\FilesystemLoader;

$loader = new FilesystemLoader(__DIR__ . '/templates');
$twig = new Environment($loader, [
  'cache' => __DIR__ . '/cache',
]);
echo $twig->render('foo.twig');

./templates/foo.twig:

<div class="wrapper">
  {% embed 'bar.twig' with {} only %}{% endembed %}
</div>

./templates/bar.twig:

Hello from Bar!

Output:

$ drush scr var/scripts/twig/test.php 
<div class="wrapper">
  Hello from Bar!
</div>

niklan’s picture

Status: Active » Needs review

I'm almost given up, but found a major clue. It seems that \Drupal\Core\Template\ComponentNodeVisitor::leaveNode should exit if the node has a parent.

It seems like when you render a node with a parent set, this filter validate_component_props receives a wrong context, which leads to an exception during validation.

I've tested locally, and everything seems to be working fine now.

niklan’s picture

Well, the pipeline confirms that it fixes a problem and doesn't break anything else (at least what has been tested). On my project, everything works as expected now as well. Honestly, for me, it is hard to explain why this helps.

Just an assumption from debugging: It looks like such components are represented twice in the Twig Node Tree, one of them is some kind of container (wrapper), it doesn't have a payload with variables, but \Drupal\Core\Template\ComponentNodeVisitor::leaveNode still adds a validation function to it, which leads to an exception. Twig also adds 'extends' to 'embed' tag, which can also be a potential hint to a source of the problem. It internally compiles something like include 'sdc_test:wrapper' extends 'sdc_test:wrapper', and that extends have a different context, but passing checks for component name in \Drupal\Core\Template\ComponentNodeVisitor::leaveNode.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative, +Needs issue summary update

Hello could the issue summary be completed to include the proposed solution section of the default template please

Thanks

niklan’s picture

Issue summary: View changes
Status: Needs work » Needs review

Updated summary and simplified it a little, since there is a failtest and a possible solution exists.

niklan’s picture

Issue summary: View changes

smustgrave changed the visibility of the branch 3464719-failtest to hidden.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs issue summary update

Thanks! Removing issue summary tag

  1) Drupal\KernelTests\Components\ComponentRenderTest::testWrapperComponent
    Twig\Error\RuntimeError: An exception has been thrown during the rendering
    of a template ("[text] The property text is required").

Shows test coverage

Didn't see anything in the code that needed tweak.

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: +Needs subsystem maintainer review

Reading the code I'm wondering if this change will lead to things not happening that should. What about the attach_library call? Going to ping @e0ipso to have a look as SDC maintainer.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new1.84 KB

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

smustgrave’s picture

Status: Needs work » Needs review

False positive

e0ipso’s picture

Status: Needs review » Postponed (maintainer needs more info)

Can we check weather the fix in #3446933: SDC incorrectly throws an exception about embedded slots also fixes this?

niklan’s picture

Tested locally and it seems to have resolved the issue as well.

smustgrave’s picture

Status: Postponed (maintainer needs more info) » Closed (duplicate)

Going to close this one as a duplicate and everyone seemed to help so checking all credit.