Jeroen De Dauw has uploaded a new change for review. https://gerrit.wikimedia.org/r/72723
Change subject: Split off StrategicDeserializer from TypedObjectDeserializer and added QueryOptionsDeserializer ...................................................................... Split off StrategicDeserializer from TypedObjectDeserializer and added QueryOptionsDeserializer Change-Id: Ia808de8b65fdcc61466bc5c152b79583407c02a5 --- A Tests/Phpunit/Deserializers/QueryOptionsDeserializerTest.php M src/Ask/Deserializers/DescriptionDeserializer.php M src/Ask/Deserializers/QueryOptionsDeserializer.php M src/Ask/Deserializers/SelectionRequestDeserializer.php M src/Ask/Deserializers/SortExpressionDeserializer.php A src/Ask/Deserializers/StrategicDeserializer.php M src/Ask/Deserializers/TypedObjectDeserializer.php 7 files changed, 305 insertions(+), 34 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Ask refs/changes/23/72723/1 diff --git a/Tests/Phpunit/Deserializers/QueryOptionsDeserializerTest.php b/Tests/Phpunit/Deserializers/QueryOptionsDeserializerTest.php new file mode 100644 index 0000000..4601e9b --- /dev/null +++ b/Tests/Phpunit/Deserializers/QueryOptionsDeserializerTest.php @@ -0,0 +1,190 @@ +<?php + +namespace Ask\Tests\Phpunit\Deserializers; + +use Ask\Deserializers\QueryOptionsDeserializer; +use Ask\Deserializers\SortExpressionDeserializer; +use DataValues\DataValueFactory; + +/** + * @covers Ask\Deserializers\QueryOptionsDeserializer + * + * @file + * @since 0.1 + * + * @ingroup Ask + * @group Ask + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < [email protected] > + */ +class QueryOptionsDeserializerTest extends \PHPUnit_Framework_TestCase { + + protected function newQueryOptionsDeserializer() { + $dvFactory = new DataValueFactory(); + $dvFactory->registerDataValue( 'string', 'DataValues\StringValue' ); + + $sortExpressionSerializer = new SortExpressionDeserializer( $dvFactory ); + + return new QueryOptionsDeserializer( $sortExpressionSerializer ); + } + + /** + * @dataProvider invalidObjectTypeProvider + */ + public function testCannotDeserializeWithInvalidObjectType( $notQueryOptions ) { + $serializer = $this->newQueryOptionsDeserializer(); + + $this->assertFalse( $serializer->canDeserialize( $notQueryOptions ) ); + + $this->setExpectedException( 'Ask\Deserializers\Exceptions\UnsupportedTypeException' ); + $serializer->deserialize( $notQueryOptions ); + } + + public function invalidObjectTypeProvider() { + $argLists = array(); + + $argLists[] = array( array( + 'objectType' => 'foobar', + 'limit' => 10, + 'offset' => 0, + 'sort' => array( + 'expressions' => array() + ) + ) ); + + $argLists[] = array( array( + 'objectType' => 'QUERYOPTIONS', + ) ); + + $argLists[] = array( array( + 'objectType' => null, + ) ); + + $argLists[] = array( array( + 'objectType' => array(), + ) ); + + $argLists[] = array( array( + 'objectType' => 42, + ) ); + + return $argLists; + } + + /** + * @dataProvider missingObjectTypeProvider + */ + public function testCannotDeserilaizeWithoutObjectType( $notQueryOptions ) { + $serializer = $this->newQueryOptionsDeserializer(); + + $this->assertFalse( $serializer->canDeserialize( $notQueryOptions ) ); + + $this->setExpectedException( 'Ask\Deserializers\Exceptions\MissingTypeException' ); + $serializer->deserialize( $notQueryOptions ); + } + + public function missingObjectTypeProvider() { + $argLists = array(); + + $argLists[] = array( null ); + $argLists[] = array( array() ); + $argLists[] = array( 'foo bar' ); + + $argLists[] = array( array( + 'limit' => 10, + 'offset' => 0, + 'sort' => array( + 'expressions' => array() + ) + ) ); + + $argLists[] = array( array( + 'ObjectType' => 'sortExpression', + ) ); + + $argLists[] = array( array( + 'OBJECTTYPE' => 'sortExpression', + ) ); + + return $argLists; + } + + /** + * @dataProvider optionsWithMissingAttributeProvider + */ + public function testPropertySelectionRequiresAllAttributes( array $incompleteSerialization ) { + $this->setExpectedException( 'Ask\Deserializers\Exceptions\MissingAttributeException' ); + $this->newQueryOptionsDeserializer()->deserialize( $incompleteSerialization ); + } + + + + public function optionsWithMissingAttributeProvider() { + $argLists = array(); + + $argLists[] = array( array( + 'objectType' => 'queryOptions', + 'offset' => 0, + 'sort' => array( + 'expressions' => array() + ) + ) ); + + $argLists[] = array( array( + 'objectType' => 'queryOptions', + 'limit' => 10, + 'sort' => array( + 'expressions' => array() + ) + ) ); + + $argLists[] = array( array( + 'objectType' => 'queryOptions', + 'limit' => 10, + 'offset' => 0, + ) ); + + return $argLists; + } + + /** + * @dataProvider optionsWithInvalidAttributeProvider + */ + public function testPropertySelectionRequiresValidAttributes( array $invalidSerialization ) { + $this->setExpectedException( 'Ask\Deserializers\Exceptions\DeserializationException' ); + $this->newQueryOptionsDeserializer()->deserialize( $invalidSerialization ); + } + + public function optionsWithInvalidAttributeProvider() { + $argLists = array(); + + $argLists[] = array( array( + 'objectType' => 'queryOptions', + 'limit' => 'hax', + 'offset' => 0, + 'sort' => array( + 'expressions' => array() + ) + ) ); + + $argLists[] = array( array( + 'objectType' => 'queryOptions', + 'limit' => 10, + 'offset' => 'hax', + 'sort' => array( + 'expressions' => array() + ) + ) ); + + $argLists[] = array( array( + 'objectType' => 'queryOptions', + 'limit' => 10, + 'offset' => 0, + 'sort' => 'hax' + ) ); + + return $argLists; + } + +} diff --git a/src/Ask/Deserializers/DescriptionDeserializer.php b/src/Ask/Deserializers/DescriptionDeserializer.php index 582d8da..c27f9b1 100644 --- a/src/Ask/Deserializers/DescriptionDeserializer.php +++ b/src/Ask/Deserializers/DescriptionDeserializer.php @@ -34,7 +34,7 @@ } protected function newDeserializer() { - return new TypedObjectDeserializer( + return new StrategicDeserializer( new DescriptionDeserializationStrategy( $this->dataValueFactory, $this diff --git a/src/Ask/Deserializers/QueryOptionsDeserializer.php b/src/Ask/Deserializers/QueryOptionsDeserializer.php index a4abe2d..f8ef4bd 100644 --- a/src/Ask/Deserializers/QueryOptionsDeserializer.php +++ b/src/Ask/Deserializers/QueryOptionsDeserializer.php @@ -1,2 +1,54 @@ <?php +namespace Ask\Deserializers; + +use Ask\Language\Option\QueryOptions; +use Ask\Language\Option\SortOptions; + +/** + * @since 0.1 + * + * @file + * @ingroup Ask + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < [email protected] > + */ +class QueryOptionsDeserializer extends TypedObjectDeserializer { + + protected $sortExpressionDeserializer; + + public function __construct( Deserializer $sortExpressionDeserializer ) { + $this->sortExpressionDeserializer = $sortExpressionDeserializer; + + parent::__construct( 'queryOptions' ); + } + + public function deserialize( $serialization ) { + $this->assertCanDeserialize( $serialization ); + return $this->getDeserialization( $serialization ); + } + + protected function getDeserialization( array $serialization ) { + $this->requireAttributes( $serialization, 'limit', 'offset', 'sort' ); + $this->assertAttributeIsArray( $serialization, 'sort' ); + $this->assertAttributeInternalType( $serialization, 'limit', 'integer' ); + $this->assertAttributeInternalType( $serialization, 'offset', 'integer' ); + + $this->requireAttribute( $serialization['sort'], 'expressions' ); + $this->assertAttributeIsArray( $serialization['sort'], 'expressions' ); + + $sortExpressions = array(); + + foreach ( $serialization['sort']['expressions'] as $sortExpressionSerialization ) { + $sortExpressions[] = $this->sortExpressionDeserializer->deserialize( $sortExpressionSerialization ); + } + + return new QueryOptions( + $serialization['limit'], + $serialization['offset'], + new SortOptions( $sortExpressions ) + ); + } + +} diff --git a/src/Ask/Deserializers/SelectionRequestDeserializer.php b/src/Ask/Deserializers/SelectionRequestDeserializer.php index c7e25bb..cd6e422 100644 --- a/src/Ask/Deserializers/SelectionRequestDeserializer.php +++ b/src/Ask/Deserializers/SelectionRequestDeserializer.php @@ -26,7 +26,7 @@ } protected function newDeserializer() { - return new TypedObjectDeserializer( + return new StrategicDeserializer( new SelectionRequestDeserializationStrategy( $this->dataValueFactory, $this diff --git a/src/Ask/Deserializers/SortExpressionDeserializer.php b/src/Ask/Deserializers/SortExpressionDeserializer.php index 6f967b2..4b5bf1e 100644 --- a/src/Ask/Deserializers/SortExpressionDeserializer.php +++ b/src/Ask/Deserializers/SortExpressionDeserializer.php @@ -26,7 +26,7 @@ } protected function newDeserializer() { - return new TypedObjectDeserializer( + return new StrategicDeserializer( new SortExpressionDeserializationStrategy( $this->dataValueFactory ), 'sortExpression', 'sortExpressionType' diff --git a/src/Ask/Deserializers/StrategicDeserializer.php b/src/Ask/Deserializers/StrategicDeserializer.php new file mode 100644 index 0000000..890a10b --- /dev/null +++ b/src/Ask/Deserializers/StrategicDeserializer.php @@ -0,0 +1,49 @@ +<?php + +namespace Ask\Deserializers; + +use Ask\Deserializers\Strategies\TypedDeserializationStrategy; + +/** + * @since 0.1 + * + * @file + * @ingroup Ask + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < [email protected] > + */ +class StrategicDeserializer extends TypedObjectDeserializer { + + protected $deserializationStrategy; + protected $subTypeKey; + + /** + * @param TypedDeserializationStrategy $deserializationStrategy + * @param string $objectType The objectType that is supported. For instance "description" or "selectionRequest". + * @param string $subTypeKey The name of the key used for the specific type of object. For instance "descriptionType" or "sortExpressionType". + */ + public function __construct( TypedDeserializationStrategy $deserializationStrategy, $objectType, $subTypeKey ) { + $this->deserializationStrategy = $deserializationStrategy; + $this->subTypeKey = $subTypeKey; + + parent::__construct( $objectType ); + } + + public function deserialize( $serialization ) { + $this->assertCanDeserialize( $serialization ); + return $this->getDeserialization( $serialization ); + } + + protected function getDeserialization( array $serialization ) { + $this->requireAttribute( $serialization, $this->subTypeKey ); + $this->requireAttributes( $serialization, 'value' ); + $this->assertAttributeIsArray( $serialization, 'value' ); + + $specificType = $serialization[$this->subTypeKey]; + $valueSerialization = $serialization['value']; + + return $this->deserializationStrategy->getDeserializedValue( $specificType, $valueSerialization ); + } + +} diff --git a/src/Ask/Deserializers/TypedObjectDeserializer.php b/src/Ask/Deserializers/TypedObjectDeserializer.php index 4bae5a4..462161b 100644 --- a/src/Ask/Deserializers/TypedObjectDeserializer.php +++ b/src/Ask/Deserializers/TypedObjectDeserializer.php @@ -17,26 +17,12 @@ * @licence GNU GPL v2+ * @author Jeroen De Dauw < [email protected] > */ -class TypedObjectDeserializer implements Deserializer { +abstract class TypedObjectDeserializer implements Deserializer { - protected $deserializationStrategy; protected $objectType; - protected $subTypeKey; - /** - * @param TypedDeserializationStrategy $deserializationStrategy - * @param string $objectType The objectType that is supported. For instance "description" or "selectionRequest". - * @param string $subTypeKey The name of the key used for the specific type of object. For instance "descriptionType" or "sortExpressionType". - */ - public function __construct( TypedDeserializationStrategy $deserializationStrategy, $objectType, $subTypeKey ) { - $this->deserializationStrategy = $deserializationStrategy; + public function __construct( $objectType ) { $this->objectType = $objectType; - $this->subTypeKey = $subTypeKey; - } - - public function deserialize( $serialization ) { - $this->assertCanDeserialize( $serialization ); - return $this->getDeserialization( $serialization ); } protected function assertCanDeserialize( $serialization ) { @@ -53,24 +39,13 @@ return $this->hasObjectType( $serialization ) && $this->hasCorrectObjectType( $serialization ); } - protected function hasCorrectObjectType( $serialization ) { + private function hasCorrectObjectType( $serialization ) { return $serialization['objectType'] === $this->objectType; } - protected function hasObjectType( $serialization ) { + private function hasObjectType( $serialization ) { return is_array( $serialization ) && array_key_exists( 'objectType', $serialization ); - } - - protected function getDeserialization( array $serialization ) { - $this->requireAttribute( $serialization, $this->subTypeKey ); - $this->requireAttributes( $serialization, 'value' ); - $this->assertAttributeIsArray( $serialization, 'value' ); - - $specificType = $serialization[$this->subTypeKey]; - $valueSerialization = $serialization['value']; - - return $this->deserializationStrategy->getDeserializedValue( $specificType, $valueSerialization ); } protected function requireAttributes( array $array ) { @@ -91,10 +66,15 @@ } protected function assertAttributeIsArray( array $array, $attributeName ) { - if ( !is_array( $array[$attributeName] ) ) { + $this->assertAttributeInternalType( $array, $attributeName, 'array' ); + } + + protected function assertAttributeInternalType( array $array, $attributeName, $internalType ) { + if ( gettype( $array[$attributeName] ) !== $internalType ) { throw new InvalidAttributeException( $attributeName, - $array[$attributeName] + $array[$attributeName], + "The internal type of this attribute needs to be '$internalType'" ); } } -- To view, visit https://gerrit.wikimedia.org/r/72723 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ia808de8b65fdcc61466bc5c152b79583407c02a5 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Ask Gerrit-Branch: master Gerrit-Owner: Jeroen De Dauw <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
