Skip to content

Commit

Permalink
Merge pull request #5033 from neos/task/3859-datastructure-tests
Browse files Browse the repository at this point in the history
BUGFIX: Fix handling of unset/nulled DataStructure keys
  • Loading branch information
kitsunet committed May 20, 2024
2 parents fab8256 + 3d1aff1 commit 16744cd
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 1 deletion.
18 changes: 17 additions & 1 deletion Neos.Fusion/Classes/FusionObjects/AbstractArrayFusionObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ protected function evaluateNestedProperties(?string $defaultFusionPrototypeName

$result = [];
foreach ($sortedChildFusionKeys as $key) {
if ($this->isUnset($key)) {
continue;
}
$propertyPath = $key;
if ($defaultFusionPrototypeName !== null && $this->isUntyped($key)) {
$propertyPath .= '<' . $defaultFusionPrototypeName . '>';
Expand Down Expand Up @@ -204,6 +207,17 @@ protected function filterIgnoredProperties(array $properties, array $ignoredProp
return $properties;
}

/**
* Returns TRUE if the given fusion key has been removed via ">"
*
* @param string|int $key fusion child key path to check
* @return bool
*/
protected function isUnset(string|int $key): bool
{
return $this->properties[$key] === ['__stopInheritanceChain' => true];
}

/**
* Returns TRUE if the given fusion key has no type, meaning neither
* having a fusion objectType, eelExpression or value
Expand All @@ -217,6 +231,8 @@ protected function isUntyped(string|int $key): bool
if (!is_array($property)) {
return false;
}
return !isset($property['__objectType']) && !isset($property['__eelExpression']) && !isset($property['__value']);
return !array_key_exists('__objectType', $property)
&& !array_key_exists('__eelExpression', $property)
&& !array_key_exists('__value', $property);
}
}
32 changes: 32 additions & 0 deletions Neos.Fusion/Tests/Functional/FusionObjects/DataStructureTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/

use Neos\Fusion\Exception\MissingFusionImplementationException;
use Neos\Utility\PositionalArraySorter;

/**
* Testcase for the Fusion Dictionary
Expand Down Expand Up @@ -145,4 +146,35 @@ public function unsetUntypedChildKeysWillRenderAsDataStructure(): void
$view->setFusionPath('dataStructure/unsetUntypedChildKeyWillRenderAsDataStructure');
self::assertEquals(['buz' => 456, 'keyWithUnsetType' => ['bat' => 123]], $view->render());
}

/**
* @test
*/
public function unsetChildKeyWillNotRender(): void
{
$view = $this->buildView();
$view->setFusionPath('dataStructure/unsetChildKeyWillNotRender');
self::assertEquals(['foo' => 'bar'], $view->render());
}

/**
* @test
* NOTE: This test mainly documents the current behavior. "null1" is removed by the {@see PositionalArraySorter} currently
*/
public function nulledChildKeyWillRenderAsNull(): void
{
$view = $this->buildView();
$view->setFusionPath('dataStructure/nulledChildKeyWillRenderAsNull');
self::assertEquals(['foo' => 'bar', 'null2' => null], $view->render());
}

/**
* @test
*/
public function appliedNullValueWillRenderAsNull(): void
{
$view = $this->buildView();
$view->setFusionPath('dataStructure/appliedNullValueWillRenderAsNull');
self::assertEquals(['nullAttribute' => null], $view->render());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,20 @@ dataStructure.unsetUntypedChildKeyWillRenderAsDataStructure = Neos.Fusion:DataSt
}
buz = 456
}

dataStructure.unsetChildKeyWillNotRender = Neos.Fusion:DataStructure {
foo = 'bar'
baz >
}

dataStructure.nulledChildKeyWillRenderAsNull = Neos.Fusion:DataStructure {
foo = 'bar'
null1 = null
null2 = ${null}
}

dataStructure.appliedNullValueWillRenderAsNull = Neos.Fusion:DataStructure {
@apply.attributes = ${{
nullAttribute: null
}}
}
78 changes: 78 additions & 0 deletions Neos.Neos/Tests/Behavior/Features/Fusion/DataStructure.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
@fixtures
Feature: Tests for the "Neos.Fusion:DataStructure" Fusion prototype

Background:
Given I have the following Fusion setup:
"""fusion
include: resource://Neos.Fusion/Private/Fusion/Root.fusion
include: resource://Neos.Neos/Private/Fusion/Root.fusion
prototype(Neos.Neos:Test.DataStructure.Example) < prototype(Neos.Fusion:DataStructure) {
foo = 'string'
bar {
baz = true
foos {
bars = 123
removed >
null1 = null
null2 = ${null}
}
}
}
"""

Scenario: DataStructure (default)
When I execute the following Fusion code:
"""fusion
test = Neos.Neos:Test.DataStructure.Example {
@process.toJson = ${Json.stringify(value)}
}
"""
Then I expect the following Fusion rendering result:
"""
{"foo":"string","bar":{"baz":true,"foos":{"bars":123,"null2":null}}}
"""

Scenario: DataStructure (with nulled keys)
When I execute the following Fusion code:
"""fusion
test = Neos.Neos:Test.DataStructure.Example {
added = 123.45
bar.foos >
@process.toJson = ${Json.stringify(value)}
}
"""
Then I expect the following Fusion rendering result:
"""
{"foo":"string","bar":{"baz":true},"added":123.45}
"""

Scenario: DataStructure (with removed keys)
When I execute the following Fusion code:
"""fusion
test = Neos.Neos:Test.DataStructure.Example {
added = 123.45
bar.foos >
@process.toJson = ${Json.stringify(value)}
}
"""
Then I expect the following Fusion rendering result:
"""
{"foo":"string","bar":{"baz":true},"added":123.45}
"""

# @see https://github.com/neos/neos-development-collection/issues/3859
Scenario: DataStructure (applied null keys)
When I execute the following Fusion code:
"""fusion
test = Neos.Fusion:DataStructure {
@apply.attributes = ${{
nullAttribute: null
}}
@process.toJson = ${Json.stringify(value)}
}
"""
Then I expect the following Fusion rendering result:
"""
{"nullAttribute":null}
"""

0 comments on commit 16744cd

Please sign in to comment.