Jeroen De Dauw has uploaded a new change for review. https://gerrit.wikimedia.org/r/70331
Change subject: Added first serialization code ...................................................................... Added first serialization code The idea here is to implement serialization and unserialization using the "canHandle" pattern as suggested we do in this case by Tobias Schlitt Change-Id: I07ca8cc2b9981078755fd25617e9251fd0d9ce9f --- A Tests/Phpunit/Serializers/AskSerializerTest.php A Tests/Phpunit/Serializers/DescriptionSerializerTest.php A Tests/Phpunit/Serializers/Exceptions/UnsupportedObjectExceptionTest.php A includes/Ask/Serializers/AskSerializer.php A includes/Ask/Serializers/DescriptionSerializer.php A includes/Ask/Serializers/Exceptions/SerializationException.php A includes/Ask/Serializers/Exceptions/UnsupportedObjectException.php A includes/Ask/Serializers/Serializer.php 8 files changed, 412 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Ask refs/changes/31/70331/1 diff --git a/Tests/Phpunit/Serializers/AskSerializerTest.php b/Tests/Phpunit/Serializers/AskSerializerTest.php new file mode 100644 index 0000000..29a93a2 --- /dev/null +++ b/Tests/Phpunit/Serializers/AskSerializerTest.php @@ -0,0 +1,108 @@ +<?php + +namespace Ask\Tests\Serializers; + +use Ask\Serializers\AskSerializer; + +/** + * @covers Ask\Serializers\AskSerializer + * + * @file + * @since 0.1 + * + * @ingroup Ask + * @group Ask + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < [email protected] > + */ +class AskSerializerTest extends \PHPUnit_Framework_TestCase { + + public function testConstructWithNoSerializers() { + $serializer = new AskSerializer( array() ); + + $this->assertFalse( $serializer->canSerialize( 'foo' ) ); + $this->assertFalse( $serializer->canSerialize( null ) ); + + $this->setExpectedException( 'Ask\Serializers\Exceptions\UnsupportedObjectException' ); + + $serializer->serialize( 'foo' ); + } + + public function testConstructWithInvalidArgumentsCausesException() { + $this->setExpectedException( 'InvalidArgumentException' ); + new AskSerializer( array( new \stdClass() ) ); + } + + public function testCanSerialize() { + $subSerializer = $this->getMock( 'Ask\Serializers\Serializer' ); + + $subSerializer->expects( $this->exactly( 4 ) ) + ->method( 'canSerialize' ) + ->will( $this->returnCallback( function( $value ) { + return $value > 9000; + } ) ); + + $serializer = new AskSerializer( array( $subSerializer ) ); + + $this->assertFalse( $serializer->canSerialize( 0 ) ); + $this->assertFalse( $serializer->canSerialize( 42 ) ); + $this->assertTrue( $serializer->canSerialize( 9001 ) ); + $this->assertTrue( $serializer->canSerialize( 31337 ) ); + } + + public function testSerializeWithSerializableValues() { + $subSerializer = $this->getMock( 'Ask\Serializers\Serializer' ); + + $subSerializer->expects( $this->any() ) + ->method( 'canSerialize' ) + ->will( $this->returnValue( true ) ); + + $subSerializer->expects( $this->any() ) + ->method( 'serialize' ) + ->will( $this->returnValue( 42 ) ); + + $serializer = new AskSerializer( array( $subSerializer ) ); + + $this->assertEquals( 42, $serializer->serialize( 'foo' ) ); + $this->assertEquals( 42, $serializer->serialize( null ) ); + } + + public function testSerializeWithUnserializableValue() { + $subSerializer = $this->getMock( 'Ask\Serializers\Serializer' ); + + $subSerializer->expects( $this->once() ) + ->method( 'canSerialize' ) + ->will( $this->returnValue( false ) ); + + $serializer = new AskSerializer( array( $subSerializer ) ); + + $this->setExpectedException( 'Ask\Serializers\Exceptions\UnsupportedObjectException' ); + $serializer->serialize( 0 ); + } + + public function testSerializeWithMultipleSubSerializers() { + $subSerializer0 = $this->getMock( 'Ask\Serializers\Serializer' ); + + $subSerializer0->expects( $this->any() ) + ->method( 'canSerialize' ) + ->will( $this->returnValue( true ) ); + + $subSerializer0->expects( $this->any() ) + ->method( 'serialize' ) + ->will( $this->returnValue( 42 ) ); + + $subSerializer1 = $this->getMock( 'Ask\Serializers\Serializer' ); + + $subSerializer1->expects( $this->any() ) + ->method( 'canSerialize' ) + ->will( $this->returnValue( false ) ); + + $subSerializer2 = clone $subSerializer1; + + $serializer = new AskSerializer( array( $subSerializer1, $subSerializer0, $subSerializer2 ) ); + + $this->assertEquals( 42, $serializer->serialize( 'foo' ) ); + } + +} diff --git a/Tests/Phpunit/Serializers/DescriptionSerializerTest.php b/Tests/Phpunit/Serializers/DescriptionSerializerTest.php new file mode 100644 index 0000000..63e1aa3 --- /dev/null +++ b/Tests/Phpunit/Serializers/DescriptionSerializerTest.php @@ -0,0 +1,68 @@ +<?php + +namespace Ask\Tests\Serializers; + +use Ask\Serializers\DescriptionSerializer; + +/** + * @covers Ask\Serializers\DescriptionSerializer + * + * @file + * @since 0.1 + * + * @ingroup Ask + * @group Ask + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < [email protected] > + */ +class DescriptionSerializerTest extends \PHPUnit_Framework_TestCase { + + public function testSerializeDescription() { + $description = $this->getMock( 'Ask\Language\Description\Description' ); + + // We unfortunately cannot mock out toArray as it is final. + $description->expects( $this->once() ) + ->method( 'getType' ) + ->will( $this->returnValue( 'the' ) ); + + $description->expects( $this->once() ) + ->method( 'getArrayValue' ) + ->will( $this->returnValue( 'game' ) ); + + $serializer = new DescriptionSerializer(); + $actualSerialization = $serializer->serialize( $description ); + + $expectedSerialization = array( + 'type' => 'the', + 'value' => 'game', + ); + + $this->assertEquals( $expectedSerialization, $actualSerialization ); + } + + /** + * @dataProvider nonDescriptionProvider + */ + public function testCannotSerializeNonDescriptions( $notADescription ) { + $serializer = new DescriptionSerializer(); + + $this->assertFalse( $serializer->canSerialize( $notADescription ) ); + + $this->setExpectedException( 'Ask\Serializers\Exceptions\UnsupportedObjectException' ); + $serializer->serialize( $notADescription ); + } + + public function nonDescriptionProvider() { + $argLists = array(); + + $argLists[] = array( null ); + $argLists[] = array( 'foo bar' ); + $argLists[] = array( new \stdClass() ); + $argLists[] = array( array() ); + $argLists[] = array( 42 ); + + return $argLists; + } + +} diff --git a/Tests/Phpunit/Serializers/Exceptions/UnsupportedObjectExceptionTest.php b/Tests/Phpunit/Serializers/Exceptions/UnsupportedObjectExceptionTest.php new file mode 100644 index 0000000..c4d0c6d --- /dev/null +++ b/Tests/Phpunit/Serializers/Exceptions/UnsupportedObjectExceptionTest.php @@ -0,0 +1,48 @@ +<?php + +namespace Ask\Tests\Serializers\Exceptions; + +use Ask\Serializers\Exceptions\UnsupportedObjectException; + +/** + * @covers Ask\Serializers\Exceptions\UnsupportedObjectException + * + * @file + * @since 0.1 + * + * @ingroup Ask + * @group Ask + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < [email protected] > + */ +class UnsupportedObjectExceptionTest extends \PHPUnit_Framework_TestCase { + + public function testConstructorWithOnlyRequiredArguments() { + $object = (object)array( 'the' => 'game' ); + $serializer = $this->getMock( 'Ask\Serializers\Serializer' ); + + $exception = new UnsupportedObjectException( $object, $serializer ); + + $this->assertRequiredFieldsAreSet( $exception, $object, $serializer ); + } + + public function testConstructorWithAllArguments() { + $object = (object)array( 'the' => 'game' ); + $serializer = $this->getMock( 'Ask\Serializers\Serializer' ); + $message = 'NyanData all the way across the sky!'; + $previous = new \Exception( 'Onoez!' ); + + $exception = new UnsupportedObjectException( $object, $serializer, $message, $previous ); + + $this->assertRequiredFieldsAreSet( $exception, $object, $serializer ); + $this->assertEquals( $message, $exception->getMessage() ); + $this->assertEquals( $previous, $exception->getPrevious() ); + } + + protected function assertRequiredFieldsAreSet( UnsupportedObjectException $exception, $object, $serializer ) { + $this->assertEquals( $object, $exception->getUnsupportedObject() ); + $this->assertEquals( $serializer, $exception->getSerializer() ); + } + +} diff --git a/includes/Ask/Serializers/AskSerializer.php b/includes/Ask/Serializers/AskSerializer.php new file mode 100644 index 0000000..9481700 --- /dev/null +++ b/includes/Ask/Serializers/AskSerializer.php @@ -0,0 +1,57 @@ +<?php + +namespace Ask\Serializers; + +use Ask\Serializers\Exceptions\UnsupportedObjectException; +use InvalidArgumentException; + +/** + * @since 0.1 + * + * @file + * @ingroup Ask + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < [email protected] > + */ +class AskSerializer implements Serializer { + + /** + * @var Serializer[] + */ + protected $serializers; + + public function __construct( array $serializers ) { + $this->assertAreSerializers( $serializers ); + $this->serializers = $serializers; + } + + protected function assertAreSerializers( array $serializers ) { + foreach ( $serializers as $serializer ) { + if ( !( $serializer instanceof Serializer ) ) { + throw new InvalidArgumentException( 'Got an object that is not an instance of Ask\Serializers\Serializer' ); + } + } + } + + public function serialize( $askObject ) { + foreach ( $this->serializers as $serializer ) { + if ( $serializer->canSerialize( $askObject ) ) { + return $serializer->serialize( $askObject ); + } + } + + throw new UnsupportedObjectException( $askObject, $this ); + } + + public function canSerialize( $askObject ) { + foreach ( $this->serializers as $serializer ) { + if ( $serializer->canSerialize( $askObject ) ) { + return true; + } + } + + return false; + } + +} diff --git a/includes/Ask/Serializers/DescriptionSerializer.php b/includes/Ask/Serializers/DescriptionSerializer.php new file mode 100644 index 0000000..471fab5 --- /dev/null +++ b/includes/Ask/Serializers/DescriptionSerializer.php @@ -0,0 +1,31 @@ +<?php + +namespace Ask\Serializers; + +use Ask\Language\Description\Description; +use Ask\Serializers\Exceptions\UnsupportedObjectException; + +/** + * @since 0.1 + * + * @file + * @ingroup Ask + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < [email protected] > + */ +class DescriptionSerializer implements Serializer { + + public function serialize( $askObject ) { + if ( $askObject instanceof Description ) { + return $askObject->toArray(); + } + + throw new UnsupportedObjectException( $askObject, $this ); + } + + public function canSerialize( $askObject ) { + return $askObject instanceof Description; + } + +} diff --git a/includes/Ask/Serializers/Exceptions/SerializationException.php b/includes/Ask/Serializers/Exceptions/SerializationException.php new file mode 100644 index 0000000..c12d862 --- /dev/null +++ b/includes/Ask/Serializers/Exceptions/SerializationException.php @@ -0,0 +1,33 @@ +<?php + +namespace Ask\Serializers\Exceptions; + +use Ask\Serializers\Serializer; + +/** + * @since 0.1 + * + * @file + * @ingroup Ask + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < [email protected] > + */ +abstract class SerializationException extends \RuntimeException { + + protected $serializer; + + public function __construct( Serializer $serializer, $message = '', \Exception $previous = null ) { + $this->serializer = $serializer; + + parent::__construct( $message, 0, $previous ); + } + + /** + * @return Serializer + */ + public function getSerializer() { + return $this->serializer; + } + +} diff --git a/includes/Ask/Serializers/Exceptions/UnsupportedObjectException.php b/includes/Ask/Serializers/Exceptions/UnsupportedObjectException.php new file mode 100644 index 0000000..634f63a --- /dev/null +++ b/includes/Ask/Serializers/Exceptions/UnsupportedObjectException.php @@ -0,0 +1,33 @@ +<?php + +namespace Ask\Serializers\Exceptions; + +use Ask\Serializers\Serializer; + +/** + * @since 0.1 + * + * @file + * @ingroup Ask + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < [email protected] > + */ +class UnsupportedObjectException extends SerializationException { + + protected $unsupportedObject; + + public function __construct( $unsupportedObject, Serializer $serializer, $message = '', \Exception $previous = null ) { + $this->unsupportedObject = $unsupportedObject; + + parent::__construct( $serializer, $message, $previous ); + } + + /** + * @return mixed + */ + public function getUnsupportedObject() { + return $this->unsupportedObject; + } + +} diff --git a/includes/Ask/Serializers/Serializer.php b/includes/Ask/Serializers/Serializer.php new file mode 100644 index 0000000..d0735a9 --- /dev/null +++ b/includes/Ask/Serializers/Serializer.php @@ -0,0 +1,34 @@ +<?php + +namespace Ask\Serializers; + +/** + * @since 0.1 + * + * @file + * @ingroup Ask + * + * @licence GNU GPL v2+ + * @author Jeroen De Dauw < [email protected] > + */ +interface Serializer { + + /** + * @since 0.1 + * + * @param mixed $askObject + * + * @return array|int|string|bool|float A possibly nested structure consisting of only arrays and scalar values + */ + public function serialize( $askObject ); + + /** + * @since 0.1 + * + * @param mixed $askObject + * + * @return boolean + */ + public function canSerialize( $askObject ); + +} -- To view, visit https://gerrit.wikimedia.org/r/70331 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I07ca8cc2b9981078755fd25617e9251fd0d9ce9f 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
