Merge "Changed 'expiry' to American English 'expiration' in en.json"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 18 Feb 2016 19:34:26 +0000 (19:34 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 18 Feb 2016 19:34:26 +0000 (19:34 +0000)
includes/EditPage.php
includes/Title.php
includes/api/ApiQueryWatchlist.php
includes/db/Database.php
includes/registration/ExtensionProcessor.php
includes/session/SessionManager.php
includes/specials/SpecialBotPasswords.php
tests/phpunit/includes/registration/ExtensionProcessorTest.php

index 5ebb44a..82fcdcf 100644 (file)
@@ -1420,6 +1420,11 @@ class EditPage {
                        }
                }
 
+               // "wpExtraQueryRedirect" is a hidden input to modify
+               // after save URL and is not used by actual edit form
+               $request = RequestContext::getMain()->getRequest();
+               $extraQueryRedirect = $request->getVal( 'wpExtraQueryRedirect' );
+
                switch ( $status->value ) {
                        case self::AS_HOOK_ERROR_EXPECTED:
                        case self::AS_CONTENT_TOO_BIG:
@@ -1443,6 +1448,13 @@ class EditPage {
 
                        case self::AS_SUCCESS_NEW_ARTICLE:
                                $query = $resultDetails['redirect'] ? 'redirect=no' : '';
+                               if ( $extraQueryRedirect ) {
+                                       if ( $query === '' ) {
+                                               $query = $extraQueryRedirect;
+                                       } else {
+                                               $query = $query . '&' . $extraQueryRedirect;
+                                       }
+                               }
                                $anchor = isset( $resultDetails['sectionanchor'] ) ? $resultDetails['sectionanchor'] : '';
                                $wgOut->redirect( $this->mTitle->getFullURL( $query ) . $anchor );
                                return false;
@@ -1464,6 +1476,14 @@ class EditPage {
                                                $extraQuery = 'redirect=no&' . $extraQuery;
                                        }
                                }
+                               if ( $extraQueryRedirect ) {
+                                       if ( $extraQuery === '' ) {
+                                               $extraQuery = $extraQueryRedirect;
+                                       } else {
+                                               $extraQuery = $extraQuery . '&' . $extraQueryRedirect;
+                                       }
+                               }
+
                                $wgOut->redirect( $this->mTitle->getFullURL( $extraQuery ) . $sectionanchor );
                                return false;
 
index 38ee2ee..c0ec97f 100644 (file)
@@ -3434,7 +3434,7 @@ class Title implements LinkTarget {
         * WARNING: do not use this function on arbitrary user-supplied titles!
         * On heavily-used templates it will max out the memory.
         *
-        * @param array $options May be FOR UPDATE
+        * @param array $options Query option to Database::select()
         * @return Title[] Array of Title the Title objects linking here
         */
        public function getTemplateLinksTo( $options = [] ) {
@@ -3448,7 +3448,7 @@ class Title implements LinkTarget {
         * WARNING: do not use this function on arbitrary user-supplied titles!
         * On heavily-used templates it will max out the memory.
         *
-        * @param array $options May be FOR UPDATE
+        * @param array $options Query option to Database::select()
         * @param string $table Table name
         * @param string $prefix Fields prefix
         * @return array Array of Title objects linking here
@@ -3461,11 +3461,7 @@ class Title implements LinkTarget {
                        return [];
                }
 
-               if ( count( $options ) > 0 ) {
-                       $db = wfGetDB( DB_MASTER );
-               } else {
-                       $db = wfGetDB( DB_SLAVE );
-               }
+               $db = wfGetDB( DB_SLAVE );
 
                $blNamespace = "{$prefix}_namespace";
                $blTitle = "{$prefix}_title";
@@ -4703,6 +4699,18 @@ class Title implements LinkTarget {
                        return $wgLang;
                }
 
+               // Checking if DB language is set
+               $dbPageLanguage = $this->getDbPageLanguageCode();
+               if ( $dbPageLanguage ) {
+                       $pageLang = wfGetLangObj( $dbPageLanguage );
+                       $variant = $pageLang->getPreferredVariant();
+                       if ( $pageLang->getCode() !== $variant ) {
+                               $pageLang = Language::factory( $variant );
+                       }
+
+                       return $pageLang;
+               }
+
                // @note Can't be cached persistently, depends on user settings.
                // @note ContentHandler::getPageViewLanguage() may need to load the
                //   content to determine the page language!
index 7e561cb..db2cf86 100644 (file)
@@ -192,8 +192,11 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                        $this->addWhereIf( 'rc_user != 0', isset( $show['!anon'] ) );
                        $this->addWhereIf( 'rc_patrolled = 0', isset( $show['!patrolled'] ) );
                        $this->addWhereIf( 'rc_patrolled != 0', isset( $show['patrolled'] ) );
-                       $this->addWhereIf( 'wl_notificationtimestamp IS NOT NULL', isset( $show['unread'] ) );
-                       $this->addWhereIf( 'wl_notificationtimestamp IS NULL', isset( $show['!unread'] ) );
+                       $this->addWhereIf( 'rc_timestamp >= wl_notificationtimestamp', isset( $show['unread'] ) );
+                       $this->addWhereIf(
+                               'wl_notificationtimestamp IS NULL OR rc_timestamp < wl_notificationtimestamp',
+                               isset( $show['!unread'] )
+                       );
                }
 
                if ( !is_null( $params['type'] ) ) {
index d741b2f..351d438 100644 (file)
@@ -1069,7 +1069,9 @@ abstract class DatabaseBase implements IDatabase {
                $table, $var, $cond = '', $fname = __METHOD__, $options = [], $join_conds = []
        ) {
                if ( $var === '*' ) { // sanity
-                       throw new DBUnexpectedError( $this, "Cannot use a * field: got '$var'" );
+                       throw new DBUnexpectedError( $this, "Cannot use a * field" );
+               } elseif ( !is_string( $var ) ) { // sanity
+                       throw new DBUnexpectedError( $this, "Cannot use an array of fields" );
                }
 
                if ( !is_array( $options ) ) {
index 2318c87..fe9304f 100644 (file)
@@ -253,14 +253,24 @@ class ExtensionProcessor implements Processor {
                        ? $info['ResourceFileModulePaths']
                        : false;
                if ( isset( $defaultPaths['localBasePath'] ) ) {
-                       $defaultPaths['localBasePath'] = "$dir/{$defaultPaths['localBasePath']}";
+                       if ( $defaultPaths['localBasePath'] === '' ) {
+                               // Avoid double slashes (e.g. /extensions/Example//path)
+                               $defaultPaths['localBasePath'] = $dir;
+                       } else {
+                               $defaultPaths['localBasePath'] = "$dir/{$defaultPaths['localBasePath']}";
+                       }
                }
 
                foreach ( [ 'ResourceModules', 'ResourceModuleSkinStyles' ] as $setting ) {
                        if ( isset( $info[$setting] ) ) {
                                foreach ( $info[$setting] as $name => $data ) {
                                        if ( isset( $data['localBasePath'] ) ) {
-                                               $data['localBasePath'] = "$dir/{$data['localBasePath']}";
+                                               if ( $data['localBasePath'] === '' ) {
+                                                       // Avoid double slashes (e.g. /extensions/Example//path)
+                                                       $data['localBasePath'] = $dir;
+                                               } else {
+                                                       $data['localBasePath'] = "$dir/{$data['localBasePath']}";
+                                               }
                                        }
                                        if ( $defaultPaths ) {
                                                $data += $defaultPaths;
index 5573ec7..0abec1b 100644 (file)
@@ -358,19 +358,21 @@ final class SessionManager implements SessionManagerInterface {
 
                // Try the local user from the slave DB
                $localId = User::idFromName( $user->getName() );
+               $flags = 0;
 
                // Fetch the user ID from the master, so that we don't try to create the user
                // when they already exist, due to replication lag
                // @codeCoverageIgnoreStart
                if ( !$localId && wfGetLB()->getReaderIndex() != 0 ) {
                        $localId = User::idFromName( $user->getName(), User::READ_LATEST );
+                       $flags = User::READ_LATEST;
                }
                // @codeCoverageIgnoreEnd
 
                if ( $localId ) {
                        // User exists after all.
                        $user->setId( $localId );
-                       $user->loadFromId();
+                       $user->loadFromId( $flags );
                        return false;
                }
 
@@ -475,12 +477,21 @@ final class SessionManager implements SessionManagerInterface {
                        $status = $user->addToDatabase();
                        if ( !$status->isOK() ) {
                                // @codeCoverageIgnoreStart
-                               $logger->error( __METHOD__ . ': failed with message ' . $status->getWikiText(),
-                                       [
-                                               'username' => $userName,
-                               ] );
-                               $user->setId( 0 );
-                               $user->loadFromId();
+                               // double-check for a race condition (T70012)
+                               $id = User::idFromName( $user->getName(), User::READ_LATEST );
+                               if ( $id ) {
+                                       $logger->info( __METHOD__ . ': tried to autocreate existing user',
+                                               [
+                                                       'username' => $userName,
+                                               ] );
+                               } else {
+                                       $logger->error( __METHOD__ . ': failed with message ' . $status->getWikiText(),
+                                               [
+                                                       'username' => $userName,
+                                               ] );
+                               }
+                               $user->setId( $id );
+                               $user->loadFromId( User::READ_LATEST );
                                return false;
                                // @codeCoverageIgnoreEnd
                        }
index 47e3316..8aa81fb 100644 (file)
@@ -347,6 +347,24 @@ class SpecialBotPasswords extends FormSpecialPage {
                $out->addReturnTo( $this->getPageTitle() );
        }
 
+       /**
+        * Return an array of subpages beginning with $search that this special page will accept.
+        *
+        * @param string $search Prefix to search for
+        * @param int $limit Maximum number of results to return (usually 10)
+        * @param int $offset Number of results to skip (usually 0)
+        * @return string[] Matching subpages
+        */
+       public function prefixSearchSubpages( $search, $limit, $offset ) {
+               $user = User::newFromName( $search );
+               if ( !$user ) {
+                       // No prefix suggestion for invalid user
+                       return [];
+               }
+               // Autocomplete subpage as user list - public to allow caching
+               return UserNamePrefixSearch::search( 'public', $search, $limit, $offset );
+       }
+
        protected function getGroupName() {
                return 'users';
        }
index 7f84e33..35aca48 100644 (file)
@@ -218,7 +218,7 @@ class ExtensionProcessorTest extends MediaWikiTestCase {
        }
 
        public static function provideExtractResourceLoaderModules() {
-               $dir = __DIR__ . '/FooBar/';
+               $dir = __DIR__ . '/FooBar';
                return [
                        // Generic module with localBasePath/remoteExtPath specified
                        [
@@ -285,7 +285,7 @@ class ExtensionProcessorTest extends MediaWikiTestCase {
                                                ],
                                                'test.bar' => [
                                                        'styles' => 'bar.js',
-                                                       'localBasePath' => $dir . 'subdir',
+                                                       'localBasePath' => "$dir/subdir",
                                                        'remoteExtPath' => 'FooBar/subdir',
                                                ],
                                                'test.class' => [