Bene has uploaded a new change for review. https://gerrit.wikimedia.org/r/274768
Change subject: Create a new media info entity type ...................................................................... Create a new media info entity type Bug: T125824 Change-Id: I5bddacca3e57b9f6f683d48b32e269a475c1cb09 --- A phpunit.xml.dist A src/DataModel/MediaInfo.php A src/DataModel/MediaInfoId.php A tests/bootstrap.php A tests/phpunit/DatatModel/MediaInfoIdTest.php A tests/phpunit/DatatModel/MediaInfoTest.php 6 files changed, 645 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikibaseMediaInfo refs/changes/68/274768/1 diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..98df909 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,24 @@ +<phpunit backupGlobals="false" + backupStaticAttributes="false" + bootstrap="tests/bootstrap.php" + cacheTokens="false" + colors="true" + convertErrorsToExceptions="true" + convertNoticesToExceptions="true" + convertWarningsToExceptions="true" + stopOnError="false" + stopOnFailure="false" + stopOnIncomplete="false" + stopOnSkipped="false" + verbose="true"> + <testsuites> + <testsuite name="WikibaseMediaInfo"> + <directory>tests</directory> + </testsuite> + </testsuites> + <filter> + <whitelist addUncoveredFilesFromWhitelist="true"> + <directory suffix=".php">src</directory> + </whitelist> + </filter> +</phpunit> diff --git a/src/DataModel/MediaInfo.php b/src/DataModel/MediaInfo.php new file mode 100644 index 0000000..56d2d74 --- /dev/null +++ b/src/DataModel/MediaInfo.php @@ -0,0 +1,156 @@ +<?php + +namespace Wikibase\MediaInfo\DataModel; + +use InvalidArgumentException; +use Wikibase\DataModel\Entity\EntityDocument; +use Wikibase\DataModel\Entity\EntityId; +use Wikibase\DataModel\Statement\StatementList; +use Wikibase\DataModel\Statement\StatementListProvider; +use Wikibase\DataModel\Term\DescriptionsProvider; +use Wikibase\DataModel\Term\LabelsProvider; +use Wikibase\DataModel\Term\TermList; + +/** + * Represents a media info entity, containing an id, a list of labels, a list of descriptions + * and a list of statements. + * + * @since 0.1 + * + * @license GPL-2.0+ + * @author Bene* < [email protected] > + */ +class MediaInfo implements EntityDocument, LabelsProvider, DescriptionsProvider, StatementListProvider { + + const ENTITY_TYPE = 'mediainfo'; + + /** + * @var MediaInfoId|null + */ + private $id; + + /** + * @var TermList + */ + private $labels; + + /** + * @var TermList + */ + private $descriptions; + + /** + * @var StatementList + */ + private $statements; + + /** + * @param MediaInfoId|null $id + * @param TermList|null $labels + * @param TermList|null $descriptions + * @param StatementList|null $statements + */ + public function __construct( + MediaInfoId $id = null, + TermList $labels = null, + TermList $descriptions = null, + StatementList $statements = null + ) { + $this->id = $id; + $this->labels = $labels ?: new TermList(); + $this->descriptions = $descriptions ?: new TermList(); + $this->statements = $statements ?: new StatementList(); + } + + /** + * @return string + */ + public function getType() { + return self::ENTITY_TYPE; + } + + /** + * @return EntityId|null + */ + public function getId() { + return $this->id; + } + + /** + * @param MediaInfoId $id + */ + public function setId( $id ) { + if ( !( $id instanceof MediaInfoId ) ) { + throw new InvalidArgumentException( '$id must be an instance of MediaInfoId' ); + } + + $this->id = $id; + } + + /** + * @return TermList + */ + public function getLabels() { + return $this->labels; + } + + /** + * @return TermList + */ + public function getDescriptions() { + return $this->descriptions; + } + + /** + * @return StatementList + */ + public function getStatements() { + return $this->statements; + } + + /** + * @return bool + */ + public function isEmpty() { + return $this->labels->isEmpty() + && $this->descriptions->isEmpty() + && $this->statements->isEmpty(); + } + + /** + * @see EntityDocument::equals + * + * @param mixed $target + * + * @return bool + */ + public function equals( $target ) { + if ( $this === $target ) { + return true; + } + + return $target instanceof self + && $this->labels->equals( $target->labels ) + && $this->descriptions->equals( $target->descriptions ) + && $this->statements->equals( $target->statements ); + } + + /** + * @see EntityDocument::copy + * + * @return MediaInfo + */ + public function copy() { + return clone $this; + } + + /** + * @see http://php.net/manual/en/language.oop5.cloning.php + */ + public function __clone() { + $this->labels = unserialize( serialize( $this->labels ) ); + $this->descriptions = unserialize( serialize( $this->descriptions ) ); + $this->statements = unserialize( serialize( $this->statements ) ); + } + +} diff --git a/src/DataModel/MediaInfoId.php b/src/DataModel/MediaInfoId.php new file mode 100644 index 0000000..839d0d9 --- /dev/null +++ b/src/DataModel/MediaInfoId.php @@ -0,0 +1,65 @@ +<?php + +namespace Wikibase\MediaInfo\DataModel; + +use InvalidArgumentException; +use Wikibase\DataModel\Entity\EntityId; + +/** + * @since 0.1 + * + * @license GPL-2.0+ + * @author Bene* < [email protected] > + */ +class MediaInfoId extends EntityId { + + const PATTERN = '/^M[1-9]\d*$/i'; + + /** + * @param string $idSerialization + * + * @throws InvalidArgumentException + */ + public function __construct( $idSerialization ) { + $this->assertValidIdFormat( $idSerialization ); + $this->serialization = strtoupper( $idSerialization ); + } + + private function assertValidIdFormat( $idSerialization ) { + if ( !is_string( $idSerialization ) ) { + throw new InvalidArgumentException( '$idSerialization must be a string; got ' . gettype( $idSerialization ) ); + } + + if ( !preg_match( self::PATTERN, $idSerialization ) ) { + throw new InvalidArgumentException( '$idSerialization must match ' . self::PATTERN ); + } + } + + /** + * @see EntityId::getEntityType + * + * @return string + */ + public function getEntityType() { + return 'mediainfo'; + } + + /** + * @see Serializable::serialize + * + * @return string + */ + public function serialize() { + return json_encode( array( 'mediainfo', $this->serialization ) ); + } + + /** + * @see Serializable::unserialize + * + * @param string $value + */ + public function unserialize( $value ) { + list( , $this->serialization ) = json_decode( $value ); + } + +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..13698c5 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,23 @@ +<?php + +/** + * PHPUnit test bootstrap file for the Wikibase MediaInfo component. + * + * @licence GNU GPL v2+ + * @author Bene* < [email protected] > + */ + +if ( PHP_SAPI !== 'cli' ) { + die( 'Not an entry point' ); +} + +error_reporting( E_ALL | E_STRICT ); +ini_set( 'display_errors', 1 ); + +if ( !is_readable( __DIR__ . '/../vendor/autoload.php' ) ) { + die( 'You need to install this package with Composer before you can run the tests' ); +} + +$autoLoader = require __DIR__ . '/../vendor/autoload.php'; + +unset( $autoLoader ); diff --git a/tests/phpunit/DatatModel/MediaInfoIdTest.php b/tests/phpunit/DatatModel/MediaInfoIdTest.php new file mode 100644 index 0000000..6758109 --- /dev/null +++ b/tests/phpunit/DatatModel/MediaInfoIdTest.php @@ -0,0 +1,100 @@ +<?php + +namespace Wikibase\MediaInfo\Tests\DataModel; + +use InvalidArgumentException; +use PHPUnit_Framework_TestCase; +use Wikibase\MediaInfo\DataModel\MediaInfoId; + +/** + * @covers Wikibase\MediaInfo\DataModel\MediaInfoId + * + * @license GPL-2.0+ + * @author Bene* < [email protected] > + */ +class MediaInfoIdTest extends PHPUnit_Framework_TestCase { + + public function provideValidIds() { + return array( + array( 'm1' ), + array( 'M2' ), + array( 'm1238253457982347893264' ), + array( 'M123456789123456789123456789' ) + ); + } + + /** + * @dataProvider provideValidIds + */ + public function testValidIds( $serialization ) { + $id = new MediaInfoId( $serialization ); + + $this->assertEquals( strtoupper( $serialization ), $id->getSerialization() ); + } + + public function provideInvalidIds() { + return array( + array( null ), + array( false ), + array( 0 ), + array( 42 ), + array( '' ), + array( 'm' ), + array( 'M' ), + array( '42' ), + array( 'm0' ), + array( 'M0123' ), + array( ' m123' ), + array( 'M123 ' ), + array( 'm 2' ), + array( 'm34534;' ), + array( 'M3.14159' ), + array( '345m' ), + array( '1M22' ) + ); + } + + /** + * @dataProvider provideInvalidIds + * @expectedException InvalidArgumentException + */ + public function testInvalidIds( $serialization ) { + new MediaInfoId( $serialization ); + } + + public function testGetEntityType() { + $id = new MediaInfoId( 'M1' ); + + $this->assertEquals( 'mediainfo', $id->getEntityType() ); + } + + public function testSerialize() { + $id = new MediaInfoId( 'M1' ); + + $this->assertEquals( '["mediainfo","M1"]', $id->serialize() ); + } + + /** + * @dataProvider serializationProvider + */ + public function testUnserialize( $json, $expected ) { + $id = new MediaInfoId( 'M1' ); + $id->unserialize( $json ); + $this->assertSame( $expected, $id->getSerialization() ); + } + + public function serializationProvider() { + return array( + array( '["mediainfo","M2"]', 'M2' ), + + // All these cases are kind of an injection vector and allow constructing invalid ids. + array( '["string","M2"]', 'M2' ), + array( '["","string"]', 'string' ), + array( '["",""]', '' ), + array( '["",2]', 2 ), + array( '["",null]', null ), + array( '', null ), + ); + } + +} diff --git a/tests/phpunit/DatatModel/MediaInfoTest.php b/tests/phpunit/DatatModel/MediaInfoTest.php new file mode 100644 index 0000000..efed6f3 --- /dev/null +++ b/tests/phpunit/DatatModel/MediaInfoTest.php @@ -0,0 +1,277 @@ +<?php + +namespace Wikibase\MediaInfo\Tests\DataModel; + +use InvalidArgumentException; +use PHPUnit_Framework_TestCase; +use Wikibase\DataModel\Entity\Item; +use Wikibase\DataModel\Entity\ItemId; +use Wikibase\DataModel\Snak\PropertyNoValueSnak; +use Wikibase\DataModel\Statement\StatementList; +use Wikibase\DataModel\Term\TermList; +use Wikibase\MediaInfo\DataModel\MediaInfo; +use Wikibase\MediaInfo\DataModel\MediaInfoId; + +/** + * @covers Wikibase\MediaInfo\DataModel\MediaInfo + * + * @license GPL-2.0+ + * @author Bene* < [email protected] > + */ +class MediaInfoTest extends PHPUnit_Framework_TestCase { + + public function testConstructor() { + $id = new MediaInfoId( 'M1' ); + $labels = new TermList(); + $descriptions = new TermList(); + $statements = new StatementList(); + + $mediaInfo = new MediaInfo( $id, $labels, $descriptions, $statements ); + + $this->assertSame( $id, $mediaInfo->getId() ); + $this->assertSame( $labels, $mediaInfo->getLabels() ); + $this->assertSame( $descriptions, $mediaInfo->getDescriptions() ); + $this->assertSame( $statements, $mediaInfo->getStatements() ); + } + + public function testEmptyConstructor() { + $mediaInfo = new MediaInfo(); + + $this->assertNull( $mediaInfo->getId() ); + $this->assertEquals( new TermList(), $mediaInfo->getLabels() ); + $this->assertEquals( new TermList(), $mediaInfo->getDescriptions() ); + $this->assertEquals( new StatementList(), $mediaInfo->getStatements() ); + } + + public function testGetEntityType() { + $mediaInfo = new MediaInfo(); + + $this->assertEquals( 'mediainfo', $mediaInfo->getType() ); + } + + public function testSetNewId() { + $mediaInfo = new MediaInfo(); + $id = new MediaInfoId( 'M1' ); + $mediaInfo->setId( $id ); + + $this->assertSame( $id, $mediaInfo->getId() ); + } + + public function testOverrideId() { + $mediaInfo = new MediaInfo( new MediaInfoId( 'M1' ) ); + $id = new MediaInfoId( 'M1' ); + $mediaInfo->setId( $id ); + + $this->assertSame( $id, $mediaInfo->getId() ); + } + + public function provideInvalidIds() { + return array( + array( null ), + array( false ), + array( 42 ), + array( 'M1' ), + array( new ItemId( 'Q1' ) ) + ); + } + + /** + * @dataProvider provideInvalidIds + * @expectedException InvalidArgumentException + */ + public function testSetInvalidId( $id ) { + $mediaInfo = new MediaInfo(); + $mediaInfo->setId( $id ); + } + + public function testIsEmpty() { + $mediaInfo = new MediaInfo(); + + $this->assertTrue( $mediaInfo->isEmpty() ); + } + + public function testIsEmptyWithId() { + $mediaInfo = new MediaInfo( new MediaInfoId( 'M1' ) ); + + $this->assertTrue( $mediaInfo->isEmpty() ); + } + + public function testIsNotEmptyWithLabel() { + $mediaInfo = new MediaInfo(); + $mediaInfo->getLabels()->setTextForLanguage( 'en', 'Foo' ); + + $this->assertFalse( $mediaInfo->isEmpty() ); + } + + public function testIsNotEmptyWithDescription() { + $mediaInfo = new MediaInfo(); + $mediaInfo->getDescriptions()->setTextForLanguage( 'en', 'Foo' ); + + $this->assertFalse( $mediaInfo->isEmpty() ); + } + + public function testIsNotEmptyWithStatement() { + $mediaInfo = new MediaInfo(); + $mediaInfo->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) ); + + $this->assertFalse( $mediaInfo->isEmpty() ); + } + + public function testEqualsEmpty() { + $mediaInfo = new MediaInfo(); + + $this->assertTrue( $mediaInfo->equals( new MediaInfo() ) ); + } + + public function testEqualsSameId() { + $mediaInfo = new MediaInfo( new MediaInfoId( 'M1' ) ); + + $this->assertTrue( $mediaInfo->equals( new MediaInfo( new MediaInfoId( 'M1' ) ) ) ); + } + + public function testEqualsDifferentId() { + $mediaInfo = new MediaInfo( new MediaInfoId( 'M1' ) ); + + $this->assertTrue( $mediaInfo->equals( new MediaInfo( new MediaInfoId( 'M2' ) ) ) ); + } + + public function testEqualsNoId() { + $mediaInfo = new MediaInfo( new MediaInfoId( 'M1' ) ); + + $this->assertTrue( $mediaInfo->equals( new MediaInfo() ) ); + } + + public function testEqualsSameObject() { + $mediaInfo = new MediaInfo(); + + $this->assertTrue( $mediaInfo->equals( $mediaInfo ) ); + } + + public function testEqualsSameLabels() { + $mediaInfo1 = new MediaInfo(); + $mediaInfo2 = new MediaInfo(); + + $mediaInfo1->getLabels()->setTextForLanguage( 'en', 'Foo' ); + $mediaInfo2->getLabels()->setTextForLanguage( 'en', 'Foo' ); + + $this->assertTrue( $mediaInfo1->equals( $mediaInfo2 ) ); + } + + public function testEqualsSameDescriptions() { + $mediaInfo1 = new MediaInfo(); + $mediaInfo2 = new MediaInfo(); + + $mediaInfo1->getDescriptions()->setTextForLanguage( 'en', 'Foo' ); + $mediaInfo2->getDescriptions()->setTextForLanguage( 'en', 'Foo' ); + + $this->assertTrue( $mediaInfo1->equals( $mediaInfo2 ) ); + } + + public function testEqualsSameStatements() { + $mediaInfo1 = new MediaInfo(); + $mediaInfo2 = new MediaInfo(); + + $mediaInfo1->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) ); + $mediaInfo2->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) ); + + $this->assertTrue( $mediaInfo1->equals( $mediaInfo2 ) ); + } + + public function testNotEqualsNull() { + $mediaInfo = new MediaInfo(); + + $this->assertFalse( $mediaInfo->equals( null ) ); + } + + public function testNotEqualsItem() { + $mediaInfo = new MediaInfo(); + + $this->assertFalse( $mediaInfo->equals( new Item() ) ); + } + + public function testNotEqualsDifferentLabels() { + $mediaInfo1 = new MediaInfo(); + $mediaInfo2 = new MediaInfo(); + + $mediaInfo1->getLabels()->setTextForLanguage( 'en', 'Foo' ); + $mediaInfo2->getLabels()->setTextForLanguage( 'en', 'Bar' ); + + $this->assertFalse( $mediaInfo1->equals( $mediaInfo2 ) ); + } + + public function testNotEqualsDifferentDescriptions() { + $mediaInfo1 = new MediaInfo(); + $mediaInfo2 = new MediaInfo(); + + $mediaInfo1->getDescriptions()->setTextForLanguage( 'en', 'Foo' ); + $mediaInfo2->getDescriptions()->setTextForLanguage( 'en', 'Bar' ); + + $this->assertFalse( $mediaInfo1->equals( $mediaInfo2 ) ); + } + + public function testNotEqualsDifferentStatements() { + $mediaInfo1 = new MediaInfo(); + $mediaInfo2 = new MediaInfo(); + + $mediaInfo1->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) ); + $mediaInfo2->getStatements()->addNewStatement( new PropertyNoValueSnak( 24 ) ); + + $this->assertFalse( $mediaInfo1->equals( $mediaInfo2 ) ); + } + + public function testCopyEmptyEquals() { + $mediaInfo = new MediaInfo(); + + $this->assertEquals( $mediaInfo, $mediaInfo->copy() ); + } + + public function testCopyWithIdEquals() { + $mediaInfo = new MediaInfo( new MediaInfoId( 'M1' ) ); + + $this->assertEquals( $mediaInfo, $mediaInfo->copy() ); + } + + public function testCopyWithContentEquals() { + $mediaInfo = new MediaInfo( new MediaInfoId( 'M1' ) ); + $mediaInfo->getLabels()->setTextForLanguage( 'en', 'Foo' ); + $mediaInfo->getDescriptions()->setTextForLanguage( 'en', 'Foo' ); + $mediaInfo->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) ); + + $this->assertEquals( $mediaInfo, $mediaInfo->copy() ); + } + + public function testCopyObjectReferences() { + $id = new MediaInfoId( 'M1' ); + $labels = new TermList(); + $descriptions = new TermList(); + $statements = new StatementList(); + + $mediaInfo = new MediaInfo( $id, $labels, $descriptions, $statements ); + $copy = $mediaInfo->copy(); + + $this->assertSame( $id, $copy->getId() ); + $this->assertNotSame( $labels, $copy->getLabels() ); + $this->assertNotSame( $descriptions, $copy->getDescriptions() ); + $this->assertNotSame( $statements, $copy->getStatements() ); + } + + public function testCopyModification() { + $mediaInfo = new MediaInfo( new MediaInfoId( 'M1' ) ); + $mediaInfo->getLabels()->setTextForLanguage( 'en', 'Foo' ); + $mediaInfo->getDescriptions()->setTextForLanguage( 'en', 'Foo' ); + $mediaInfo->getStatements()->addNewStatement( new PropertyNoValueSnak( 42 ) ); + + $copy = $mediaInfo->copy(); + + $copy->setId( new MediaInfoId( 'M2' ) ); + $copy->getLabels()->setTextForLanguage( 'en', 'Bar' ); + $copy->getDescriptions()->setTextForLanguage( 'en', 'Bar' ); + $copy->getStatements()->addNewStatement( new PropertyNoValueSnak( 24 ) ); + + $this->assertEquals( 'M1', $mediaInfo->getId()->getSerialization() ); + $this->assertEquals( 'Foo', $mediaInfo->getLabels()->getByLanguage( 'en' )->getText() ); + $this->assertEquals( 'Foo', $mediaInfo->getDescriptions()->getByLanguage( 'en' )->getText() ); + $this->assertEquals( 1, $mediaInfo->getStatements()->count() ); + } + +} -- To view, visit https://gerrit.wikimedia.org/r/274768 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I5bddacca3e57b9f6f683d48b32e269a475c1cb09 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/WikibaseMediaInfo Gerrit-Branch: master Gerrit-Owner: Bene <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
