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

Change subject: (bug 49742) introducing PropertyInfoTable.
......................................................................


(bug 49742) introducing PropertyInfoTable.

This is the first over several changes that introduce a system for
fast access to property meta-info.

Change-Id: I197360a45f8ce1aefe29460c19142f2dfbee1525
---
M lib/WikibaseLib.classes.php
A lib/includes/store/PropertyInfoStore.php
A lib/includes/store/sql/PropertyInfoTable.php
A lib/includes/store/sql/wb_property_info.sql
A lib/includes/store/sql/wb_property_info.sqlite.sql
A lib/tests/phpunit/store/PropertyInfoStoreTestHelper.php
A lib/tests/phpunit/store/PropertyInfoTableTest.php
M repo/Wikibase.classes.php
M repo/includes/content/PropertyContent.php
M repo/includes/store/Store.php
M repo/includes/store/sql/SqlStore.php
A repo/includes/updates/PropertyInfoDeletion.php
A repo/includes/updates/PropertyInfoUpdate.php
13 files changed, 827 insertions(+), 25 deletions(-)

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



diff --git a/lib/WikibaseLib.classes.php b/lib/WikibaseLib.classes.php
index cd1d7f0..7098d8a 100644
--- a/lib/WikibaseLib.classes.php
+++ b/lib/WikibaseLib.classes.php
@@ -133,12 +133,15 @@
                'Wikibase\TermCombinationMatchFinder' => 
'includes/store/TermCombinationMatchFinder.php',
                'Wikibase\TermMatchScoreCalculator' => 
'includes/store/TermMatchScoreCalculator.php',
                'Wikibase\TermPropertyLabelResolver' => 
'includes/store/TermPropertyLabelResolver.php',
-               'Wikibase\TermSqlIndex' => 
'includes/store/sql/TermSqlIndex.php',
+
+               'Wikibase\PropertyInfoStore' => 
'includes/store/PropertyInfoStore.php',
 
                // includes/store/sql
                'Wikibase\CachingEntityLoader' => 
'includes/store/sql/CachingEntityLoader.php',
                'Wikibase\SiteLinkTable' => 
'includes/store/sql/SiteLinkTable.php',
                'Wikibase\WikiPageEntityLookup' => 
'includes/store/sql/WikiPageEntityLookup.php',
+               'Wikibase\TermSqlIndex' => 
'includes/store/sql/TermSqlIndex.php',
+               'Wikibase\PropertyInfoTable' => 
'includes/store/sql/PropertyInfoTable.php',
 
                // includes/util
                'Wikibase\HttpAcceptNegotiator' => 
'includes/util/HttpAcceptNegotiator.php',
@@ -175,6 +178,8 @@
                'Wikibase\Test\EntityLookupTest' => 
'tests/phpunit/EntityLookupTest.php',
                'Wikibase\Test\MockChunkAccess' => 
'tests/phpunit/store/MockChunkAccess.php',
                'Wikibase\Test\TermIndexTest' => 
'tests/phpunit/store/TermIndexTest.php',
+
+               'Wikibase\Test\PropertyInfoStoreTestHelper' => 
'tests/phpunit/store/PropertyInfoStoreTestHelper.php',
        );
 
        return $classes;
diff --git a/lib/includes/store/PropertyInfoStore.php 
b/lib/includes/store/PropertyInfoStore.php
new file mode 100644
index 0000000..04f27ed
--- /dev/null
+++ b/lib/includes/store/PropertyInfoStore.php
@@ -0,0 +1,95 @@
+<?php
+ /**
+ *
+ * Copyright © 26.06.13 by the authors listed below.
+ *
+ * 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
+ *
+ * @license GPL 2+
+ * @file
+ * @ingroup WikibaseLib
+ *
+ * @author Daniel Kinzler
+ */
+
+
+namespace Wikibase;
+
+
+use DBError;
+
+interface PropertyInfoStore {
+
+       /**
+        * Key to use in the info array for the property's data type ID.
+        */
+       const KEY_DATA_TYPE = 'type';
+
+       /**
+        * Returns the property info for the given property ID.
+        *
+        * @note: Even if the property is known to exist, this method may not 
return
+        *        an info array, or the info array may not contain all well 
known fields.
+        *
+        * @param EntityId $propertyId
+        *
+        * @return array|null
+        *
+        * @throws StorageException
+        * @throws DBError
+        */
+       public function getPropertyInfo( EntityId $propertyId );
+
+       /**
+        * Returns the property info for all properties.
+        * The caller is responsible for avoiding calling this if there are too 
many properties.
+        *
+        * @note: There is no guarantee that an info array is returned for all 
existing properties.
+        *        Also, it is not guaranteed that the ionfo arrays will contain 
all well known fields.
+        *
+        * @return array[] An associative array mapping property IDs to info 
arrays.
+        *
+        * @throws StorageException
+        * @throws \DBError
+        */
+       public function getAllPropertyInfo();
+
+       /**
+        * Update the info for the given property.
+        *
+        * @note: All well known fields MUST be set in $info.
+        *
+        * @param EntityId $propertyId
+        * @param array    $info
+        *
+        * @throws StorageException
+        * @throws DBError
+        */
+       public function setPropertyInfo( EntityId $propertyId, array $info );
+
+       /**
+        * Remove the info entry for the given property.
+        *
+        * @param EntityId $propertyId
+        *
+        * @return bool true iff something was deleted
+        *
+        * @throws StorageException
+        * @throws DBError
+        */
+       public function removePropertyInfo( EntityId $propertyId );
+
+}
\ No newline at end of file
diff --git a/lib/includes/store/sql/PropertyInfoTable.php 
b/lib/includes/store/sql/PropertyInfoTable.php
new file mode 100644
index 0000000..8c1c3e0
--- /dev/null
+++ b/lib/includes/store/sql/PropertyInfoTable.php
@@ -0,0 +1,270 @@
+<?php
+ /**
+ *
+ * Copyright © 26.06.13 by the authors listed below.
+ *
+ * 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
+ *
+ * @license GPL 2+
+ * @file
+ * @ingroup WikibaseLib
+ *
+ * @author Daniel Kinzler
+ */
+
+
+namespace Wikibase;
+
+
+use DBError;
+
+/**
+ * Class PropertyInfoTable implemnents PropertyInfoStore on top of an SQL 
table.
+ *
+ * @since 0.4
+ *
+ * @package Wikibase
+ */
+class PropertyInfoTable extends \DBAccessBase implements PropertyInfoStore {
+
+       /**
+        * @var string
+        */
+       protected $table;
+
+       /**
+        * @var bool
+        */
+       protected $readonly;
+
+       /**
+        * @param string $table The table to use
+        * @param bool $readonly Whether the table can be modified.
+        * @param string|bool $wiki The wiki's database to connect to.
+        *        Must be a value LBFactory understands. Defaults to false, 
which is the local wiki.
+        */
+       public function __construct( $readonly, $wiki = false ) {
+               assert( is_bool( $readonly ) );
+               assert( is_string( $wiki ) || $wiki === false );
+
+               $this->table = 'wb_property_info';
+               $this->readonly = $readonly;
+               $this->wiki = $wiki;
+       }
+
+       /**
+        * Register the updates needed for creating the appropriate table(s).
+        *
+        * @param \DatabaseUpdater $updater
+        */
+       public static function registerDatabaseUpdates( \DatabaseUpdater 
$updater ) {
+               $table = 'wb_property_info';
+
+               if ( !$updater->tableExists( $table ) ) {
+                       $type = $updater->getDB()->getType();
+                       $fileBase = __DIR__ . '/' . $table;
+
+                       $file = $fileBase . '.' . $type . '.sql';
+                       if ( !file_exists( $file ) ) {
+                               $file = $fileBase . '.sql';
+                       }
+
+                       $updater->addExtensionTable( $table, $file );
+               }
+       }
+
+       /**
+        * @see   PropertyInfoStore::getPropertyInfo
+        *
+        * @param EntityId $propertyId
+        *
+        * @return array|null
+        *
+        * @throws \InvalidArgumentException
+        * @throws \DBError
+        */
+       public function getPropertyInfo( EntityId $propertyId ) {
+               if ( $propertyId->getEntityType() !== Property::ENTITY_TYPE ) {
+                       throw new \InvalidArgumentException( 'Property ID 
expected! ' . $propertyId );
+               }
+
+               wfProfileIn( __METHOD__ );
+
+               $dbw = $this->getConnection( DB_SLAVE );
+
+               $res = $dbw->selectField(
+                       $this->table,
+                       'pi_info',
+                       array( 'pi_property_id' => $propertyId->getNumericId() 
),
+                       __METHOD__
+               );
+
+               $this->releaseConnection( $dbw );
+
+               if ( $res === false ) {
+                       $info = null;
+               } else {
+                       $info = json_decode( $res, true );
+
+                       if ( $info === null ) {
+                               wfLogWarning( "failed to decode property info 
blob for " . $propertyId . ": " . $res );
+                       }
+               }
+
+               wfProfileOut( __METHOD__ );
+               return $info;
+       }
+
+       /**
+        * @see   PropertyInfoStore::getAllPropertyInfo
+        *
+        * @return array[]
+        *
+        * @throws \DBError
+        */
+       public function getAllPropertyInfo() {
+               wfProfileIn( __METHOD__ );
+               $dbw = $this->getConnection( DB_SLAVE );
+
+               $res = $dbw->select(
+                       $this->table,
+                       array( 'pi_property_id', 'pi_info' ),
+                       array(),
+                       __METHOD__
+               );
+
+               $infos = array();
+
+               while ( $row = $res->fetchObject() ) {
+                       $info = json_decode( $row->pi_info );
+
+                       if ( $info === null ) {
+                               wfLogWarning( "failed to decode property info 
blob for property "
+                                       . $row->pi_property_id . ": " . 
$row->pi_info );
+                               continue;
+                       }
+
+                       $infos[$row->pi_property_id] = $info;
+               }
+
+               $this->releaseConnection( $dbw );
+
+               wfProfileOut( __METHOD__ );
+               return $infos;
+       }
+
+       /**
+        * @see PropertyInfoStore::setPropertyInfo
+        *
+        * @param EntityId $propertyId
+        * @param array    $info
+        *
+        * @throws \DBError
+        * @throws \InvalidArgumentException
+        */
+       public function setPropertyInfo( EntityId $propertyId, array $info ) {
+               if ( $propertyId->getEntityType() !== Property::ENTITY_TYPE ) {
+                       throw new \InvalidArgumentException( 'Property ID 
expected! ' . $propertyId );
+               }
+
+               if ( $this->readonly ) {
+                       throw new DBError( 'Cannot write when in readonly mode' 
);
+               }
+
+               if ( !isset( $info[ PropertyInfoStore::KEY_DATA_TYPE ]) ) {
+                       throw new \InvalidArgumentException( 'Missing required 
info field: ' . PropertyInfoStore::KEY_DATA_TYPE );
+               }
+
+               wfProfileIn( __METHOD__ );
+
+               $type = $info[ PropertyInfoStore::KEY_DATA_TYPE ];
+               $json = json_encode( $info );
+
+               $dbw = $this->getConnection( DB_MASTER );
+
+               $dbw->replace(
+                       $this->table,
+                       array( 'pi_property_id' ),
+                       array(
+                               'pi_property_id' => $propertyId->getNumericId(),
+                               'pi_info' => $json,
+                               'pi_type' => $type,
+                       ),
+                       __METHOD__
+               );
+
+               $this->releaseConnection( $dbw );
+
+               wfProfileOut( __METHOD__ );
+       }
+
+       /**
+        * @see   PropertyInfoStore::removePropertyInfo
+        *
+        * @param EntityId $propertyId
+        *
+        * @throws DBError
+        * @throws \InvalidArgumentException
+        * @return bool
+        */
+       public function removePropertyInfo( EntityId $propertyId ) {
+               if ( $propertyId->getEntityType() !== Property::ENTITY_TYPE ) {
+                       throw new \InvalidArgumentException( 'Property ID 
expected! ' . $propertyId );
+               }
+
+               if ( $this->readonly ) {
+                       throw new DBError( 'Cannot write when in readonly mode' 
);
+               }
+
+               wfProfileIn( __METHOD__ );
+               $dbw = $this->getConnection( DB_MASTER );
+
+               $dbw->delete(
+                       $this->table,
+                       array( 'pi_property_id' => $propertyId->getNumericId() 
),
+                       __METHOD__
+               );
+
+               $c = $dbw->affectedRows();
+               $this->releaseConnection( $dbw );
+
+               wfProfileOut( __METHOD__ );
+               return $c > 0 ? true : false;
+       }
+
+       /**
+        * Returns a database connection suitable for writing to the database 
that
+        * contains the property info table.
+        *
+        * This is for use for closely related classes that want to operate 
directly
+        * on the database table.
+        */
+       public function getWriteConnection() {
+               return $this->getConnection( DB_MASTER );
+       }
+
+       /**
+        * Returns the (logical) name of the database table that contains the 
property info.
+        *
+        * This is for use for closely related classes that want to operate 
directly
+        * on the database table.
+        *
+        * @return string
+        */
+       public function getTableName() {
+               return $this->table;
+       }
+}
\ No newline at end of file
diff --git a/lib/includes/store/sql/wb_property_info.sql 
b/lib/includes/store/sql/wb_property_info.sql
new file mode 100644
index 0000000..82a1dc6
--- /dev/null
+++ b/lib/includes/store/sql/wb_property_info.sql
@@ -0,0 +1,10 @@
+-- property info table --
+
+CREATE TABLE IF NOT EXISTS /*_*/wb_property_info (
+  pi_property_id    INT unsigned        NOT NULL,
+  pi_type           VARBINARY(32)       NOT NULL,
+  pi_info           BLOB                NOT NULL,
+  PRIMARY KEY ( pi_property_id ),
+  INDEX pi_type ( pi_type )
+) /*$wgDBTableOptions*/;
+
diff --git a/lib/includes/store/sql/wb_property_info.sqlite.sql 
b/lib/includes/store/sql/wb_property_info.sqlite.sql
new file mode 100644
index 0000000..5905930
--- /dev/null
+++ b/lib/includes/store/sql/wb_property_info.sqlite.sql
@@ -0,0 +1,10 @@
+-- property info table --
+
+CREATE TABLE IF NOT EXISTS /*_*/wb_property_info (
+  pi_property_id    INT unsigned        NOT NULL,
+  pi_type           VARBINARY(32)       NOT NULL,
+  pi_info           BLOB                NOT NULL
+) /*$wgDBTableOptions*/;
+
+CREATE INDEX IF NOT EXISTS /*i*/pi_info ON /*_*/wb_property_info (pi_info);
+
diff --git a/lib/tests/phpunit/store/PropertyInfoStoreTestHelper.php 
b/lib/tests/phpunit/store/PropertyInfoStoreTestHelper.php
new file mode 100644
index 0000000..757ae34
--- /dev/null
+++ b/lib/tests/phpunit/store/PropertyInfoStoreTestHelper.php
@@ -0,0 +1,150 @@
+<?php
+
+namespace Wikibase\Test;
+
+use Wikibase\EntityId;
+use Wikibase\Property;
+use Wikibase\PropertyInfoStore;
+
+use Wikibase\SiteLinkTable;
+use Wikibase\Item;
+
+/**
+ * Helper for testing PropertyInfoStore implementations
+ *
+ * @file
+ * @since 0.4
+ *
+ * @ingroup WikibaseLib
+ * @ingroup Test
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class PropertyInfoStoreTestHelper {
+
+       /**
+        * @var \PHPUnit_Framework_TestCase
+        */
+       protected $test;
+
+       public function __construct( \PHPUnit_Framework_TestCase $testCase, 
$storeBuilder ) {
+               $this->test = $testCase;
+               $this->storeBuilder = $storeBuilder;
+       }
+
+       protected function newPropertyInfoStore() {
+               return call_user_func( $this->storeBuilder );
+       }
+
+       public static function provideSetPropertyInfo() {
+               return array(
+                       array( // #0: ok
+                               new EntityId( Property::ENTITY_TYPE, 23 ),
+                               array( PropertyInfoStore::KEY_DATA_TYPE => 
'string' ),
+                               null
+                       ),
+                       array( // #1: not a property
+                               new EntityId( Item::ENTITY_TYPE, 23 ),
+                               array( PropertyInfoStore::KEY_DATA_TYPE => 
'string' ),
+                               'InvalidArgumentException'
+                       ),
+                       array( // #2: missing required field
+                               new EntityId( Property::ENTITY_TYPE, 23 ),
+                               array(),
+                               'InvalidArgumentException'
+                       ),
+                       array( // #3: extra data
+                               new EntityId( Property::ENTITY_TYPE, 23 ),
+                               array( PropertyInfoStore::KEY_DATA_TYPE => 
'string', 'foo' => 'bar' ),
+                               null
+                       ),
+               );
+       }
+
+       public function testSetPropertyInfo( EntityId $id, array $info, 
$expectedException ) {
+               if ( $expectedException !== null ) {
+                       $this->test->setExpectedException( $expectedException );
+               }
+
+               $table = $this->newPropertyInfoStore();
+
+               $table->setPropertyInfo( $id, $info );
+               $res = $table->getPropertyInfo( $id );
+
+               $this->test->assertEquals( $info, $res );
+       }
+
+       public function testGetPropertyInfo() {
+               $table = $this->newPropertyInfoStore();
+               $p23 = new EntityId( Property::ENTITY_TYPE, 23 );
+               $q23 = new EntityId( Item::ENTITY_TYPE, 23 );
+               $p42 = new EntityId( Property::ENTITY_TYPE, 42 );
+               $info23 = array( PropertyInfoStore::KEY_DATA_TYPE => 'string' );
+               $info42 = array( PropertyInfoStore::KEY_DATA_TYPE => 'string', 
'foo' => 'bar' );
+
+               $this->test->assertNull( $table->getPropertyInfo( $p23 ), "not 
set yet, should be null" );
+
+               $table->setPropertyInfo( $p23, $info23 );
+
+               $this->test->assertNull( $table->getPropertyInfo( $p42 ), "not 
set yet, should be null" );
+               $this->test->assertEquals( $info23, $table->getPropertyInfo( 
$p23 ), "should return what was set" );
+
+               $table->setPropertyInfo( $p42, $info42 );
+
+               $this->test->assertEquals( $info42, $table->getPropertyInfo( 
$p42 ), "should return what was set" );
+               $this->test->assertEquals( $info23, $table->getPropertyInfo( 
$p23 ), "should return what was set" );
+
+               $this->test->setExpectedException( 'InvalidArgumentException' );
+               $table->getPropertyInfo( $q23 );
+       }
+
+       public function testGetAllPropertyInfo() {
+               $table = $this->newPropertyInfoStore();
+               $p23 = new EntityId( Property::ENTITY_TYPE, 23 );
+               $p42 = new EntityId( Property::ENTITY_TYPE, 42 );
+               $info23 = array( PropertyInfoStore::KEY_DATA_TYPE => 'string' );
+               $info42 = array( PropertyInfoStore::KEY_DATA_TYPE => 'string', 
'foo' => 'bar' );
+
+               $this->test->assertCount( 0, $table->getAllPropertyInfo(), 
"should initially be empty" );
+
+               $table->setPropertyInfo( $p23, $info23 );
+               $this->test->assertCount( 1, $table->getAllPropertyInfo(), 
"after adding one property" );
+
+               $table->setPropertyInfo( $p42, $info42 );
+               $this->test->assertCount( 2, $table->getAllPropertyInfo(), 
"after adding the second property" );
+
+               $table->removePropertyInfo( $p23 );
+               $this->test->assertCount( 1, $table->getAllPropertyInfo(), 
"after removing one property" );
+       }
+
+       public function testRemovePropertyInfo() {
+               $table = $this->newPropertyInfoStore();
+               $p23 = new EntityId( Property::ENTITY_TYPE, 23 );
+               $q23 = new EntityId( Item::ENTITY_TYPE, 23 );
+               $p42 = new EntityId( Property::ENTITY_TYPE, 42 );
+               $info23 = array( PropertyInfoStore::KEY_DATA_TYPE => 'string' );
+
+               $table->setPropertyInfo( $p23, $info23 );
+
+               $this->test->assertFalse( $table->removePropertyInfo( $p42 ), 
"deleted unknown" );
+               $this->test->assertTrue( $table->removePropertyInfo( $p23 ), 
"deleted something" );
+               $this->test->assertFalse( $table->removePropertyInfo( $p23 ), 
"deleted nothing" );
+
+               $this->test->setExpectedException( 'InvalidArgumentException' );
+               $table->removePropertyInfo( $q23 );
+
+       }
+
+       public function testPropertyInfoPersistance() {
+               $p23 = new EntityId( Property::ENTITY_TYPE, 23 );
+               $info23 = array( PropertyInfoStore::KEY_DATA_TYPE => 'string' );
+
+               $table1 = $this->newPropertyInfoStore();
+               $table1->setPropertyInfo( $p23, $info23 );
+
+               $table2 = $this->newPropertyInfoStore();
+               $this->test->assertEquals( $info23, $table2->getPropertyInfo( 
$p23 ), "should return persisted info" );
+       }
+
+}
diff --git a/lib/tests/phpunit/store/PropertyInfoTableTest.php 
b/lib/tests/phpunit/store/PropertyInfoTableTest.php
new file mode 100644
index 0000000..a8856a9
--- /dev/null
+++ b/lib/tests/phpunit/store/PropertyInfoTableTest.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace Wikibase\Test;
+
+use Wikibase\EntityId;
+use Wikibase\Property;
+use Wikibase\PropertyInfoTable;
+use Wikibase\Settings;
+use Wikibase\Item;
+
+/**
+ * @covers Wikibase\PropertyInfoTable
+ *
+ * @file
+ * @since 0.4
+ *
+ * @ingroup WikibaseLib
+ * @ingroup Test
+ *
+ * @group Wikibase
+ * @group WikibaseLib
+ * @group WikibaseStore
+ * @group WikibasePropertyInfo
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class PropertyInfoTableTest extends \MediaWikiTestCase {
+
+       /**
+        * @var PropertyInfoStoreTestHelper
+        */
+       public $helper;
+
+       public function __construct( $name = null, $data = array(), $dataName = 
'' ) {
+               parent::__construct( $name, $data, $dataName );
+
+               $this->helper = new PropertyInfoStoreTestHelper( $this, array( 
$this, 'newPropertyInfoTable' ) );
+       }
+
+       public function setUp() {
+               parent::setUp();
+
+               if ( !defined( 'WB_VERSION' ) ) {
+                       $this->markTestSkipped( "Skipping because 
WikibaseClient doesn't have a local wb_property_info table." );
+               }
+
+               //FIXME: usePropertyInfoTable is defined in a follow-up
+               //if ( !Settings::get( 'usePropertyInfoTable' ) ) {
+               //      $this->markTestSkipped( "Skipping because 
wb_property_info isn't configured." );
+               //}
+
+               $this->tablesUsed[] = 'wb_property_info';
+       }
+
+       public function newPropertyInfoTable() {
+               return new PropertyInfoTable( false );
+       }
+
+       public function provideSetPropertyInfo() {
+               return $this->helper->provideSetPropertyInfo();
+       }
+
+       /**
+        * @dataProvider provideSetPropertyInfo
+        */
+       public function testSetPropertyInfo( EntityId $id, array $info, 
$expectedException ) {
+               $this->helper->testSetPropertyInfo( $id, $info, 
$expectedException );
+       }
+
+       public function testGetPropertyInfo() {
+               $this->helper->testGetPropertyInfo();
+       }
+
+       public function testGetAllPropertyInfo() {
+               $this->helper->testGetAllPropertyInfo();
+       }
+
+       public function testRemovePropertyInfo() {
+               $this->helper->testRemovePropertyInfo();
+       }
+
+       public function testPropertyInfoPersistance() {
+               $this->helper->testPropertyInfoPersistance();
+       }
+
+}
diff --git a/repo/Wikibase.classes.php b/repo/Wikibase.classes.php
index adfa41e..63f62e1 100644
--- a/repo/Wikibase.classes.php
+++ b/repo/Wikibase.classes.php
@@ -149,6 +149,8 @@
                'Wikibase\EntityModificationUpdate' => 
'includes/updates/EntityModificationUpdate.php',
                'Wikibase\ItemDeletionUpdate' => 
'includes/updates/ItemDeletionUpdate.php',
                'Wikibase\ItemModificationUpdate' => 
'includes/updates/ItemModificationUpdate.php',
+               'Wikibase\PropertyInfoUpdate' => 
'includes/updates/PropertyInfoUpdate.php',
+               'Wikibase\PropertyInfoDeletion' => 
'includes/updates/PropertyInfoDeletion.php',
 
                // includes/Validators
                'Wikibase\Validators\SnakValidator' => 
'includes/Validators/SnakValidator.php',
diff --git a/repo/includes/content/PropertyContent.php 
b/repo/includes/content/PropertyContent.php
index 7113dee..48f495c 100644
--- a/repo/includes/content/PropertyContent.php
+++ b/repo/includes/content/PropertyContent.php
@@ -3,6 +3,7 @@
 namespace Wikibase;
 use Title, Content, ParserOptions, ParserOutput, WikiPage, User, Status, 
DataUpdate;
 use \ValueFormatters\ValueFormatterFactory;
+use Wikibase\Repo\WikibaseRepo;
 
 /**
  * Content object for articles representing Wikibase properties.
@@ -159,9 +160,43 @@
         * @return DataUpdate[]
         */
        public function getDeletionUpdates( \WikiPage $page, \ParserOutput 
$parserOutput = null ) {
+               //XXX: access to services should be done via the ContentHandler.
+               $infoStore = 
WikibaseRepo::getDefaultInstance()->getStore()->getPropertyInfoStore();
+
                return array_merge(
                        parent::getDeletionUpdates( $page, $parserOutput ),
-                       array( new EntityDeletionUpdate( $this ) )
+                       array(
+                               new EntityDeletionUpdate( $this ),
+                               new PropertyInfoDeletion( 
$this->getProperty()->getId(), $infoStore ),
+                       )
+               );
+       }
+
+       /**
+        * @see ContentHandler::getSecondaryDataUpdates
+        *
+        * @since 0.1
+        *
+        * @param Title $title
+        * @param Content|null $old
+        * @param boolean $recursive
+        *
+        * @param null|ParserOutput $parserOutput
+        *
+        * @return DataUpdate[]
+        */
+       public function getSecondaryDataUpdates( Title $title, Content $old = 
null,
+               $recursive = false, ParserOutput $parserOutput = null ) {
+
+               //XXX: access to services should be done via the ContentHandler.
+               $infoStore = 
WikibaseRepo::getDefaultInstance()->getStore()->getPropertyInfoStore();
+
+               return array_merge(
+                       parent::getSecondaryDataUpdates( $title, $old, 
$recursive, $parserOutput ),
+                       array(
+                               new EntityModificationUpdate( $this ),
+                               new PropertyInfoUpdate( $this->getProperty(), 
$infoStore ),
+                       )
                );
        }
 
@@ -182,28 +217,6 @@
 
                $propertyView = new PropertyView( $valueFormatters );
                return $propertyView->getParserOutput( $this, $options, 
$generateHtml );
-       }
-
-       /**
-        * @see ContentHandler::getSecondaryDataUpdates
-        *
-        * @since 0.1
-        *
-        * @param Title $title
-        * @param Content|null $old
-        * @param boolean $recursive
-        *
-        * @param null|ParserOutput $parserOutput
-        *
-        * @return DataUpdate[]
-        */
-       public function getSecondaryDataUpdates( Title $title, Content $old = 
null,
-               $recursive = false, ParserOutput $parserOutput = null ) {
-
-               return array_merge(
-                       parent::getSecondaryDataUpdates( $title, $old, 
$recursive, $parserOutput ),
-                       array( new EntityModificationUpdate( $this ) )
-               );
        }
 
 }
diff --git a/repo/includes/store/Store.php b/repo/includes/store/Store.php
index b61037a..1f3bf61 100644
--- a/repo/includes/store/Store.php
+++ b/repo/includes/store/Store.php
@@ -95,4 +95,13 @@
         */
        public function getEntityLookup();
 
+       /**
+        * Returns an PropertyInfoStore
+        *
+        * @since 0.4
+        *
+        * @return PropertyInfoStore
+        */
+       public function getPropertyInfoStore();
+
 }
diff --git a/repo/includes/store/sql/SqlStore.php 
b/repo/includes/store/sql/SqlStore.php
index 8869547..7f1c49e 100644
--- a/repo/includes/store/sql/SqlStore.php
+++ b/repo/includes/store/sql/SqlStore.php
@@ -37,6 +37,11 @@
        private $entityLookup = null;
 
        /**
+        * @var PropertyInfoTable
+        */
+       private $propertyInfoTable = null;
+
+       /**
         * @var TermIndex
         */
        private $termIndex = null;
@@ -178,8 +183,10 @@
                        }
                }
                else {
-                       wfWarn( "Database type '$type' is not supported by 
Wikibase Client." );
+                       wfWarn( "Database type '$type' is not supported by 
Wikibase." );
                }
+
+               PropertyInfoTable::registerDatabaseUpdates( $updater );
        }
 
        /**
@@ -243,4 +250,31 @@
                return new CachingEntityLoader( $lookup );
        }
 
+       /**
+        * @see Store::getPropertyInfoStore
+        *
+        * @since 0.4
+        *
+        * @return PropertyInfoStore
+        */
+       public function getPropertyInfoStore() {
+               if ( !$this->propertyInfoTable ) {
+                       $this->propertyInfoTable = 
$this->newPropertyInfoTable();
+               }
+
+               return $this->propertyInfoTable;
+       }
+
+       /**
+        * Creates a new PropertyInfoTable
+        *
+        * @return PropertyInfoTable
+        */
+       protected function newPropertyInfoTable() {
+               //FIXME: use usePropertyInfoTable defined in follow-up
+               //FIXME: use CachingPropertyInfoStore defined in follow-up
+               $table = new PropertyInfoTable( false );
+               return $table;
+       }
+
 }
diff --git a/repo/includes/updates/PropertyInfoDeletion.php 
b/repo/includes/updates/PropertyInfoDeletion.php
new file mode 100644
index 0000000..63e98cb
--- /dev/null
+++ b/repo/includes/updates/PropertyInfoDeletion.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Wikibase;
+
+/**
+ * Removes a property info entry.
+ *
+ * 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 WikibaseRepo
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class PropertyInfoDeletion extends \DataUpdate {
+
+       /**
+        * Constructor.
+        *
+        * @param EntityId          $id
+        * @param PropertyInfoStore $store
+        */
+       public function __construct( EntityId $id, PropertyInfoStore $store ) {
+               $this->propertyId = $id;
+               $this->store = $store;
+       }
+
+       /**
+        * Perform the actual work
+        */
+       function doUpdate() {
+               wfDebugLog( __CLASS__, __FUNCTION__ . ': deleting property info 
for ' . $this->propertyId );
+               $this->store->removePropertyInfo( $this->propertyId );
+       }
+}
diff --git a/repo/includes/updates/PropertyInfoUpdate.php 
b/repo/includes/updates/PropertyInfoUpdate.php
new file mode 100644
index 0000000..5d456c8
--- /dev/null
+++ b/repo/includes/updates/PropertyInfoUpdate.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Wikibase;
+
+/**
+ * Updates property info entries.
+ *
+ * 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 WikibaseRepo
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class PropertyInfoUpdate extends \DataUpdate {
+
+       /**
+        * Constructor.
+        *
+        * @param Property          $property
+        * @param PropertyInfoStore $store
+        */
+       public function __construct( Property $property, PropertyInfoStore 
$store ) {
+               $this->property = $property;
+               $this->store = $store;
+       }
+
+       /**
+        * Perform the actual work
+        */
+       function doUpdate() {
+               //XXX: Where to encode the knowledge about how to extract an 
info array from a Property object?
+               //     Should we have a PropertyInfo class? Or can we put this 
into the Property class?
+
+               $info = array(
+                       PropertyInfoStore::KEY_DATA_TYPE => 
$this->property->getDataTypeId()
+               );
+
+               $id = $this->property->getId();
+               $oldInfo = $this->store->getPropertyInfo( $id );
+
+               if ( $oldInfo !== $info ) {
+                       wfDebugLog( __CLASS__, __FUNCTION__ . ': property info 
for ' . $id . ' changed, updating' );
+                       $this->store->setPropertyInfo( $id, $info );
+               } else {
+                       wfDebugLog( __CLASS__, __FUNCTION__ . ': property info 
for ' . $id . ' didn\'t change, skipping update' );
+               }
+       }
+}

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I197360a45f8ce1aefe29460c19142f2dfbee1525
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Daniel Werner <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: jenkins-bot

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

Reply via email to