From a71ebfb181352b4f2f811bd0e1aeb7eefa83374c Mon Sep 17 00:00:00 2001 From: mateuszdebinski <58430570+mateuszdebinski@users.noreply.github.com> Date: Fri, 21 May 2021 13:22:09 +0200 Subject: [PATCH] IBX-366: Implemented DateMetadataCriterion to REST API (#3100) --- .../Content/Query/Criterion/DateMetadata.php | 4 +- .../Input/Parser/Criterion/DateMetadata.php | 76 +++++++- .../Parser/Criterion/DateMetadataTest.php | 165 ++++++++++++++++++ 3 files changed, 240 insertions(+), 5 deletions(-) create mode 100644 eZ/Publish/Core/REST/Server/Tests/Input/Parser/Criterion/DateMetadataTest.php diff --git a/eZ/Publish/API/Repository/Values/Content/Query/Criterion/DateMetadata.php b/eZ/Publish/API/Repository/Values/Content/Query/Criterion/DateMetadata.php index 32d3d715f33..2632bab1089 100644 --- a/eZ/Publish/API/Repository/Values/Content/Query/Criterion/DateMetadata.php +++ b/eZ/Publish/API/Repository/Values/Content/Query/Criterion/DateMetadata.php @@ -36,12 +36,12 @@ class DateMetadata extends Criterion implements CriterionInterface /** * DateMetadata target: modification date. */ - const MODIFIED = 'modified'; + public const MODIFIED = 'modified'; /** * DateMetadata target: creation date. */ - const CREATED = 'created'; + public const CREATED = 'created'; /** * Creates a new DateMetadata criterion on $metadata. diff --git a/eZ/Publish/Core/REST/Server/Input/Parser/Criterion/DateMetadata.php b/eZ/Publish/Core/REST/Server/Input/Parser/Criterion/DateMetadata.php index b08cc1800e1..1ed04541bc8 100644 --- a/eZ/Publish/Core/REST/Server/Input/Parser/Criterion/DateMetadata.php +++ b/eZ/Publish/Core/REST/Server/Input/Parser/Criterion/DateMetadata.php @@ -8,14 +8,32 @@ */ namespace eZ\Publish\Core\REST\Server\Input\Parser\Criterion; +use eZ\Publish\API\Repository\Values\Content\Query\Criterion\Operator; use eZ\Publish\Core\REST\Common\Input\BaseParser; use eZ\Publish\Core\REST\Common\Input\ParsingDispatcher; +use eZ\Publish\API\Repository\Values\Content\Query\Criterion\DateMetadata as DateMetadataCriterion; +use eZ\Publish\Core\REST\Common\Exceptions; /** * Parser for ViewInput Criterion. */ class DateMetadata extends BaseParser { + private const OPERATORS = [ + 'IN' => Operator::IN, + 'EQ' => Operator::EQ, + 'GT' => Operator::GT, + 'GTE' => Operator::GTE, + 'LT' => Operator::LT, + 'LTE' => Operator::LTE, + 'BETWEEN' => Operator::BETWEEN, + ]; + + private const TARGETS = [ + DateMetadataCriterion::MODIFIED, + DateMetadataCriterion::CREATED, + ]; + /** * Parses input structure to a Criterion object. * @@ -23,11 +41,63 @@ class DateMetadata extends BaseParser * @param \eZ\Publish\Core\REST\Common\Input\ParsingDispatcher $parsingDispatcher * * @throws \eZ\Publish\Core\REST\Common\Exceptions\Parser + */ + public function parse(array $data, ParsingDispatcher $parsingDispatcher): DateMetadataCriterion + { + if (!isset($data['DateMetadataCriterion'])) { + throw new Exceptions\Parser('Invalid format'); + } + + $dateMetadata = $data['DateMetadataCriterion']; + + if (!isset($dateMetadata['Target'])) { + throw new Exceptions\Parser('Invalid format'); + } + + $target = strtolower($dateMetadata['Target']); + + if (!in_array($target, self::TARGETS, true)) { + throw new Exceptions\Parser('Invalid format'); + } + + if (!isset($dateMetadata['Value'])) { + throw new Exceptions\Parser('Invalid format'); + } + + if (!in_array(gettype($dateMetadata['Value']), ['integer', 'array'], true)) { + throw new Exceptions\Parser('Invalid format'); + } + + $value = $dateMetadata['Value']; + + if (!isset($dateMetadata['Operator'])) { + throw new Exceptions\Parser('Invalid format'); + } + + $operator = $this->getOperator($dateMetadata['Operator']); + + return new DateMetadataCriterion($target, $operator, $value); + } + + /** + * Get operator for the given literal name. * - * @return \eZ\Publish\API\Repository\Values\Content\Query\Criterion\DateMetadata + * For the full list of supported operators: + * + * @see \eZ\Publish\Core\REST\Server\Input\Parser\Criterion\DateMetadata::OPERATORS */ - public function parse(array $data, ParsingDispatcher $parsingDispatcher) + private function getOperator(string $operatorName): string { - throw new \Exception('@todo implement'); + $operatorName = strtoupper($operatorName); + if (!isset(self::OPERATORS[$operatorName])) { + throw new Exceptions\Parser( + sprintf( + 'Unexpected DateMetadata operator. Expected one of: %s', + implode(', ', array_keys(self::OPERATORS)) + ) + ); + } + + return self::OPERATORS[$operatorName]; } } diff --git a/eZ/Publish/Core/REST/Server/Tests/Input/Parser/Criterion/DateMetadataTest.php b/eZ/Publish/Core/REST/Server/Tests/Input/Parser/Criterion/DateMetadataTest.php new file mode 100644 index 00000000000..64b47cb13c8 --- /dev/null +++ b/eZ/Publish/Core/REST/Server/Tests/Input/Parser/Criterion/DateMetadataTest.php @@ -0,0 +1,165 @@ + ['Target' => 'modified', 'Value' => [14, 1620739489], 'Operator' => 'BETWEEN']], + new DateMetadataCriterion('modified', Operator::BETWEEN, [14, 1620739489]), + ], + [ + ['DateMetadataCriterion' => ['Target' => 'modified', 'Value' => 14, 'Operator' => 'GT']], + new DateMetadataCriterion('modified', Operator::GT, 14), + ], + [ + ['DateMetadataCriterion' => ['Target' => 'created', 'Value' => 14, 'Operator' => 'GTE']], + new DateMetadataCriterion('created', Operator::GTE, 14), + ], + [ + ['DateMetadataCriterion' => ['Target' => 'created', 'Value' => 14, 'Operator' => 'EQ']], + new DateMetadataCriterion('created', Operator::EQ, 14), + ], + [ + ['DateMetadataCriterion' => ['Target' => 'created', 'Value' => 1620739489, 'Operator' => 'LT']], + new DateMetadataCriterion('created', Operator::LT, 1620739489), + ], + [ + ['DateMetadataCriterion' => ['Target' => 'created', 'Value' => 1620739489, 'Operator' => 'LTE']], + new DateMetadataCriterion('created', Operator::LTE, 1620739489), + ], + [ + ['DateMetadataCriterion' => ['Target' => 'created', 'Value' => [14, 58, 167, 165245, 1620739489], 'Operator' => 'IN']], + new DateMetadataCriterion('created', Operator::IN, [14, 58, 167, 165245, 1620739489]), + ], + ]; + } + + /** + * Tests the DateMetaData parser. + * + * @param string[] $data + * @dataProvider testParseProvider + */ + public function testParse(array $data, DateMetadataCriterion $expected): void + { + $dateMetadata = $this->getParser(); + $result = $dateMetadata->parse($data, $this->getParsingDispatcherMock()); + + $this->assertEquals( + $expected, + $result, + 'DateMetadata parser not created correctly.' + ); + } + + public function testParseExceptionOnInvalidCriterionFormat(): void + { + $this->expectExceptionMessage('Invalid format'); + $this->expectException(Exceptions\Parser::class); + $inputArray = [ + 'foo' => 'Michael learns to mock', + ]; + + $dataKeyValueObjectClass = $this->getParser(); + $dataKeyValueObjectClass->parse($inputArray, $this->getParsingDispatcherMock()); + } + + public function testParseExceptionOnInvalidTargetFormat(): void + { + $this->expectExceptionMessage('Invalid format'); + $this->expectException(Exceptions\Parser::class); + + $inputArray = [ + 'DateMetadataCriterion' => [ + 'foo' => 'Mock around the clock', + 'Value' => 42, + ], + ]; + + $dataKeyValueObjectClass = $this->getParser(); + $dataKeyValueObjectClass->parse($inputArray, $this->getParsingDispatcherMock()); + } + + public function testParseExceptionOnWrongTargetType(): void + { + $this->expectExceptionMessage('Invalid format'); + $this->expectException(Exceptions\Parser::class); + + $inputArray = [ + 'DateMetadataCriterion' => [ + 'Target' => 'Mock around the clock', + 'Value' => 42, + ], + ]; + + $dataKeyValueObjectClass = $this->getParser(); + $dataKeyValueObjectClass->parse($inputArray, $this->getParsingDispatcherMock()); + } + + public function testParseExceptionOnInvalidValueFormat(): void + { + $this->expectExceptionMessage('Invalid format'); + $this->expectException(Exceptions\Parser::class); + + $inputArray = [ + 'DateMetadataCriterion' => [ + 'Target' => 'modified', + 'foo' => 42, + ], + ]; + + $dataKeyValueObjectClass = $this->getParser(); + $dataKeyValueObjectClass->parse($inputArray, $this->getParsingDispatcherMock()); + } + + public function testParseExceptionOnWrongValueType(): void + { + $this->expectExceptionMessage('Invalid format'); + $this->expectException(Exceptions\Parser::class); + + $inputArray = [ + 'DateMetadataCriterion' => [ + 'Target' => 'modified', + 'Value' => new \stdClass(), + ], + ]; + + $dataKeyValueObjectClass = $this->getParser(); + $dataKeyValueObjectClass->parse($inputArray, $this->getParsingDispatcherMock()); + } + + public function testParseExceptionOnInvalidOperatorFormat(): void + { + $this->expectExceptionMessage('Invalid format'); + $this->expectException(Exceptions\Parser::class); + + $inputArray = [ + 'DateMetadataCriterion' => [ + 'Target' => 'modified', + 'Value' => 42, + ], + ]; + + $dataKeyValueObjectClass = $this->getParser(); + $dataKeyValueObjectClass->parse($inputArray, $this->getParsingDispatcherMock()); + } + + protected function internalGetParser(): DateMetadata + { + return new DateMetadata(); + } +}