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

Change subject: Dispatch snak formatting by data type.
......................................................................


Dispatch snak formatting by data type.

This allows DispatchingSnakFormatter to dispatch by data type
as well as snak type.

Bug: T112758
Change-Id: I7075e0cd09774f881b13301bd88209837b44a121
---
M lib/includes/formatters/DispatchingSnakFormatter.php
M lib/includes/formatters/OutputFormatSnakFormatterFactory.php
M lib/tests/phpunit/formatters/DispatchingSnakFormatterTest.php
3 files changed, 202 insertions(+), 91 deletions(-)

Approvals:
  Hoo man: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/lib/includes/formatters/DispatchingSnakFormatter.php 
b/lib/includes/formatters/DispatchingSnakFormatter.php
index 5ff3bff..dc2db52 100644
--- a/lib/includes/formatters/DispatchingSnakFormatter.php
+++ b/lib/includes/formatters/DispatchingSnakFormatter.php
@@ -4,11 +4,14 @@
 
 use InvalidArgumentException;
 use ValueFormatters\FormattingException;
+use Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup;
+use Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookupException;
 use Wikibase\DataModel\Snak\Snak;
+use Wikimedia\Assert\Assert;
 
 /**
- * DispatchingSnakFormatter will format a snak by delegating the formatting to 
an appropriate
- * SnakFormatter for the snak's type.
+ * DispatchingSnakFormatter will format a Snak by delegating the formatting to 
an appropriate
+ * SnakFormatter based on the snak type or the associated property's data type.
  *
  * @license GPL 2+
  * @author Daniel Kinzler
@@ -16,45 +19,81 @@
 class DispatchingSnakFormatter implements SnakFormatter {
 
        /**
-        * @var SnakFormatter[] a map of snak type IDs to SnakFormatter objects
-        */
-       private $formatters;
-
-       /**
         * @var string
         */
        private $format;
 
        /**
-        * @param string $format
-        * @param SnakFormatter[] $formatters a map of snak type IDs to 
SnakFormatter objects
-        *
-        * @throws \InvalidArgumentException
+        * @var PropertyDataTypeLookup
         */
-       public function __construct( $format, array $formatters ) {
-               if ( !is_string( $format ) ) {
-                       throw new InvalidArgumentException( '$format must be a 
string' );
-               }
+       private $dataTypeLookup;
 
+       /**
+        * @var SnakFormatter[]
+        */
+       private $formattersByDataType;
+
+       /**
+        * @var SnakFormatter[]
+        */
+       private $formattersBySnakType;
+
+       /**
+        * @param string $format The output format generated by this formatter. 
All formatters
+        *  provided to the constructor must produce the same output format.
+        * @param PropertyDataTypeLookup $dataTypeLookup
+        * @param SnakFormatter[] $formattersBySnakType An associative array 
mapping snak types
+        *  to SnakFormatter objects. If no formatter is defined for the a 
given snak type,
+        *  $formattersByDataType will be checked for a SnakFormatter for the 
snak's data type.
+        * @param SnakFormatter[] $formattersByDataType An associative array 
mapping data types
+        *  to SnakFormatter objects. If no formatter is defined for the a 
given data type,
+        *  the "*" key in this array is checked for a default formatter.
+        *
+        * @throws InvalidArgumentException
+        */
+       public function __construct(
+               $format,
+               PropertyDataTypeLookup $dataTypeLookup,
+               array $formattersBySnakType,
+               array $formattersByDataType
+       ) {
+               Assert::parameterType( 'string', $format, '$format' );
+
+               $this->assertFormatterArray( $format, $formattersBySnakType );
+               $this->assertFormatterArray( $format, $formattersByDataType );
+
+               $this->format = $format;
+               $this->dataTypeLookup = $dataTypeLookup;
+               $this->formattersBySnakType = $formattersBySnakType;
+               $this->formattersByDataType = $formattersByDataType;
+       }
+
+       private function assertFormatterArray( $format, array $formatters ) {
                foreach ( $formatters as $type => $formatter ) {
                        if ( !is_string( $type ) ) {
-                               throw new InvalidArgumentException( 
'$formatters must map type IDs to formatters.' );
+                               throw new InvalidArgumentException( 'formatter 
array must map type IDs to formatters.' );
                        }
 
                        if ( !( $formatter instanceof SnakFormatter ) ) {
-                               throw new InvalidArgumentException( 
'$formatters must contain instances for SnakFormatter.' );
+                               throw new InvalidArgumentException( 'formatter 
array must contain instances of SnakFormatter.' );
                        }
 
                        if ( $formatter->getFormat() !== $format ) {
                                throw new InvalidArgumentException( 'The 
formatter supplied for ' . $type
-                                               . ' returns ' . 
$formatter->getFormat() . ', but we expect ' . $format . '.' );
+                                       . ' produces ' . 
$formatter->getFormat() . ', but we expect ' . $format . '.' );
                        }
                }
+       }
 
-               $this->format = $format;
-               $this->formatters = $formatters;
-
-               //XXX: this should perhaps use, or be, a 
OutputFormatSnakFormatterFactory
+       /**
+        * @param Snak $snak
+        *
+        * @throws PropertyDataTypeLookupException
+        * @return string The Snak's data type
+        */
+       private function getSnakDataType( Snak $snak ) {
+               return $this->dataTypeLookup->getDataTypeIdForProperty( 
$snak->getPropertyId() );
+               // @todo: wrap the PropertyDataTypeLookupException, but make 
sure ErrorHandlingSnakFormatter still handles it.
        }
 
        /**
@@ -64,38 +103,30 @@
         * @param Snak $snak
         *
         * @throws FormattingException
-        * @return string
+        * @throws PropertyDataTypeLookupException
+        * @return string The formatted snak value, in the format specified by 
getFormat().
         */
        public function formatSnak( Snak $snak ) {
-               $type = $snak->getType();
-               $formatter = $this->getFormatter( $type );
+               $snakType = $snak->getType();
 
-               if ( !$formatter ) {
-                       throw new FormattingException( "No formatter found for 
snak type $type" );
+               if ( isset(  $this->formattersBySnakType[$snakType] ) ) {
+                       $formatter = $this->formattersBySnakType[$snakType];
+                       return $formatter->formatSnak( $snak );
                }
 
-               $text = $formatter->formatSnak( $snak );
-               return $text;
-       }
+               $dataType = $this->getSnakDataType( $snak );
 
-       /**
-        * @param string $type
-        *
-        * @return null|SnakFormatter
-        */
-       public function getFormatter( $type ) {
-               if ( !isset( $this->formatters[$type] ) ) {
-                       return null;
+               if ( isset( $this->formattersByDataType[$dataType] ) ) {
+                       $formatter = $this->formattersByDataType[$dataType];
+                       return $formatter->formatSnak( $snak );
                }
 
-               return $this->formatters[$type];
-       }
+               if ( isset( $this->formattersByDataType['*'] ) ) {
+                       $formatter = $this->formattersByDataType['*'];
+                       return $formatter->formatSnak( $snak );
+               }
 
-       /**
-        * @return string[]
-        */
-       public function getSnakTypes() {
-               return array_keys( $this->formatters );
+               throw new FormattingException( "No formatter found for snak 
type $snakType and data type $dataType" );
        }
 
        /**
diff --git a/lib/includes/formatters/OutputFormatSnakFormatterFactory.php 
b/lib/includes/formatters/OutputFormatSnakFormatterFactory.php
index 2bd058b..1dc158f 100644
--- a/lib/includes/formatters/OutputFormatSnakFormatterFactory.php
+++ b/lib/includes/formatters/OutputFormatSnakFormatterFactory.php
@@ -87,13 +87,23 @@
                        $this->dataTypeFactory
                );
 
-               $formatters = array(
+               $formattersBySnakType = array(
                        'novalue' => $noValueSnakFormatter,
                        'somevalue' => $someValueSnakFormatter,
-                       'value' => $valueSnakFormatter,
+                       // for 'value' snaks, rely on $formattersByDataType
                );
 
-               $snakFormatter = new DispatchingSnakFormatter( $format, 
$formatters );
+               $formattersByDataType = array(
+                       // TODO: get specialized SnakFormatters from factory 
functions.
+                       '*' => $valueSnakFormatter
+               );
+
+               $snakFormatter = new DispatchingSnakFormatter(
+                       $format,
+                       $this->propertyDataTypeLookup,
+                       $formattersBySnakType,
+                       $formattersByDataType
+               );
 
                if ( $options->getOption( SnakFormatter::OPT_ON_ERROR ) === 
SnakFormatter::ON_ERROR_WARN ) {
                        $snakFormatter = new ErrorHandlingSnakFormatter(
diff --git a/lib/tests/phpunit/formatters/DispatchingSnakFormatterTest.php 
b/lib/tests/phpunit/formatters/DispatchingSnakFormatterTest.php
index 12d38ee..ea148c1 100644
--- a/lib/tests/phpunit/formatters/DispatchingSnakFormatterTest.php
+++ b/lib/tests/phpunit/formatters/DispatchingSnakFormatterTest.php
@@ -3,10 +3,13 @@
 namespace Wikibase\Lib\Test;
 
 use DataValues\StringValue;
+use ValueFormatters\StringFormatter;
 use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup;
 use Wikibase\DataModel\Snak\PropertyNoValueSnak;
 use Wikibase\DataModel\Snak\PropertySomeValueSnak;
 use Wikibase\DataModel\Snak\PropertyValueSnak;
+use Wikibase\DataModel\Snak\Snak;
 use Wikibase\Lib\DispatchingSnakFormatter;
 use Wikibase\Lib\MessageSnakFormatter;
 use Wikibase\Lib\SnakFormatter;
@@ -25,12 +28,54 @@
 class DispatchingSnakFormatterTest extends \PHPUnit_Framework_TestCase {
 
        /**
+        * @param string $dataType
+        *
+        * @return PropertyDataTypeLookup
+        */
+       private function getDataTypeLookup( $dataType = 'string' ) {
+               $dataTypeLookup = $this->getMock( 
'Wikibase\DataModel\Services\Lookup\PropertyDataTypeLookup' );
+
+               $dataTypeLookup->expects( $this->any() )
+                       ->method( 'getDataTypeIdForProperty' )
+                       ->will( $this->returnValue( $dataType ) );
+
+               return $dataTypeLookup;
+       }
+
+       /**
+        * @param string $output the return value for formatSnak
+        * @param string $format the return value for getFormat
+        *
+        * @return SnakFormatter
+        */
+       private function makeSnakFormatter( $output, $format = 
SnakFormatter::FORMAT_PLAIN ) {
+               $formatter = $this->getMock( 'Wikibase\Lib\SnakFormatter' );
+
+               $formatter->expects( $this->any() )
+                       ->method( 'formatSnak' )
+                       ->will( $this->returnValue( $output ) );
+
+               $formatter->expects( $this->any() )
+                       ->method( 'getFormat' )
+                       ->will( $this->returnValue( $format ) );
+
+               return $formatter;
+       }
+
+       /**
         * @dataProvider constructorErrorsProvider
         */
-       public function testConstructorErrors( $format, array $formatters, 
$error ) {
-               $this->setExpectedException( $error );
+       public function testConstructorErrors( $format, array 
$formattersBySnakType, array $formattersByDataType ) {
+               $this->setExpectedException( 'InvalidArgumentException' );
 
-               new DispatchingSnakFormatter( $format, $formatters );
+               $dataTypeLookup = $this->getDataTypeLookup();
+
+               new DispatchingSnakFormatter(
+                       $format,
+                       $dataTypeLookup,
+                       $formattersBySnakType,
+                       $formattersByDataType
+               );
        }
 
        public function constructorErrorsProvider() {
@@ -44,69 +89,94 @@
                        'format must be a string' => array(
                                17,
                                array(),
-                               'InvalidArgumentException'
+                               array(),
                        ),
-                       'keys must be strings' => array(
+                       'snak types must be strings' => array(
                                SnakFormatter::FORMAT_PLAIN,
                                array( 17 => $formatter ),
-                               'InvalidArgumentException'
+                               array( 'string' => $formatter ),
                        ),
-                       'formatters must be instances of SnakFormatter' => 
array(
+                       'data types must be strings' => array(
+                               SnakFormatter::FORMAT_PLAIN,
+                               array(),
+                               array( 17 => $formatter ),
+                       ),
+                       'snak type formatters must be SnakFormatters' => array(
                                SnakFormatter::FORMAT_PLAIN,
                                array( 'novalue' => 17 ),
-                               'InvalidArgumentException'
+                               array( 'string' => $formatter ),
                        ),
-                       'mismatching output format' => array(
+                       'data type formatters must be SnakFormatters' => array(
+                               SnakFormatter::FORMAT_PLAIN,
+                               array(),
+                               array( 'string' => 17 ),
+                       ),
+                       'snak type formatters mismatches output format' => 
array(
                                SnakFormatter::FORMAT_HTML,
                                array( 'novalue' => $formatter ),
-                               'InvalidArgumentException'
+                               array( 'string' => $formatter ),
+                       ),
+                       'data type formatters mismatches output format' => 
array(
+                               SnakFormatter::FORMAT_HTML,
+                               array(),
+                               array( 'string' => $formatter ),
                        ),
                );
        }
 
-       public function testFormatSnak() {
-               $novalue = wfMessage( 
'wikibase-snakview-snaktypeselector-novalue' );
-               $somevalue = wfMessage( 
'wikibase-snakview-snaktypeselector-somevalue' );
-               $value = wfMessage( 'wikibase-snakview-snaktypeselector-value' 
);
+       public function provideFormatSnak() {
+               $p23 = new PropertyId( 'P23' );
 
-               $formatter = new DispatchingSnakFormatter( 
SnakFormatter::FORMAT_PLAIN, array(
-                       'novalue' => new MessageSnakFormatter( 'novalue', 
$novalue, SnakFormatter::FORMAT_PLAIN ),
-                       'somevalue' => new MessageSnakFormatter( 'somevalue', 
$somevalue, SnakFormatter::FORMAT_PLAIN ),
-                       'value' => new MessageSnakFormatter( 'value', $value, 
SnakFormatter::FORMAT_PLAIN ),
-               ) );
-
-               $novalueSnak = new PropertyNoValueSnak( new PropertyId( 'P23' ) 
);
-               $somevalueSnak = new PropertySomeValueSnak( new PropertyId( 
'P23' ) );
-               $valueSnak = new PropertyValueSnak( new PropertyId( 'P23' ), 
new StringValue( 'test' ) );
-
-               $this->assertEquals( $novalue->text(), $formatter->formatSnak( 
$novalueSnak ) );
-               $this->assertEquals( $somevalue->text(), 
$formatter->formatSnak( $somevalueSnak ) );
-               $this->assertEquals( $value->text(), $formatter->formatSnak( 
$valueSnak ) );
+               return array(
+                       'novalue' => array(
+                               'NO VALUE',
+                               new PropertyNoValueSnak( $p23 ),
+                               'string'
+                       ),
+                       'somevalue' => array(
+                               'SOME VALUE',
+                               new PropertySomeValueSnak( $p23 ),
+                               'string'
+                       ),
+                       'string value' => array(
+                               'STRING VALUE',
+                               new PropertyValueSnak( $p23, new StringValue( 
'dummy' ) ),
+                               'string'
+                       ),
+                       'other value' => array(
+                               'OTHER VALUE',
+                               new PropertyValueSnak( $p23, new StringValue( 
'dummy' ) ),
+                               'url'
+                       ),
+               );
        }
 
-       public function testGetSnakTypes() {
-               $novalue = wfMessage( 
'wikibase-snakview-snaktypeselector-novalue' );
-               $somevalue = wfMessage( 
'wikibase-snakview-snaktypeselector-somevalue' );
-               $value = wfMessage( 'wikibase-snakview-snaktypeselector-value' 
);
-
-               $formatters = array(
-                       'novalue' => new MessageSnakFormatter( 'novalue', 
$novalue, SnakFormatter::FORMAT_PLAIN ),
-                       'somevalue' => new MessageSnakFormatter( 'somevalue', 
$somevalue, SnakFormatter::FORMAT_PLAIN ),
-                       'value' => new MessageSnakFormatter( 'value', $value, 
SnakFormatter::FORMAT_PLAIN ),
+       /**
+        * @dataProvider provideFormatSnak
+        */
+       public function testFormatSnak( $expected, Snak $snak, $dataType ) {
+               $formattersBySnakType = array(
+                       'novalue' => $this->makeSnakFormatter( 'NO VALUE' ),
+                       'somevalue' => $this->makeSnakFormatter( 'SOME VALUE' ),
                );
 
-               $formatter = new DispatchingSnakFormatter( 
SnakFormatter::FORMAT_PLAIN, $formatters );
+               $formattersByDataType = array(
+                       'string' =>  $this->makeSnakFormatter( 'STRING VALUE' ),
+                       '*' => $this->makeSnakFormatter( 'OTHER VALUE' ),
+               );
 
-               $this->assertEquals( array_keys( $formatters ), 
$formatter->getSnakTypes() );
+               $formatter = new DispatchingSnakFormatter(
+                       SnakFormatter::FORMAT_PLAIN,
+                       $this->getDataTypeLookup( $dataType ),
+                       $formattersBySnakType,
+                       $formattersByDataType
+               );
 
-               foreach ( $formatters as $type => $expected ) {
-                       $actual = $formatter->getFormatter( $type );
-                       $this->assertSame( $formatters[$type], $actual );
-               }
+               $this->assertEquals( $expected, $formatter->formatSnak( $snak ) 
);
        }
 
        public function testGetFormat() {
-               $formatter = new DispatchingSnakFormatter( 'test', array() );
+               $formatter = new DispatchingSnakFormatter( 'test', 
$this->getDataTypeLookup(), array(), array() );
                $this->assertEquals( 'test', $formatter->getFormat() );
        }
 

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I7075e0cd09774f881b13301bd88209837b44a121
Gerrit-PatchSet: 3
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Hoo man <[email protected]>
Gerrit-Reviewer: Jonas Kress (WMDE) <[email protected]>
Gerrit-Reviewer: Thiemo Mättig (WMDE) <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to