-
-
Notifications
You must be signed in to change notification settings - Fork 224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FEATURE: Add PropertyValueCriteriaMatcher
#4701
Merged
ahaeslich
merged 7 commits into
neos:9.0
from
mficzel:90/addProppertyValueCriteriaMatcher
Mar 11, 2024
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
b28aeb1
FEATURE: Add ``PropertyValueCriteriaMatcher``
mficzel d887854
Update Neos.ContentRepository.Core/Classes/Projection/ContentGraph/Fi…
mficzel 41f89df
TASK: Simplify implementation and avoid passing around function which…
mficzel d667d7d
BUGFIX: Use strict comparison for quals operation
mficzel 94b42fc
TASK: Move public matches node method to the top
mficzel 5e6c640
TASK: Add methods `matchesSerializedPropertyValues`
mficzel 893d6e6
TASK: Use empty `PropertyConverter` instead of `$subjectProvider->pro…
mhsdesign File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
105 changes: 105 additions & 0 deletions
105
...ore/Classes/Projection/ContentGraph/Filter/PropertyValue/PropertyValueCriteriaMatcher.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue; | ||
|
||
use Neos\ContentRepository\Core\Feature\NodeModification\Dto\SerializedPropertyValues; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\AndCriteria; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\NegateCriteria; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\OrCriteria; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\PropertyValueContains; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\PropertyValueCriteriaInterface; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\PropertyValueEndsWith; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\PropertyValueEquals; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\PropertyValueGreaterThan; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\PropertyValueGreaterThanOrEqual; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\PropertyValueLessThan; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\PropertyValueLessThanOrEqual; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue\Criteria\PropertyValueStartsWith; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\Node; | ||
use Neos\ContentRepository\Core\Projection\ContentGraph\PropertyCollection; | ||
|
||
/** | ||
* Performs property checks against a given set of constraints | ||
* | ||
* @internal | ||
*/ | ||
final class PropertyValueCriteriaMatcher | ||
{ | ||
public static function matchesNode(Node $node, PropertyValueCriteriaInterface $propertyValueCriteria): bool | ||
{ | ||
return static::matchesSerializedPropertyValues($node->properties->serialized(), $propertyValueCriteria); | ||
} | ||
|
||
public static function matchesPropertyCollection(PropertyCollection $propertyCollection, PropertyValueCriteriaInterface $propertyValueCriteria): bool | ||
{ | ||
return static::matchesSerializedPropertyValues($propertyCollection->serialized(), $propertyValueCriteria); | ||
} | ||
|
||
public static function matchesSerializedPropertyValues(SerializedPropertyValues $serializedPropertyValues, PropertyValueCriteriaInterface $propertyValueCriteria): bool | ||
{ | ||
return match ($propertyValueCriteria::class) { | ||
AndCriteria::class => self::matchesSerializedPropertyValues($serializedPropertyValues, $propertyValueCriteria->criteria1) | ||
&& self::matchesSerializedPropertyValues($serializedPropertyValues, $propertyValueCriteria->criteria2), | ||
OrCriteria::class => self::matchesSerializedPropertyValues($serializedPropertyValues, $propertyValueCriteria->criteria1) | ||
|| self::matchesSerializedPropertyValues($serializedPropertyValues, $propertyValueCriteria->criteria2), | ||
NegateCriteria::class => !self::matchesSerializedPropertyValues($serializedPropertyValues, $propertyValueCriteria->criteria), | ||
PropertyValueContains::class => self::propertyValueContains($serializedPropertyValues, $propertyValueCriteria), | ||
PropertyValueEndsWith::class => self::propertyValueEndsWith($serializedPropertyValues, $propertyValueCriteria), | ||
PropertyValueStartsWith::class => self::propertyValueStartsWith($serializedPropertyValues, $propertyValueCriteria), | ||
PropertyValueEquals::class => self::propertyValueEquals($serializedPropertyValues, $propertyValueCriteria), | ||
PropertyValueGreaterThan::class => $serializedPropertyValues->propertyExists($propertyValueCriteria->propertyName->value) | ||
&& $serializedPropertyValues->getProperty($propertyValueCriteria->propertyName->value)?->value > $propertyValueCriteria->value, | ||
PropertyValueGreaterThanOrEqual::class => $serializedPropertyValues->propertyExists($propertyValueCriteria->propertyName->value) | ||
&& $serializedPropertyValues->getProperty($propertyValueCriteria->propertyName->value)?->value >= $propertyValueCriteria->value, | ||
PropertyValueLessThan::class => $serializedPropertyValues->propertyExists($propertyValueCriteria->propertyName->value) | ||
&& $serializedPropertyValues->getProperty($propertyValueCriteria->propertyName->value)?->value < $propertyValueCriteria->value, | ||
PropertyValueLessThanOrEqual::class => $serializedPropertyValues->propertyExists($propertyValueCriteria->propertyName->value) | ||
&& $serializedPropertyValues->getProperty($propertyValueCriteria->propertyName->value)?->value <= $propertyValueCriteria->value, | ||
default => throw new \InvalidArgumentException(sprintf('Invalid/unsupported property value criteria "%s"', get_debug_type($propertyValueCriteria)), 1679561073), | ||
}; | ||
} | ||
|
||
private static function propertyValueContains(SerializedPropertyValues $serializedPropertyValues, PropertyValueContains $propertyValueCriteria): bool | ||
{ | ||
$propertyValue = $serializedPropertyValues->getProperty($propertyValueCriteria->propertyName->value)?->value; | ||
if ($propertyValueCriteria->caseSensitive) { | ||
return is_string($propertyValue) ? str_contains($propertyValue, $propertyValueCriteria->value) : false; | ||
} else { | ||
return is_string($propertyValue) ? str_contains(mb_strtolower($propertyValue), mb_strtolower($propertyValueCriteria->value)) : false; | ||
} | ||
} | ||
|
||
private static function propertyValueStartsWith(SerializedPropertyValues $serializedPropertyValues, PropertyValueStartsWith $propertyValueCriteria): bool | ||
{ | ||
$propertyValue = $serializedPropertyValues->getProperty($propertyValueCriteria->propertyName->value)?->value; | ||
if ($propertyValueCriteria->caseSensitive) { | ||
return is_string($propertyValue) ? str_starts_with($propertyValue, $propertyValueCriteria->value) : false; | ||
} else { | ||
return is_string($propertyValue) ? str_starts_with(mb_strtolower($propertyValue), mb_strtolower($propertyValueCriteria->value)) : false; | ||
} | ||
} | ||
|
||
private static function propertyValueEndsWith(SerializedPropertyValues $serializedPropertyValues, PropertyValueEndsWith $propertyValueCriteria): bool | ||
{ | ||
$propertyValue = $serializedPropertyValues->getProperty($propertyValueCriteria->propertyName->value)?->value; | ||
if ($propertyValueCriteria->caseSensitive) { | ||
return is_string($propertyValue) ? str_ends_with($propertyValue, $propertyValueCriteria->value) : false; | ||
} else { | ||
return is_string($propertyValue) ? str_ends_with(mb_strtolower($propertyValue), mb_strtolower($propertyValueCriteria->value)) : false; | ||
} | ||
} | ||
|
||
private static function propertyValueEquals(SerializedPropertyValues $serializedPropertyValues, PropertyValueEquals $propertyValueCriteria): bool | ||
{ | ||
if (!$serializedPropertyValues->propertyExists($propertyValueCriteria->propertyName->value)) { | ||
return false; | ||
} | ||
$propertyValue = $serializedPropertyValues->getProperty($propertyValueCriteria->propertyName->value)?->value; | ||
if ($propertyValueCriteria->caseSensitive) { | ||
return $propertyValue === $propertyValueCriteria->value; | ||
} | ||
return (is_string($propertyValue) ? mb_strtolower($propertyValue) : $propertyValue) === (is_string($propertyValueCriteria->value) ? mb_strtolower($propertyValueCriteria->value) : $propertyValueCriteria->value); | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i like to propose to use here as first parameter the serialised node properties directly. Using the higher level object is not necessary and might even introduce bugs as the matching should only happen on the serialised properties. Also it will be easier to test.
A last testrun is now triggered at #4898 but i assume everything will be green and youll get my approval :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this is an actual benefit. In which usecase would one have serialized properties but not the propertyCollection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Introduded
matchesSerializedPropertyValues
as separate method that is used bymatchNode
andmatchPropertyCollection
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thänks. My reasoning here was just simply that when developing i came mostly across the
SerializedPropertyValues
and not the abstraction of thePropertyCollection
which is not always available and harder to construct as it needs the serialiser. Also by passing in the serialised properties it becomes more obvious that the filtering happens on that level..