jenkins-bot has submitted this change and it was merged.
Change subject: Introduce SqlSubscriptionLookup
......................................................................
Introduce SqlSubscriptionLookup
This also introduces DualSubscriptionLookup that allows
subscriptions to be looked up in the subscription table
as well as the sitelink table, to allow incremental migration
of client wikis.
NOTE: this patch does not yet hook up the new classes to be used.
Bug: T66590
Bug: T90755
Change-Id: I239420457100b5565c132048bf57b64f7f304d56
---
A repo/includes/store/DualSubscriptionLookup.php
A repo/includes/store/sql/SqlSubscriptionLookup.php
A repo/tests/phpunit/includes/store/DualSubscriptionLookupTest.php
M repo/tests/phpunit/includes/store/SiteLinkSubscriptionLookupTest.php
A repo/tests/phpunit/includes/store/sql/SqlSubscriptionLookupTest.php
5 files changed, 392 insertions(+), 1 deletion(-)
Approvals:
Hoo man: Looks good to me, approved
jenkins-bot: Verified
diff --git a/repo/includes/store/DualSubscriptionLookup.php
b/repo/includes/store/DualSubscriptionLookup.php
new file mode 100644
index 0000000..667f7d3
--- /dev/null
+++ b/repo/includes/store/DualSubscriptionLookup.php
@@ -0,0 +1,88 @@
+<?php
+
+namespace Wikibase\Store;
+
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\DataModel\Entity\ItemId;
+
+/**
+ * Implementation of SubscriptionLookup based on two other SubscriptionLookup.
+ * This provides a unified view on two subscription mechanisms.
+ *
+ * @since 0.5
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class DualSubscriptionLookup implements SubscriptionLookup {
+
+ /**
+ * @var SubscriptionLookup
+ */
+ private $primary;
+
+ /**
+ * @var SubscriptionLookup
+ */
+ private $secondary;
+
+ /**
+ * @param SubscriptionLookup $primary
+ * @param SubscriptionLookup $secondary
+ */
+ public function __construct( SubscriptionLookup $primary,
SubscriptionLookup $secondary ) {
+ $this->primary = $primary;
+ $this->secondary = $secondary;
+ }
+
+ /**
+ * Returns a list of entities a given site is subscribed to.
+ *
+ * This implementations combines the results of queries to both of the
lookups
+ * provided to the constructor.
+ *
+ * @param string $siteId Site ID of the client site.
+ * @param EntityId[]|null $entityIds The entities we are interested in,
or null for "any".
+ *
+ * @return EntityId[] a list of entity IDs the client wiki is
subscribed to.
+ * The result is limited to entity ids also present in
$entityIds, if given.
+ */
+ public function getSubscriptions( $siteId, array $entityIds ) {
+ if ( empty( $entityIds ) ) {
+ return array();
+ }
+
+ $primarySubscriptions = $this->reIndexEntityIds(
+ $this->primary->getSubscriptions( $siteId, $entityIds )
+ );
+
+ $entityIds = array_diff( $this->reIndexEntityIds( $entityIds ),
$primarySubscriptions );
+
+ if ( empty( $entityIds ) ) {
+ return $primarySubscriptions;
+ }
+
+ $secondarySubscriptions = $this->reIndexEntityIds(
+ $this->secondary->getSubscriptions( $siteId, $entityIds
)
+ );
+
+ $subscriptions = array_merge( $primarySubscriptions,
$secondarySubscriptions );
+ return $subscriptions;
+ }
+
+ /**
+ * @param EntityId[] $entityIds
+ *
+ * @return ItemId[] The ItemIds from EntityId[], keyed by numeric id.
+ */
+ private function reIndexEntityIds( array $entityIds ) {
+ $reindexed = array();
+
+ foreach ( $entityIds as $id ) {
+ $key = $id->getSerialization();
+ $reindexed[$key] = $id;
+ }
+
+ return $reindexed;
+ }
+}
diff --git a/repo/includes/store/sql/SqlSubscriptionLookup.php
b/repo/includes/store/sql/SqlSubscriptionLookup.php
new file mode 100644
index 0000000..8662712
--- /dev/null
+++ b/repo/includes/store/sql/SqlSubscriptionLookup.php
@@ -0,0 +1,129 @@
+<?php
+
+namespace Wikibase\Store\Sql;
+
+use DatabaseBase;
+use LoadBalancer;
+use ResultWrapper;
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\Store\SubscriptionLookup;
+
+/**
+ * Implementation of SubscriptionLookup based on a database table.
+ *
+ * @since 0.5
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class SqlSubscriptionLookup implements SubscriptionLookup {
+
+ /**
+ * @var LoadBalancer
+ */
+ private $dbLoadBalancer;
+
+ /**
+ * @param LoadBalancer $dbLoadBalancer
+ */
+ public function __construct( LoadBalancer $dbLoadBalancer ) {
+ $this->dbLoadBalancer = $dbLoadBalancer;
+ }
+
+ /**
+ * Returns a list of entities a given site is subscribed to.
+ *
+ * @param string $siteId Site ID of the client site.
+ * @param EntityId[] $entityIds The entities we are interested in, or
null for "any".
+ *
+ * @return EntityId[] a list of entity IDs the client wiki is
subscribed to.
+ * The result is limited to entity ids also present in
$entityIds, if given.
+ */
+ public function getSubscriptions( $siteId, array $entityIds ) {
+ if ( empty( $entityIds ) ) {
+ return array();
+ }
+
+ $dbr = $this->dbLoadBalancer->getConnection( DB_SLAVE );
+
+ // NOTE: non-Item ids are ignored, since only items can be
subscribed to
+ // via sitelinks.
+ $entityIds = $this->reIndexEntityIds( $entityIds );
+ $subscribedIds = $this->querySubscriptions( $dbr, $siteId,
array_keys( $entityIds ) );
+
+ // collect the item IDs present in these links
+ $linkedEntityIds = array();
+ foreach ( $subscribedIds as $id ) {
+ $linkedEntityIds[$id] = $entityIds[$id];
+ }
+
+ $this->dbLoadBalancer->reuseConnection( $dbr );
+
+ return $linkedEntityIds;
+ }
+
+ /**
+ * For a set of potential subscriptions, returns the existing
subscriptions.
+ *
+ * @param DatabaseBase $db
+ * @param string $subscriber
+ * @param string[]|null $idsToCheck Id strings to check
+ *
+ * @return string[] Entity ID strings from $subscriptions which
$subscriber is subscribed to.
+ */
+ private function querySubscriptions( DatabaseBase $db, $subscriber,
array $idsToCheck = null ) {
+ $where = array(
+ 'cs_subscriber_id' => $subscriber,
+ );
+
+ if ( $idsToCheck ) {
+ $where['cs_entity_id'] = $idsToCheck;
+ }
+
+ $rows = $db->select(
+ 'wb_changes_subscription',
+ 'cs_entity_id',
+ $where,
+ __METHOD__
+ );
+
+ $subscriptions = $this->extractColumn( $rows, 'cs_entity_id' );
+
+ return $subscriptions;
+ }
+
+ /**
+ * @param EntityId[] $entityIds
+ *
+ * @return EntityId[] The ItemIds from EntityId[], keyed by numeric id.
+ */
+ private function reIndexEntityIds( array $entityIds ) {
+ $reindexed = array();
+
+ foreach ( $entityIds as $id ) {
+ $key = $id->getSerialization();
+ $reindexed[$key] = $id;
+ }
+
+ return $reindexed;
+ }
+
+ /**
+ * @param object[]|ResultWrapper $rows Plain objects
+ * @param string $field The name of the field to extract from each
plain object
+ *
+ * @return array
+ */
+ private function extractColumn( $rows, $field ) {
+ $values = array();
+
+ foreach ( $rows as $row ) {
+ $values[] = $row->$field;
+ }
+
+ return $values;
+ }
+
+
+}
diff --git a/repo/tests/phpunit/includes/store/DualSubscriptionLookupTest.php
b/repo/tests/phpunit/includes/store/DualSubscriptionLookupTest.php
new file mode 100644
index 0000000..870315e
--- /dev/null
+++ b/repo/tests/phpunit/includes/store/DualSubscriptionLookupTest.php
@@ -0,0 +1,108 @@
+<?php
+
+namespace Wikibase\Test;
+
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\Store\DualSubscriptionLookup;
+use Wikibase\Store\SubscriptionLookup;
+
+/**
+ * @covers Wikibase\Store\DualSubscriptionLookup
+ *
+ * @group Wikibase
+ * @group WikibaseStore
+ * @group WikibaseChange
+ * @group WikibaseRepo
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class DualSubscriptionLookupTest extends \PHPUnit_Framework_TestCase {
+
+ /**
+ * @return SubscriptionLookup
+ */
+ private function getSubscriptionLookup( array $subscriptions ) {
+ $lookup = $this->getMock( 'Wikibase\Store\SubscriptionLookup' );
+
+ $lookup->expects( $this->any() )
+ ->method( 'getSubscriptions' )
+ ->will( $this->returnCallback( function ( $siteId,
array $ids ) use ( $subscriptions ) {
+ return array_intersect( $subscriptions, $ids );
+ } ) );
+
+ return $lookup;
+ }
+
+ public function provideGetSubscriptions() {
+ $p1 = new PropertyId( 'P1' );
+ $p3 = new PropertyId( 'P3' );
+ $q2 = new ItemId( 'Q2' );
+ $q7 = new ItemId( 'Q7' );
+
+ return array(
+ 'empty' => array(
+ array(),
+ array(),
+ array(),
+ array(),
+ ),
+ 'empty request' => array(
+ array( $p1 ),
+ array( $q7 ),
+ array(),
+ array(),
+ ),
+ 'empty lookups' => array(
+ array(),
+ array(),
+ array( $p1, $q2, $q7, $p3 ),
+ array(),
+ ),
+ 'partial' => array(
+ array( $p1 ),
+ array( $q7 ),
+ array( $p1, $q2, $q7, $p3 ),
+ array( $p1, $q7 ),
+ ),
+ 'primary covers' => array(
+ array( $p1 ),
+ array( $q7 ),
+ array( $p1 ),
+ array( $p1 ),
+ ),
+ 'secondary covers' => array(
+ array( $p1 ),
+ array( $q7 ),
+ array( $q7 ),
+ array( $q7 ),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider provideGetSubscriptions
+ */
+ public function testGetSubscriptions( $primary, $secondary, $requested,
$expected ) {
+ $primary = $this->getSubscriptionLookup( $primary );
+ $secondary = $this->getSubscriptionLookup( $secondary );
+
+ $lookup = new DualSubscriptionLookup( $primary, $secondary );
+
+ $subscriptions = $lookup->getSubscriptions( 'enwiki',
$requested );
+
+ $this->assertEquals( $this->getIdStrings( $expected ),
$this->getIdStrings( $subscriptions ) );
+ }
+
+ private function getIdStrings( array $ids ) {
+ $strings = array_map( function ( EntityId $id ) {
+ return $id->getSerialization();
+ }, $ids );
+
+ sort( $strings );
+ return $strings;
+ }
+
+}
diff --git
a/repo/tests/phpunit/includes/store/SiteLinkSubscriptionLookupTest.php
b/repo/tests/phpunit/includes/store/SiteLinkSubscriptionLookupTest.php
index 5c65c15..e8d60b6 100644
--- a/repo/tests/phpunit/includes/store/SiteLinkSubscriptionLookupTest.php
+++ b/repo/tests/phpunit/includes/store/SiteLinkSubscriptionLookupTest.php
@@ -15,7 +15,6 @@
* @group WikibaseStore
* @group WikibaseChange
* @group WikibaseRepo
- * @group Database
*
* @licence GNU GPL v2+
* @author Daniel Kinzler
diff --git
a/repo/tests/phpunit/includes/store/sql/SqlSubscriptionLookupTest.php
b/repo/tests/phpunit/includes/store/sql/SqlSubscriptionLookupTest.php
new file mode 100644
index 0000000..c02bbab
--- /dev/null
+++ b/repo/tests/phpunit/includes/store/sql/SqlSubscriptionLookupTest.php
@@ -0,0 +1,67 @@
+<?php
+
+namespace Wikibase\Test;
+
+use MediaWikiTestCase;
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\Store\Sql\SqlSubscriptionLookup;
+
+/**
+ * @covers Wikibase\Store\Sql\SqlSubscriptionLookup
+ *
+ * @group Wikibase
+ * @group WikibaseStore
+ * @group WikibaseChange
+ * @group WikibaseRepo
+ * @group Database
+ *
+ * @licence GNU GPL v2+
+ * @author Daniel Kinzler
+ */
+class SqlSubscriptionLookupTest extends MediaWikiTestCase {
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->tablesUsed[] = 'wb_changes_subscription';
+ }
+
+ private function insertSubscriptions( array $rows ) {
+ $dbw = wfGetDB( DB_MASTER );
+
+ $dbw->insert( 'wb_changes_subscription', $rows, __METHOD__ );
+ }
+
+ public function testGetSubscriptions() {
+ $subscriptions = array(
+ array( 'cs_subscriber_id' => 'enwiki', 'cs_entity_id'
=> 'P1' ),
+ array( 'cs_subscriber_id' => 'enwiki', 'cs_entity_id'
=> 'Q3' ),
+ array( 'cs_subscriber_id' => 'enwiki', 'cs_entity_id'
=> 'Q7' ),
+ array( 'cs_subscriber_id' => 'dewiki', 'cs_entity_id'
=> 'Q2' ),
+ );
+
+ $this->insertSubscriptions( $subscriptions );
+
+ $lookup = new SqlSubscriptionLookup( wfGetLB() );
+
+ $subscriptions = $lookup->getSubscriptions( 'enwiki', array(
+ new PropertyId( 'P1' ),
+ new ItemId( 'Q2' ),
+ new ItemId( 'Q7' ),
+ new PropertyId( 'P3' ),
+ ) );
+
+ $actual = array_map( function ( EntityId $id ) {
+ return $id->getSerialization();
+ }, $subscriptions );
+
+ sort( $actual );
+
+ $expected = array( 'P1', 'Q7' );
+
+ $this->assertEquals( $expected, $actual );
+ }
+
+}
--
To view, visit https://gerrit.wikimedia.org/r/202372
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I239420457100b5565c132048bf57b64f7f304d56
Gerrit-PatchSet: 6
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: Thiemo Mättig (WMDE) <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits