jenkins-bot has submitted this change and it was merged.
Change subject: Make use of Serializers in API results for sitelinks
......................................................................
Make use of Serializers in API results for sitelinks
Bug: 49863
Change-Id: I1f9bff8106c5a50ae30e043727b4a85b73c67fe4
---
M lib/WikibaseLib.classes.php
M lib/includes/serializers/ItemSerializer.php
A lib/includes/serializers/SiteLinkSerializer.php
A lib/tests/phpunit/serializers/SiteLinkSerializerTest.php
M repo/includes/api/ApiWikibase.php
M repo/includes/api/EditEntity.php
6 files changed, 344 insertions(+), 172 deletions(-)
Approvals:
Daniel Kinzler: Looks good to me, approved
jenkins-bot: Verified
diff --git a/lib/WikibaseLib.classes.php b/lib/WikibaseLib.classes.php
index abdffc9..70beb58 100644
--- a/lib/WikibaseLib.classes.php
+++ b/lib/WikibaseLib.classes.php
@@ -111,6 +111,7 @@
'Wikibase\Lib\Serializers\LabelSerializer' =>
'includes/serializers/LabelSerializer.php',
'Wikibase\Lib\Serializers\DescriptionSerializer' =>
'includes/serializers/DescriptionSerializer.php',
'Wikibase\Lib\Serializers\AliasSerializer' =>
'includes/serializers/AliasSerializer.php',
+ 'Wikibase\Lib\Serializers\SiteLinkSerializer' =>
'includes/serializers/SiteLinkSerializer.php',
'Wikibase\Lib\Serializers\PropertySerializer' =>
'includes/serializers/PropertySerializer.php',
'Wikibase\Lib\Serializers\ReferenceSerializer' =>
'includes/serializers/ReferenceSerializer.php',
'Wikibase\Lib\Serializers\SerializationOptions' =>
'includes/serializers/SerializationOptions.php',
diff --git a/lib/includes/serializers/ItemSerializer.php
b/lib/includes/serializers/ItemSerializer.php
index 43f6eea..e326357 100644
--- a/lib/includes/serializers/ItemSerializer.php
+++ b/lib/includes/serializers/ItemSerializer.php
@@ -2,10 +2,8 @@
namespace Wikibase\Lib\Serializers;
use MWException;
-use Wikibase\DataModel\SimpleSiteLink;
use Wikibase\Entity;
use Wikibase\Item;
-use Wikibase\SiteLink;
/**
* Serializer for items.
@@ -33,8 +31,32 @@
* @licence GNU GPL v2+
* @author Jeroen De Dauw < [email protected] >
* @author John Erling Blad < [email protected] >
+ * @author Tobias Gritschacher < [email protected] >
*/
class ItemSerializer extends EntitySerializer {
+
+ /**
+ * @since 0.4
+ *
+ * @var \SiteSQLStore
+ */
+ protected $siteStore;
+
+ /**
+ * Constructor.
+ *
+ * @since 0.4
+ *
+ * @param EntitySerializationOptions $options
+ */
+ public function __construct( EntitySerializationOptions $options,
\SiteSQLStore $siteStore = null ) {
+ if ( $siteStore === null ) {
+ $this->siteStore = \SiteSQLStore::newInstance();
+ } else {
+ $this->siteStore = $siteStore;
+ }
+ parent::__construct( $options );
+ }
/**
* @see EntitySerializer::getEntityTypeSpecificSerialization
@@ -54,94 +76,11 @@
$serialization = array();
if ( in_array( 'sitelinks', $this->options->getProps() ) ) {
- $serialization['sitelinks'] =
$this->getSiteLinksSerialization( $item );
+ $siteLinkSerializer = new SiteLinkSerializer(
$this->options, $this->siteStore );
+ $siteLinks = $item->getSimpleSiteLinks();
+ $serialization['sitelinks'] =
$siteLinkSerializer->getSerialized( $siteLinks );
}
return $serialization;
}
-
- /**
- * @since 0.2
- *
- * @param Item $item
- *
- * @return array
- */
- protected function getSiteLinksSerialization( Item $item ) {
- $serialization = array();
-
- $includeUrls = in_array( 'sitelinks/urls',
$this->options->getProps() );
-
- foreach ( $this->getSortedSiteLinks( $item ) as $link ) {
- $response = array(
- 'site' => $link->getSiteId(),
- 'title' => $link->getPageName(),
- );
-
- if ( $includeUrls ) {
- // FIXME: deprecated method usage
- $site = \Sites::singleton()->getSite(
$link->getSiteId() );
-
- if ( $site !== null ) {
- $siteLink = new SiteLink( $site,
$link->getPageName() );
- $response['url'] = $siteLink->getUrl();
- }
- }
-
- if ( $this->options->shouldUseKeys() ) {
- $serialization[$link->getSiteId()] = $response;
- }
- else {
- $serialization[] = $response;
- }
- }
-
- if ( !$this->options->shouldUseKeys() ) {
- $this->setIndexedTagName( $serialization, 'sitelink' );
- }
-
- return $serialization;
- }
-
- /**
- * Returns the sitelinks for the provided item sorted based
- * on the set serialization options.
- *
- * @since 0.2
- *
- * @param Item $item
- * @return SimpleSiteLink[]
- */
- protected function getSortedSiteLinks( Item $item ) {
- $siteLinks = $item->getSimpleSiteLinks();
-
- $sortDirection = $this->options->getSortDirection();
-
- if ( $sortDirection !== EntitySerializationOptions::SORT_NONE )
{
- $sortOk = false;
-
- if ( $sortDirection ===
EntitySerializationOptions::SORT_ASC ) {
- $sortOk = usort(
- $siteLinks,
- function( SimpleSiteLink $a,
SimpleSiteLink $b ) {
- return strcmp( $a->getSiteId(),
$b->getSiteId() );
- }
- );
- } elseif ( $sortDirection ===
EntitySerializationOptions::SORT_DESC ) {
- $sortOk = usort(
- $siteLinks,
- function( SimpleSiteLink $a,
SimpleSiteLink $b ) {
- return strcmp( $b->getSiteId(),
$a->getSiteId() );
- }
- );
- }
-
- if ( !$sortOk ) {
- $siteLinks = $item->getSimpleSiteLinks();
- }
- }
-
- return $siteLinks;
- }
-
}
diff --git a/lib/includes/serializers/SiteLinkSerializer.php
b/lib/includes/serializers/SiteLinkSerializer.php
new file mode 100644
index 0000000..4255cb5
--- /dev/null
+++ b/lib/includes/serializers/SiteLinkSerializer.php
@@ -0,0 +1,160 @@
+<?php
+
+namespace Wikibase\Lib\Serializers;
+
+use InvalidArgumentException;
+use Wikibase\SiteLink;
+use Wikibase\DataModel\SimpleSiteLink;
+
+/**
+ * Serializer for sitelinks.
+ *
+ * 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 Jeroen De Dauw < [email protected] >
+ * @author John Erling Blad < [email protected] >
+ * @author Tobias Gritschacher < [email protected] >
+ */
+class SiteLinkSerializer extends SerializerObject {
+
+ /**
+ * @see ApiSerializerObject::$options
+ *
+ * @since 0.4
+ *
+ * @var EntitySerializationOptions
+ */
+ protected $options;
+
+ /**
+ * @since 0.4
+ *
+ * @var SiteSQLStore $siteStore
+ */
+ protected $siteStore;
+
+ /**
+ * Constructor.
+ *
+ * @since 0.4
+ *
+ * @param EntitySerializationOptions $options
+ * @param SiteSQLStore $siteStore
+ */
+ public function __construct( EntitySerializationOptions $options,
\SiteSQLStore $siteStore ) {
+ $this->options = new MultiLangSerializationOptions();
+ $this->siteStore = $siteStore;
+ parent::__construct( $options );
+ }
+
+ /**
+ * Returns a serialized array of sitelinks.
+ *
+ * @since 0.4
+ *
+ * @param array $sitelinks
+ *
+ * @return array
+ * @throws InvalidArgumentException
+ */
+ public final function getSerialized( $siteLinks ) {
+ if ( !is_array( $siteLinks ) ) {
+ throw new InvalidArgumentException( 'SiteLinkSerializer
can only serialize an array of sitelinks' );
+ }
+
+ $serialization = array();
+
+ $includeUrls = in_array( 'sitelinks/url',
$this->options->getProps() );
+
+ foreach ( $this->sortSiteLinks( $siteLinks ) as $link ) {
+ $response = array(
+ 'site' => $link->getSiteId(),
+ 'title' => $link->getPageName(),
+ );
+
+ if ( $includeUrls ) {
+ $site = $this->siteStore->getSite(
$link->getSiteId() );
+
+ if ( $site !== null ) {
+ $siteLink = new SiteLink( $site,
$link->getPageName() );
+ $response['url'] = $siteLink->getUrl();
+ }
+ }
+
+ if ( in_array( 'sitelinks/removed',
$this->options->getProps() ) ) {
+ $response['removed'] = '';
+ }
+
+ if ( $this->options->shouldUseKeys() ) {
+ $serialization[$link->getSiteId()] = $response;
+ }
+ else {
+ $serialization[] = $response;
+ }
+ }
+
+ if ( !$this->options->shouldUseKeys() ) {
+ $this->setIndexedTagName( $serialization, 'sitelink' );
+ }
+
+ return $serialization;
+ }
+
+ /**
+ * Sorts the siteLinks according to the options.
+ *
+ * @since 0.4
+ *
+ * @param array $siteLinks
+ * @return SimpleSiteLink[]
+ */
+ protected function sortSiteLinks( $siteLinks ) {
+ $unsortedSiteLinks = $siteLinks;
+ $sortDirection = $this->options->getSortDirection();
+
+ if ( $sortDirection !== EntitySerializationOptions::SORT_NONE )
{
+ $sortOk = false;
+
+ if ( $sortDirection ===
EntitySerializationOptions::SORT_ASC ) {
+ $sortOk = usort(
+ $siteLinks,
+ function( SimpleSiteLink $a,
SimpleSiteLink $b ) {
+ return strcmp( $a->getSiteId(),
$b->getSiteId() );
+ }
+ );
+ } elseif ( $sortDirection ===
EntitySerializationOptions::SORT_DESC ) {
+ $sortOk = usort(
+ $siteLinks,
+ function( SimpleSiteLink $a,
SimpleSiteLink $b ) {
+ return strcmp( $b->getSiteId(),
$a->getSiteId() );
+ }
+ );
+ }
+
+ if ( !$sortOk ) {
+ $siteLinks = $unsortedSiteLinks;
+ }
+ }
+
+ return $siteLinks;
+ }
+}
diff --git a/lib/tests/phpunit/serializers/SiteLinkSerializerTest.php
b/lib/tests/phpunit/serializers/SiteLinkSerializerTest.php
new file mode 100644
index 0000000..127d08b
--- /dev/null
+++ b/lib/tests/phpunit/serializers/SiteLinkSerializerTest.php
@@ -0,0 +1,135 @@
+<?php
+
+namespace Wikibase\Test;
+
+use Wikibase\Lib\Serializers\EntitySerializationOptions;
+use Wikibase\Lib\Serializers\SiteLinkSerializer;
+use Wikibase\DataModel\SimpleSiteLink;
+use ValueFormatters\FormatterOptions;
+use Wikibase\Lib\EntityIdFormatter;
+
+/**
+ * @covers Wikibase\Lib\Serializers\SiteLinkSerializer
+ *
+ * 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
+ *
+ * @file
+ * @since 0.4
+ *
+ * @ingroup WikibaseLib
+ * @ingroup Test
+ *
+ * @group Wikibase
+ * @group WikibaseSerialization
+ * @group WikibaseSiteLinkSerializer
+ *
+ * @licence GNU GPL v2+
+ * @author Tobias Gritschacher < [email protected] >
+ */
+class SiteLinkSerializerTest extends \PHPUnit_Framework_TestCase {
+
+ public function validProvider() {
+ $validArgs = array();
+ $idFormatter = $this->getIdFormatter();
+
+ $options = new EntitySerializationOptions( $idFormatter );
+ $options->setUseKeys( true );
+ $siteLinks = array(
+ new SimpleSiteLink( "enwiki", "Rome" ),
+ new SimpleSiteLink( "dewiki", "Rom" ),
+ new SimpleSiteLink( "itwiki", "Roma" ),
+ );
+ $expectedSerialization = array(
+ "enwiki" => array( "site" => "enwiki", "title" =>
"Rome" ),
+ "dewiki" => array( "site" => "dewiki", "title" => "Rom"
),
+ "itwiki" => array( "site" => "itwiki", "title" =>
"Roma" ),
+ );
+ $validArgs[] = array( $siteLinks, $options,
$expectedSerialization );
+
+ $options = new EntitySerializationOptions( $idFormatter );
+ $options->setUseKeys( true );
+ $options->addProp( "sitelinks/removed" );
+ $siteLinks = array(
+ new SimpleSiteLink( "enwiki", "" ),
+ new SimpleSiteLink( "dewiki", "" ),
+ new SimpleSiteLink( "itwiki", "" ),
+ );
+ $expectedSerialization = array(
+ "enwiki" => array( "site" => "enwiki", "title"
=> "", "removed" => "" ),
+ "dewiki" => array( "site" => "dewiki", "title"
=> "", "removed" => "" ),
+ "itwiki" => array( "site" => "itwiki", "title"
=> "", "removed" => "" ),
+ );
+ $validArgs[] = array( $siteLinks, $options,
$expectedSerialization );
+
+ $options = new EntitySerializationOptions( $idFormatter );
+ $options->setUseKeys( false );
+ $siteLinks = array(
+ new SimpleSiteLink( "enwiki", "Rome" ),
+ new SimpleSiteLink( "dewiki", "Rom" ),
+ new SimpleSiteLink( "itwiki", "Roma" ),
+ );
+ $expectedSerialization = array(
+ array( "site" => "enwiki", "title" => "Rome" ),
+ array( "site" => "dewiki", "title" => "Rom" ),
+ array( "site" => "itwiki", "title" => "Roma" ),
+ "_element" => "sitelink",
+ );
+ $validArgs[] = array( $siteLinks, $options,
$expectedSerialization );
+
+ return $validArgs;
+ }
+
+ /**
+ * @dataProvider validProvider
+ */
+ public function testGetSerialized( $siteLinks, $options,
$expectedSerialization ) {
+ $siteStore = \SiteSQLStore::newInstance();
+ $siteStore->reset();
+ $siteLinkSerializer = new SiteLinkSerializer( $options,
$siteStore );
+ $serializedSiteLinks = $siteLinkSerializer->getSerialized(
$siteLinks );
+
+ $this->assertEquals( $expectedSerialization,
$serializedSiteLinks );
+ }
+
+ public function invalidProvider() {
+ $invalidArgs = array();
+
+ $invalidArgs[] = array( 'foo' );
+ $invalidArgs[] = array( 42 );
+
+ return $invalidArgs;
+ }
+
+ /**
+ * @dataProvider invalidProvider
+ * @expectedException InvalidArgumentException
+ */
+ public function testInvalidGetSerialized( $sitelinks ) {
+ $options = new EntitySerializationOptions(
$this->getIdFormatter() );
+ $siteStore = \SiteSQLStore::newInstance();
+ $siteLinkSerializer = new SiteLinkSerializer( $options,
$siteStore );
+ $serializedSiteLinks = $siteLinkSerializer->getSerialized(
$sitelinks );
+ }
+
+ protected function getIdFormatter() {
+ $formatterOptions = new FormatterOptions( array(
EntityIdFormatter::OPT_PREFIX_MAP => array(
+ 'item' => 'i',
+ 'property' => 'p',
+ ) ) );
+
+ return new EntityIdFormatter( $formatterOptions );
+ }
+}
diff --git a/repo/includes/api/ApiWikibase.php
b/repo/includes/api/ApiWikibase.php
index defeb90..71877a1 100644
--- a/repo/includes/api/ApiWikibase.php
+++ b/repo/includes/api/ApiWikibase.php
@@ -9,9 +9,12 @@
use Wikibase\Settings;
use Wikibase\EditEntity;
use Wikibase\SiteLink;
+use Wikibase\Repo\WikibaseRepo;
use Wikibase\Lib\Serializers\LabelSerializer;
use Wikibase\Lib\Serializers\DescriptionSerializer;
use Wikibase\Lib\Serializers\AliasSerializer;
+use Wikibase\Lib\Serializers\SiteLinkSerializer;
+use Wikibase\Lib\Serializers\EntitySerializationOptions;
use Wikibase\Lib\Serializers\MultiLangSerializationOptions;
/**
@@ -25,6 +28,7 @@
*
* @licence GNU GPL v2+
* @author John Erling Blad < [email protected] >
+ * @author Tobias Gritschacher < [email protected] >
*/
abstract class ApiWikibase extends \ApiBase {
@@ -125,7 +129,6 @@
* @param string $name name used for the entry
* @param string $tag tag used for indexed entries in xml formats and
similar
*
- * @return array|bool
*/
protected function addAliasesToResult( array $aliases, $path, $name =
'aliases', $tag = 'alias' ) {
$options = new MultiLangSerializationOptions();
@@ -143,12 +146,9 @@
}
/**
- * Add sitelinks to result
+ * Get serialized sitelinks and add them to result
*
- * @deprecated
- * TODO: move to \Wikibase\EntitySerializer
- *
- * @since 0.1
+ * @since 0.4
*
* @param array $siteLinks the site links to insert in the result, as
SiteLink objects
* @param array|string $path where the data is located
@@ -157,90 +157,31 @@
* @param array $options additional information to include in the
listelinks structure. For example:
* * 'url' will include the full URL of the sitelink in
the result
* * 'removed' will mark the sitelinks as removed
- * * other options will simply be included as flags.
*
- * @return array|bool
*/
protected function addSiteLinksToResult( array $siteLinks, $path, $name
= 'sitelinks', $tag = 'sitelink', $options = null ) {
- $value = array();
- $idx = 0;
+ $serializerOptions = new EntitySerializationOptions(
WikibaseRepo::getDefaultInstance()->getIdFormatter() );
+ $serializerOptions->setSortDirection(
EntitySerializationOptions::SORT_NONE );
if ( isset( $options ) ) {
- // figure out if the entries shall be sorted
- $dir = null;
- if ( in_array( 'ascending', $options ) ) {
- $dir = 'ascending';
- }
- elseif ( in_array( 'descending', $options ) ) {
- $dir = 'descending';
+ if ( in_array( EntitySerializationOptions::SORT_ASC,
$options ) ) {
+ $serializerOptions->setSortDirection(
EntitySerializationOptions::SORT_ASC );
+ } elseif ( in_array(
EntitySerializationOptions::SORT_DESC, $options ) ) {
+ $serializerOptions->setSortDirection(
EntitySerializationOptions::SORT_DESC );
}
- if ( isset( $dir ) ) {
- // Sort the sitelinks according to their global
id
- $saftyCopy = $siteLinks; // keep a shallow copy;
+ if ( in_array( 'url', $options ) ) {
+ $serializerOptions->addProp( 'sitelinks/url' );
+ }
- $sortOk = false;
-
- if ( $dir === 'ascending' ) {
- $sortOk = usort(
- $siteLinks,
- function( SimpleSiteLink $a,
SimpleSiteLink $b ) {
- return strcmp(
$a->getSiteId(), $b->getSiteId() );
- }
- );
- } elseif ( $dir === 'descending' ) {
- $sortOk = usort(
- $siteLinks,
- function( SimpleSiteLink $a,
SimpleSiteLink $b ) {
- return strcmp(
$b->getSiteId(), $a->getSiteId() );
- }
- );
- }
-
- if ( !$sortOk ) {
- $siteLinks = $saftyCopy;
- }
+ if ( in_array( 'removed', $options ) ) {
+ $serializerOptions->addProp(
'sitelinks/removed' );
}
}
- /**
- * @var SimpleSiteLink $link
- */
- foreach ( $siteLinks as $link ) {
- $response = array(
- 'site' => $link->getSiteId(),
- 'title' => $link->getPageName(),
- );
-
- if ( $options !== null ) {
- foreach ( $options as $opt ) {
- if ( isset( $response[$opt] ) ) {
- //skip
- } elseif ( $opt === 'url' ) {
- //include full url in the result
- $site =
\Sites::singleton()->getSite( $link->getSiteId() );
-
- if ( $site === null ) {
- $response['url'] = '';
- }
- else {
- $siteLink = new
SiteLink(
- $site,
-
$link->getPageName()
- );
-
- $response['url'] =
$siteLink->getUrl();
- }
- } else {
- //include some flag in the
result
- $response[$opt] = '';
- }
- }
- }
-
- $key = $this->getUsekeys() ? $link->getSiteId() :
$idx++;
- $value[$key] = $response;
- }
+ $siteStore = \SiteSQLStore::newInstance();
+ $siteLinkSerializer = new SiteLinkSerializer(
$serializerOptions, $siteStore );
+ $value = $siteLinkSerializer->getSerialized( $siteLinks );
if ( $value !== array() ) {
if ( !$this->getUsekeys() ) {
@@ -261,7 +202,6 @@
* @param string $name name used for the entry
* @param string $tag tag used for indexed entries in xml formats and
similar
*
- * @return array|bool
*/
protected function addDescriptionsToResult( array $descriptions, $path,
$name = 'descriptions', $tag = 'description' ) {
$options = new MultiLangSerializationOptions();
@@ -289,7 +229,6 @@
* @param string $name name used for the entry
* @param string $tag tag used for indexed entries in xml formats and
similar
*
- * @return array|bool
*/
protected function addLabelsToResult( array $labels, $path, $name =
'labels', $tag = 'label' ) {
$options = new MultiLangSerializationOptions();
diff --git a/repo/includes/api/EditEntity.php b/repo/includes/api/EditEntity.php
index 9cef820..bf76340 100644
--- a/repo/includes/api/EditEntity.php
+++ b/repo/includes/api/EditEntity.php
@@ -31,6 +31,7 @@
* @licence GNU GPL v2+
* @author John Erling Blad < [email protected] >
* @author Daniel Kinzler
+ * @author Tobias Gritschacher < [email protected] >
*/
class EditEntity extends ModifyEntity {
@@ -171,9 +172,6 @@
$this->addLabelsToResult( $entity->getLabels(), 'entity' );
$this->addDescriptionsToResult( $entity->getDescriptions(),
'entity' );
$this->addAliasesToResult( $entity->getAllAliases(), 'entity' );
-
- // TODO: This is a temporary fix that should be handled
properly with a
- // serializer class that is specific for the given entity
if ( $entity->getType() === Item::ENTITY_TYPE ) {
$this->addSiteLinksToResult(
$entity->getSimpleSiteLinks(), 'entity' );
}
--
To view, visit https://gerrit.wikimedia.org/r/69689
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I1f9bff8106c5a50ae30e043727b4a85b73c67fe4
Gerrit-PatchSet: 14
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Tobias Gritschacher <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[email protected]>
Gerrit-Reviewer: Tobias Gritschacher <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits