Cdentinger has uploaded a new change for review. https://gerrit.wikimedia.org/r/302956
Change subject: Merge branch 'master' into deployment ...................................................................... Merge branch 'master' into deployment + cc54c6b0845048a4e33ac3b22f927e74c9410372 Catch exceptions in setClientVariables + b9f42d726a55c3fec94de83895ea4dbcdc5aa361 Localisation updates from https://translatewiki.net. + 083c2abab8b99e81c1f151b5ee870fae78dd377d Do away with redundant YAML quoting + 3f01b1dc17df31d1c2d8e6d73a3271e6c1d208f0 Localisation updates from https://translatewiki.net. + 3b7b9fa0431d600b054664c9249870c2d76775dd More places where batch jobs shouldn't be pulling from the request + 231433acbae9e616075c7835de9f4c6e959ca1d1 Rename "data" variable to a more specific name + 6ae60d233c1ecbd162e4729117d17fbf599e66f6 Protect mirroring from bad queue + 61d8b3e6c6a3835e8519243f959dccab171a68d1 List countries for Amex so it stops appearing for ZA Removed tests. Change-Id: I31bdca461351c05298e0db09e2757d1d9f5c4053 --- D tests/Adapter/GlobalCollect/GlobalCollectOrphanAdapterTest.php D tests/DonationDataTest.php 2 files changed, 0 insertions(+), 606 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/DonationInterface refs/changes/56/302956/1 diff --git a/tests/Adapter/GlobalCollect/GlobalCollectOrphanAdapterTest.php b/tests/Adapter/GlobalCollect/GlobalCollectOrphanAdapterTest.php deleted file mode 100644 index 22e43a8..0000000 --- a/tests/Adapter/GlobalCollect/GlobalCollectOrphanAdapterTest.php +++ /dev/null @@ -1,196 +0,0 @@ -<<<<<<< HEAD (3d0691 Merge branch 'master' into deployment) -======= -<?php - -/** - * Wikimedia Foundation - * - * LICENSE - * - * 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. - * - */ -use Psr\Log\LogLevel; - -/** - * - * @group Fundraising - * @group DonationInterface - * @group GlobalCollect - * @group OrphanSlayer - */ -class DonationInterface_Adapter_GlobalCollect_Orphans_GlobalCollectTest extends DonationInterfaceTestCase { - public function setUp() { - parent::setUp(); - - $this->setMwGlobals( array( - 'wgGlobalCollectGatewayEnabled' => true, - 'wgDonationInterfaceAllowedHtmlForms' => array( - 'cc-vmad' => array( - 'gateway' => 'globalcollect', - 'payment_methods' => array('cc' => array( 'visa', 'mc', 'amex', 'discover' )), - 'countries' => array( - '+' => array( 'US', ), - ), - ), - ), - ) ); - } - - /** - * @param $name string The name of the test case - * @param $data array Any parameters read from a dataProvider - * @param $dataName string|int The name or index of the data set - */ - function __construct( $name = null, array $data = array(), $dataName = '' ) { - parent::__construct( $name, $data, $dataName ); - $this->testAdapterClass = 'TestingGlobalCollectOrphanAdapter'; - $this->dummy_utm_data = array ( - 'utm_source' => 'dummy_source', - 'utm_campaign' => 'dummy_campaign', - 'utm_medium' => 'dummy_medium', - 'date' => time(), - ); - } - - public function testConstructor() { - - $options = $this->getDonorTestData(); - $class = $this->testAdapterClass; - - $gateway = $this->getFreshGatewayObject(); - - $this->assertInstanceOf( $class, $gateway ); - - $this->verifyNoLogErrors(); - } - - - public function testBatchOrderID_generate() { - - //no data on construct, generate Order IDs - $gateway = $this->getFreshGatewayObject( null, array ( 'order_id_meta' => array ( 'generate' => TRUE ) ) ); - $this->assertTrue( $gateway->getOrderIDMeta( 'generate' ), 'The order_id meta generate setting override is not working properly. Order_id generation may be broken.' ); - $this->assertNotNull( $gateway->getData_Unstaged_Escaped( 'order_id' ), 'Failed asserting that an absent order id is not left as null, when generating our own' ); - - $data = array_merge( $this->getDonorTestData(), $this->dummy_utm_data ); - $data['order_id'] = '55555'; - - //now, add data and check that we didn't kill the oid. Still generating. - $gateway->loadDataAndReInit( $data, $useDB = false ); - $this->assertEquals( $gateway->getData_Unstaged_Escaped( 'order_id' ), '55555', 'loadDataAndReInit failed to stick OrderID' ); - - $data['order_id'] = '444444'; - $gateway->loadDataAndReInit( $data, $useDB = false ); - $this->assertEquals( $gateway->getData_Unstaged_Escaped( 'order_id' ), '444444', 'loadDataAndReInit failed to stick OrderID' ); - - $this->verifyNoLogErrors(); - } - - public function testBatchOrderID_no_generate() { - - //no data on construct, do not generate Order IDs - $gateway = $this->getFreshGatewayObject( null, array ( 'order_id_meta' => array ( 'generate' => FALSE ) ) ); - $this->assertFalse( $gateway->getOrderIDMeta( 'generate' ), 'The order_id meta generate setting override is not working properly. Deferred order_id generation may be broken.' ); - $this->assertNull( $gateway->getData_Unstaged_Escaped( 'order_id' ), 'Failed asserting that an absent order id is left as null, when not generating our own' ); - - $data = array_merge( $this->getDonorTestData(), $this->dummy_utm_data ); - $data['order_id'] = '66666'; - - //now, add data and check that we didn't kill the oid. Still not generating - $gateway->loadDataAndReInit( $data, $useDB = false ); - $this->assertEquals( $gateway->getData_Unstaged_Escaped( 'order_id' ), '66666', 'loadDataAndReInit failed to stick OrderID' ); - - $data['order_id'] = '777777'; - $gateway->loadDataAndReInit( $data, $useDB = false ); - $this->assertEquals( $gateway->getData_Unstaged_Escaped( 'order_id' ), '777777', 'loadDataAndReInit failed to stick OrderID on second batch item' ); - - $this->verifyNoLogErrors(); - } - - public function testGCFormLoad() { - $init = $this->getDonorTestData( 'US' ); - unset( $init['order_id'] ); - $init['payment_method'] = 'cc'; - $init['payment_submethod'] = 'visa'; - $init['ffname'] = 'cc-vmad'; - - $assertNodes = array ( - 'submethod-mc' => array ( - 'nodename' => 'input' - ), - 'selected-amount' => array ( - 'nodename' => 'span', - 'innerhtmlmatches' => '/^\s*' . - str_replace( '$', '\$', - Amount::format( 1.55, 'USD', $init['language'] . '_' . $init['country'] ) - ). - '\s*$/', - ), - 'state' => array ( - 'nodename' => 'select', - 'selected' => 'CA', - ), - ); - - $this->verifyFormOutput( 'GlobalCollectGateway', $init, $assertNodes, true ); - } - - /** - * Tests to make sure that certain error codes returned from GC will - * trigger order cancellation, even if retryable errors also exist. - * @dataProvider mcNoRetryCodeProvider - */ - public function testNoMastercardFinesForRepeatOnBadCodes( $code ) { - $gateway = $this->getFreshGatewayObject( null, array ( 'order_id_meta' => array ( 'generate' => FALSE ) ) ); - - //Toxic card should not retry, even if there's an order id collision - $init = array_merge( $this->getDonorTestData(), $this->dummy_utm_data ); - $init['ffname'] = 'cc-vmad'; - $init['order_id'] = '55555'; - $init['email'] = '[email protected]'; - $init['contribution_tracking_id'] = mt_rand(); - $gateway->loadDataAndReInit( $init, $useDB = false ); - - $gateway->setDummyGatewayResponseCode( $code ); - $result = $gateway->do_transaction( 'Confirm_CreditCard' ); - $this->assertEquals( 1, count( $gateway->curled ), "Gateway kept trying even with response code $code! MasterCard could fine us a thousand bucks for that!" ); - $this->assertEquals( false, $result->getCommunicationStatus(), "Error code $code should mean status of do_transaction is false" ); - $errors = $result->getErrors(); - $this->assertFalse( empty( $errors ), 'Orphan adapter needs to see the errors to consider it rectified' ); - $this->assertTrue( array_key_exists( '1000001', $errors ), 'Orphan adapter needs error 1000001 to consider it rectified' ); - $loglines = $this->getLogMatches( LogLevel::INFO, "/Got error code $code, not retrying to avoid MasterCard fines./" ); - $this->assertNotEmpty( $loglines, "GC Error $code is not generating the expected payments log error" ); - } - - /** - * Don't fraud-fail someone for bad CVV if GET_ORDERSTATUS - * comes back with STATUSID 25 and no CVVRESULT - * @group CvvResult - */ - function testConfirmCreditCardStatus25() { - $gateway = $this->getFreshGatewayObject( null, array ( 'order_id_meta' => array ( 'generate' => FALSE ) ) ); - - $init = array_merge( $this->getDonorTestData(), $this->dummy_utm_data ); - $init['ffname'] = 'cc-vmad'; - $init['order_id'] = '55555'; - $init['email'] = '[email protected]'; - $init['contribution_tracking_id'] = mt_rand(); - - $gateway->loadDataAndReInit( $init, $useDB = false ); - $gateway->setDummyGatewayResponseCode( '25' ); - - $gateway->do_transaction( 'Confirm_CreditCard' ); - $action = $gateway->getValidationAction(); - $this->assertEquals( 'process', $action, 'Gateway should not fraud fail on STATUSID 25' ); - } -} ->>>>>>> BRANCH (438a07 Merge "Protect mirroring from bad queue") diff --git a/tests/DonationDataTest.php b/tests/DonationDataTest.php deleted file mode 100644 index 50ddc1e..0000000 --- a/tests/DonationDataTest.php +++ /dev/null @@ -1,410 +0,0 @@ -<<<<<<< HEAD (3d0691 Merge branch 'master' into deployment) -======= -<?php -/** - * Wikimedia Foundation - * - * LICENSE - * - * 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. - * - */ -use Psr\Log\LogLevel; - -/** - * @group Fundraising - * @group DonationInterface - * @group Splunge - * @group DonationData - */ -class DonationInterface_DonationDataTest extends DonationInterfaceTestCase { - - /** - * @param $name string The name of the test case - * @param $data array Any parameters read from a dataProvider - * @param $dataName string|int The name or index of the data set - */ - public function __construct( $name = null, array $data = array(), $dataName = '' ) { - $request = RequestContext::getMain()->getRequest(); - - $adapterclass = TESTS_ADAPTER_DEFAULT; - $this->testAdapterClass = $adapterclass; - - parent::__construct( $name, $data, $dataName ); - - $this->testData = array( - 'amount' => '128.00', - 'appeal' => 'JimmyQuote', - 'email' => '[email protected]', - 'fname' => 'Testocres', - 'lname' => 'McTestingyou', - 'street' => '123 Fake Street', - 'city' => 'Springfield', - 'state' => 'US', - 'zip' => '99999', - 'country' => 'US', - 'card_num' => '42', - 'card_type' => 'visa', - 'expiration' => '1138', - 'cvv' => '665', - 'currency_code' => 'USD', - 'payment_method' => 'cc', - 'payment_submethod' => 'visa', - 'numAttempt' => '5', - 'referrer' => 'http://www.testing.com/', - 'utm_source' => '..cc', - 'utm_medium' => 'large', - 'utm_campaign' => 'yes', - 'email-opt' => '', - 'test_string' => '', - 'wmf_token' => '113811', - 'contribution_tracking_id' => '', - 'data_hash' => '', - 'action' => '', - 'gateway' => 'DonationData', - 'owa_session' => '', - 'owa_ref' => 'http://localhost/importedTestData', - 'user_ip' => $request->getIP(), - 'server_ip' => $request->getIP(), - ); - - } - - - /** - * @covers DonationData::__construct - * @covers DonationData::getDataEscaped - * @covers DonationData::populateData - */ - public function testConstruct(){ - $context = RequestContext::getMain(); - $request = $context->getRequest(); - - $ddObj = new DonationData( $this->getFreshGatewayObject( self::$initial_vars ) ); //as if we were posted. - $returned = $ddObj->getDataEscaped(); - $expected = array( 'posted' => '', - 'amount' => '0.00', - 'appeal' => 'JimmyQuote', - 'country' => 'XX', - 'payment_method' => '', - 'referrer' => '', - 'utm_source' => '..', - 'language' => $context->getLanguage()->getCode(), - 'gateway' => 'globalcollect', - 'payment_submethod' => '', - 'recurring' => '', - 'user_ip' => $request->getIP(), - 'server_ip' => $request->getIP(), - ); - unset($returned['contribution_tracking_id']); - unset($returned['order_id']); - $this->assertEquals($expected, $returned, "Staged post data does not match expected (largely empty)."); - } - - /** - * Test construction with external data (for tests and possible batch operations) - */ - public function testConstructWithExternalData() { - $request = RequestContext::getMain()->getRequest(); - - $expected = array ( - 'amount' => '35.00', - 'appeal' => 'JimmyQuote', - 'contribution_tracking_id' => mt_rand(), - 'email' => '[email protected]', - 'fname' => 'Tester', - 'lname' => 'Testington', - 'street' => '548 Market St.', - 'city' => 'San Francisco', - 'state' => 'CA', - 'zip' => '94104', - 'country' => 'US', - 'card_num' => '378282246310005', - 'card_type' => 'amex', - 'expiration' => '0415', - 'cvv' => '001', - 'currency_code' => 'USD', - 'payment_method' => 'cc', - 'referrer' => 'http://www.baz.test.com/index.php?action=foo&action=bar', - 'utm_source' => 'test_src..cc', - 'utm_medium' => 'test_medium', - 'utm_campaign' => 'test_campaign', - 'language' => 'en', - 'wmf_token' => '', - 'data_hash' => '', - 'action' => '', - 'gateway' => 'globalcollect', - 'owa_session' => '', - 'owa_ref' => 'http://localhost/defaultTestData', - 'street_supplemental' => '3rd floor', - 'payment_submethod' => 'amex', - 'issuer_id' => '', - 'utm_source_id' => '', - 'user_ip' => '12.12.12.12', - 'server_ip' => $request->getIP(), - 'recurring' => '', - ); - - $adapter = $this->getFreshGatewayObject( self::$initial_vars, array( 'batch_mode' => true ) ); - $ddObj = new DonationData( $adapter, $expected ); //external data - $returned = $ddObj->getDataEscaped(); - - - $this->assertNotNull( $returned['contribution_tracking_id'], 'There is no contribution tracking ID' ); - $this->assertNotEquals( $returned['contribution_tracking_id'], '', 'There is not a valid contribution tracking ID' ); - - unset($returned['order_id']); - - $this->assertEquals($expected, $returned, "Staged default test data does not match expected."); - } - - /** - * Test construction with data jammed in request. - */ - public function testConstructWithFauxRequest() { - $request = RequestContext::getMain()->getRequest(); - - $expected = array ( - 'amount' => '35.00', - 'appeal' => 'JimmyQuote', - 'email' => '[email protected]', - 'fname' => 'Tester', - 'lname' => 'Testington', - 'street' => '548 Market St.', - 'city' => 'San Francisco', - 'state' => 'CA', - 'zip' => '94104', - 'country' => 'US', - 'card_num' => '378282246310005', - 'card_type' => 'amex', - 'expiration' => '0415', - 'cvv' => '001', - 'currency_code' => 'USD', - 'payment_method' => 'cc', - 'referrer' => 'http://www.baz.test.com/index.php?action=foo&action=bar', - 'utm_source' => 'test_src..cc', - 'utm_medium' => 'test_medium', - 'utm_campaign' => 'test_campaign', - 'language' => 'en', - 'gateway' => 'globalcollect', - 'owa_ref' => 'http://localhost/getTestData', - 'street_supplemental' => '3rd floor', - 'payment_submethod' => 'amex', - 'user_ip' => $request->getIP(), - 'server_ip' => $request->getIP(), - 'recurring' => '', - 'posted' => '', - ); - - RequestContext::getMain()->setRequest( new FauxRequest( $expected, false ) ); - - $ddObj = new DonationData( $this->getFreshGatewayObject( self::$initial_vars ) ); //Get all data from request - $returned = $ddObj->getDataEscaped(); - - $this->assertNotNull( $returned['contribution_tracking_id'], 'There is no contribution tracking ID' ); - $this->assertNotEquals( $returned['contribution_tracking_id'], '', 'There is not a valid contribution tracking ID' ); - - unset( $returned['order_id'] ); - unset( $returned['contribution_tracking_id'] ); - - $this->assertEquals( $expected, $returned, "Staged default test data does not match expected." ); - } - - /** - * Check that constructor outputs certain information to logs - */ - public function testDebugLog() { - $expected = array ( - 'payment_method' => 'cc', - 'utm_source' => 'test_src..cc', - 'utm_medium' => 'test_medium', - 'utm_campaign' => 'test_campaign', - 'payment_submethod' => 'amex', - 'currency_code' => 'USD', - ); - - $this->setUpRequest( $expected ); - - $ddObj = new DonationData( $this->getFreshGatewayObject( ) ); - $matches = $this->getLogMatches( LogLevel::DEBUG, '/setUtmSource: Payment method is cc, recurring = false, utm_source = cc$/' ); - $this->assertNotEmpty( $matches ); - $matches = $this->getLogMatches( LogLevel::DEBUG, "/Got currency from 'currency_code', now: USD$/" ); - $this->assertNotEmpty( $matches ); - } - - /** - * - */ - public function testRepopulate(){ - $expected = $this->testData; - - // Some changes from the default - $expected['recurring'] = ''; - $expected['language'] = RequestContext::getMain()->getLanguage()->getCode(); - $expected['gateway'] = 'globalcollect'; - - // Just unset a handful... doesn't matter what, really. - unset($expected['comment-option']); - unset($expected['email-opt']); - unset($expected['test_string']); - - $ddObj = new DonationData( $this->getFreshGatewayObject( self::$initial_vars ), $expected ); //change to test mode with explicit test data - $returned = $ddObj->getDataEscaped(); - //unset these, because they're always new - $unsettable = array( - 'order_id', - 'contribution_tracking_id' - ); - - foreach ( $unsettable as $thing ) { - unset( $returned[$thing] ); - unset( $expected[$thing] ); - } - - $this->assertEquals( $expected, $returned, "The forced test data did not populate as expected." ); - } - - /** - * - */ - public function testIsSomething(){ - $data = $this->testData; - unset( $data['zip'] ); - - $ddObj = new DonationData( $this->getFreshGatewayObject( self::$initial_vars ), $data ); //change to test mode with explicit test data - $this->assertEquals($ddObj->isSomething('zip'), false, "Zip should currently be nothing."); - $this->assertEquals($ddObj->isSomething('lname'), true, "Lname should currently be something."); - } - - /** - * - */ - public function testSetNormalizedAmount_amtGiven() { - $data = $this->testData; - $data['amount'] = 'this is not a number'; - $data['amountGiven'] = 42.50; - $ddObj = new DonationData( $this->getFreshGatewayObject( self::$initial_vars ), $data ); //change to test mode with explicit test data - $returned = $ddObj->getDataEscaped(); - $this->assertEquals( 42.50, $returned['amount'], "Amount was not properly reset" ); - $this->assertArrayNotHasKey( 'amountGiven', $returned, "amountGiven should have been removed from the data" ); - } - - /** - * - */ - public function testSetNormalizedAmount_amount() { - $data = $this->testData; - $data['amount'] = 88.15; - $data['amountGiven'] = 42.50; - $ddObj = new DonationData( $this->getFreshGatewayObject( self::$initial_vars ), $data ); //change to test mode with explicit test data - $returned = $ddObj->getDataEscaped(); - $this->assertEquals( 88.15, $returned['amount'], "Amount was not properly reset" ); - $this->assertArrayNotHasKey( 'amountGiven', $returned, "amountGiven should have been removed from the data" ); - } - - /** - * - */ - public function testSetNormalizedAmount_negativeAmount() { - $data = $this->testData; - $data['amount'] = -1; - $data['amountOther'] = 3.25; - $ddObj = new DonationData( $this->getFreshGatewayObject( self::$initial_vars ), $data ); //change to test mode with explicit test data - $returned = $ddObj->getDataEscaped(); - $this->assertEquals(3.25, $returned['amount'], "Amount was not properly reset"); - $this->assertArrayNotHasKey( 'amountOther', $returned, "amountOther should have been removed from the data"); - } - - /** - * - */ - public function testSetNormalizedAmount_noGoodAmount() { - $data = $this->testData; - $data['amount'] = 'splunge'; - $data['amountGiven'] = 'wombat'; - $data['amountOther'] = 'macedonia'; - $ddObj = new DonationData( $this->getFreshGatewayObject( self::$initial_vars ), $data ); //change to test mode with explicit test data - $returned = $ddObj->getDataEscaped(); - $this->assertEquals( 'invalid', $returned['amount'], "Amount was not properly reset"); - $this->assertArrayNotHasKey( 'amountOther', $returned, "amountOther should have been removed from the data"); - $this->assertArrayNotHasKey( 'amountGiven', $returned, "amountGiven should have been removed from the data"); - } - - /** - * If the currency code is not three letters, we should try to guess it from - * the country code. - */ - public function testSetNormalizedCurrencyCode_BadData() { - $data = $this->testData; - // When missing or not a recognized currency code, we'll guess from the - // country - in this test data, US. - $data['currency_code'] = 'splunge'; - $ddObj = new DonationData( $this->getFreshGatewayObject( self::$initial_vars ), $data ); - $returned = $ddObj->getDataEscaped(); - $this->assertEquals( 'USD', $returned['currency_code'], 'Currency code was not properly reset'); - } - - /** - * - */ - public function testSetNormalizedLanguage_uselang() { - $data = $this->testData; - unset( $data['uselang'] ); - unset( $data['language'] ); - - $data['uselang'] = 'no'; - - $ddObj = new DonationData( $this->getFreshGatewayObject( self::$initial_vars ), $data ); //change to test mode with explicit test data - $returned = $ddObj->getDataEscaped(); - $this->assertEquals( 'no', $returned['language'], "Language 'no' was normalized out of existance. Sad." ); - $this->assertArrayNotHasKey( 'uselang', $returned, "'uselang' should have been removed from the data" ); - } - - /** - * - */ - public function testSetNormalizedLanguage_language() { - $data = $this->testData; - unset( $data['uselang'] ); - unset( $data['language'] ); - - $data['language'] = 'no'; - - $ddObj = new DonationData( $this->getFreshGatewayObject( self::$initial_vars ), $data ); //change to test mode with explicit test data - $returned = $ddObj->getDataEscaped(); - $this->assertEquals( 'no', $returned['language'], "Language 'no' was normalized out of existance. Sad." ); - $this->assertArrayNotHasKey( 'uselang', $returned, "'uselang' should have been removed from the data" ); - } - - /** - * TODO: Make sure ALL these functions in DonationData are tested, either directly or through a calling function. - * I know that's more regression-ish, but I stand by it. :p - function setNormalizedOrderIDs(){ - function generateOrderId() { - public function sanitizeInput( &$value, $key, $flags=ENT_COMPAT, $double_encode=false ) { - function setGateway(){ - function doCacheStuff(){ - public function getEditToken( $salt = '' ) { - public static function generateToken( $salt = '' ) { - function matchEditToken( $val, $salt = '' ) { - function unsetEditToken() { - public function checkTokens() { - function wasPosted(){ - function setUtmSource() { - public function getOptOuts() { - public function getCleanTrackingData( $clean_optouts = false ) { - function saveContributionTracking() { - public static function insertContributionTracking( $tracking_data ) { - public function updateContributionTracking( $force = false ) { - - */ -} ->>>>>>> BRANCH (438a07 Merge "Protect mirroring from bad queue") -- To view, visit https://gerrit.wikimedia.org/r/302956 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I31bdca461351c05298e0db09e2757d1d9f5c4053 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/DonationInterface Gerrit-Branch: deployment Gerrit-Owner: Cdentinger <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
