Tpt has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/328543 )
Change subject: index content handler ...................................................................... index content handler Change-Id: If38aadd396186049cbc35302723fc14c3749822f --- M ProofreadPage.body.php M extension.json A includes/index/IndexContent.php A includes/index/IndexContentHandler.php A maintenance/fixProofreadIndexPagesContentModel.php A tests/includes/index/IndexContentHandlerTest.php A tests/includes/index/IndexContentTest.php 7 files changed, 699 insertions(+), 2 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ProofreadPage refs/changes/43/328543/1 diff --git a/ProofreadPage.body.php b/ProofreadPage.body.php index a29dd54..904ffe6 100644 --- a/ProofreadPage.body.php +++ b/ProofreadPage.body.php @@ -91,6 +91,9 @@ if ( $title->inNamespace( self::getPageNamespaceId() ) ) { $model = CONTENT_MODEL_PROOFREAD_PAGE; return false; + } elseif ( $title->inNamespace( self::getIndexNamespaceId() ) ) { + $model = CONTENT_MODEL_PROOFREAD_INDEX; + return false; } else { return true; } @@ -701,6 +704,7 @@ // fix issue with content type hardcoded in database if ( isset( $wgContentHandlerUseDB ) && $wgContentHandlerUseDB ) { $updater->addPostDatabaseUpdateMaintenance( 'FixProofreadPagePagesContentModel' ); + $updater->addPostDatabaseUpdateMaintenance( 'FixProofreadIndexPagesContentModel' ); } return true; @@ -876,6 +880,8 @@ // Content handler define( 'CONTENT_MODEL_PROOFREAD_PAGE', 'proofread-page' ); + define( 'CONTENT_MODEL_PROOFREAD_INDEX', 'proofread-index' ); $wgContentHandlers[CONTENT_MODEL_PROOFREAD_PAGE] = '\ProofreadPage\Page\PageContentHandler'; + $wgContentHandlers[CONTENT_MODEL_PROOFREAD_INDEX] = '\ProofreadPage\Index\IndexContentHandler'; } } diff --git a/extension.json b/extension.json index 31cd4ed..15a115f 100644 --- a/extension.json +++ b/extension.json @@ -59,6 +59,9 @@ "ProofreadIndexValueArc": "includes/index/ProofreadIndexValue.php", "ProofreadIndexValueArk": "includes/index/ProofreadIndexValue.php", "ProofreadIndexPage": "includes/index/ProofreadIndexPage.php", + "ProofreadPage\\Index\\IndexContent": "includes/index/IndexContent.php", + "ProofreadPage\\Index\\IndexContentHandler": "includes/index/IndexContentHandler.php", + "ProofreadPage\\Index\\PropertyConfigFactory": "includes/index/PropertyConfigFactory.php", "ProofreadIndexDbConnector": "includes/index/ProofreadIndexDbConnector.php", "ProofreadPage\\Pagination\\PaginationFactory": "includes/Pagination/PaginationFactory.php", "ProofreadPage\\Pagination\\PageNumber": "includes/Pagination/PageNumber.php", @@ -92,12 +95,13 @@ "PagesWithoutScans": "SpecialPagesWithoutScans.php", "ApiQueryProofread": "ApiQueryProofread.php", "ApiQueryProofreadInfo": "ApiQueryProofreadInfo.php", - "FixProofreadPagePagesContentModel": "maintenance/fixProofreadPagePagesContentModel.php", "ProofreadPage\\FileProviderMock": "tests/phpunit/FileProviderMock.php", "ProofreadPageTestCase": "tests/phpunit/ProofreadPageTestCase.php", "ProofreadIndexPageTest": "tests/phpunit/index/ProofreadIndexPageTest.php", "ProofreadPagePageTest": "tests/phpunit/page/ProofreadPagePageTest.php", - "ProofreadPage\\Page\\PageContentTest": "tests/phpunit/page/PageContentTest.php" + "ProofreadPage\\Page\\PageContentTest": "tests/phpunit/page/PageContentTest.php", + "FixProofreadPagePagesContentModel": "maintenance/fixProofreadPagePagesContentModel.php", + "FixProofreadIndexPagesContentModel": "maintenance/fixProofreadIndexPagesContentModel.php" }, "ResourceModules": { "jquery.mousewheel": { diff --git a/includes/index/IndexContent.php b/includes/index/IndexContent.php new file mode 100644 index 0000000..06f5d1f --- /dev/null +++ b/includes/index/IndexContent.php @@ -0,0 +1,168 @@ +<?php + +namespace ProofreadPage\Index; + +use Content; +use MagicWord; +use ParserOptions; +use TextContent; +use Title; +use User; +use WikitextContent; + +/** + * @licence GNU GPL v2+ + * + * Content of a Index: page + */ +class IndexContent extends TextContent { + + /** + * @var WikitextContent[] + */ + private $fields = []; + + /** + * @param WikitextContent[] $fields + */ + public function __construct( array $fields ) { + $this->fields = $fields; + + parent::__construct( '', CONTENT_MODEL_PROOFREAD_INDEX ); + } + + /** + * Returns an associative array property name => value as WikitextContent + * @return WikitextContent[] + */ + public function getFields() { + return $this->fields; + } + + /** + * @see Content:isEmpty + */ + public function isEmpty() { + foreach ( $this->fields as $value ) { + if ( !empty( $value ) ) { + return false; + } + } + + return true; + } + + /** + * @see Content::equals + */ + public function equals( Content $that = null ) { + if ( + !( $that instanceof IndexContent ) || $that->getModel() !== $this->getModel() || + array_keys( $this->fields ) == array_keys( $that->fields ) + ) { + return false; + } + + foreach ( $this->fields as $key => $value ) { + if ( !$value->equals( $that->fields[$key] ) ) { + return false; + } + } + + return true; + } + + /** + * @see Content::getWikitextForTransclusion + */ + public function getWikitextForTransclusion() { + return $this->serialize( CONTENT_FORMAT_WIKITEXT ); + } + + /** + * @see Content::getNativeData + */ + public function getNativeData() { + return $this->serialize(); + } + + /** + * @see Content::getTextForSummary + */ + public function getTextForSummary( $maxlength = 250 ) { + return ''; + } + + /** + * @see Content::preSaveTransform + */ + public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) { + $fields = []; + + foreach ( $this->fields as $key => $value ) { + $fields[$key] = $value->preSaveTransform( $title, $user, $popts ); + } + + return new IndexContent( $fields ); + } + + /** + * @see Content::preloadTransform + */ + public function preloadTransform( Title $title, ParserOptions $popts, $params = [] ) { + $fields = []; + + foreach ( $this->fields as $key => $value ) { + $fields[$key] = $value->preloadTransform( $title, $popts, $params ); + } + + return new IndexContent( $fields ); + } + + /** + * @see Content::getSize + */ + public function getSize() { + $size = 0; + + foreach ( $this->fields as $value ) { + $size += $value->getSize(); + } + + return $size; + } + + /** + * @see Content::isCountable + */ + public function isCountable( $hasLinks = null, Title $title = null ) { + foreach ( $this->fields as $value ) { + if ( $value->isCountable( $hasLinks, $title ) ) { + return true; + } + } + + return false; + } + + /** + * @see Content::matchMagicWord + */ + public function matchMagicWord( MagicWord $word ) { + foreach ( $this->fields as $value ) { + if ( $value->matchMagicWord( $word ) ) { + return true; + } + } + + return false; + } + + /** + * @see Content::getParserOutput + */ + public function getParserOutput( Title $title, $revId = null, ParserOptions $options = null, $generateHtml = true ) { + $wikitextContent = new WikitextContent( $this->serialize( CONTENT_FORMAT_WIKITEXT ) ); + return $wikitextContent->getParserOutput( $title, $revId, $options, $generateHtml ); + } +} diff --git a/includes/index/IndexContentHandler.php b/includes/index/IndexContentHandler.php new file mode 100644 index 0000000..5dce5f9 --- /dev/null +++ b/includes/index/IndexContentHandler.php @@ -0,0 +1,166 @@ +<?php + +namespace ProofreadPage\Index; + +use Content; +use ContentHandler; +use Parser; +use PPFrame; +use TextContentHandler; +use Title; +use WikitextContent; +use WikitextContentHandler; + +/** + * @licence GNU GPL v2+ + * + * Content handler for a Index: pages + */ +class IndexContentHandler extends TextContentHandler { + + /** + * @var WikitextContentHandler + */ + private $wikitextContentHandler; + + public function __construct( $modelId = CONTENT_MODEL_PROOFREAD_INDEX ) { + $this->wikitextContentHandler = ContentHandler::getForModelID( CONTENT_MODEL_WIKITEXT ); + + parent::__construct( $modelId, [ CONTENT_FORMAT_WIKITEXT ] ); + } + + /** + * @see ContentHandler::serializeContent + */ + public function serializeContent( Content $content, $format = null ) { + $this->checkFormat( $format ); + + return $this->serializeContentInWikitext( $content ); + } + + /** + * @param IndexContent $content + * @return string + */ + private function serializeContentInWikitext( IndexContent $content ) { + $text = "{{:MediaWiki:Proofreadpage_index_template"; + + /** @var WikitextContent $value */ + foreach ( $content->getFields() as $key => $value ) { + $text .= "\n|" . $key . "=" . $value->serialize(); + } + + return $text . "\n}}"; + } + + /** + * @see ContentHandler::unserializeContent + */ + public function unserializeContent( $text, $format = null ) { + $this->checkFormat( $format ); + + return $this->unserializeContentInWikitext( $text ); + } + + /** + * @param $text + * @return IndexContent + */ + private function unserializeContentInWikitext( $text ) { + $parser = self::getParser(); + $dom = $parser->preprocessToDom( $text ); + $frame = $parser->getPreprocessor()->newFrame(); + $dom = $dom->getFirstChild(); + $childframe = $frame->newChild( $dom->getChildrenOfType( 'part' ) ); + $values = []; + foreach ( $childframe->namedArgs as $varName => $value ) { + $values[$varName] = $parser->getPreprocessor()->newFrame()->expand( $value, PPFrame::NO_ARGS | PPFrame::NO_TEMPLATES); + } + return new IndexContent( $values ); + } + + /** + * @see ContentHandler::makeEmptyContent + */ + public function makeEmptyContent() { + return new IndexContent( [] ); + } + + /** + * @see ContentHandler::merge3 + */ + public function merge3( Content $oldContent, Content $myContent, Content $yourContent ) { + $this->checkModelID( $oldContent->getModel() ); + $this->checkModelID( $myContent->getModel() ); + $this->checkModelID( $yourContent->getModel() ); + + $oldFields = $oldContent->getFields(); + $myFields = $myContent->getFields(); + $yourFields = $yourContent->getFields(); + + // We adds yourFields to myFields + foreach ( $yourFields as $key => $yourValue ) { + if ( array_key_exists( $key, $myFields ) ) { + $oldValue = array_key_exists( $key, $oldFields ) ? $oldFields[$key] : $this->wikitextContentHandler->makeEmptyContent(); + $myFields[$key] = $this->wikitextContentHandler->merge3( $oldValue, $myFields[$key], $yourValue ); + + if ( $myFields[$key] === false ) { + return false; + } + } else { + $myFields[$key] = $yourValue; + } + } + + return new IndexContent( $myFields ); + } + + /** + * @see ContentHandler::makeParserOptions + */ + public function makeParserOptions( $context ) { + $parserOptions = parent::makeParserOptions( $context ); + $parserOptions->setEditSection( false ); + + return $parserOptions; + } + + /** + * @see ContentHandler::makeRedirectContent + * @todo is it the right content for redirects? + */ + public function makeRedirectContent( Title $destination, $text = '' ) { + return $this->wikitextContentHandler->makeRedirectContent( $destination, $text ); + } + + /** + * @see ContentHandler::supportsRedirects + */ + public function supportsRedirects() { + return true; + } + + /** + * @see ContentHandler::isParserCacheSupported + */ + public function isParserCacheSupported() { + return true; + } + + /** + * Return the Parser object done for internal use + * Needed to avoid side effects of $parser->replaceVariables + * + * @return Parser + */ + private static function getParser() { + global $wgParser; + static $parser = null; + + if ( $parser === null ) { + $parser = clone $wgParser; + } + + return $parser; + } +} diff --git a/maintenance/fixProofreadIndexPagesContentModel.php b/maintenance/fixProofreadIndexPagesContentModel.php new file mode 100644 index 0000000..4dcea10 --- /dev/null +++ b/maintenance/fixProofreadIndexPagesContentModel.php @@ -0,0 +1,75 @@ +<?php +/** + * 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 + * @ingroup ProofreadPage + */ + +if ( !class_exists( 'LoggedUpdateMaintenance' ) ) { + $basePath = getenv( 'MW_INSTALL_PATH' ) !== false ? getenv( 'MW_INSTALL_PATH' ) : __DIR__ . '/../../..'; + require_once $basePath . '/maintenance/Maintenance.php'; +} + +/** + * Set the content model type for Page: pages + */ +class FixProofreadPagePagesContentModel extends LoggedUpdateMaintenance { + + public function __construct() { + parent::__construct(); + + $this->mDescription = 'Set the content model type for Index: pages'; + } + + /** + * @see LoggedUpdateMaintenance::doDBUpdates + */ + public function doDBUpdates() { + $db = wfGetDB( DB_MASTER ); + if ( !$db->fieldExists( 'page', 'page_content_model', __METHOD__ ) ) { + $this->error( 'page_content_model field of page table does not exists.' ); + return false; + } + + $db->update( + 'page', + [ + 'page_content_model' => CONTENT_MODEL_PROOFREAD_INDEX + ], + [ + 'page_namespace' => ProofreadPage::getIndexNamespaceId(), + 'page_content_model' => CONTENT_MODEL_WIKITEXT + ], + __METHOD__ + ); + + $this->output( "Update of the content model for Index: pages is done.\n" ); + + return true; + } + + /** + * @see LoggedUpdateMaintenance::getUpdateKey + */ + public function getUpdateKey() { + return 'FixPagePagesContentModel'; + } + +} + +$maintClass = 'FixProofreadPagePagesContentModel'; +require_once ( RUN_MAINTENANCE_IF_MAIN ); diff --git a/tests/includes/index/IndexContentHandlerTest.php b/tests/includes/index/IndexContentHandlerTest.php new file mode 100644 index 0000000..ae5e07b --- /dev/null +++ b/tests/includes/index/IndexContentHandlerTest.php @@ -0,0 +1,109 @@ +<?php + +namespace ProofreadPage\Index; + +use ContentHandler; +use ProofreadPage\DataModel\PropertyConfig; +use ProofreadPage\DataModel\PropertyConfigSet; +use ProofreadPageTestCase; +use Title; +use WikitextContent; + +/** + * @group ProofreadIndex + * @covers \ProofreadPage\Index\IndexContentHandler + */ +class IndexContentHandlerTest extends ProofreadPageTestCase { + + /** + * @var ContentHandler + */ + protected $handler; + + public function setUp() { + parent::setUp(); + + $this->handler = new IndexContentHandler(); + } + + public function wikitextSerializationProvider() { + return [ + [ new IndexContent( [] ), "{{:MediaWiki:Proofreadpage_index_template\n}}" ], + [ new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ), "{{:MediaWiki:Proofreadpage_index_template\n|foo=bar\n}}" ] + ]; + } + + /** + * @dataProvider wikitextSerializationProvider + */ + public function testSerializeContentInWikitext( IndexContent $content, $serialization ) { + $this->assertEquals( $serialization, $this->handler->serializeContent( $content ) ); + } + + public function wikitextUnserializationProvider() { + return [ + [ new IndexContent( [] ), "{{:MediaWiki:Proofreadpage_index_template\n}}" ], + [ new IndexContent( [] ), 'foo' ], + [ new IndexContent( [] ), '' ], + [ new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ), "{{:MediaWiki:Proofreadpage_index_template\n|foo=bar\n}}" ] + ]; + } + + /** + * @dataProvider wikitextUnserializationProvider + */ + public function testUnserializeContentInWikitext( IndexContent $content, $serialization ) { + $this->assertEquals( + $content, + $this->handler->unserializeContent( $serialization ) + ); + } + + public function testMakeEmptyContent() { + $content = $this->handler->makeEmptyContent(); + $this->assertTrue( $content->isEmpty() ); + } + + public static function merge3Provider() { + return [ + [ + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ), + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ), + new IndexContent( [] ), + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ) + ], + [ + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ), + new IndexContent( [] ), + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ), + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ) + ], + [ + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ), + new IndexContent( [ 'foo' => new WikitextContent( 'baz' ) ] ), + new IndexContent( [ 'foo' => new WikitextContent( 'bat' ) ] ), + false + ], + [ + new IndexContent( [ 'foo' => new WikitextContent( "test\n" ) ] ), + new IndexContent( [ 'foo' => new WikitextContent( "test2\n" ) ] ), + new IndexContent( [ 'foo' => new WikitextContent( "test\n" ) ] ), + new IndexContent( [ 'foo' => new WikitextContent( "test2\n" ) ] ) + ], + ]; + } + + /** + * @dataProvider merge3Provider + */ + public function testMerge3( $oldContent, $myContent, $yourContent, $expected ) { + $merged = $this->handler->merge3( $oldContent, $myContent, $yourContent ); + + $this->assertEquals( $expected, $merged ); + } + + public function testMakeRedirectContent() { + $title = Title::makeTitle( NS_MAIN, 'Test' ); + $this->assertTrue( $title->equals( $this->handler->makeRedirectContent( $title )->getRedirectTarget() ) ); + } +} diff --git a/tests/includes/index/IndexContentTest.php b/tests/includes/index/IndexContentTest.php new file mode 100644 index 0000000..8128c0e --- /dev/null +++ b/tests/includes/index/IndexContentTest.php @@ -0,0 +1,169 @@ +<?php + +namespace ProofreadPage\Index; + +use FauxRequest; +use ParserOptions; +use ProofreadPageTestCase; +use RequestContext; +use Title; +use User; +use WikitextContent; + +/** + * @group ProofreadIndex + * @covers \ProofreadPage\Index\IndexContent + */ +class IndexContentTest extends ProofreadPageTestCase { + + /** + * @var RequestContext + */ + private $requestContext; + + protected function setUp() { + parent::setUp(); + + // Anon user + $user = new User(); + $user->setName( '127.0.0.1' ); + + $this->setMwGlobals( [ + 'wgUser' => $user, + 'wgTextModelsToParse' => [ + CONTENT_MODEL_PROOFREAD_INDEX + ] + ] ); + + $this->requestContext = new RequestContext( new FauxRequest() ); + $this->requestContext->setTitle( Title::makeTitle( 250, 'Test.jpg' ) ); + $this->requestContext->setUser( $user ); + } + + public function testGetModel() { + $content = new IndexContent( [] ); + $this->assertEquals( CONTENT_MODEL_PROOFREAD_INDEX, $content->getModel() ); + } + + public function testGetFields() { + $content = new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ); + $this->assertEquals( [ 'foo' => new WikitextContent( 'bar' ) ], $content->getFields() ); + } + + public function testGetContentHandler() { + $content = new IndexContent( [] ); + $this->assertEquals( CONTENT_MODEL_PROOFREAD_INDEX, $content->getContentHandler()->getModelID() ); + } + + public function testCopy() { + $content = new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ); + $this->assertEquals( $content, $content->copy() ); + } + + public function equalsProvider() { + return [ + [ + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ), + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ), + true + ], + [ + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ), 'bar' => new WikitextContent( 'foo' ) ] ), + new IndexContent( [ 'bar' => new WikitextContent( 'foo' ), 'foo' => new WikitextContent( 'bar' ) ] ), + true + ], + [ + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ), + new IndexContent( [ 'foo' => new WikitextContent( 'baz' ) ] ), + false + ], + [ + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ), + new IndexContent( [] ), + false + ], + ]; + } + + /** + * @dataProvider equalsProvider + */ + public function testEquals( IndexContent $a, IndexContent $b, $equal ) { + $this->assertEquals( $equal, $a->equals( $b ) ); + } + + public function testGetWikitextForTransclusion() { + $content = new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ); + return $this->assertEquals( "{{:MediaWiki:Proofreadpage_index_template\n|foo=bar\n}}", $content->getWikitextForTransclusion() ); + } + + public function getTextForSummaryProvider() { + return [ + [ + new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ), + 16, + '' + ] + ]; + } + + /** + * @dataProvider getTextForSummaryProvider + */ + public function testGetTextForSummary( IndexContent $content, $length, $result ) { + $this->assertEquals( $result, $content->getTextForSummary( $length ) ); + } + + public function preSaveTransformProvider() { + return [ + [ + new IndexContent( [ 'foo' => new WikitextContent( 'Hello ~~~' ) ] ), + new IndexContent( [ 'foo' => new WikitextContent( 'Hello [[Special:Contributions/127.0.0.1|127.0.0.1]]' ) ] ) + ], + ]; + } + + /** + * @dataProvider preSaveTransformProvider + */ + public function testPreSaveTransform( IndexContent $content, IndexContent $expectedContent ) { + global $wgContLang; + + $options = ParserOptions::newFromUserAndLang( $this->requestContext->getUser(), $wgContLang ); + + $content = $content->preSaveTransform( $this->requestContext->getTitle(), $this->requestContext->getUser(), $options ); + + $this->assertEquals( $expectedContent, $content ); + } + + public function preloadTransformProvider() { + return [ + [ + new IndexContent( [ 'foo' => new WikitextContent( 'hello this is ~~~' ) ] ), + new IndexContent( [ 'foo' => new WikitextContent( 'hello this is ~~~' ) ] ) + ], + [ + new IndexContent( [ 'foo' => new WikitextContent( 'hello \'\'this\'\' is <noinclude>foo</noinclude><includeonly>bar</includeonly>' ) ] ), + new IndexContent( [ 'foo' => new WikitextContent( 'hello \'\'this\'\' is bar' ) ] ) + ], + ]; + } + + /** + * @dataProvider preloadTransformProvider + */ + public function testPreloadTransform( IndexContent $content, IndexContent $expectedContent ) { + global $wgContLang; + + $options = ParserOptions::newFromUserAndLang( $this->requestContext->getUser(), $wgContLang ); + + $content = $content->preloadTransform( $this->requestContext->getTitle(), $options ); + + $this->assertEquals( $expectedContent, $content ); + } + + public function testGetSize() { + $content = new IndexContent( [ 'foo' => new WikitextContent( 'bar' ) ] ); + $this->assertEquals( 3, $content->getSize() ); + } +} -- To view, visit https://gerrit.wikimedia.org/r/328543 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: If38aadd396186049cbc35302723fc14c3749822f Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/ProofreadPage Gerrit-Branch: master Gerrit-Owner: Tpt <thoma...@hotmail.fr> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits