Merge "Avoid logging query in wasDeletedSinceLastEdit() if the page still exists"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 21 Jul 2015 06:24:53 +0000 (06:24 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 21 Jul 2015 06:24:53 +0000 (06:24 +0000)
16 files changed:
.jshintrc
includes/GlobalFunctions.php
includes/Message.php
includes/User.php
includes/installer/PostgresUpdater.php
includes/jobqueue/jobs/EmaillingJob.php
includes/mail/EmailNotification.php
includes/mail/UserMailer.php
includes/search/SearchPostgres.php
includes/specials/SpecialEmailuser.php
maintenance/postgres/archives/patch-textsearch_bug66650.sql [new file with mode: 0644]
maintenance/postgres/update-keys.sql
resources/src/mediawiki/mediawiki.js
resources/src/startup.js
tests/phpunit/includes/MessageTest.php
tests/qunit/suites/resources/mediawiki/mediawiki.test.js

index d72c31d..b84d276 100644 (file)
--- a/.jshintrc
+++ b/.jshintrc
@@ -22,6 +22,7 @@
                "mediaWiki": true,
                "JSON": true,
                "OO": true,
+               "performance": true,
                "jQuery": false,
                "QUnit": false,
                "sinon": false
index 21b584b..6f354c3 100644 (file)
@@ -1421,7 +1421,7 @@ function wfGetLangObj( $langcode = false ) {
  *
  * This function replaces all old wfMsg* functions.
  *
- * @param string|string[] $key Message key, or array of keys
+ * @param string|string[]|MessageSpecifier $key Message key, or array of keys, or a MessageSpecifier
  * @param mixed $params,... Normal message parameters
  * @return Message
  *
index ee41db0..54abfd1 100644 (file)
@@ -226,8 +226,9 @@ class Message implements MessageSpecifier, Serializable {
        /**
         * @since 1.17
         *
-        * @param string|string[] $key Message key or array of message keys to try and use the first
-        * non-empty message for.
+        * @param string|string[]|MessageSpecifier $key Message key, or array of
+        * message keys to try and use the first non-empty message for, or a
+        * MessageSpecifier to copy from.
         * @param array $params Message parameters.
         * @param Language $language Optional language of the message, defaults to $wgLang.
         *
@@ -236,6 +237,16 @@ class Message implements MessageSpecifier, Serializable {
        public function __construct( $key, $params = array(), Language $language = null ) {
                global $wgLang;
 
+               if ( $key instanceof MessageSpecifier ) {
+                       if ( $params ) {
+                               throw new InvalidArgumentException(
+                                       '$params must be empty if $key is a MessageSpecifier'
+                               );
+                       }
+                       $params = $key->getParams();
+                       $key = $key->getKey();
+               }
+
                if ( !is_string( $key ) && !is_array( $key ) ) {
                        throw new InvalidArgumentException( '$key must be a string or an array' );
                }
@@ -362,7 +373,7 @@ class Message implements MessageSpecifier, Serializable {
         *
         * @since 1.17
         *
-        * @param string|string[] $key Message key or array of keys.
+        * @param string|string[]|MessageSpecifier $key
         * @param mixed $param,... Parameters as strings.
         *
         * @return Message
index d627a6d..4c044bd 100644 (file)
@@ -4252,7 +4252,9 @@ class User implements IDBAccessObject {
                }
                $to = MailAddress::newFromUser( $this );
 
-               return UserMailer::send( $to, $sender, $subject, $body, $replyto );
+               return UserMailer::send( $to, $sender, $subject, $body, array(
+                       'replyTo' => $replyto,
+               ) );
        }
 
        /**
index 6ac5436..4410271 100644 (file)
@@ -407,6 +407,8 @@ class PostgresUpdater extends DatabaseUpdater {
                        array( 'addPgField', 'mwuser', 'user_password_expires', 'TIMESTAMPTZ NULL' ),
                        array( 'changeFieldPurgeTable', 'l10n_cache', 'lc_value', 'bytea',
                                "replace(lc_value,'\','\\\\')::bytea" ),
+                       // 1.23.9
+                       array( 'rebuildTextSearch'),
 
                        // 1.24
                        array( 'addPgField', 'page_props', 'pp_sortkey', 'float NULL' ),
@@ -947,4 +949,12 @@ END;
                        $this->applyPatch( 'patch-tsearch2funcs.sql', false, "Rewriting tsearch2 triggers" );
                }
        }
+
+       protected function rebuildTextSearch() {
+               if ( $this->updateRowExists( 'patch-textsearch_bug66650.sql' ) ) {
+                       $this->output( "...bug 66650 already fixed or not applicable.\n" );
+                       return true;
+               };
+               $this->applyPatch( 'patch-textsearch_bug66650.sql', false, "Rebuilding text search for bug 66650" );
+       }
 }
index 68e96fc..beeb067 100644 (file)
@@ -38,7 +38,7 @@ class EmaillingJob extends Job {
                        $this->params['from'],
                        $this->params['subj'],
                        $this->params['body'],
-                       $this->params['replyto']
+                       array( 'replyTo' => $this->params['replyto'] )
                );
 
                return $status->isOK();
index 1027732..0eed450 100644 (file)
@@ -478,7 +478,9 @@ class EmailNotification {
                                $wgContLang->userTime( $this->timestamp, $watchingUser ) ),
                        $this->body );
 
-               return UserMailer::send( $to, $this->from, $this->subject, $body, $this->replyto );
+               return UserMailer::send( $to, $this->from, $this->subject, $body, array(
+                       'replyTo' => $this->replyto,
+               ) );
        }
 
        /**
@@ -503,7 +505,9 @@ class EmailNotification {
                                $wgContLang->time( $this->timestamp, false, false ) ),
                        $this->body );
 
-               return UserMailer::send( $addresses, $this->from, $this->subject, $body, $this->replyto );
+               return UserMailer::send( $addresses, $this->from, $this->subject, $body, array(
+                       'replyTo' => $this->replyto,
+               ) );
        }
 
 }
index 546cc8c..d83ae93 100644 (file)
@@ -102,16 +102,32 @@ class UserMailer {
         * @param MailAddress $from Sender's email
         * @param string $subject Email's subject.
         * @param string $body Email's text or Array of two strings to be the text and html bodies
-        * @param MailAddress $replyto Optional reply-to email (default: null).
-        * @param string $contentType Optional custom Content-Type (default: text/plain; charset=UTF-8)
+        * @param array $options:
+        *              'replyTo' MailAddress
+        *              'contentType' string default 'text/plain; charset=UTF-8'
+        *
+        * Previous versions of this function had $replyto as the 5th argument and $contentType
+        * as the 6th. These are still supported for backwards compatability, but deprecated.
+        *
         * @throws MWException
         * @throws Exception
         * @return Status
         */
-       public static function send( $to, $from, $subject, $body, $replyto = null,
-               $contentType = 'text/plain; charset=UTF-8'
-       ) {
+       public static function send( $to, $from, $subject, $body, $options = array() ) {
                global $wgSMTP, $wgEnotifMaxRecips, $wgAdditionalMailParams, $wgAllowHTMLEmail;
+               $contentType = 'text/plain; charset=UTF-8';
+               if ( is_array( $options ) ) {
+                       $replyto = isset( $options['replyTo'] ) ? $options['replyTo'] : null;
+                       $contentType = isset( $options['contentType'] ) ? $options['contentType'] : $contentType;
+               } else {
+                       // Old calling style
+                       wfDeprecated( __METHOD__ . ' with $replyto as 5th parameter', '1.26' );
+                       $replyto = $options;
+                       if ( func_num_args() === 6 ) {
+                               $contentType = func_get_arg( 5 );
+                       }
+               }
+
                $mime = null;
                if ( !is_array( $to ) ) {
                        $to = array( $to );
index bda10b0..71e3b63 100644 (file)
@@ -186,7 +186,7 @@ class SearchPostgres extends SearchDatabase {
        function update( $pageid, $title, $text ) {
                ## We don't want to index older revisions
                $sql = "UPDATE pagecontent SET textvector = NULL WHERE textvector IS NOT NULL and old_id IN " .
-                               "(SELECT rev_text_id FROM revision WHERE rev_page = " . intval( $pageid ) .
+                               "(SELECT DISTINCT rev_text_id FROM revision WHERE rev_page = " . intval( $pageid ) .
                                " ORDER BY rev_text_id DESC OFFSET 1)";
                $this->db->query( $sql );
                return true;
index c55fa94..1754471 100644 (file)
@@ -356,7 +356,9 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                        $replyTo = null;
                }
 
-               $status = UserMailer::send( $to, $mailFrom, $subject, $text, $replyTo );
+               $status = UserMailer::send( $to, $mailFrom, $subject, $text, array(
+                       'replyTo' => $replyTo,
+               ) );
 
                if ( !$status->isGood() ) {
                        return $status;
diff --git a/maintenance/postgres/archives/patch-textsearch_bug66650.sql b/maintenance/postgres/archives/patch-textsearch_bug66650.sql
new file mode 100644 (file)
index 0000000..e4f5681
--- /dev/null
@@ -0,0 +1,5 @@
+UPDATE /*_*/pagecontent SET textvector=to_tsvector(old_text)
+WHERE textvector IS NULL AND old_id IN 
+(SELECT  max(rev_text_id) FROM revision GROUP BY rev_page);
+
+INSERT INTO /*_*/updatelog(ul_key) VALUES ('patch-textsearch_bug66650.sql');
index 7761d0c..b858551 100644 (file)
@@ -27,3 +27,8 @@ INSERT INTO /*_*/updatelog (ul_key, ul_value)
        VALUES( 'user_former_groups-ufg_group-patch-ufg_group-length-increase-255.sql', null );
 INSERT INTO /*_*/updatelog (ul_key, ul_value)
        VALUES( 'user_properties-up_property-patch-up_property.sql', null );
+
+-- PostgreSQL-specific patches.
+
+INSERT INTO /*_*/updatelog (ul_key, ul_value)
+       VALUES( 'patch-textsearch_bug66650.sql', null );
index 2c88e93..c0b1642 100644 (file)
                        function addEmbeddedCSS( cssText, callback ) {
                                var $style, styleEl;
 
+                               function fireCallbacks() {
+                                       var oldCallbacks = cssCallbacks;
+                                       // Reset cssCallbacks variable so it's not polluted by any calls to
+                                       // addEmbeddedCSS() from one of the callbacks (T105973)
+                                       cssCallbacks = $.Callbacks();
+                                       oldCallbacks.fire().empty();
+                               }
+
                                if ( callback ) {
                                        cssCallbacks.add( callback );
                                }
                                                } else {
                                                        styleEl.appendChild( document.createTextNode( cssText ) );
                                                }
-                                               cssCallbacks.fire().empty();
+                                               fireCallbacks();
                                                return;
                                        }
                                }
 
                                $( newStyleTag( cssText, getMarker() ) ).data( 'ResourceLoaderDynamicStyleTag', true );
 
-                               cssCallbacks.fire().empty();
+                               fireCallbacks();
                        }
 
                        /**
index 80cc7d9..5ee295b 100644 (file)
@@ -6,6 +6,14 @@
 
 var mediaWikiLoadStart = ( new Date() ).getTime();
 
+if ( !window.performance ) {
+       window.performance = {};
+}
+if ( !performance.mark ) {
+       performance.mark = function () {};
+}
+performance.mark( 'mediaWikiStartUp' );
+
 /**
  * Returns false for Grade C supported browsers.
  *
index cf08dbe..9c953a6 100644 (file)
@@ -21,6 +21,17 @@ class MessageTest extends MediaWikiLangTestCase {
                $this->assertEquals( $key, $message->getKey() );
                $this->assertEquals( $params, $message->getParams() );
                $this->assertEquals( $expectedLang, $message->getLanguage() );
+
+               $messageSpecifier = $this->getMockForAbstractClass( 'MessageSpecifier' );
+               $messageSpecifier->expects( $this->any() )
+                       ->method( 'getKey' )->will( $this->returnValue( $key ) );
+               $messageSpecifier->expects( $this->any() )
+                       ->method( 'getParams' )->will( $this->returnValue( $params ) );
+               $message = new Message( $messageSpecifier, array(), $language );
+
+               $this->assertEquals( $key, $message->getKey() );
+               $this->assertEquals( $params, $message->getParams() );
+               $this->assertEquals( $expectedLang, $message->getLanguage() );
        }
 
        public static function provideConstructor() {
index 77fecb3..c8f0011 100644 (file)
 
        } );
 
+       QUnit.asyncTest( 'mw.loader.implement( dependency with styles )', 4, function ( assert ) {
+               var $element = $( '<div class="mw-test-implement-e"></div>' ).appendTo( '#qunit-fixture' ),
+                       $element2 = $( '<div class="mw-test-implement-e2"></div>' ).appendTo( '#qunit-fixture' );
+
+               assert.notEqual(
+                       $element.css( 'float' ),
+                       'right',
+                       'style is clear'
+               );
+               assert.notEqual(
+                       $element2.css( 'float' ),
+                       'left',
+                       'style is clear'
+               );
+
+               mw.loader.register( [
+                       [ 'test.implement.e', '0', ['test.implement.e2']],
+                       [ 'test.implement.e2', '0' ]
+               ] );
+
+               mw.loader.implement(
+                       'test.implement.e',
+                       function () {
+                               assert.equal(
+                                       $element.css( 'float' ),
+                                       'right',
+                                       'Depending module\'s style is applied'
+                               );
+                               QUnit.start();
+                       },
+                       {
+                               'all': '.mw-test-implement-e { float: right; }'
+                       }
+               );
+
+               mw.loader.implement(
+                       'test.implement.e2',
+                       function () {
+                               assert.equal(
+                                       $element2.css( 'float' ),
+                                       'left',
+                                       'Dependency\'s style is applied'
+                               );
+                       },
+                       {
+                               'all': '.mw-test-implement-e2 { float: left; }'
+                       }
+               );
+
+               mw.loader.load( [
+                       'test.implement.e'
+               ] );
+       } );
+
        QUnit.test( 'mw.loader.implement( only scripts )', 1, function ( assert ) {
                mw.loader.implement( 'test.onlyscripts', function () {} );
                assert.strictEqual( mw.loader.getState( 'test.onlyscripts' ), 'ready' );