From 6bdb8162a808fc09e97a54f3d8e3e01ac17eff51 Mon Sep 17 00:00:00 2001 From: Xenofon Spafaridis Date: Sat, 13 Feb 2016 13:04:05 +0200 Subject: [PATCH] Allow to filter relationships using Operator::OPERATOR_EMPTY --- src/Filter.php | 53 +++++++++++++++++++++++++++------------- src/Model/Directives.php | 22 +++++++++++------ tests/src/FilterTest.php | 21 ++++++++++++++++ 3 files changed, 72 insertions(+), 24 deletions(-) diff --git a/src/Filter.php b/src/Filter.php index bb3f212..f272932 100644 --- a/src/Filter.php +++ b/src/Filter.php @@ -109,10 +109,11 @@ public function __construct( } foreach ($relationships as $relationshipKey => $relationshipValue) { - if (!is_array($relationshipValue)) { + if (!is_array($relationshipValue) && $relationshipValue !== Operator::OPERATOR_EMPTY) { throw new \Exception(sprintf( - 'Values for relationship filter "%s" MUST be an array', - $relationshipKey + 'Values for relationship filter "%s" MUST be an array or Operator::"%s"', + $relationshipKey, + Operator::OPERATOR_EMPTY )); } } @@ -168,7 +169,7 @@ public function validate($modelClass) */ if ($this->relationships !== null) { - foreach ($this->relationships as $relationshipKey => $value) { + foreach ($this->relationships as $relationshipKey => $relationshipValue) { if (!$modelClass::relationshipExists($relationshipKey)) { throw new RequestException(sprintf( 'Not a valid relationship for filter relationship "%"', @@ -176,11 +177,15 @@ public function validate($modelClass) )); } + if ($relationshipValue === Operator::OPERATOR_EMPTY) { + continue; + } + //@TODO add relationship validator $relationshipValidator = [UnsignedIntegerValidator::class, 'parseStatic']; //Run validator, if any value is incorrect IncorrectParametersException will be thrown - foreach ($value as $id) { + foreach ($relationshipValue as $id) { call_user_func($relationshipValidator, $id); } } @@ -296,6 +301,16 @@ public function validate($modelClass) * Article::class * ); * ``` + * @example + * ```php + * $filter = Filter::parseFromParameters( + * (object) [ + * 'filter' => [ + * 'tag' => Operator::OPERATOR_EMPTY + * ] + * ], + * Article::class + * ); * @throws RequestException * @throws \Exception * @throws IncorrectParametersException @@ -352,18 +367,22 @@ public static function parseFromParameters($parameters, $modelClass) )); } - //Todo use filterValidation model - //$function = 'intval'; - - //Split multiples and trim additional spaces and force string - $values = array_map( - 'strval', - //array_map( - // $function, - // array_map('trim', explode(',', trim($filterValue))) - //) - array_map('trim', explode(',', trim($filterValue))) - ); + if ($filterValue === Operator::OPERATOR_EMPTY) { + $values = Operator::OPERATOR_EMPTY; + } else { + //Todo use filterValidation model + //$function = 'intval'; + + //Split multiples and trim additional spaces and force string + $values = array_map( + 'strval', + //array_map( + // $function, + // array_map('trim', explode(',', trim($filterValue))) + //) + array_map('trim', explode(',', trim($filterValue))) + ); + } $filterRelationships->{$filterKey} = $values; } else { diff --git a/src/Model/Directives.php b/src/Model/Directives.php index 11b6927..6e29bab 100644 --- a/src/Model/Directives.php +++ b/src/Model/Directives.php @@ -250,13 +250,21 @@ protected static function handleFilter( $relationship = $relationships->{$relationshipKey}; if ($relationship->type === Relationship::TYPE_TO_ONE) { - $additionalQuery[] = sprintf( - '%s "%s"."%s" IN (%s)', - ($hasWhere ? 'AND' : 'WHERE'), - static::$table, - $relationship->recordDataAttribute, - self::handleFilterParseIn($relationshipFilterValue) - ); + if ($relationshipFilterValue === Operator::OPERATOR_EMPTY) { + $additionalQuery[] = sprintf( + '%s "%s"."%s" IS NULL', + ($hasWhere ? 'AND' : 'WHERE'), + $relationship->recordDataAttribute + ); + } else { + $additionalQuery[] = sprintf( + '%s "%s"."%s" IN (%s)', + ($hasWhere ? 'AND' : 'WHERE'), + static::$table, + $relationship->recordDataAttribute, + self::handleFilterParseIn($relationshipFilterValue) + ); + } $hasWhere = true; } else { throw new NotImplementedException( diff --git a/tests/src/FilterTest.php b/tests/src/FilterTest.php index f2a80f1..c1a0d3f 100644 --- a/tests/src/FilterTest.php +++ b/tests/src/FilterTest.php @@ -123,6 +123,27 @@ public function testParseFromParametersPrimaryUsingIntval() $this->assertEquals([4], $filter->primary); } + /** + * @covers ::parseFromParameters + */ + public function testParseFromParametersRelationshipEmpty() + { + $parameters = (object) [ + 'filter' => (object) [ //Will accept both arrays and object + 'tag' => Operator::OPERATOR_EMPTY + ] + ]; + + $filter = Filter::parseFromParameters( + $parameters, + Article::class //Use article resource model's filters + ); + + $this->assertInstanceOf(Filter::class, $filter); + + $this->assertEquals(Operator::OPERATOR_EMPTY, $filter->relationships->tag); + } + /** * @covers ::parseFromParameters */