jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/336542 )

Change subject: Adding logging functionality for statements
......................................................................


Adding logging functionality for statements

Deployment: Set $wgWBClientSettings['disabledUsageAspects'] = [ 'C' ];
for all wikis despite the one(s) we want to test with.

Bug: T151717

Change-Id: I57e12454a3935238a596e9732316748fbc53a194
---
M client/includes/DataAccess/Scribunto/Scribunto_LuaWikibaseEntityLibrary.php
M client/includes/DataAccess/Scribunto/WikibaseLuaEntityBindings.php
M client/includes/DataAccess/Scribunto/mw.wikibase.entity.lua
M client/includes/DataAccess/StatementTransclusionInteractor.php
M 
client/tests/phpunit/includes/DataAccess/PropertyParserFunction/PropertyParserFunctionIntegrationTest.php
M 
client/tests/phpunit/includes/DataAccess/PropertyParserFunction/StatementsParserFunctionIntegrationTest.php
M 
client/tests/phpunit/includes/DataAccess/Scribunto/LuaWikibaseEntityLibraryTests.lua
M 
client/tests/phpunit/includes/DataAccess/Scribunto/Scribunto_LuaWikibaseEntityLibraryTest.php
M 
client/tests/phpunit/includes/DataAccess/Scribunto/WikibaseLuaEntityBindingsTest.php
M 
client/tests/phpunit/includes/DataAccess/StatementTransclusionInteractorTest.php
10 files changed, 189 insertions(+), 25 deletions(-)

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



diff --git 
a/client/includes/DataAccess/Scribunto/Scribunto_LuaWikibaseEntityLibrary.php 
b/client/includes/DataAccess/Scribunto/Scribunto_LuaWikibaseEntityLibrary.php
index 8ff2b93..a2b2c94 100644
--- 
a/client/includes/DataAccess/Scribunto/Scribunto_LuaWikibaseEntityLibrary.php
+++ 
b/client/includes/DataAccess/Scribunto/Scribunto_LuaWikibaseEntityLibrary.php
@@ -18,6 +18,7 @@
  *
  * @license GPL-2.0+
  * @author Marius Hoch < h...@online.de >
+ * @author Andrew Hall
  */
 class Scribunto_LuaWikibaseEntityLibrary extends Scribunto_LuaLibraryBase {
 
@@ -79,6 +80,7 @@
                        $richWikitextTransclusionInteractor,
                        $wikibaseClient->getEntityIdParser(),
                        $lang,
+                       $this->getUsageAccumulator(),
                        $wikibaseClient->getSettings()->getSetting( 
'siteGlobalID' )
                );
        }
@@ -123,6 +125,16 @@
        }
 
        /**
+        * Add a statement usage (called once specific statements are accessed).
+        *
+        * @param string $entityId The Entity from which the statements were 
accessed.
+        * @param string $propertyId Property id of the statements accessed.
+        */
+       public function addStatementUsage( $entityId, $propertyId ) {
+               $this->getImplementation()->addStatementUsage( $entityId, 
$propertyId );
+       }
+
+       /**
         * Register mw.wikibase.entity.lua library
         *
         * @return array
@@ -136,6 +148,7 @@
                        'getLanguageCode' => [ $this, 'getLanguageCode' ],
                        'formatStatements' => [ $this, 'formatStatements' ],
                        'formatPropertyValues' => [ $this, 
'formatPropertyValues' ],
+                       'addStatementUsage' => [ $this, 'addStatementUsage' ],
                ];
 
                return $this->getEngine()->registerInterface(
diff --git a/client/includes/DataAccess/Scribunto/WikibaseLuaEntityBindings.php 
b/client/includes/DataAccess/Scribunto/WikibaseLuaEntityBindings.php
index a39d476..a2715ca 100644
--- a/client/includes/DataAccess/Scribunto/WikibaseLuaEntityBindings.php
+++ b/client/includes/DataAccess/Scribunto/WikibaseLuaEntityBindings.php
@@ -4,6 +4,7 @@
 
 use Language;
 use Wikibase\Client\DataAccess\StatementTransclusionInteractor;
+use Wikibase\Client\Usage\UsageAccumulator;
 use Wikibase\DataModel\Entity\EntityIdParser;
 
 /**
@@ -35,6 +36,11 @@
        private $language;
 
        /**
+        * @var UsageAccumulator
+        */
+       private $usageAccumulator;
+
+       /**
         * @var string
         */
        private $siteId;
@@ -44,6 +50,7 @@
         * @param StatementTransclusionInteractor 
$richWikitextTransclusionInteractor
         * @param EntityIdParser $entityIdParser
         * @param Language $language
+        * @param UsageAccumulator $usageAccumulator
         * @param string $siteId
         */
        public function __construct(
@@ -51,12 +58,14 @@
                StatementTransclusionInteractor 
$richWikitextTransclusionInteractor,
                EntityIdParser $entityIdParser,
                Language $language,
+               UsageAccumulator $usageAccumulator,
                $siteId
        ) {
                $this->plainTextTransclusionInteractor = 
$plainTextTransclusionInteractor;
                $this->richWikitextTransclusionInteractor = 
$richWikitextTransclusionInteractor;
                $this->entityIdParser = $entityIdParser;
                $this->language = $language;
+               $this->usageAccumulator = $usageAccumulator;
                $this->siteId = $siteId;
        }
 
@@ -101,6 +110,19 @@
        }
 
        /**
+        * Add a statement usage (called once specific statements are accessed).
+        *
+        * @param string $entityId The Entity from which the statements were 
accessed.
+        * @param string $propertyId Property id of the statements accessed.
+        */
+       public function addStatementUsage( $entityId, $propertyId ) {
+               $entityId = $this->entityIdParser->parse( $entityId );
+               $propertyId = $this->entityIdParser->parse( $propertyId );
+
+               $this->usageAccumulator->addStatementUsage( $entityId, 
$propertyId );
+       }
+
+       /**
         * Get global site ID (e.g. "enwiki")
         * This is basically a helper function.
         * @TODO: Make this part of mw.site in the Scribunto extension.
diff --git a/client/includes/DataAccess/Scribunto/mw.wikibase.entity.lua 
b/client/includes/DataAccess/Scribunto/mw.wikibase.entity.lua
index c589483..112cba9 100644
--- a/client/includes/DataAccess/Scribunto/mw.wikibase.entity.lua
+++ b/client/includes/DataAccess/Scribunto/mw.wikibase.entity.lua
@@ -26,6 +26,43 @@
        RANK_DEPRECATED = 0
 }
 
+-- Function to mask an entity's claims table in order to log access
+-- to individual claims of an entity.
+-- Code for logging based on: http://www.lua.org/pil/13.4.4.html
+--
+-- @param {table} entity
+local maskClaimsTable = function( entity )
+       if entity.claims == nil then
+               return entity
+       end
+       local actualEntityClaims = entity.claims
+       entity.claims = {}
+
+       local pseudoClaimsMetatable = {}
+       pseudoClaimsMetatable.__index = function( emptyTable, propertyID )
+               php.addStatementUsage(entity.id, propertyID)
+               return actualEntityClaims[propertyID]
+       end
+
+       pseudoClaimsMetatable.__newindex = function( emptyTable, propertyID, 
data )
+               error( 'Entity cannot be modified' )
+       end
+
+       local logNext = function( emptyTable, propertyID )
+               if propertyID ~= nil then
+                       php.addStatementUsage(entity.id, propertyID)
+               end
+               return next( actualEntityClaims, propertyID )
+       end
+
+       pseudoClaimsMetatable.__pairs = function( emptyTable )
+               return logNext, {}, nil
+       end
+
+       setmetatable( entity.claims, pseudoClaimsMetatable )
+       return entity
+end
+
 -- Create new entity object from given data
 --
 -- @param {table} data
@@ -43,7 +80,7 @@
                error( 'mw.wikibase.entity must not be constructed using legacy 
data' )
        end
 
-       local entity = data
+       local entity = maskClaimsTable( data )
        setmetatable( entity, metatable )
 
        return entity
diff --git a/client/includes/DataAccess/StatementTransclusionInteractor.php 
b/client/includes/DataAccess/StatementTransclusionInteractor.php
index 0bc58b3..efdaf82 100644
--- a/client/includes/DataAccess/StatementTransclusionInteractor.php
+++ b/client/includes/DataAccess/StatementTransclusionInteractor.php
@@ -92,16 +92,24 @@
                        return '';
                }
 
+               // Currently statement usage implies other usage.
                $this->usageAccumulator->addOtherUsage( $entityId );
+
+               // If the entity doesn't exist, we just want to resolve the 
property id
+               // for usage tracking purposes, so don't let the exception 
bubble up.
+               $shouldThrow = $entity !== null;
+
+               $propertyId = $this->resolvePropertyId( $propertyLabelOrId, 
$shouldThrow );
+
+               if ( $propertyId ) {
+                       // XXX: This means we only track a statement usage if 
the property id /label
+                       // can be resolved. This requires the property to exist!
+                       $this->usageAccumulator->addStatementUsage( $entityId, 
$propertyId );
+               }
 
                if ( $entity === null ) {
                        return '';
                }
-
-               $propertyId = $this->propertyIdResolver->resolvePropertyId(
-                       $propertyLabelOrId,
-                       $this->language->getCode()
-               );
 
                $snaks = $this->snaksFinder->findSnaks(
                        $entity,
@@ -113,6 +121,31 @@
        }
 
        /**
+        * @param string $propertyLabelOrId property label or ID (Pxxx)
+        * @param bool $shouldThrow Whether PropertyLabelNotResolvedException 
should be thrown
+        *
+        * @return PropertyId|null
+        *
+        * @throws PropertyLabelNotResolvedException
+        */
+       private function resolvePropertyId( $propertyLabelOrId, $shouldThrow ) {
+               try {
+                       $propertyId = 
$this->propertyIdResolver->resolvePropertyId(
+                               $propertyLabelOrId,
+                               $this->language->getCode()
+                       );
+               } catch ( PropertyLabelNotResolvedException 
$propertyLabelNotResolvedException ) {
+                       if ( !$shouldThrow ) {
+                               return null;
+                       }
+
+                       throw $propertyLabelNotResolvedException;
+               }
+
+               return $propertyId;
+       }
+
+       /**
         * @param Snak[] $snaks
         *
         * @return string wikitext
diff --git 
a/client/tests/phpunit/includes/DataAccess/PropertyParserFunction/PropertyParserFunctionIntegrationTest.php
 
b/client/tests/phpunit/includes/DataAccess/PropertyParserFunction/PropertyParserFunctionIntegrationTest.php
index fdaa350..733ed83 100644
--- 
a/client/tests/phpunit/includes/DataAccess/PropertyParserFunction/PropertyParserFunctionIntegrationTest.php
+++ 
b/client/tests/phpunit/includes/DataAccess/PropertyParserFunction/PropertyParserFunctionIntegrationTest.php
@@ -80,7 +80,7 @@
 
                $usageAccumulator = new ParserOutputUsageAccumulator( $result );
                $this->assertArrayEquals(
-                       [ 'P342#L.de', 'Q32487#O' ],
+                       [ 'P342#L.de', 'Q32487#O', 'Q32487#C.P342' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -92,7 +92,7 @@
 
                $usageAccumulator = new ParserOutputUsageAccumulator( $result );
                $this->assertArrayEquals(
-                       [ 'Q32487#O' ],
+                       [ 'Q32487#O', 'Q32487#C.P342' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -104,7 +104,7 @@
 
                $usageAccumulator = new ParserOutputUsageAccumulator( $result );
                $this->assertArrayEquals(
-                       [ 'Q32488#O' ],
+                       [ 'Q32488#O', 'Q32488#C.P342' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -116,7 +116,7 @@
 
                $usageAccumulator = new ParserOutputUsageAccumulator( $result );
                $this->assertArrayEquals(
-                       [ 'Q32489#O' ],
+                       [ 'Q32489#O', 'Q32489#C.P342' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -128,7 +128,7 @@
 
                $usageAccumulator = new ParserOutputUsageAccumulator( $result );
                $this->assertArrayEquals(
-                       [ 'Q1234567#O' ],
+                       [ 'Q1234567#O', 'Q1234567#C.P342' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -143,7 +143,7 @@
 
                $usageAccumulator = new ParserOutputUsageAccumulator( $result );
                $this->assertArrayEquals(
-                       [ 'Q32487#O' ],
+                       [ 'Q32487#O' ], // 'Q32487#C.P2147483645' is not 
tracked, as P2147483645 doesn't exist
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
diff --git 
a/client/tests/phpunit/includes/DataAccess/PropertyParserFunction/StatementsParserFunctionIntegrationTest.php
 
b/client/tests/phpunit/includes/DataAccess/PropertyParserFunction/StatementsParserFunctionIntegrationTest.php
index 29390ff..229d81a 100644
--- 
a/client/tests/phpunit/includes/DataAccess/PropertyParserFunction/StatementsParserFunctionIntegrationTest.php
+++ 
b/client/tests/phpunit/includes/DataAccess/PropertyParserFunction/StatementsParserFunctionIntegrationTest.php
@@ -81,7 +81,7 @@
 
                $usageAccumulator = new ParserOutputUsageAccumulator( $result );
                $this->assertArrayEquals(
-                       [ 'P342#L.de', 'Q32487#O' ],
+                       [ 'P342#L.de', 'Q32487#O', 'Q32487#C.P342' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -93,7 +93,7 @@
 
                $usageAccumulator = new ParserOutputUsageAccumulator( $result );
                $this->assertArrayEquals(
-                       [ 'Q32487#O' ],
+                       [ 'Q32487#O', 'Q32487#C.P342' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -105,7 +105,7 @@
 
                $usageAccumulator = new ParserOutputUsageAccumulator( $result );
                $this->assertArrayEquals(
-                       [ 'Q32488#O' ],
+                       [ 'Q32488#O', 'Q32488#C.P342' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -117,7 +117,7 @@
 
                $usageAccumulator = new ParserOutputUsageAccumulator( $result );
                $this->assertArrayEquals(
-                       [ 'Q32489#O' ],
+                       [ 'Q32489#O', 'Q32489#C.P342' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -129,7 +129,7 @@
 
                $usageAccumulator = new ParserOutputUsageAccumulator( $result );
                $this->assertArrayEquals(
-                       [ 'Q1234567#O' ],
+                       [ 'Q1234567#O', 'Q1234567#C.P342' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -144,7 +144,7 @@
 
                $usageAccumulator = new ParserOutputUsageAccumulator( $result );
                $this->assertArrayEquals(
-                       [ 'Q32487#O' ],
+                       [ 'Q32487#O' ], // 'Q32487#C.P2147483645' is not 
tracked, as P2147483645 doesn't exist
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
diff --git 
a/client/tests/phpunit/includes/DataAccess/Scribunto/LuaWikibaseEntityLibraryTests.lua
 
b/client/tests/phpunit/includes/DataAccess/Scribunto/LuaWikibaseEntityLibraryTests.lua
index 04c328e..2c173bf 100644
--- 
a/client/tests/phpunit/includes/DataAccess/Scribunto/LuaWikibaseEntityLibraryTests.lua
+++ 
b/client/tests/phpunit/includes/DataAccess/Scribunto/LuaWikibaseEntityLibraryTests.lua
@@ -190,12 +190,46 @@
        return entity:formatStatements( 'P342', mw.wikibase.entity.claimRanks )
 end
 
+local function testClaimsPairSize()
+       local entity = mw.wikibase.getEntityObject( 'Q32487' )
+       local count = 0
+       for a,b in pairs(entity.claims) do
+               count = count + 1
+       end
+
+       return count
+end
+
+local function testClaimsPairContent()
+       local testItem = getNewTestItem()
+       local claimsTable = {}
+       for a in pairs(testItem.claims) do
+               claimsTable[a] = testItem.claims[a]
+       end
+       return claimsTable
+end
+
+local function testClaimsNewIndex()
+       local entity = mw.wikibase.getEntityObject( 'Q32487' )
+       entity['claims']['P321'] = ""
+end
+
+
 local tests = {
        -- Unit Tests
 
        { name = 'mw.wikibase.entity exists', func = testExists, 
type='ToString',
          expect = { 'table' }
        },
+       { name = 'mw.wikibase.testClaimsPairSize', func = testClaimsPairSize,
+         expect = { 1 }
+       },
+       { name = 'mw.wikibase.testClaimsPairContent', func = 
testClaimsPairContent,
+         expect = { {P321={}, P4321={}}, }
+       },
+       { name = 'mw.wikibase.testClaimsNewIndex', func = testClaimsNewIndex,
+         expect = 'Entity cannot be modified'
+       },
        { name = 'mw.wikibase.entity.create with empty table', func = 
testCreate,
          args = { {} },
          expect = 'Expected a non-empty table obtained via 
mw.wikibase.getEntityObject'
diff --git 
a/client/tests/phpunit/includes/DataAccess/Scribunto/Scribunto_LuaWikibaseEntityLibraryTest.php
 
b/client/tests/phpunit/includes/DataAccess/Scribunto/Scribunto_LuaWikibaseEntityLibraryTest.php
index eb93192..64444da 100644
--- 
a/client/tests/phpunit/includes/DataAccess/Scribunto/Scribunto_LuaWikibaseEntityLibraryTest.php
+++ 
b/client/tests/phpunit/includes/DataAccess/Scribunto/Scribunto_LuaWikibaseEntityLibraryTest.php
@@ -158,6 +158,7 @@
                        $this->assertArrayHasKey( 'Q885588#L.de', $usages );
                }
                $this->assertArrayHasKey( 'Q32488#O', $usages );
+               $this->assertArrayHasKey( 'Q32488#C.P456', $usages );
 
                $this->assertSame( $allowDataAccessInUserLanguage, $cacheSplit 
);
        }
@@ -212,6 +213,7 @@
                        $this->assertArrayHasKey( 'Q885588#L.de', $usages );
                }
                $this->assertArrayHasKey( 'Q32488#O', $usages );
+               $this->assertArrayHasKey( 'Q32488#C.P456', $usages );
 
                $this->assertSame( $allowDataAccessInUserLanguage, $cacheSplit 
);
        }
diff --git 
a/client/tests/phpunit/includes/DataAccess/Scribunto/WikibaseLuaEntityBindingsTest.php
 
b/client/tests/phpunit/includes/DataAccess/Scribunto/WikibaseLuaEntityBindingsTest.php
index 3ec01dd..be8e455 100644
--- 
a/client/tests/phpunit/includes/DataAccess/Scribunto/WikibaseLuaEntityBindingsTest.php
+++ 
b/client/tests/phpunit/includes/DataAccess/Scribunto/WikibaseLuaEntityBindingsTest.php
@@ -6,8 +6,10 @@
 use PHPUnit_Framework_TestCase;
 use Wikibase\Client\DataAccess\Scribunto\WikibaseLuaEntityBindings;
 use Wikibase\Client\DataAccess\StatementTransclusionInteractor;
+use Wikibase\Client\Usage\EntityUsage;
+use Wikibase\Client\Usage\HashUsageAccumulator;
 use Wikibase\DataModel\Entity\ItemId;
-use Wikibase\DataModel\Entity\ItemIdParser;
+use Wikibase\DataModel\Entity\BasicEntityIdParser;
 use Wikibase\DataModel\Statement\Statement;
 
 /**
@@ -23,9 +25,13 @@
 class WikibaseLuaEntityBindingsTest extends PHPUnit_Framework_TestCase {
 
        /**
+        * @param HashUsageAccumulator|null $usageAccumulator
+        *
         * @return WikibaseLuaEntityBindings
         */
-       private function getWikibaseLuaEntityBindings() {
+       private function getWikibaseLuaEntityBindings( HashUsageAccumulator 
$usageAccumulator = null ) {
+               $usageAccumulator = $usageAccumulator ?: new 
HashUsageAccumulator();
+
                $plainTextTransclusionInteractor = $this->getMockBuilder( 
StatementTransclusionInteractor::class )
                        ->disableOriginalConstructor()
                        ->getMock();
@@ -47,8 +53,9 @@
                return new WikibaseLuaEntityBindings(
                        $plainTextTransclusionInteractor,
                        $richWikitextTransclusionInteractor,
-                       new ItemIdParser(),
+                       new BasicEntityIdParser(),
                        Language::factory( 'es' ),
+                       $usageAccumulator,
                        'enwiki'
                );
        }
@@ -79,6 +86,22 @@
                );
        }
 
+       public function testAddStatementUsage() {
+               $q2013 = new ItemId( 'Q2013' );
+               $usageAccumulator = new HashUsageAccumulator();
+
+               $wikibaseLuaEntityBindings = 
$this->getWikibaseLuaEntityBindings( $usageAccumulator );
+               $wikibaseLuaEntityBindings->addStatementUsage( 
$q2013->getSerialization(), 'P1337', true );
+
+               $this->assertCount( 1, $usageAccumulator->getUsages() );
+               $this->assertEquals(
+                       [
+                               'Q2013#C.P1337' => new EntityUsage( $q2013, 
EntityUsage::STATEMENT_USAGE, 'P1337' )
+                       ],
+                       $usageAccumulator->getUsages()
+               );
+       }
+
        public function testGetGlobalSiteId() {
                $wikibaseLuaEntityBindings = 
$this->getWikibaseLuaEntityBindings();
 
diff --git 
a/client/tests/phpunit/includes/DataAccess/StatementTransclusionInteractorTest.php
 
b/client/tests/phpunit/includes/DataAccess/StatementTransclusionInteractorTest.php
index 5a1f857..8b1349d 100644
--- 
a/client/tests/phpunit/includes/DataAccess/StatementTransclusionInteractorTest.php
+++ 
b/client/tests/phpunit/includes/DataAccess/StatementTransclusionInteractorTest.php
@@ -64,7 +64,7 @@
                $this->assertSame( $expected, $result );
 
                $this->assertEquals(
-                       [ 'Q42#O' ],
+                       [ 'Q42#O', 'Q42#C.P1337' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -101,7 +101,7 @@
                $this->assertSame( '', $renderer->render( new ItemId( 'Q42' ), 
'P1337' ) );
 
                $this->assertEquals(
-                       [ 'Q42#O' ],
+                       [ 'Q42#O', 'Q42#C.P1337' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -118,7 +118,7 @@
                $this->assertSame( '', $renderer->render( new ItemId( 'Q43' ), 
'P1337' ) );
 
                $this->assertEquals(
-                       [ 'Q43#O' ],
+                       [ 'Q43#O', 'Q43#C.P1337' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }
@@ -135,7 +135,7 @@
                $this->assertSame( '', $renderer->render( new ItemId( 'Q43333' 
), 'P1337' ) );
 
                $this->assertEquals(
-                       [ 'Q43333#O' ],
+                       [ 'Q43333#O', 'Q43333#C.P1337' ],
                        array_keys( $usageAccumulator->getUsages() )
                );
        }

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I57e12454a3935238a596e9732316748fbc53a194
Gerrit-PatchSet: 30
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Hall1467 <hall1...@umn.edu>
Gerrit-Reviewer: Aleksey Bekh-Ivanov (WMDE) <aleksey.bekh-iva...@wikimedia.de>
Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de>
Gerrit-Reviewer: Hall1467 <hall1...@umn.edu>
Gerrit-Reviewer: Hoo man <h...@online.de>
Gerrit-Reviewer: Jackmcbarn <jackmcb...@gmail.com>
Gerrit-Reviewer: Matěj Suchánek <matejsuchane...@gmail.com>
Gerrit-Reviewer: Thiemo Mättig (WMDE) <thiemo.maet...@wikimedia.de>
Gerrit-Reviewer: WMDE-leszek <leszek.mani...@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