jenkins-bot has submitted this change and it was merged.

Change subject: OutputFormatSnakFormatterFactory to construct SnakFormatter 
based on factory callbacks
......................................................................


OutputFormatSnakFormatterFactory to construct SnakFormatter based on factory 
callbacks

This allows SnakFormatters to be defined dynamically, by registering a 
constructor callback, just like we do for ValueFormatters.

Bug: T112754
Bug: T112755
Change-Id: Iff9f832be681b941093d5cfe1e53f709ac23cdd7
---
M client/includes/WikibaseClient.php
M docs/datatypes.wiki
M lib/includes/DataTypeDefinitions.php
M lib/includes/formatters/OutputFormatSnakFormatterFactory.php
M lib/tests/phpunit/DataTypeDefinitionsTest.php
M lib/tests/phpunit/formatters/OutputFormatSnakFormatterFactoryTest.php
M repo/includes/WikibaseRepo.php
7 files changed, 124 insertions(+), 15 deletions(-)

Approvals:
  Thiemo Mättig (WMDE): Looks good to me, approved
  jenkins-bot: Verified



diff --git a/client/includes/WikibaseClient.php 
b/client/includes/WikibaseClient.php
index 07c9f1b..b92ca27 100644
--- a/client/includes/WikibaseClient.php
+++ b/client/includes/WikibaseClient.php
@@ -588,6 +588,7 @@
         */
        private function newSnakFormatterFactory() {
                $factory = new OutputFormatSnakFormatterFactory(
+                       
$this->dataTypeDefinitions->getSnakFormatterFactoryCallbacks(),
                        $this->getValueFormatterFactory(),
                        $this->getPropertyDataTypeLookup(),
                        $this->getDataTypeFactory()
diff --git a/docs/datatypes.wiki b/docs/datatypes.wiki
index 1a6a152..05064e8 100644
--- a/docs/datatypes.wiki
+++ b/docs/datatypes.wiki
@@ -41,6 +41,7 @@
 * validator-factory-callback (repo only): a callable that acts as a factory 
for the list of validators that should be used to check any user supplied 
values of the given data type. The callable will be called without any 
arguments, and must return a list of ValueValidator objects.
 * parser-factory-callback (repo only): a callable that acts as a factory for a 
ValueParser for this data type.
 * formatter-factory-callback (repo and client): a callable that acts as a 
factory for ValueFormatters for use with this data type.
+* snak-formatter-factory-callback (repo and client): a callable that acts as a 
factory for SnakFormatters for use with this data type. If not defined, a 
SnakFormatter is created from the ValueFormatter for the given data type.
 * rdf-builder-factory-callback (repo only): a callable that acts as a factory 
for ValueSnakRdfBuilder for use with this data type.
 
 Since for each property data type the associated value type is known, this 
provides a convenient
diff --git a/lib/includes/DataTypeDefinitions.php 
b/lib/includes/DataTypeDefinitions.php
index 2f89ce8..aa292fd 100644
--- a/lib/includes/DataTypeDefinitions.php
+++ b/lib/includes/DataTypeDefinitions.php
@@ -242,6 +242,15 @@
        }
 
        /**
+        * @see OutputFormatSnakFormatterFactory
+        *
+        * @return callable[]
+        */
+       public function getSnakFormatterFactoryCallbacks() {
+               return $this->getMapForDefinitionField( 
'snak-formatter-factory-callback' );
+       }
+
+       /**
         * @see ValueSnakRdfBuilderFactory
         *
         * @param string $mode PREFIXED_MODE to request a callback map with 
"VT:" and "PT:" prefixes
diff --git a/lib/includes/formatters/OutputFormatSnakFormatterFactory.php 
b/lib/includes/formatters/OutputFormatSnakFormatterFactory.php
index bf03a82..e7a5085 100644
--- a/lib/includes/formatters/OutputFormatSnakFormatterFactory.php
+++ b/lib/includes/formatters/OutputFormatSnakFormatterFactory.php
@@ -10,9 +10,12 @@
 use ValueFormatters\ValueFormatter;
 use Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup;
 use Wikibase\Lib\Formatters\ErrorHandlingSnakFormatter;
+use Wikimedia\Assert\Assert;
 
 /**
- * Service for obtaining a SnakFormatter for a desired output format.
+ * Factory service for obtaining a SnakFormatter for a desired output format.
+ * Implemented based on constructor callbacks and a default SnakFormatter 
implementation
+ * that uses TypedValueFormatters.
  *
  * @license GPL 2+
  * @author Daniel Kinzler
@@ -35,18 +38,35 @@
        private $propertyDataTypeLookup;
 
        /**
+        * @var callable[]
+        */
+       private $snakFormatterConstructorCallbacks;
+
+       /**
+        * @param callable[] $snakFormatterConstructorCallbacks An associative 
array mapping property
+        *        data type IDs to callbacks. The callbacks will be invoked 
with two parameters: the
+        *        desired output format, and the FormatterOptions. Each 
callback must return an
+        *        instance of SnakFormatter.
         * @param OutputFormatValueFormatterFactory $valueFormatterFactory
         * @param PropertyDataTypeLookup $propertyDataTypeLookup
         * @param DataTypeFactory $dataTypeFactory
         */
        public function __construct(
+               array $snakFormatterConstructorCallbacks,
                OutputFormatValueFormatterFactory $valueFormatterFactory,
                PropertyDataTypeLookup $propertyDataTypeLookup,
                DataTypeFactory $dataTypeFactory
        ) {
+               Assert::parameterElementType(
+                       'callable',
+                       $snakFormatterConstructorCallbacks,
+                       '$snakFormatterConstructorCallbacks'
+               );
+
                $this->valueFormatterFactory = $valueFormatterFactory;
-               $this->dataTypeFactory = $dataTypeFactory;
                $this->propertyDataTypeLookup = $propertyDataTypeLookup;
+               $this->dataTypeFactory = $dataTypeFactory;
+               $this->snakFormatterConstructorCallbacks = 
$snakFormatterConstructorCallbacks;
        }
 
        /**
@@ -92,10 +112,10 @@
                        // for 'value' snaks, rely on $formattersByDataType
                );
 
-               $formattersByDataType = array(
-                       // TODO: get specialized SnakFormatters from factory 
functions.
-                       '*' => $valueSnakFormatter
-               );
+               $formattersByDataType = $this->createSnakFormatters( $format, 
$options );
+
+               // Register default formatter for the special '*' key.
+               $formattersByDataType['*'] = $valueSnakFormatter;
 
                $snakFormatter = new DispatchingSnakFormatter(
                        $format,
@@ -127,4 +147,31 @@
                return $msg;
        }
 
+       /**
+        * Instantiate SnakFormatters based on the constructor callbacks passed 
to the constructor.
+        *
+        * @param string $format
+        * @param FormatterOptions $options
+        *
+        * @return SnakFormatter[]
+        */
+       private function createSnakFormatters( $format, FormatterOptions 
$options ) {
+               $formatters = array();
+
+               foreach ( $this->snakFormatterConstructorCallbacks as $key => 
$callback ) {
+                       $instance = call_user_func( $callback, $format, 
$options );
+
+                       Assert::postcondition(
+                               $instance instanceof SnakFormatter,
+                               "Constructor callback did not return a 
SnakFormatter for $key"
+                       );
+
+                       $formatters[$key] = $instance;
+               }
+
+               //FIXME: format fallback via escaping, as implemented in 
OutputFormatValueFormatterFactory!
+
+               return $formatters;
+       }
+
 }
diff --git a/lib/tests/phpunit/DataTypeDefinitionsTest.php 
b/lib/tests/phpunit/DataTypeDefinitionsTest.php
index b952667..569dfb4 100644
--- a/lib/tests/phpunit/DataTypeDefinitionsTest.php
+++ b/lib/tests/phpunit/DataTypeDefinitionsTest.php
@@ -27,6 +27,7 @@
                                'value-type' => 'FOO',
                                'validator-factory-callback' => 
'DataTypeDefinitionsTest::getFooValidators',
                                'parser-factory-callback' => 
'DataTypeDefinitionsTest::getFooParser',
+                               'snak-formatter-factory-callback' => 
'DataTypeDefinitionsTest::getFooSnakFormatter',
                        ),
                        'PT:bar' => array(
                                'value-type' => 'BAR',
diff --git 
a/lib/tests/phpunit/formatters/OutputFormatSnakFormatterFactoryTest.php 
b/lib/tests/phpunit/formatters/OutputFormatSnakFormatterFactoryTest.php
index 3613d86..5eee006 100644
--- a/lib/tests/phpunit/formatters/OutputFormatSnakFormatterFactoryTest.php
+++ b/lib/tests/phpunit/formatters/OutputFormatSnakFormatterFactoryTest.php
@@ -11,6 +11,7 @@
 use ValueFormatters\ValueFormatter;
 use Wikibase\DataModel\Entity\PropertyId;
 use Wikibase\DataModel\Snak\PropertyValueSnak;
+use Wikibase\DataModel\Snak\Snak;
 use Wikibase\LanguageFallbackChainFactory;
 use Wikibase\Lib\OutputFormatSnakFormatterFactory;
 use Wikibase\Lib\OutputFormatValueFormatterFactory;
@@ -29,15 +30,22 @@
  */
 class OutputFormatSnakFormatterFactoryTest extends \PHPUnit_Framework_TestCase 
{
 
-       private function newOutputFormatSnakFormatterFactory() {
+       private function newOutputFormatSnakFormatterFactory( $dataType = 
'string' ) {
                $self = $this;
-               $callbacks = array(
+
+               $snakFormatterCallbacks = array(
+                       'commonsMedia' => function( $format, FormatterOptions 
$options ) use ( $self ) {
+                               return $self->makeMockSnakFormatter( $format );
+                       },
+               );
+
+               $valueFormatterCallbacks = array(
                        'VT:string' => function( $format, FormatterOptions 
$options ) use ( $self ) {
                                return $self->makeMockValueFormatter( $format );
                        },
                );
                $valueFormatterFactory = new OutputFormatValueFormatterFactory(
-                       $callbacks,
+                       $valueFormatterCallbacks,
                        Language::factory( 'en' ),
                        new LanguageFallbackChainFactory()
                );
@@ -47,12 +55,13 @@
                );
                $dataTypeLookup->expects( $this->any() )
                        ->method( 'getDataTypeIdForProperty' )
-                       ->will( $this->returnValue( 'string' ) );
+                       ->will( $this->returnValue( $dataType ) );
 
                return new OutputFormatSnakFormatterFactory(
+                       $snakFormatterCallbacks,
                        $valueFormatterFactory,
                        $dataTypeLookup,
-                       new DataTypeFactory( array( 'string' => 'string' ) )
+                       new DataTypeFactory( array( 'string' => 'string', 
'commonsMedia' => 'string' ) )
                );
        }
 
@@ -70,17 +79,55 @@
                return $mock;
        }
 
+       public function makeMockSnakFormatter( $format ) {
+               $mock = $this->getMock( 'Wikibase\Lib\SnakFormatter' );
+
+               $mock->expects( $this->any() )
+                       ->method( 'formatSnak' )
+                       ->will( $this->returnCallback(
+                               function( Snak $snak ) use ( $format ) {
+                                       $s = $snak->getType() . '/' . 
$snak->getPropertyId();
+
+                                       if ( $snak instanceof PropertyValueSnak 
) {
+                                               $s .= '=' . strval( 
$snak->getDataValue()->getValue() );
+                                       }
+
+                                       return $s . ' (' . $format . ')';
+                               }
+                       ) );
+
+               $mock->expects( $this->any() )
+                       ->method( 'getFormat' )
+                       ->will( $this->returnValue( $format ) );
+
+               return $mock;
+       }
+
        public function getSnakFormatterProvider() {
                return array(
-                       'plain' => array(
+                       'plain value' => array(
                                SnakFormatter::FORMAT_PLAIN,
+                               'string',
                                new StringValue( 'foo' ),
                                'foo (text/plain)',
                        ),
-                       'html' => array(
+                       'html value' => array(
                                SnakFormatter::FORMAT_HTML,
+                               'string',
                                new StringValue( 'foo' ),
                                'foo (text/html)',
+                       ),
+                       'plain snak' => array(
+                               SnakFormatter::FORMAT_PLAIN,
+                               'commonsMedia', // the mock has a SnakFormatter 
for commonsMedia
+                               new StringValue( 'foo.jpg' ),
+                               'value/P5=foo.jpg (text/plain)',
+                       ),
+                       'html snak' => array(
+                               SnakFormatter::FORMAT_HTML,
+                               'commonsMedia', // the mock has a SnakFormatter 
for commonsMedia
+                               new StringValue( 'foo.jpg' ),
+                               'value/P5=foo.jpg (text/html)',
                        ),
                );
        }
@@ -88,8 +135,8 @@
        /**
         * @dataProvider getSnakFormatterProvider
         */
-       public function testGetSnakFormatter( $format, DataValue $value, 
$expected ) {
-               $factory = $this->newOutputFormatSnakFormatterFactory();
+       public function testGetSnakFormatter( $format, $dataType, DataValue 
$value, $expected ) {
+               $factory = $this->newOutputFormatSnakFormatterFactory( 
$dataType );
                $formatter = $factory->getSnakFormatter( $format, new 
FormatterOptions() );
 
                $this->assertInstanceOf( 'Wikibase\Lib\SnakFormatter', 
$formatter );
@@ -144,6 +191,7 @@
                );
 
                $factory = new OutputFormatSnakFormatterFactory(
+                       array(),
                        $valueFormatterFactory,
                        $this->getMock( 
'Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup' ),
                        new DataTypeFactory( array() )
diff --git a/repo/includes/WikibaseRepo.php b/repo/includes/WikibaseRepo.php
index 64ac2bd..84685aa 100644
--- a/repo/includes/WikibaseRepo.php
+++ b/repo/includes/WikibaseRepo.php
@@ -768,6 +768,7 @@
         */
        protected function newSnakFormatterFactory() {
                $factory = new OutputFormatSnakFormatterFactory(
+                       
$this->dataTypeDefinitions->getSnakFormatterFactoryCallbacks(),
                        $this->getValueFormatterFactory(),
                        $this->getPropertyDataTypeLookup(),
                        $this->getDataTypeFactory()
@@ -883,6 +884,7 @@
 
                // Create a new SnakFormatterFactory based on the specialized 
ValueFormatterFactory.
                $snakFormatterFactory = new OutputFormatSnakFormatterFactory(
+                       array(), // XXX: do we want 
$this->dataTypeDefinitions->getSnakFormatterFactoryCallbacks()
                        $valueFormatterFactory,
                        $this->getPropertyDataTypeLookup(),
                        $this->getDataTypeFactory()

-- 
To view, visit https://gerrit.wikimedia.org/r/253683
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Iff9f832be681b941093d5cfe1e53f709ac23cdd7
Gerrit-PatchSet: 14
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <daniel.kinz...@wikimedia.de>
Gerrit-Reviewer: Addshore <addshorew...@gmail.com>
Gerrit-Reviewer: Adrian Lang <adrian.he...@wikimedia.de>
Gerrit-Reviewer: Aude <aude.w...@gmail.com>
Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de>
Gerrit-Reviewer: Jonas Kress (WMDE) <jonas.kr...@wikimedia.de>
Gerrit-Reviewer: Thiemo Mättig (WMDE) <thiemo.maet...@wikimedia.de>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to