Skip to content

Commit

Permalink
Use outerScope variable instead of Hierarchy object
Browse files Browse the repository at this point in the history
  • Loading branch information
sneakyvv committed Sep 9, 2023
1 parent 62810c5 commit 6db02ad
Show file tree
Hide file tree
Showing 8 changed files with 12 additions and 207 deletions.
13 changes: 4 additions & 9 deletions src/TwigComponent/src/ComponentRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,21 +116,16 @@ private function preRender(MountedComponent $mounted, array $context = []): PreR
}

$component = $mounted->getComponent();

// add the "parent" component when rendering a nested embedded component
if (isset($context[PreRenderEvent::EMBEDDED]) && true === $context[PreRenderEvent::EMBEDDED] && isset($context['this'])) {
$hierarchy = $context['this'] instanceof Hierarchy ? $context['this'] : new Hierarchy($context['this']);
if (isset($context['this'])) {
$hierarchy = $hierarchy->add($component);
}
}
$metadata = $this->factory->metadataFor($mounted->getName());
$variables = array_merge(
// first so values can be overridden
$context,

// keep reference to old context
['outerScope' => $context],

// add the component as "this"
['this' => $hierarchy ?? $component],
['this' => $component],

// add computed properties proxy
['computed' => new ComputedPropertiesProxy($component)],
Expand Down
53 changes: 0 additions & 53 deletions src/TwigComponent/src/Hierarchy.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
I can access my own properties: {{ divComponentName }}.
I can access the id of the Generic Element: {{ id }}.
This refers to the Generic Element: {{ this.someFunction }}.
To access my own functions I can use this.parent: {{ this.parent.someFunction }}.
To access my own functions I can use outerScope.this: {{ outerScope.this.someFunction }}.
I have access to outer context variables like {{ name }}.
{{ block(outerBlocks.content) }}
</twig:GenericElement>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
And of course the properties from DivComponentWrapper: {{ divComponentWrapperName }}.
The less obvious thing is that at this level "this" refers to the component where the content block is used, i.e. the Generic Element.
Therefore, functions through this will be {{ this.someFunction }}.
Calls to this.parent will be {{ this.parent.someFunction }}.
Calls to outerScope.this will be {{ outerScope.this.someFunction }}.
{{ block(outerBlocks.content) }}
</twig:DivComponent5>
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
Even I can access the id from Generic Element as well: {{ id }}.
Even I can access the properties from DivComponent as well: {{ divComponentName }}.
Even I can access the properties from DivComponentWrapper as well: {{ divComponentWrapperName }}.
Even I can access the functions of DivComponent via this.parent: {{ this.parent.someFunction }}.
Since we are nesting two levels deep, calls to this.parent.parent will be {{ this.parent.parent.someFunction }}.
Even I can access the functions of DivComponent via outerScope.this: {{ outerScope.this.someFunction }}.
Since we are nesting two levels deep, calls to outerScope.outerScope.this will be {{ outerScope.outerScope.this.someFunction }}.
</twig:DivComponentWrapper3>
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<twig:GenericElement element="div" class="divComponent">
{{ this.parent.foo }}
{{ outerScope.this.foo }}
</twig:GenericElement>
6 changes: 3 additions & 3 deletions src/TwigComponent/tests/Integration/EmbeddedComponentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,19 +140,19 @@ public function testPassingDownBlocksMultipleLevelsNeedsToBeDoneManually(): void

/**
* Rule 12: Blocks defined within an embedded component can access the context of the block they are replacing.
* Rule 13: Blocks defined within an embedded component can access the context of components up the hierarchy (up to their own level) via "this.parent".
* Rule 13: Blocks defined within an embedded component can access the context of components up the hierarchy (up to their own level) via "outerScope".
*/
public function testBlockDefinitionCanAccessTheContextOfTheDestinationBlocks(): void
{
$this->assertStringContainsStringIgnoringIndentation(
'<div class="divComponent">I can access my own properties: foo.I can access the id of the Generic Element: symfonyIsAwesome.This refers to the Generic Element: calling GenericElement.To access my own functions I can use this.parent: calling DivComponent.I have access to outer context variables like Fabien.I can access the id from Generic Element as well: symfonyIsAwesome.I can access the properties from DivComponent as well: foo.And of course the properties from DivComponentWrapper: bar.The less obvious thing is that at this level "this" refers to the component where the content block is used, i.e. the Generic Element.Therefore, functions through this will be calling GenericElement.Calls to this.parent will be calling DivComponent.Even I can access the id from Generic Element as well: symfonyIsAwesome.Even I can access the properties from DivComponent as well: foo.Even I can access the properties from DivComponentWrapper as well: bar.Even I can access the functions of DivComponent via this.parent: calling DivComponent.Since we are nesting two levels deep, calls to this.parent.parent will be calling DivComponentWrapper.<span class="foo">The Generic Element default foo block</span></div>',
'<div class="divComponent">I can access my own properties: foo.I can access the id of the Generic Element: symfonyIsAwesome.This refers to the Generic Element: calling GenericElement.To access my own functions I can use outerScope.this: calling DivComponent.I have access to outer context variables like Fabien.I can access the id from Generic Element as well: symfonyIsAwesome.I can access the properties from DivComponent as well: foo.And of course the properties from DivComponentWrapper: bar.The less obvious thing is that at this level "this" refers to the component where the content block is used, i.e. the Generic Element.Therefore, functions through this will be calling GenericElement.Calls to outerScope.this will be calling DivComponent.Even I can access the id from Generic Element as well: symfonyIsAwesome.Even I can access the properties from DivComponent as well: foo.Even I can access the properties from DivComponentWrapper as well: bar.Even I can access the functions of DivComponent via outerScope.this: calling DivComponent.Since we are nesting two levels deep, calls to outerScope.outerScope.this will be calling DivComponentWrapper.<span class="foo">The Generic Element default foo block</span></div>',
self::getContainer()->get(Environment::class)->render('embedded_component_blocks_context.html.twig')
);
}

public function testAccessingTheHierarchyTooHighThrowsAnException(): void
{
$this->expectExceptionMessage('Neither the property "parent" nor one of the methods "parent()", "getparent()"/"isparent()"/"hasparent()" or "__call()" exist');
$this->expectExceptionMessage('Key "this" for array with keys "app, __embedded" does not exist.');
self::getContainer()->get(Environment::class)->render('embedded_component_hierarchy_exception.html.twig');
}

Expand Down
137 changes: 0 additions & 137 deletions src/TwigComponent/tests/Unit/HierarchyTest.php

This file was deleted.

0 comments on commit 6db02ad

Please sign in to comment.