Daniel Kinzler has submitted this change and it was merged.

Change subject: Second iteration of property parser function
......................................................................


Second iteration of property parser function

* supports multiple values for a property
* returns empty string if there is some error (@todo nicer error 
handling/feedback for editor)
* supports wikibase item, commons media and strings
* supports lookup by property id; lookup by label is experimental
* has in-process caching
* handles PropertyValueSnak and ignores other Snak types (returns empty 
string), with @todo marked

@todo:

* tests
* handle no value and other property snak types
* memcached support and optimization
* use terms table for property id/label lookups
* generic value formatter for string, to put in ValueFormatters

Change-Id: I70a9ff2976940ecf601320ecece35943e89e94bc
---
M client/includes/parserhooks/ParserErrorMessageFormatter.php
M client/includes/parserhooks/PropertyParserFunction.php
M client/includes/store/ClientStore.php
M client/includes/store/sql/CachingSqlStore.php
M client/includes/store/sql/DirectSqlStore.php
M lib/WikibaseLib.php
A lib/includes/formatters/ItemFormatter.php
A lib/includes/formatters/StringFormatter.php
A lib/includes/store/PropertyLookup.php
A lib/includes/store/PropertySQLLookup.php
10 files changed, 592 insertions(+), 82 deletions(-)

Approvals:
  Daniel Kinzler: Verified; Looks good to me, approved
  jenkins-bot: Checked



diff --git a/client/includes/parserhooks/ParserErrorMessageFormatter.php 
b/client/includes/parserhooks/ParserErrorMessageFormatter.php
index 108aab2..4a9e5d1 100644
--- a/client/includes/parserhooks/ParserErrorMessageFormatter.php
+++ b/client/includes/parserhooks/ParserErrorMessageFormatter.php
@@ -53,11 +53,13 @@
         * @return string
         */
        public function format( \Message $message ) {
-               return \Html::rawElement(
+               return '';
+       /*      return \Html::rawElement(
                        'span',
                        array( 'class' => 'error' ),
             $message->inLanguage( $this->language )->text()
                );
+       */
        }
 
 }
diff --git a/client/includes/parserhooks/PropertyParserFunction.php 
b/client/includes/parserhooks/PropertyParserFunction.php
index 91fe418..c6c6949 100644
--- a/client/includes/parserhooks/PropertyParserFunction.php
+++ b/client/includes/parserhooks/PropertyParserFunction.php
@@ -1,6 +1,8 @@
 <?php
 
 namespace Wikibase;
+use ValueFormatters\FormatterOptions;
+use DataValues\DataValue;
 
 /**
  * {{#property}} parser function
@@ -30,95 +32,131 @@
  */
 class PropertyParserFunction {
 
-       /* @var Site */
-       protected $site;
+       /* @var Language */
+       protected $language;
 
-       /* @var EntityId */
-       protected $entityId;
-
-       /* @var WikiPageEntityLookup */
+       /* @var EntityLookup */
        protected $entityLookup;
+
+       /* @var PropertyLookup */
+       protected $propertyLookup;
 
        /* @var ParserErrorMessageFormatter */
        protected $errorFormatter;
 
+       /* @var array */
+       protected $availableDataTypes;
+
        /**
         * @since 0.4
         *
-        * @param \Site                       $site
-        * @param EntityId                    $entityId
-        * @param EntityLookup                $entityLookup
+        * @param \Language $language
+        * @param EntityLookup $entityLookup
+        * @param PropertyLookup $propertyLookup
         * @param ParserErrorMessageFormatter $errorFormatter
+        * @param string $dataTypes[]
         */
-       public function __construct( \Site $site, EntityId $entityId,
-               EntityLookup $entityLookup, ParserErrorMessageFormatter 
$errorFormatter ) {
-               $this->site = $site;
-               $this->entityId = $entityId;
+       public function __construct( \Language $language, EntityLookup 
$entityLookup, PropertyLookup $propertyLookup,
+               ParserErrorMessageFormatter $errorFormatter, array $dataTypes ) 
{
+               $this->language = $language;
                $this->entityLookup = $entityLookup;
+               $this->propertyLookup = $propertyLookup;
                $this->errorFormatter = $errorFormatter;
+               $this->availableDataTypes = $dataTypes;
        }
 
        /**
-        * Get data value for a property of item associated with client wiki 
page
+        * Get value of EntityId DataValue
         *
         * @since 0.4
         *
-        * @param Entity $entity
-        * @param string $propertyLabel
-        *
-        * @return Snak
-        */
-       public function getMainSnak( Entity $entity, $propertyLabel ) {
-               $claimsByProperty = array();
-
-               foreach( $entity->getClaims() as $claim ) {
-                       $propertyId = $claim->getMainSnak()->getPropertyId();
-                       $claimsByProperty[$propertyId->getNumericId()][] = 
$claim;
-               }
-
-               if ( $claimsByProperty !== array() ) {
-                       foreach( $claimsByProperty as $id => $claims ) {
-                               foreach( $claims as $claim ) {
-                                       $mainSnak = $claim->getMainSnak();
-                                       $property = 
$this->entityLookup->getEntity( $mainSnak->getPropertyId() );
-
-                                       // @todo allow lookup by entity id, in 
addition to label?
-                                       if ( $property->getLabel( 
$this->site->getLanguageCode() ) === $propertyLabel ) {
-                                               return $mainSnak;
-                                       }
-                               }
-                       }
-               }
-
-               return false;
-       }
-
-       /**
-        * Get data value for snak
-        * @todo handle all property types!
-        *
-        * @since 0.4
-        *
-        * @param Snak $snak
-        * @param string $propertyLabel
+        * @param EntityId $entityId
         *
         * @return string
         */
-       protected function getSnakValue( Snak $snak, $propertyLabel ) {
-               $propertyValue = $snak->getDataValue();
+       protected function getEntityIdValue( EntityId $entityId ) {
+               wfProfileIn( __METHOD__ );
 
-               if ( $propertyValue instanceof \Wikibase\EntityId ) {
-                       $langCode = $this->site->getLanguageCode();
-                       // @todo we could use the terms table to lookup label
-                       // we would need to have some store lookup code in 
WikibaseLib
-                       $entity = $this->entityLookup->getEntity( 
$propertyValue );
-                       $label = $entity->getLabel( 
$this->site->getLanguageCode() );
+               // @todo we could use the terms table to lookup label
+               // we would need to have some store lookup code in WikibaseLib
+               $entity = $this->entityLookup->getEntity( $entityId );
+               $label = $entity->getLabel( $this->language->getCode() );
 
-                       // @todo ick! handle when there is no label...
-                       return $label !== false ? $label : 
$entity->getPrefixedId();
+               // @todo ick! handle when there is no label...
+               $labelValue = $label !== false ? $label : '';
+
+               wfProfileOut( __METHOD__ );
+               return $labelValue;
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @param Snak $snak
+        *
+        * @return string
+        */
+       public function formatDataValue( DataValue $dataValue ) {
+               wfProfileIn( __METHOD__ );
+               $dataType = $dataValue->getType();
+
+               // @fixme why is $dataType inconsistent with data type settings?
+               if ( !in_array( $dataType, $this->availableDataTypes ) && 
$dataType !== 'wikibase-entityid' ) {
+                       // @todo error handling, data type not supported
+                       return '';
                }
 
-               return null;
+               $formatterOptions = new FormatterOptions( array( 'lang' => 
$this->language->getCode() ) );
+               $formattedValue = '';
+
+               if ( $dataType === 'wikibase-entityid' ) {
+                       $valueFormatter = new ItemFormatter( $formatterOptions, 
$this->entityLookup );
+                       $formattedValue = $valueFormatter->format( $dataValue );
+               } else if ( in_array( $dataType, array( 'commonsMedia', 
'string' ) ) ) {
+                       $valueFormatter = new StringFormatter( 
$formatterOptions );
+                       $formattedValue = $valueFormatter->format( $dataValue );
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $formattedValue;
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @param SnakList $snakList
+        *
+        * @return string - wikitext format
+        */
+       public function formatSnakList( SnakList $snakList, $propertyLabel ) {
+               wfProfileIn( __METHOD__ );
+               $values = array();
+
+               foreach( $snakList as $snak ) {
+                       // @todo handle other snak types
+                       if ( $snak instanceof PropertyValueSnak ) {
+                               $values[] = $snak->getDataValue();
+                       }
+               }
+
+               if ( $values !== array() ) {
+                       wfProfileOut( __METHOD__ );
+                       $formattedValues = array();
+
+                       foreach( $values as $dataValue ) {
+                               $formattedValues[] = $this->formatDataValue( 
$dataValue );
+                       }
+
+                       return $this->language->commaList( $formattedValues );
+               }
+
+               if ( ! isset( $errorMessage ) ) {
+                       // formatted as empty string
+                       $errorMessage = new \Message( 
'wikibase-property-notfound', array( wfEscapeWikiText( $propertyLabel ) ) );
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $this->errorFormatter->format( $errorMessage );
        }
 
        /**
@@ -128,27 +166,27 @@
         *
         * @return string - wikitext format
         */
-       public function evaluate( $propertyLabel ) {
-               $snak = $this->getMainSnak(
-                       $this->entityLookup->getEntity( $this->entityId ),
-                       $propertyLabel
-               );
+    public function evaluate( EntityId $entityId, $propertyLabel ) {
+               wfProfileIn( __METHOD__ );
 
-               if ( $snak instanceof \Wikibase\Snak ) {
-                       $snakValue = $this->getSnakValue( $snak, $propertyLabel 
);
+               $snakList = new SnakList();
 
-                       if ( $snakValue !== null ) {
-                               return wfEscapeWikiText( $snakValue );
-                       }
+               $propertyIdToFind = EntityId::newFromPrefixedId( $propertyLabel 
);
 
-                       $errorMessage = new \Message( 
'wikibase-property-notsupportedyet', array( wfEscapeWikiText( $propertyLabel ) 
) );
+               if ( $propertyIdToFind !== null ) {
+                       $snakList = 
$this->propertyLookup->getMainSnaksByPropertyId( $entityId, $propertyIdToFind );
+               } else {
+                       $langCode = $this->language->getCode();
+                       $snakList = 
$this->propertyLookup->getMainSnaksByPropertyLabel( $entityId, $propertyLabel, 
$langCode );
                }
 
-               if ( ! isset( $errorMessage ) ) {
-                       $errorMessage = new \Message( 
'wikibase-property-notfound', array( wfEscapeWikiText( $propertyLabel ) ) );
+               if ( $snakList->isEmpty() ) {
+                       wfProfileOut( __METHOD__ );
+                       return '';
                }
 
-               return $this->errorFormatter->format( $errorMessage );
+               wfProfileOut( __METHOD__ );
+               return $this->formatSnakList( $snakList, $propertyLabel );
        }
 
        /**
@@ -159,6 +197,7 @@
         * @return string
         */
        public static function render( \Parser $parser, $propertyLabel ) {
+               wfProfileIn( __METHOD__ );
                $site = \Sites::singleton()->getSite( Settings::get( 
'siteGlobalID' ) );
 
                $siteLinkLookup = 
ClientStoreFactory::getStore()->newSiteLinkTable();
@@ -168,19 +207,28 @@
 
                // @todo handle when site link is not there, such as site link 
/ entity has been deleted...
                if ( $entityId === null ) {
+                       wfProfileOut( __METHOD__ );
                        return '';
                }
 
                $entityLookup = 
ClientStoreFactory::getStore()->getEntityLookup();
 
-               $errorFormatter = new ParserErrorMessageFormatter( 
$parser->getTargetLanguage() );
+               $targetLanguage = $parser->getTargetLanguage();
+               $errorFormatter = new ParserErrorMessageFormatter( 
$targetLanguage );
 
-               $instance = new self( $site, $entityId, $entityLookup, 
$errorFormatter );
+               // returns lookup with full label and id lookup (experimental) 
or just id lookup
+               $propertyLookup = 
ClientStoreFactory::getStore()->getPropertyLookup();
 
-               return array(
-                       $instance->evaluate( $propertyLabel ),
+               $instance = new self( $targetLanguage, $entityLookup, 
$propertyLookup,
+                       $errorFormatter, Settings::get( 'dataTypes' ) );
+
+               $result = array(
+                       $instance->evaluate( $entityId, $propertyLabel ),
                        'noparse' => false
                );
+
+               wfProfileOut( __METHOD__ );
+               return $result;
        }
 
 }
diff --git a/client/includes/store/ClientStore.php 
b/client/includes/store/ClientStore.php
index 4637791..883a340 100644
--- a/client/includes/store/ClientStore.php
+++ b/client/includes/store/ClientStore.php
@@ -53,6 +53,15 @@
        public function getEntityLookup();
 
        /**
+        * Returns a new PropertyLookup
+        *
+        * @since 0.4
+        *
+        * @return PropertyLookup
+        */
+       public function getPropertyLookup();
+
+       /**
         * Returns a new ChangesTable for this store.
         *
         * @since 0.4
diff --git a/client/includes/store/sql/CachingSqlStore.php 
b/client/includes/store/sql/CachingSqlStore.php
index 16eb9e1..ef44884 100644
--- a/client/includes/store/sql/CachingSqlStore.php
+++ b/client/includes/store/sql/CachingSqlStore.php
@@ -39,6 +39,11 @@
        private $entityLookup = null;
 
        /**
+        * @var PropertyLookup
+        */
+       private $propertyLookup = null;
+
+       /**
         * @see Store::newSiteLinkTable
         *
         * @since 0.3
@@ -88,6 +93,32 @@
        }
 
        /**
+        * Get a PropertyLookup object
+        *
+        * @since 0.4
+        *
+        * @return PropertyLookup
+        */
+       public function getPropertyLookup() {
+               if ( !$this->propertyLookup ) {
+                       $this->propertyLookup = $this->newPropertyLookup();
+               }
+
+               return $this->propertyLookup;
+       }
+
+       /**
+        * Create a new PropertyLookup instance
+        *
+        * @return PropertyLookup
+        */
+       protected function newPropertyLookup() {
+               $entityLookup = $this->getEntityLookup();
+
+               return new PropertySQLLookup( $entityLookup );
+       }
+
+       /**
         * Throws an MWException, because no changes table is available.
         *
         * @since 0.4
diff --git a/client/includes/store/sql/DirectSqlStore.php 
b/client/includes/store/sql/DirectSqlStore.php
index ca70279..4c184f9 100644
--- a/client/includes/store/sql/DirectSqlStore.php
+++ b/client/includes/store/sql/DirectSqlStore.php
@@ -40,6 +40,11 @@
        private $entityLookup = null;
 
        /**
+        * @var PropertyLookup
+        */
+       private $propertyLookup = null;
+
+       /**
         * @var String|bool $repoWiki
         */
        protected $repoWiki;
@@ -90,6 +95,30 @@
        }
 
        /**
+        * Get a PropertyLookup object
+        *
+        * @return PropertyLookup
+        */
+       public function getPropertyLookup() {
+               if ( !$this->propertyLookup ) {
+                       $this->propertyLookup = $this->newPropertyLookup();
+               }
+
+               return $this->propertyLookup;
+       }
+
+       /**
+        * Create a new PropertyLookup instance
+        *
+        * @return PropertyLookup
+        */
+       protected function newPropertyLookup() {
+               $entityLookup = $this->getEntityLookup();
+
+               return new PropertySQLLookup( $entityLookup );
+       }
+
+       /**
         * @see Store::newChangesTable
         *
         * @since 0.4
diff --git a/lib/WikibaseLib.php b/lib/WikibaseLib.php
index b5e7506..763dbbc 100644
--- a/lib/WikibaseLib.php
+++ b/lib/WikibaseLib.php
@@ -143,6 +143,10 @@
 $wgAutoloadClasses['Wikibase\EntityFactory']           = $dir . 
'includes/EntityFactory.php';
 $wgAutoloadClasses['Wikibase\ItemDiff']                        = $dir . 
'includes/ItemDiff.php';
 
+// includes/formatters
+$wgAutoloadClasses['Wikibase\ItemFormatter']           = $dir . 
'includes/formatters/ItemFormatter.php';
+$wgAutoloadClasses['Wikibase\StringFormatter']         = $dir . 
'includes/formatters/StringFormatter.php';
+
 // includes/modules
 $wgAutoloadClasses['Wikibase\RepoAccessModule']                = $dir . 
'includes/modules/RepoAccessModule.php';
 $wgAutoloadClasses['Wikibase\SitesModule']                             = $dir 
. 'includes/modules/SitesModule.php';
@@ -176,6 +180,8 @@
 
 // includes/store
 $wgAutoloadClasses['Wikibase\EntityLookup']                    = $dir . 
'includes/store/EntityLookup.php';
+$wgAutoloadClasses['Wikibase\PropertyLookup']           = $dir . 
'includes/store/PropertyLookup.php';
+$wgAutoloadClasses['Wikibase\PropertySQLLookup']               = $dir . 
'includes/store/PropertySQLLookup.php';
 $wgAutoloadClasses['Wikibase\SiteLinkCache']                   = $dir . 
'includes/store/SiteLinkCache.php';
 $wgAutoloadClasses['Wikibase\SiteLinkLookup']                  = $dir . 
'includes/store/SiteLinkLookup.php';
 $wgAutoloadClasses['Wikibase\SiteLinkTable']                   = $dir . 
'includes/store/SiteLinkTable.php';
diff --git a/lib/includes/formatters/ItemFormatter.php 
b/lib/includes/formatters/ItemFormatter.php
new file mode 100644
index 0000000..fa29021
--- /dev/null
+++ b/lib/includes/formatters/ItemFormatter.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Wikibase;
+use ValueFormatters\FormatterOptions;
+
+/**
+ * Formatter for Wikibase Item values
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 0.4
+ *
+ * @file
+ * @ingroup WikibaseLib
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.w...@gmail.com >
+ */
+class ItemFormatter extends StringFormatter {
+
+       protected $entityLookup;
+
+       public function __construct( FormatterOptions $options, EntityLookup 
$entityLookup ) {
+               parent::__construct( $options );
+               $this->entityLookup = $entityLookup;
+       }
+
+       public function format( $value ) {
+               if ( !$value instanceof EntityId ) {
+                       // @todo: error!
+                       return '';
+               }
+
+               $label = $this->lookupItemLabel( $value );
+
+               if ( is_string( $label ) ) {
+                       return $this->formatString( $label );
+               }
+
+               // did not find label
+               return '';
+       }
+
+       protected function lookupItemLabel( $entityId ) {
+               $entity = $this->entityLookup->getEntity( $entityId );
+
+               $langCode = $this->getOption( 'lang' );
+
+               return $entity->getLabel( $langCode );
+       }
+
+}
diff --git a/lib/includes/formatters/StringFormatter.php 
b/lib/includes/formatters/StringFormatter.php
new file mode 100644
index 0000000..48c3766
--- /dev/null
+++ b/lib/includes/formatters/StringFormatter.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace Wikibase;
+use ValueFormatters\ValueFormatterBase;
+
+/**
+ * Formatter for string values
+ *
+ * @todo generalize and put with ValueFormatters stuff
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 0.4
+ *
+ * @file
+ * @ingroup WikibaseLib
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.w...@gmail.com >
+ */
+class StringFormatter extends ValueFormatterBase {
+
+       public function format( $dataValue ) {
+               $string = $dataValue->getValue();
+               return $this->formatString( $string );
+       }
+
+       protected function formatString( $string ) {
+               return is_string( $string ) ? wfEscapeWikiText( $string ) : '';
+       }
+
+}
diff --git a/lib/includes/store/PropertyLookup.php 
b/lib/includes/store/PropertyLookup.php
new file mode 100644
index 0000000..8469d71
--- /dev/null
+++ b/lib/includes/store/PropertyLookup.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Wikibase;
+
+/**
+ * Property lookup by label
+ *
+ * @todo use terms table to do lookups, add caching and tests
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 0.4
+ *
+ * @file
+ * @ingroup WikibaseLib
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.w...@gmail.com >
+ */
+interface PropertyLookup {
+
+       /**
+        * @since 0.4
+        *
+        * @param EntityId $entityId
+        * @param string $propertyLabel
+        *
+        * @return SnakList
+        */
+       public function getMainSnaksByPropertyId( EntityId $entityId, EntityId 
$propertyId );
+
+       /**
+        * @since 0.4
+        *
+        * @param EntityId $entityId
+        * @param string $propertyLabel
+        * @param string $langCode
+        *
+        * @return SnakList
+        */
+       public function getMainSnaksByPropertyLabel( EntityID $entityId, 
$propertyLabel, $langCode );
+
+}
diff --git a/lib/includes/store/PropertySQLLookup.php 
b/lib/includes/store/PropertySQLLookup.php
new file mode 100644
index 0000000..877c7b3
--- /dev/null
+++ b/lib/includes/store/PropertySQLLookup.php
@@ -0,0 +1,219 @@
+<?php
+
+namespace Wikibase;
+
+/**
+ * Property lookup by id and label
+ *
+ * @todo use terms table to do lookups, add caching and tests
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @since 0.4
+ *
+ * @file
+ * @ingroup WikibaseLib
+ *
+ * @licence GNU GPL v2+
+ * @author Katie Filbert < aude.w...@gmail.com >
+ */
+class PropertySQLLookup implements PropertyLookup {
+
+       /* @var WikiPageEntityLookup */
+       protected $entityLookup;
+
+       /* @var array */
+       protected $statementsByProperty;
+
+       /* @var array */
+       protected $propertiesByLabel;
+
+       /**
+        * @since 0.4
+        *
+        * @param EntityLookup $entityLookup
+        */
+       public function __construct( EntityLookup $entityLookup ) {
+               $this->entityLookup = $entityLookup;
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @param EntityId $entityId
+        */
+       public function indexPropertiesByLabel( EntityId $entityId, $langCode ) 
{
+               wfProfileIn( __METHOD__ );
+
+               $propertyList = array();
+               $statementsByProperty = array();
+
+               $entity = $this->entityLookup->getEntity( $entityId );
+
+               foreach( $entity->getClaims() as $statement ) {
+                       $propertyId = 
$statement->getMainSnak()->getPropertyId();
+
+                       if ( $propertyId === null ) {
+                               continue;
+                       }
+
+                       $statementsByProperty[$propertyId->getNumericId()][] = 
$statement;
+
+                       $property = $this->entityLookup->getEntity( $propertyId 
);
+                       $propertyLabel = $property->getLabel( $langCode );
+
+                       if ( $propertyLabel !== false ) {
+                               $id = $property->getPrefixedId();
+                               $propertyList[$id] = $propertyLabel;
+                       }
+               }
+
+               $this->propertiesByLabel[$langCode] = $propertyList;
+               $this->statementsByProperty = $statementsByProperty;
+
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @param EntityId $entityId
+        * @param string $propertyLabel
+        *
+        * @return SnakList
+        */
+       public function getMainSnaksByPropertyId( EntityId $entityId, EntityId 
$propertyId ) {
+               $entity = $this->entityLookup->getEntity( $entityId );
+               $statements = $entity->getClaims();
+
+               $snakList = new SnakList();
+
+               foreach( $statements as $statement ) {
+                       $snak = $statement->getMainSnak();
+                       $snakPropertyId = $snak->getPropertyId();
+
+                       if ( $snakPropertyId->getPrefixedId()  === 
$propertyId->getPrefixedId() ) {
+                               $snakList->addSnak( $snak );
+                       }
+               }
+
+               return $snakList;
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @param EntityId $propertyId
+        *
+        * @return string|false
+        */
+       public function getPropertyLabel( EntityId $propertyId, $langCode ) {
+               wfProfileIn( __METHOD__ );
+               $property = $this->entityLookup->getEntity( $propertyId );
+               $propertyLabel = $property->getLabel( $langCode );
+
+               wfProfileOut( __METHOD__ );
+               return $propertyLabel;
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @param EntityId $propertyId
+        *
+        * @return Statement[]
+        */
+       public function getStatementsByProperty( EntityId $propertyId ) {
+               wfProfileIn( __METHOD__ );
+               $numericId = $propertyId->getNumericId();
+
+               $statements = array_key_exists( $numericId, 
$this->statementsByProperty )
+                       ? $this->statementsByProperty[$numericId] : array();
+
+               wfProfileOut( __METHOD__ );
+               return $statements;
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @param EntityId $propertyId
+        *
+        * @return SnakList
+        */
+       protected function getSnakListForProperty( EntityId $propertyId ) {
+               wfProfileIn( __METHOD__ );
+               $statements = $this->getStatementsByProperty( $propertyId );
+               $snakList = new SnakList();
+
+               foreach( $statements as $statement ) {
+                       $snakList->addSnak( $statement->getMainSnak() );
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $snakList;
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @param string $propertyLabel
+        * @param string $langCode
+        *
+        * @return EntityId|null
+        */
+       protected function getPropertyIdByLabel( $propertyLabel, $langCode ) {
+               wfProfileIn( __METHOD__ );
+               $propertyId = array_search( $propertyLabel, 
$this->propertiesByLabel[$langCode] );
+               if ( $propertyId !== false ) {
+                       $entityId = EntityId::newFromPrefixedId( $propertyId );
+
+                       wfProfileOut( __METHOD__ );
+                       return $entityId;
+               }
+
+               wfProfileOut( __METHOD__ );
+               return null;
+       }
+
+       /**
+        * @since 0.4
+        *
+        * @param EntityId $entityId
+        * @param string $propertyLabel
+        * @param string $langCode
+        *
+        * @return SnakList
+        */
+       public function getMainSnaksByPropertyLabel( EntityId $entityId, 
$propertyLabel, $langCode ) {
+               wfProfileIn( __METHOD__ );
+
+               $snakList = new SnakList();
+
+               if ( defined( 'WB_EXPERIMENTAL_FEATURES' ) && 
WB_EXPERIMENTAL_FEATURES ) {
+                       if ( $this->propertiesByLabel === null ) {
+                               $this->indexPropertiesByLabel( $entityId, 
$langCode );
+                       }
+
+                       $propertyId = $this->getPropertyIdByLabel( 
$propertyLabel, $langCode );
+                       $snakList = $propertyId !== null ? 
$this->getSnakListForProperty( $propertyId ) : $snakList;
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $snakList;
+       }
+
+}

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I70a9ff2976940ecf601320ecece35943e89e94bc
Gerrit-PatchSet: 15
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Aude <aude.w...@gmail.com>
Gerrit-Reviewer: Aude <aude.w...@gmail.com>
Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de>
Gerrit-Reviewer: John Erling Blad <john.b...@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