Merge "Move WikiEditor's special character data and messages into core for use in...
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 27 Mar 2015 18:40:36 +0000 (18:40 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 27 Mar 2015 18:40:36 +0000 (18:40 +0000)
18 files changed:
RELEASE-NOTES-1.25
includes/DefaultSettings.php
includes/Html.php
includes/LinkFilter.php
includes/MediaWiki.php
includes/User.php
includes/WebResponse.php
includes/api/ApiParse.php
includes/debug/logger/legacy/Logger.php
includes/debug/logger/monolog/Handler.php
includes/page/WikiPage.php
includes/profiler/Profiler.php
includes/profiler/ProfilerStub.php
includes/templates/Usercreate.php
resources/Resources.php
tests/phpunit/data/helpers/WellProtectedClass.php
tests/phpunit/includes/TestingAccessWrapper.php
tests/phpunit/includes/TestingAccessWrapperTest.php

index 6462767..b7a1a8e 100644 (file)
@@ -45,6 +45,8 @@ production.
 * The 'daemonized' flag must be set to true in $wgJobTypeConf for any redis
   job queues. This means that mediawiki/services/jobrunner service has to
   be installed and running for any such queues to work.
+* $wgAutopromoteOnce no longer supports the 'view' event. For keeping some
+  compatibility, any 'view' event triggers will still trigger on 'edit'.
 
 === New features in 1.25 ===
 * (T64861) Updated plural rules to CLDR 26. Includes incompatible changes
index 1df809e..5ab557e 100644 (file)
@@ -4863,7 +4863,6 @@ $wgAutopromote = array(
  * @endcode
  * Where event is either:
  *    - 'onEdit' (when user edits)
- *    - 'onView' (when user views the wiki)
  *
  * Criteria has the same format as $wgAutopromote
  *
@@ -4872,7 +4871,6 @@ $wgAutopromote = array(
  */
 $wgAutopromoteOnce = array(
        'onEdit' => array(),
-       'onView' => array()
 );
 
 /**
index 6bd661f..4b69885 100644 (file)
@@ -170,7 +170,7 @@ class Html {
         * @return string Raw HTML
         */
        public static function linkButton( $contents, $attrs, $modifiers = array() ) {
-               return Html::element( 'a',
+               return self::element( 'a',
                        self::buttonAttributes( $attrs, $modifiers ),
                        $contents
                );
@@ -192,7 +192,7 @@ class Html {
        public static function submitButton( $contents, $attrs, $modifiers = array() ) {
                $attrs['type'] = 'submit';
                $attrs['value'] = $contents;
-               return Html::element( 'input', self::buttonAttributes( $attrs, $modifiers ) );
+               return self::element( 'input', self::buttonAttributes( $attrs, $modifiers ) );
        }
 
        /**
@@ -716,7 +716,7 @@ class Html {
                $attribs['value'] = $value;
                $attribs['name'] = $name;
                if ( in_array( $type, array( 'text', 'search', 'email', 'password', 'number' ) ) ) {
-                       $attribs = Html::getTextInputAttributes( $attribs );
+                       $attribs = self::getTextInputAttributes( $attribs );
                }
                return self::element( 'input', $attribs );
        }
@@ -819,7 +819,7 @@ class Html {
                } else {
                        $spacedValue = $value;
                }
-               return self::element( 'textarea', Html::getTextInputAttributes( $attribs ), $spacedValue );
+               return self::element( 'textarea', self::getTextInputAttributes( $attribs ), $spacedValue );
        }
 
        /**
@@ -890,7 +890,7 @@ class Html {
                        } elseif ( is_int( $nsId ) ) {
                                $nsName = $wgContLang->convertNamespace( $nsId );
                        }
-                       $optionsHtml[] = Html::element(
+                       $optionsHtml[] = self::element(
                                'option', array(
                                        'disabled' => in_array( $nsId, $params['disable'] ),
                                        'value' => $nsId,
@@ -909,7 +909,7 @@ class Html {
 
                $ret = '';
                if ( isset( $params['label'] ) ) {
-                       $ret .= Html::element(
+                       $ret .= self::element(
                                'label', array(
                                        'for' => isset( $selectAttribs['id'] ) ? $selectAttribs['id'] : null,
                                ), $params['label']
@@ -917,11 +917,11 @@ class Html {
                }
 
                // Wrap options in a <select>
-               $ret .= Html::openElement( 'select', $selectAttribs )
+               $ret .= self::openElement( 'select', $selectAttribs )
                        . "\n"
                        . implode( "\n", $optionsHtml )
                        . "\n"
-                       . Html::closeElement( 'select' );
+                       . self::closeElement( 'select' );
 
                return $ret;
        }
@@ -962,7 +962,7 @@ class Html {
                        $attribs['version'] = $wgHtml5Version;
                }
 
-               $html = Html::openElement( 'html', $attribs );
+               $html = self::openElement( 'html', $attribs );
 
                if ( $html ) {
                        $html .= "\n";
@@ -998,25 +998,25 @@ class Html {
         * @return string
         */
        static function infoBox( $text, $icon, $alt, $class = '' ) {
-               $s = Html::openElement( 'div', array( 'class' => "mw-infobox $class" ) );
+               $s = self::openElement( 'div', array( 'class' => "mw-infobox $class" ) );
 
-               $s .= Html::openElement( 'div', array( 'class' => 'mw-infobox-left' ) ) .
-                               Html::element( 'img',
+               $s .= self::openElement( 'div', array( 'class' => 'mw-infobox-left' ) ) .
+                               self::element( 'img',
                                        array(
                                                'src' => $icon,
                                                'alt' => $alt,
                                        )
                                ) .
-                               Html::closeElement( 'div' );
+                               self::closeElement( 'div' );
 
-               $s .= Html::openElement( 'div', array( 'class' => 'mw-infobox-right' ) ) .
+               $s .= self::openElement( 'div', array( 'class' => 'mw-infobox-right' ) ) .
                                $text .
-                               Html::closeElement( 'div' );
-               $s .= Html::element( 'div', array( 'style' => 'clear: left;' ), ' ' );
+                               self::closeElement( 'div' );
+               $s .= self::element( 'div', array( 'style' => 'clear: left;' ), ' ' );
 
-               $s .= Html::closeElement( 'div' );
+               $s .= self::closeElement( 'div' );
 
-               $s .= Html::element( 'div', array( 'style' => 'clear: left;' ), ' ' );
+               $s .= self::element( 'div', array( 'style' => 'clear: left;' ), ' ' );
 
                return $s;
        }
index 340ae8f..99aaaa0 100644 (file)
@@ -92,7 +92,7 @@ class LinkFilter {
         * @return array Array to be passed to DatabaseBase::buildLike() or false on error
         */
        public static function makeLikeArray( $filterEntry, $protocol = 'http://' ) {
-               $db = wfGetDB( DB_MASTER );
+               $db = wfGetDB( DB_SLAVE );
 
                $target = $protocol . $filterEntry;
                $bits = wfParseUrl( $target );
index 2644023..c086a39 100644 (file)
@@ -199,8 +199,6 @@ class MediaWiki {
                        throw new PermissionsError( 'read', $permErrors );
                }
 
-               $pageView = false; // was an article or special page viewed?
-
                // Interwiki redirects
                if ( $title->isExternal() ) {
                        $rdfrom = $request->getVal( 'rdfrom' );
@@ -263,7 +261,6 @@ class MediaWiki {
                        }
                // Special pages
                } elseif ( NS_SPECIAL == $title->getNamespace() ) {
-                       $pageView = true;
                        // Actions that need to be made when we have a special pages
                        SpecialPageFactory::executePath( $title, $this->context );
                } else {
@@ -271,7 +268,6 @@ class MediaWiki {
                        // may be a redirect to another article or URL.
                        $article = $this->initializeArticle();
                        if ( is_object( $article ) ) {
-                               $pageView = true;
                                $this->performAction( $article, $requestTitle );
                        } elseif ( is_string( $article ) ) {
                                $output->redirect( $article );
@@ -280,12 +276,6 @@ class MediaWiki {
                                        . " returned neither an object nor a URL" );
                        }
                }
-
-               if ( $pageView ) {
-                       // Promote user to any groups they meet the criteria for
-                       $user->addAutopromoteOnceGroups( 'onView' );
-               }
-
        }
 
        /**
index 2f9b716..78693c1 100644 (file)
@@ -2309,7 +2309,9 @@ class User implements IDBAccessObject {
                        if ( $this->mQuickTouched === null ) {
                                $key = wfMemcKey( 'user-quicktouched', 'id', $this->mId );
                                $timestamp = $wgMemc->get( $key );
-                               if ( !$timestamp ) {
+                               if ( $timestamp ) {
+                                       $this->mQuickTouched = $timestamp;
+                               } else {
                                        # Set the timestamp to get HTTP 304 cache hits
                                        $this->touch();
                                }
index 83ac51a..ab34931 100644 (file)
@@ -60,7 +60,7 @@ class WebResponse {
         * @param int|null $expire Unix timestamp (in seconds) when the cookie should expire.
         *        0 (the default) causes it to expire $wgCookieExpiration seconds from now.
         *        null causes it to be a session cookie.
-        * @param array|null $options Assoc of additional cookie options:
+        * @param array $options Assoc of additional cookie options:
         *     prefix: string, name prefix ($wgCookiePrefix)
         *     domain: string, cookie domain ($wgCookieDomain)
         *     path: string, cookie path ($wgCookiePath)
@@ -72,7 +72,7 @@ class WebResponse {
         *   'prefix', 'domain', and 'secure'
         * @since 1.22 Replaced $prefix, $domain, and $forceSecure with $options
         */
-       public function setcookie( $name, $value, $expire = 0, $options = null ) {
+       public function setcookie( $name, $value, $expire = 0, $options = array() ) {
                global $wgCookiePath, $wgCookiePrefix, $wgCookieDomain;
                global $wgCookieSecure, $wgCookieExpiration, $wgCookieHttpOnly;
 
@@ -188,9 +188,9 @@ class FauxResponse extends WebResponse {
         * @param string $name The name of the cookie.
         * @param string $value The value to be stored in the cookie.
         * @param int|null $expire Ignored in this faux subclass.
-        * @param array|null $options Ignored in this faux subclass.
+        * @param array $options Ignored in this faux subclass.
         */
-       public function setcookie( $name, $value, $expire = 0, $options = null ) {
+       public function setcookie( $name, $value, $expire = 0, $options = array() ) {
                $this->cookies[$name] = $value;
        }
 
index b621861..73bea83 100644 (file)
@@ -231,12 +231,11 @@ class ApiParse extends ApiBase {
                                        $result_array['wikitext'] = array();
                                        ApiResult::setContent( $result_array['wikitext'], $this->content->serialize( $format ) );
                                }
-                               if ( !is_null( $params['summary'] ) ) {
+                               if ( !is_null( $params['summary'] ) ||
+                                       ( !is_null( $params['sectiontitle'] ) && $this->section === 'new' )
+                               ) {
                                        $result_array['parsedsummary'] = array();
-                                       ApiResult::setContent(
-                                               $result_array['parsedsummary'],
-                                               Linker::formatComment( $params['summary'], $titleObj )
-                                       );
+                                       ApiResult::setContent( $result_array['parsedsummary'], $this->formatSummary( $titleObj, $params ) );
                                }
 
                                $result->addValue( null, $this->getModuleName(), $result_array );
@@ -273,12 +272,11 @@ class ApiParse extends ApiBase {
                        ApiResult::setContent( $result_array['text'], $p_result->getText() );
                }
 
-               if ( !is_null( $params['summary'] ) ) {
+               if ( !is_null( $params['summary'] ) ||
+                       ( !is_null( $params['sectiontitle'] ) && $this->section === 'new' )
+               ) {
                        $result_array['parsedsummary'] = array();
-                       ApiResult::setContent(
-                               $result_array['parsedsummary'],
-                               Linker::formatComment( $params['summary'], $titleObj )
-                       );
+                       ApiResult::setContent( $result_array['parsedsummary'], $this->formatSummary( $titleObj, $params ) );
                }
 
                if ( isset( $prop['langlinks'] ) ) {
@@ -502,6 +500,30 @@ class ApiParse extends ApiBase {
                return $section;
        }
 
+       /**
+        * This mimicks the behavior of EditPage in formatting a summary
+        *
+        * @param Title $title of the page being parsed
+        * @param Array $params the API parameters of the request
+        * @return Content|bool
+        */
+       private function formatSummary( $title, $params ) {
+               global $wgParser;
+               $summary = !is_null( $params['summary'] ) ? $params['summary'] : '';
+               $sectionTitle = !is_null( $params['sectiontitle'] ) ? $params['sectiontitle'] : '';
+
+               if ( $this->section === 'new' && ( $sectionTitle === '' || $summary === '' ) ) {
+                       if( $sectionTitle !== '' ) {
+                               $summary = $params['sectiontitle'];
+                       }
+                       if ( $summary !== '' ) {
+                               $summary = wfMessage( 'newsectionsummary' )->rawParams( $wgParser->stripSectionName( $summary ) )
+                                       ->inContentLanguage()->text();
+                       }
+               }
+               return Linker::formatComment( $summary, $title, $this->section === 'new' );
+       }
+
        private function formatLangLinks( $links ) {
                $result = array();
                foreach ( $links as $link ) {
index c53aeaa..610635d 100644 (file)
@@ -290,6 +290,7 @@ class MWLoggerLegacyLogger extends AbstractLogger {
         *
         * @param string $message
         * @param array $context
+        * @return string Interpolated message
         */
        public static function interpolate( $message, array $context ) {
                if ( strpos( $message, '{' ) !== false ) {
index a872d84..9e7678d 100644 (file)
@@ -30,7 +30,8 @@
  * - HOST: IPv4, IPv6 or hostname
  * - PORT: server port
  * - PREFIX: optional (but recommended) prefix telling udp2log how to route
- * the log event
+ * the log event. The special prefix "{channel}" will use the log event's
+ * channel as the prefix value.
  *
  * When not targeting a udp2log stream this class will act as a drop-in
  * replacement for Monolog's StreamHandler.
@@ -194,7 +195,9 @@ class MWLoggerMonologHandler extends \Monolog\Handler\AbstractProcessingHandler
 
                        // Clean it up for the multiplexer
                        if ( $this->prefix !== '' ) {
-                               $text = preg_replace( '/^/m', "{$this->prefix} ", $text );
+                               $leader = ( $this->prefix === '{channel}' ) ?
+                                       $record['channel'] : $this->prefix;
+                               $text = preg_replace( '/^/m', "{$leader} ", $text );
 
                                // Limit to 64KB
                                if ( strlen( $text ) > 65506 ) {
index 2315dc7..0452c41 100644 (file)
@@ -1992,6 +1992,7 @@ class WikiPage implements Page, IDBAccessObject {
                // Promote user to any groups they meet the criteria for
                $dbw->onTransactionIdle( function () use ( $user ) {
                        $user->addAutopromoteOnceGroups( 'onEdit' );
+                       $user->addAutopromoteOnceGroups( 'onView' ); // b/c
                } );
 
                return $status;
index 69470fd..1c9824a 100644 (file)
@@ -134,7 +134,7 @@ abstract class Profiler {
        /**
         * @param ScopedCallback $section
         */
-       public function scopedProfileOut( ScopedCallback &$section ) {
+       public function scopedProfileOut( ScopedCallback &$section = null ) {
                $section = null;
        }
 
index 5580f94..1d04536 100644 (file)
@@ -28,7 +28,7 @@
  */
 class ProfilerStub extends Profiler {
        public function scopedProfileIn( $section ) {
-               return new ScopedCallback( null ); // no-op
+               return null; // no-op
        }
 
        public function getFunctionStats() {
index dc9da63..f09b6bb 100644 (file)
@@ -261,7 +261,7 @@ class UsercreateTemplate extends BaseTemplate {
                                <?php
                                echo Html::submitButton(
                                        $this->getMsg( $this->data['loggedin'] ? 'createacct-another-submit' : 'createacct-submit' ),
-                                       $attrs = array(
+                                       array(
                                                'id' => 'wpCreateaccount',
                                                'name' => 'wpCreateaccount',
                                                'tabindex' => $tabIndex++
index 52fedec..4464e4b 100644 (file)
@@ -849,6 +849,7 @@ return array(
                'scripts' => array(
                        'resources/src/mediawiki/mediawiki.confirmCloseWindow.js',
                ),
+               'targets' => array( 'desktop', 'mobile' ),
        ),
        'mediawiki.debug' => array(
                'scripts' => array(
index 7114cc9..99c7f64 100644 (file)
@@ -14,4 +14,8 @@ class WellProtectedClass {
        public function getProperty() {
                return $this->property;
        }
+
+       protected function whatSecondArg( $a, $b = false ) {
+               return $b;
+       }
 }
index d4ad363..84c0f9b 100644 (file)
@@ -31,7 +31,7 @@ class TestingAccessWrapper {
                $classReflection = new ReflectionClass( $this->object );
                $methodReflection = $classReflection->getMethod( $method );
                $methodReflection->setAccessible( true );
-               return $methodReflection->invoke( $this->object, $args );
+               return $methodReflection->invokeArgs( $this->object, $args );
        }
 
        public function __set( $name, $value ) {
index 8da8e42..7e5b91a 100644 (file)
@@ -27,4 +27,8 @@ class TestingAccessWrapperTest extends MediaWikiTestCase {
                $this->assertSame( 2, $this->wrapped->property );
                $this->assertSame( 2, $this->raw->getProperty() );
        }
+
+       function testCallMethodTwoArgs() {
+               $this->assertSame( 'two', $this->wrapped->whatSecondArg( 'one', 'two' ) );
+       }
 }