Skip to content

Commit

Permalink
FEATURE: Add PropertyValueCriteriaMatcher
Browse files Browse the repository at this point in the history
The property value criteria matcher accepts a ``PropertyValueCriteriaInterface`` and
provides static methods to check wether a ``Node`` or a ``PropertyCollection`` matches those criteria.
  • Loading branch information
mficzel committed Nov 3, 2023
1 parent a0db8af commit d0e65c5
Show file tree
Hide file tree
Showing 3 changed files with 423 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,9 @@ public function splitByScope(NodeType $nodeType): array
);
}

/**
* @phpstan-assert-if-true !null $this->getProperty()
*/
public function propertyExists(string $propertyName): bool
{
return isset($this->values[$propertyName]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

declare(strict_types=1);

namespace Neos\ContentRepository\Core\Projection\ContentGraph\Filter\PropertyValue;

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 matchesPropertyCollection(PropertyCollection $propertyCollection, PropertyValueCriteriaInterface $propertyValueCriteria): bool
{
switch (true) {
case $propertyValueCriteria instanceof AndCriteria:
return self::matchesPropertyCollection($propertyCollection, $propertyValueCriteria->criteria1) && self::matchesPropertyCollection($propertyCollection, $propertyValueCriteria->criteria2);
case $propertyValueCriteria instanceof OrCriteria:
return self::matchesPropertyCollection($propertyCollection, $propertyValueCriteria->criteria1) || self::matchesPropertyCollection($propertyCollection, $propertyValueCriteria->criteria2);
case $propertyValueCriteria instanceof NegateCriteria:
return !self::matchesPropertyCollection($propertyCollection, $propertyValueCriteria->criteria);
case $propertyValueCriteria instanceof PropertyValueContains:
$propertyValue = $propertyCollection->serialized()->getProperty($propertyValueCriteria->propertyName->value)->value;
return is_string($propertyValue)
? str_contains((string)$propertyValue, $propertyValueCriteria->value)
: false;
case $propertyValueCriteria instanceof PropertyValueEndsWith:
$propertyValue = $propertyCollection->serialized()->getProperty($propertyValueCriteria->propertyName->value)->value;
return is_string($propertyValue) ?
str_ends_with((string)$propertyValue, $propertyValueCriteria->value)
: false;
case $propertyValueCriteria instanceof PropertyValueStartsWith:
$propertyValue = $propertyCollection->serialized()->getProperty($propertyValueCriteria->propertyName->value)->value;
return (is_string($propertyValue) || $propertyValue instanceof \Stringable)
? str_starts_with((string)$propertyValue, $propertyValueCriteria->value)
: false;
case $propertyValueCriteria instanceof PropertyValueEquals:
return $propertyCollection->serialized()->propertyExists($propertyValueCriteria->propertyName->value)
&& $propertyCollection->serialized()->getProperty($propertyValueCriteria->propertyName->value)->value == $propertyValueCriteria->value;
case $propertyValueCriteria instanceof PropertyValueGreaterThan:
return $propertyCollection->serialized()->propertyExists($propertyValueCriteria->propertyName->value)
&& $propertyCollection->serialized()->getProperty($propertyValueCriteria->propertyName->value)->value > $propertyValueCriteria->value;
case $propertyValueCriteria instanceof PropertyValueGreaterThanOrEqual:
return $propertyCollection->serialized()->propertyExists($propertyValueCriteria->propertyName->value)
&& $propertyCollection->serialized()->getProperty($propertyValueCriteria->propertyName->value)->value >= $propertyValueCriteria->value;
case $propertyValueCriteria instanceof PropertyValueLessThan:
return $propertyCollection->serialized()->propertyExists($propertyValueCriteria->propertyName->value)
&& $propertyCollection->serialized()->getProperty($propertyValueCriteria->propertyName->value)->value < $propertyValueCriteria->value;
case $propertyValueCriteria instanceof PropertyValueLessThanOrEqual:
return $propertyCollection->serialized()->propertyExists($propertyValueCriteria->propertyName->value)
&& $propertyCollection->serialized()->getProperty($propertyValueCriteria->propertyName->value)->value <= $propertyValueCriteria->value;
default:
throw new \InvalidArgumentException(sprintf('Invalid/unsupported property value criteria "%s"', get_debug_type($propertyValueCriteria)), 1679561073);
}
}

public static function matchesNode(Node $node, PropertyValueCriteriaInterface $propertyValueCriteria): bool
{
return static::matchesPropertyCollection($node->properties, $propertyValueCriteria);
}
}
Loading

0 comments on commit d0e65c5

Please sign in to comment.