diff --git a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Filter/SearchTerm/SearchTermMatcher.php b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Filter/SearchTerm/SearchTermMatcher.php index 1d3dff96350..cb4b8977753 100644 --- a/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Filter/SearchTerm/SearchTermMatcher.php +++ b/Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Filter/SearchTerm/SearchTermMatcher.php @@ -6,6 +6,7 @@ use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValues; use Neos\ContentRepository\Core\Projection\ContentGraph\Node; +use Neos\ContentRepository\Core\SharedModel\Node\NodeAggregateId; /** * Performs search term check against the nodes properties @@ -16,27 +17,27 @@ class SearchTermMatcher { public static function matchesNode(Node $node, SearchTerm $searchTerm): bool { - return static::matchesSerializedPropertyValues($node->properties->serialized(), $searchTerm); + return static::matchesSerializedPropertyValues($node->properties->serialized(), $searchTerm, $node->aggregateId); } - public static function matchesSerializedPropertyValues(SerializedPropertyValues $serializedPropertyValues, SearchTerm $searchTerm): bool + public static function matchesSerializedPropertyValues(SerializedPropertyValues $serializedPropertyValues, SearchTerm $searchTerm, ?NodeAggregateId $nodeAggregateId = null): bool { if ($searchTerm->term === '') { return true; } - foreach ($serializedPropertyValues as $serializedPropertyValue) { - if (self::matchesValue($serializedPropertyValue->value, $searchTerm)) { + foreach ($serializedPropertyValues as $propertyName => $serializedPropertyValue) { + if (self::matchesValue($serializedPropertyValue->value, $searchTerm, $propertyName, $nodeAggregateId)) { return true; } } return false; } - private static function matchesValue(mixed $value, SearchTerm $searchTerm): bool + private static function matchesValue(mixed $value, SearchTerm $searchTerm, string $propertyName, ?NodeAggregateId $nodeAggregateId): bool { if (is_array($value) || $value instanceof \ArrayObject) { foreach ($value as $subValue) { - if (self::matchesValue($subValue, $searchTerm)) { + if (self::matchesValue($subValue, $searchTerm, $propertyName, $nodeAggregateId)) { return true; } } @@ -44,13 +45,19 @@ private static function matchesValue(mixed $value, SearchTerm $searchTerm): bool } return match (true) { + $value === null => false, is_string($value) => mb_stripos($value, $searchTerm->term) !== false, // the following behaviour might seem odd, but is implemented after how the doctrine adapter filtering is currently implemented is_int($value), is_float($value) => str_contains((string)$value, $searchTerm->term), $value === true => str_contains('true', $searchTerm->term), $value === false => str_contains('false', $searchTerm->term), - default => throw new \InvalidArgumentException(sprintf('Handling for type %s is not implemented.', get_debug_type($value))), + default => throw new \InvalidArgumentException(sprintf( + 'Handling for type %s within property "%s" of node "%s" is not implemented.', + get_debug_type($value), + $propertyName, + $nodeAggregateId?->value ?: 'unknown' + )), }; } } diff --git a/Neos.ContentRepository.Core/Tests/Unit/Projection/ContentGraph/Filter/SearchTerm/SearchTermMatcherTest.php b/Neos.ContentRepository.Core/Tests/Unit/Projection/ContentGraph/Filter/SearchTerm/SearchTermMatcherTest.php index eaf22358166..26d5f418e99 100644 --- a/Neos.ContentRepository.Core/Tests/Unit/Projection/ContentGraph/Filter/SearchTerm/SearchTermMatcherTest.php +++ b/Neos.ContentRepository.Core/Tests/Unit/Projection/ContentGraph/Filter/SearchTerm/SearchTermMatcherTest.php @@ -123,6 +123,7 @@ public function notMatchingExamples(): iterable yield 'array with unmatched string' => ['hello', self::value(['hi'])]; yield 'array key is not considered matching' => ['key', self::value(['key' => 'foo'])]; yield 'nested array key is not considered matching' => ['key', self::value([['key' => 'foo']])]; + yield 'array with null value' => ['foo', self::value([null])]; } /**