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

Reply via email to