Bene has uploaded a new change for review. https://gerrit.wikimedia.org/r/274393
Change subject: Dispatch entity views based on callbacks ...................................................................... Dispatch entity views based on callbacks This removes special case handling of entity types from DispatchingEntityViewFactory and instead takes a map of entity types to callback functions that create the actual view. The callbacks are currently defined in WikibaseRepo but should be moved to a definitions file as soon as possible. Bug: T127191 Change-Id: Ia3c8a731b966cdbf54a6f3e412eee0152f124c18 --- M repo/includes/ParserOutput/DispatchingEntityViewFactory.php M repo/includes/WikibaseRepo.php M repo/tests/phpunit/includes/ParserOutput/DispatchingEntityViewFactoryTest.php 3 files changed, 145 insertions(+), 108 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase refs/changes/93/274393/1 diff --git a/repo/includes/ParserOutput/DispatchingEntityViewFactory.php b/repo/includes/ParserOutput/DispatchingEntityViewFactory.php index 86dec22..8b654dc 100644 --- a/repo/includes/ParserOutput/DispatchingEntityViewFactory.php +++ b/repo/includes/ParserOutput/DispatchingEntityViewFactory.php @@ -2,15 +2,15 @@ namespace Wikibase\Repo\ParserOutput; -use InvalidArgumentException; +use OutOfBoundsException; use Wikibase\DataModel\Services\Lookup\LabelDescriptionLookup; use Wikibase\LanguageFallbackChain; use Wikibase\View\EditSectionGenerator; use Wikibase\View\EntityView; -use Wikibase\View\ViewFactory; +use Wikimedia\Assert\Assert; /** - * A factory to create EntityView implementations based on entity type. + * A factory to create EntityView implementations by entity type based on callbacks. * * @since 0.5 * @@ -20,15 +20,17 @@ class DispatchingEntityViewFactory { /** - * @var ViewFactory + * @var callable[] */ - private $viewFactory; + private $entityViewFactoryCallbacks; /** - * @param ViewFactory $viewFactory + * @param callable[] $entityViewFactoryCallbacks */ - public function __construct( ViewFactory $viewFactory ) { - $this->viewFactory = $viewFactory; + public function __construct( array $entityViewFactoryCallbacks ) { + Assert::parameterElementType( 'callable', $entityViewFactoryCallbacks, '$entityViewFactoryCallbacks' ); + + $this->entityViewFactoryCallbacks = $entityViewFactoryCallbacks; } /** @@ -40,7 +42,7 @@ * @param LanguageFallbackChain $languageFallbackChain * @param EditSectionGenerator $editSectionGenerator * - * @throws InvalidArgumentException + * @throws OutOfBoundsException * @return EntityView */ public function newEntityView( @@ -50,24 +52,24 @@ LanguageFallbackChain $languageFallbackChain, EditSectionGenerator $editSectionGenerator ) { - switch ( $entityType ) { - case 'item': - return $this->viewFactory->newItemView( - $languageCode, - $labelDescriptionLookup, - $languageFallbackChain, - $editSectionGenerator - ); - case 'property': - return $this->viewFactory->newPropertyView( - $languageCode, - $labelDescriptionLookup, - $languageFallbackChain, - $editSectionGenerator - ); - default: - throw new InvalidArgumentException( 'No EntityView for entity type: ' . $entityType ); + if ( !isset( $this->entityViewFactoryCallbacks[$entityType] ) ) { + throw new OutOfBoundsException( "No EntityView is registered for entity type '$entityType'" ); } + + $entityView = call_user_func( + $this->entityViewFactoryCallbacks[$entityType], + $languageCode, + $labelDescriptionLookup, + $languageFallbackChain, + $editSectionGenerator + ); + + Assert::postcondition( + $entityView instanceof EntityView, + 'Callback must return an instance of EntityView' + ); + + return $entityView; } } diff --git a/repo/includes/WikibaseRepo.php b/repo/includes/WikibaseRepo.php index 01dd0b0..ccf66fe 100644 --- a/repo/includes/WikibaseRepo.php +++ b/repo/includes/WikibaseRepo.php @@ -35,6 +35,7 @@ use Wikibase\DataModel\Services\Lookup\EntityLookup; use Wikibase\DataModel\Services\Lookup\EntityRetrievingDataTypeLookup; use Wikibase\DataModel\Services\Lookup\InProcessCachingDataTypeLookup; +use Wikibase\DataModel\Services\Lookup\LabelDescriptionLookup; use Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup; use Wikibase\DataModel\Services\Lookup\TermLookup; use Wikibase\DataModel\Services\Statement\GuidGenerator; @@ -46,6 +47,7 @@ use Wikibase\InternalSerialization\DeserializerFactory as InternalDeserializerFactory; use Wikibase\InternalSerialization\SerializerFactory as InternalSerializerFactory; use Wikibase\LabelDescriptionDuplicateDetector; +use Wikibase\LanguageFallbackChain; use Wikibase\LanguageFallbackChainFactory; use Wikibase\Lib\Changes\EntityChangeFactory; use Wikibase\Lib\ContentLanguages; @@ -108,9 +110,9 @@ use Wikibase\Store\EntityIdLookup; use Wikibase\StringNormalizer; use Wikibase\SummaryFormatter; -use Wikibase\View\EntityViewFactory; -use Wikibase\View\Template\TemplateFactory; +use Wikibase\View\EditSectionGenerator; use Wikibase\View\ViewFactory; +use Wikibase\View\Template\TemplateFactory; /** * Top level factory for the WikibaseRepo extension. @@ -1438,48 +1440,83 @@ * @return EntityParserOutputGeneratorFactory */ public function getEntityParserOutputGeneratorFactory() { - global $wgLang; + $viewFactory = $this->getViewFactory(); - $templateFactory = TemplateFactory::getDefaultInstance(); - $dataTypeLookup = $this->getPropertyDataTypeLookup(); + $entityDataFormatProvider = new EntityDataFormatProvider(); + $formats = $this->getSettings()->getSetting( 'entityDataFormats' ); + $entityDataFormatProvider->setFormatWhiteList( $formats ); + + // TODO move this to WikibaseRepo.entitytypes.php or EntityHandler resp. EntityContent + $entityViewFactoryCallbacks = array( + Item::ENTITY_TYPE => function( + $languageCode, + LabelDescriptionLookup $labelDescriptionLookup, + LanguageFallbackChain $fallbackChain, + EditSectionGenerator $editSectionGenerator + ) use ( $viewFactory ) { + return $viewFactory->newItemView( + $languageCode, + $labelDescriptionLookup, + $fallbackChain, + $editSectionGenerator + ); + }, + Property::ENTITY_TYPE => function( + $languageCode, + LabelDescriptionLookup $labelDescriptionLookup, + LanguageFallbackChain $fallbackChain, + EditSectionGenerator $editSectionGenerator + ) use ( $viewFactory ) { + return $viewFactory->newPropertyView( + $languageCode, + $labelDescriptionLookup, + $fallbackChain, + $editSectionGenerator + ); + } + ); + + return new EntityParserOutputGeneratorFactory( + new DispatchingEntityViewFactory( $entityViewFactoryCallbacks ), + $this->getStore()->getEntityInfoBuilderFactory(), + $this->getEntityContentFactory(), + $this->getLanguageFallbackChainFactory(), + TemplateFactory::getDefaultInstance(), + $entityDataFormatProvider, + // FIXME: Should this be done for all usages of this lookup, or is the impact of + // CachingPropertyInfoStore enough? + new InProcessCachingDataTypeLookup( $this->getPropertyDataTypeLookup() ), + $this->getLocalEntityUriParser(), + $this->settings->getSetting( 'preferredGeoDataProperties' ), + $this->settings->getSetting( 'preferredPageImagesProperties' ), + $this->settings->getSetting( 'globeUris' ) + ); + } + + /** + * @return ViewFactory + */ + public function getViewFactory() { + /** @var Language $wgLang */ + global $wgLang; $statementGrouperBuilder = new StatementGrouperBuilder( $this->settings->getSetting( 'statementSections' ), - $dataTypeLookup + $this->getPropertyDataTypeLookup() ); - $viewFactory = new ViewFactory( + return new ViewFactory( $this->getEntityIdHtmlLinkFormatterFactory(), new EntityIdLabelFormatterFactory(), $this->getHtmlSnakFormatterFactory(), $statementGrouperBuilder->getStatementGrouper(), $this->getSiteStore(), $this->getDataTypeFactory(), - $templateFactory, + TemplateFactory::getDefaultInstance(), new LanguageNameLookup( $wgLang->getCode() ), $this->settings->getSetting( 'siteLinkGroups' ), $this->settings->getSetting( 'specialSiteLinkGroups' ), $this->settings->getSetting( 'badgeItems' ) - ); - - $entityDataFormatProvider = new EntityDataFormatProvider(); - $formats = $this->getSettings()->getSetting( 'entityDataFormats' ); - $entityDataFormatProvider->setFormatWhiteList( $formats ); - - return new EntityParserOutputGeneratorFactory( - new DispatchingEntityViewFactory( $viewFactory ), - $this->getStore()->getEntityInfoBuilderFactory(), - $this->getEntityContentFactory(), - $this->getLanguageFallbackChainFactory(), - $templateFactory, - $entityDataFormatProvider, - // FIXME: Should this be done for all usages of this lookup, or is the impact of - // CachingPropertyInfoStore enough? - new InProcessCachingDataTypeLookup( $dataTypeLookup ), - $this->getLocalEntityUriParser(), - $this->settings->getSetting( 'preferredGeoDataProperties' ), - $this->settings->getSetting( 'preferredPageImagesProperties' ), - $this->settings->getSetting( 'globeUris' ) ); } diff --git a/repo/tests/phpunit/includes/ParserOutput/DispatchingEntityViewFactoryTest.php b/repo/tests/phpunit/includes/ParserOutput/DispatchingEntityViewFactoryTest.php index 3be5930..e8816ca 100644 --- a/repo/tests/phpunit/includes/ParserOutput/DispatchingEntityViewFactoryTest.php +++ b/repo/tests/phpunit/includes/ParserOutput/DispatchingEntityViewFactoryTest.php @@ -3,11 +3,14 @@ namespace Wikibase\Repo\Tests\ParserOutput; use InvalidArgumentException; +use LogicException; +use OutOfBoundsException; use PHPUnit_Framework_TestCase; use Wikibase\DataModel\Services\Lookup\LabelDescriptionLookup; use Wikibase\LanguageFallbackChain; use Wikibase\Repo\ParserOutput\DispatchingEntityViewFactory; use Wikibase\View\EditSectionGenerator; +use Wikibase\View\EntityView; use Wikibase\View\ItemView; use Wikibase\View\PropertyView; use Wikibase\View\ViewFactory; @@ -23,11 +26,18 @@ /** * @expectedException InvalidArgumentException */ + public function testInvalidConstructorArgument() { + new DispatchingEntityViewFactory( + array( 'invalid' ) + ); + } + + /** + * @expectedException OutOfBoundsException + */ public function testUnknownEntityType() { $factory = new DispatchingEntityViewFactory( - $this->getMockBuilder( ViewFactory::class ) - ->disableOriginalConstructor() - ->getMock() + array() ); $factory->newEntityView( @@ -39,74 +49,62 @@ ); } - public function testNewItemView() { - $labelDescriptionLookup = $this->getMock( LabelDescriptionLookup::class ); - $languageFallbackChain = new LanguageFallbackChain( array() ); - $editSectionGenerator = $this->getMock( EditSectionGenerator::class ); - $itemView = $this->getMockBuilder( ItemView::class ) - ->disableOriginalConstructor()->getMockForAbstractClass(); - - $viewFactory = $this->getMockBuilder( ViewFactory::class ) - ->disableOriginalConstructor() - ->getMock(); - - $viewFactory->expects( $this->once() ) - ->method( 'newItemView' ) - ->with( - $this->equalTo( 'en' ), - $this->identicalTo( $labelDescriptionLookup ), - $this->identicalTo( $languageFallbackChain ), - $this->identicalTo( $editSectionGenerator ) + /** + * @expectedException LogicException + */ + public function testNoEntityViewReturned() { + $factory = new DispatchingEntityViewFactory( + array( + 'foo' => function() { + return null; + } ) - ->will( $this->returnValue( $itemView ) ); - - $factory = new DispatchingEntityViewFactory( $viewFactory ); - - $actual = $factory->newEntityView( - 'item', - 'en', - $labelDescriptionLookup, - $languageFallbackChain, - $editSectionGenerator, - $itemView ); - $this->assertSame( $itemView, $actual ); + $factory->newEntityView( + 'foo', + 'en', + $this->getMock( LabelDescriptionLookup::class ), + new LanguageFallbackChain( array() ), + $this->getMock( EditSectionGenerator::class ) + ); } - public function testNewPropertyView() { + public function testNewEntityView() { $labelDescriptionLookup = $this->getMock( LabelDescriptionLookup::class ); $languageFallbackChain = new LanguageFallbackChain( array() ); $editSectionGenerator = $this->getMock( EditSectionGenerator::class ); - $propertyView = $this->getMockBuilder( PropertyView::class ) - ->disableOriginalConstructor()->getMockForAbstractClass(); - - $viewFactory = $this->getMockBuilder( ViewFactory::class ) + $entityView = $this->getMockBuilder( EntityView::class ) ->disableOriginalConstructor() - ->getMock(); + ->getMockForAbstractClass(); - $viewFactory->expects( $this->once() ) - ->method( 'newPropertyView' ) - ->with( - $this->equalTo( 'en' ), - $this->identicalTo( $labelDescriptionLookup ), - $this->identicalTo( $languageFallbackChain ), - $this->identicalTo( $editSectionGenerator ) + $factory = new DispatchingEntityViewFactory( + array( + 'foo' => function( + $languageCodeParam, + LabelDescriptionLookup $labelDescriptionLookupParam, + LanguageFallbackChain $languageFallbackChainParam, + EditSectionGenerator $editSectionGeneratorParam + ) use ( $labelDescriptionLookup, $languageFallbackChain, $editSectionGenerator, $entityView ) { + $this->assertEquals( 'en', $languageCodeParam ); + $this->assertSame( $labelDescriptionLookup, $labelDescriptionLookupParam ); + $this->assertSame( $languageFallbackChain, $languageFallbackChainParam ); + $this->assertSame( $editSectionGenerator, $editSectionGeneratorParam ); + + return $entityView; + } ) - ->will( $this->returnValue( $propertyView ) ); + ); - $factory = new DispatchingEntityViewFactory( $viewFactory ); - - $actual = $factory->newEntityView( - 'property', + $newEntityView = $factory->newEntityView( + 'foo', 'en', $labelDescriptionLookup, $languageFallbackChain, - $editSectionGenerator, - $propertyView + $editSectionGenerator ); - $this->assertSame( $propertyView, $actual ); + $this->assertSame( $entityView, $newEntityView ); } } -- To view, visit https://gerrit.wikimedia.org/r/274393 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ia3c8a731b966cdbf54a6f3e412eee0152f124c18 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Bene <benestar.wikime...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits