Merge "Kill some references to legacy skins"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Sat, 4 May 2013 13:30:52 +0000 (13:30 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Sat, 4 May 2013 13:30:52 +0000 (13:30 +0000)
21 files changed:
RELEASE-NOTES-1.22
includes/User.php
includes/api/ApiQueryImageInfo.php
includes/installer/MysqlInstaller.php
includes/specials/SpecialBlock.php
includes/specials/SpecialPreferences.php
languages/Language.php
maintenance/deleteEqualMessages.php
maintenance/jsduck/categories.json
maintenance/jsduck/config.json
resources/jquery/jquery.makeCollapsible.js
resources/mediawiki/mediawiki.js
resources/mediawiki/mediawiki.log.js
skins/common/oldshared.css
skins/common/shared.css
skins/common/wikibits.js
skins/modern/main.css
skins/monobook/Opera6Fixes.css [deleted file]
skins/monobook/Opera7Fixes.css [deleted file]
skins/monobook/Opera9Fixes.css [deleted file]
tests/qunit/suites/resources/jquery/jquery.makeCollapsible.test.js

index 850b43d..ff9622a 100644 (file)
@@ -58,6 +58,9 @@ production.
 * HTMLForm will turn multiselect checkboxes into a Chosen interface when setting cssclass 'mw-chosen'
 * rebuildLocalisationCache learned --lang option. Let you rebuild l10n caches
   of the specified languages instead of all of them.
+* mediawiki.log: Added log.warn wrapper (uses console.warn and console.trace).
+* mediawiki.log: Implemented log.deprecate. This method defines a property and
+  uses ES5 getter/setter to emit a warning when they are used.
 
 === Bug fixes in 1.22 ===
 * Disable Special:PasswordReset when $wgEnableEmail. Previously one could still
@@ -98,6 +101,7 @@ production.
   apply the new LanguageLinks hook, and thus only consider language links
   stored in the database.
 * (bug 47219) Allow specifying change type of Wikipedia feed items
+* prop=imageinfo now allows setting iiurlheight without setting iiurlwidth
 
 === Languages updated in 1.22===
 
@@ -129,6 +133,7 @@ changes to languages because of Bugzilla reports.
 * A new Special:Redirect page was added, providing lookup by revision ID,
   user ID, or file name.  The old Special:Filepath page was reimplemented
   to redirect through Special:Redirect.
+* Monobook: Removed the old conditional stylesheets for Opera 6, 7 and 9.
 
 == Compatibility ==
 
index 37a384c..5a525bf 100644 (file)
@@ -3263,7 +3263,7 @@ class User {
                        }
                        if ( !$loaded ) {
                                throw new MWException( __METHOD__ . ": hit a key conflict attempting " .
-                                       "to insert a user row, but then it doesn't exist when we select it!" );
+                                       "to insert user '{$this->mName}' row, but it was not present in select!" );
                        }
                        return Status::newFatal( 'userexists' );
                }
index c36821b..5ed9d38 100644 (file)
@@ -202,21 +202,20 @@ class ApiQueryImageInfo extends ApiQueryBase {
        public function getScale( $params ) {
                $p = $this->getModulePrefix();
 
-               // Height and width.
-               if ( $params['urlheight'] != -1 && $params['urlwidth'] == -1 ) {
-                       $this->dieUsage( "{$p}urlheight cannot be used without {$p}urlwidth", "{$p}urlwidth" );
-               }
-
                if ( $params['urlwidth'] != -1 ) {
                        $scale = array();
                        $scale['width'] = $params['urlwidth'];
                        $scale['height'] = $params['urlheight'];
+               } elseif ( $params['urlheight'] != -1 ) {
+                       // Height is specified but width isn't
+                       // Don't set $scale['width']; this signals mergeThumbParams() to fill it with the image's width
+                       $scale = array();
+                       $scale['height'] = $params['urlheight'];
                } else {
                        $scale = null;
                        if ( $params['urlparam'] ) {
                                $this->dieUsage( "{$p}urlparam requires {$p}urlwidth", "urlparam_no_width" );
                        }
-                       return $scale;
                }
 
                return $scale;
@@ -232,6 +231,12 @@ class ApiQueryImageInfo extends ApiQueryBase {
         * @return Array of parameters for transform.
         */
        protected function mergeThumbParams( $image, $thumbParams, $otherParams ) {
+
+               if ( !isset( $thumbParams['width'] ) && isset( $thumbParams['height'] ) ) {
+                       // Populate the width with the image's width, so only the height restriction applies
+                       $thumbParams['width'] = $image->getWidth();
+               }
+
                if ( !$otherParams ) {
                        return $thumbParams;
                }
@@ -257,8 +262,8 @@ class ApiQueryImageInfo extends ApiQueryBase {
 
                if ( isset( $paramList['width'] ) ) {
                        if ( intval( $paramList['width'] ) != intval( $thumbParams['width'] ) ) {
-                               $this->dieUsage( "{$p}urlparam had width of {$paramList['width']} but "
-                                       . "{$p}urlwidth was {$thumbParams['width']}", "urlparam_urlwidth_mismatch" );
+                               $this->setWarning( "Ignoring width value set in {$p}urlparam ({$paramList['width']}) "
+                                       . "in favor of width value derived from {$p}urlwidth/{$p}urlheight ({$thumbParams['width']})" );
                        }
                }
 
@@ -571,7 +576,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        'urlwidth' => array( "If {$p}prop=url is set, a URL to an image scaled to this width will be returned.",
                                'For performance reasons if this option is used, ' .
                                        'no more than ' . self::TRANSFORM_LIMIT . ' scaled images will be returned.' ),
-                       'urlheight' => "Similar to {$p}urlwidth. Cannot be used without {$p}urlwidth",
+                       'urlheight' => "Similar to {$p}urlwidth.",
                        'urlparam' => array( "A handler specific parameter string. For example, pdf's ",
                                "might use 'page15-100px'. {$p}urlwidth must be used and be consistent with {$p}urlparam" ),
                        'limit' => 'How many image revisions to return per image',
@@ -718,8 +723,6 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        array( 'code' => "{$p}urlwidth", 'info' => "{$p}urlheight cannot be used without {$p}urlwidth" ),
                        array( 'code' => 'urlparam', 'info' => "Invalid value for {$p}urlparam" ),
                        array( 'code' => 'urlparam_no_width', 'info' => "{$p}urlparam requires {$p}urlwidth" ),
-                       array( 'code' => 'urlparam_urlwidth_mismatch', 'info' => "The width set in {$p}urlparm doesn't " .
-                               "match the one in {$p}urlwidth" ),
                ) );
        }
 
index 4436173..e0bf3d7 100644 (file)
@@ -152,7 +152,6 @@ class MysqlInstaller extends DatabaseInstaller {
                                $this->getVar( '_InstallUser' ),
                                $this->getVar( '_InstallPassword' ),
                                false,
-                               false,
                                0,
                                $this->getVar( 'wgDBprefix' )
                        );
@@ -435,7 +434,6 @@ class MysqlInstaller extends DatabaseInstaller {
                                        $this->getVar( 'wgDBuser' ),
                                        $this->getVar( 'wgDBpassword' ),
                                        false,
-                                       false,
                                        0,
                                        $this->getVar( 'wgDBprefix' )
                                );
@@ -512,7 +510,6 @@ class MysqlInstaller extends DatabaseInstaller {
                                        $dbUser,
                                        $password,
                                        false,
-                                       false,
                                        0,
                                        $this->getVar( 'wgDBprefix' )
                                );
index 645de23..5a2ad62 100644 (file)
@@ -127,6 +127,8 @@ class SpecialBlock extends FormSpecialPage {
 
                $user = $this->getUser();
 
+               $suggestedDurations = self::getSuggestedDurations();
+
                $a = array(
                        'Target' => array(
                                'type' => 'text',
@@ -139,11 +141,11 @@ class SpecialBlock extends FormSpecialPage {
                                'validation-callback' => array( __CLASS__, 'validateTargetField' ),
                        ),
                        'Expiry' => array(
-                               'type' => !count( self::getSuggestedDurations() ) ? 'text' : 'selectorother',
+                               'type' => !count( $suggestedDurations ) ? 'text' : 'selectorother',
                                'label-message' => 'ipbexpiry',
                                'required' => true,
                                'tabindex' => '2',
-                               'options' => self::getSuggestedDurations(),
+                               'options' => $suggestedDurations,
                                'other' => $this->msg( 'ipbother' )->text(),
                                'default' => $this->msg( 'ipb-default-expiry' )->inContentLanguage()->text(),
                        ),
index a50e7c1..5fcf9ae 100644 (file)
@@ -52,7 +52,7 @@ class SpecialPreferences extends SpecialPage {
 
                if ( $this->getRequest()->getCheck( 'success' ) ) {
                        $out->wrapWikiMsg(
-                               "<div class=\"successbox\"><strong>\n$1\n</strong></div><div id=\"mw-pref-clear\"></div>",
+                               "<div class=\"successbox\">\n$1\n</div>",
                                'savedprefs'
                        );
                }
index 84e7f37..2fd4bb7 100644 (file)
@@ -327,18 +327,18 @@ class Language {
         */
        public static function isValidCode( $code ) {
                static $cache = array();
-               if( isset( $cache[$code] ) ) {
+               if ( isset( $cache[$code] ) ) {
                        return $cache[$code];
                }
                // People think language codes are html safe, so enforce it.
                // Ideally we should only allow a-zA-Z0-9-
                // but, .+ and other chars are often used for {{int:}} hacks
                // see bugs 37564, 37587, 36938
-               $return =
+               $cache[$code] =
                        strcspn( $code, ":/\\\000&<>'\"" ) === strlen( $code )
                        && !preg_match( Title::getTitleInvalidRegex(), $code );
-               $cache[ $code ] = $return;
-               return $return;
+
+               return $cache[$code];
        }
 
        /**
index 38e6956..878da42 100644 (file)
@@ -31,8 +31,8 @@ class DeleteEqualMessages extends Maintenance {
        public function __construct() {
                parent::__construct();
                $this->mDescription = "Deletes all pages in the MediaWiki namespace that are equal to the default message";
-               $this->addOption( 'delete', 'Actually delete the pages' );
-               $this->addOption( 'delete-talk', 'Don\'t leave orphaned talk pages behind' );
+               $this->addOption( 'delete', 'Actually delete the pages (default: dry run)' );
+               $this->addOption( 'delete-talk', 'Don\'t leave orphaned talk pages behind during deletion' );
                $this->addOption( 'lang-code', 'Check for subpages of this lang-code (default: root page against content language)', false, true );
        }
 
@@ -96,10 +96,19 @@ class DeleteEqualMessages extends Maintenance {
                }
 
                $this->output( "\n{$relevantPages} pages in the MediaWiki namespace override messages." );
-               $this->output( "\n{$equalPages} pages are equal to the default message ({$equalPagesTalks} talk pages).\n" );
+               $this->output( "\n{$equalPages} pages are equal to the default message ({$equalPagesTalks} talk pages).\n" );
 
                if ( !$doDelete ) {
-                       $this->output( "\nRun the script again with --delete to delete these pages" );
+                       $list = '';
+                       foreach ( $results as $result ) {
+                               $title = Title::makeTitle( NS_MEDIAWIKI, $result['title'] );
+                               $list .= "* [[$title]]\n";
+                               if ( $result['hasTalk'] ) {
+                                       $title = Title::makeTitle( NS_MEDIAWIKI_TALK, $result['title'] );
+                                       $list .= "* [[$title]]\n";
+                               }
+                       }
+                       $this->output( "\nList:\n$list\nRun the script again with --delete to delete these pages" );
                        if ( $equalPagesTalks !== 0 ) {
                                $this->output( " (include --delete-talk to also delete the talk pages)" );
                        }
@@ -117,25 +126,27 @@ class DeleteEqualMessages extends Maintenance {
                $user->addGroup( 'bot' );
 
                // Handle deletion
-               $this->output( "\n...deleting equal messages (this may take a long time!)...", 'msg' );
+               $this->output( "\n...deleting equal messages (this may take a long time!)..." );
                $dbw = wfGetDB( DB_MASTER );
                foreach ( $results as $result ) {
                        wfWaitForSlaves();
                        $dbw->ping();
                        $dbw->begin( __METHOD__ );
                        $title = Title::makeTitle( NS_MEDIAWIKI, $result['title'] );
+                       $this->output( "\n* [[$title]]" );
                        $page = WikiPage::factory( $title );
                        $error = ''; // Passed by ref
                        $page->doDeleteArticle( 'No longer required', false, 0, false, $error, $user );
                        if ( $result['hasTalk'] && $doDeleteTalk ) {
                                $title = Title::makeTitle( NS_MEDIAWIKI_TALK, $result['title'] );
+                               $this->output( "\n* [[$title]]" );
                                $page = WikiPage::factory( $title );
                                $error = ''; // Passed by ref
                                $page->doDeleteArticle( 'Orphaned talk page of no longer required message', false, 0, false, $error, $user );
                        }
                        $dbw->commit( __METHOD__ );
                }
-               $this->output( "done!\n", 'msg' );
+               $this->output( "\n\ndone!\n" );
        }
 }
 
index c29c91c..97417c5 100644 (file)
@@ -9,6 +9,7 @@
                                        "mw.Map",
                                        "mw.Message",
                                        "mw.loader",
+                                       "mw.log",
                                        "mw.html",
                                        "mw.html.Cdata",
                                        "mw.html.Raw"
@@ -20,7 +21,7 @@
                                        "mw.Title",
                                        "mw.notification",
                                        "mw.util",
-                                       "mw.plugin.notify"
+                                       "mw.plugin.*"
                                ]
                        },
                        {
index e932b5c..4ad75f0 100644 (file)
@@ -9,6 +9,7 @@
        "--": [
                "./external.js",
                "../../resources/mediawiki/mediawiki.js",
+               "../../resources/mediawiki/mediawiki.log.js",
                "../../resources/mediawiki/mediawiki.util.js",
                "../../resources/mediawiki/mediawiki.Title.js",
                "../../resources/mediawiki/mediawiki.notify.js",
index 09fe06e..e1a07b6 100644 (file)
         */
        function toggleLinkPremade( $that, e, options ) {
                var $collapsible = $that.eq( 0 ).closest( '.mw-collapsible' );
-               options = $.extend( { toggleClasses: true }, options );
+               options = $.extend( { toggleClasses: true, linksPassthru: true }, options );
                togglingHandler( $that, $collapsible, e, options );
        }
 
         * @param {jQuery} $collapsible
         */
        function toggleLinkCustom( $that, e, options, $collapsible ) {
-               options = $.extend( { linksPassthru: true }, options );
                togglingHandler( $that, $collapsible, e, options );
        }
 
index 6c7e697..716264d 100644 (file)
@@ -267,10 +267,17 @@ var mw = ( function ( $, undefined ) {
                /* Public Members */
 
                /**
-                * Dummy function which in debug mode can be replaced with a function that
-                * emulates console.log in console-less environments.
+                * Dummy placeholder for {@link mw.log}
+                * @method
                 */
-               log: function () { },
+               log: ( function () {
+                       var log = function () {};
+                       log.warn = function () {};
+                       log.deprecate = function ( obj, key, val ) {
+                               obj[key] = val;
+                       };
+                       return log;
+               }() ),
 
                // Make the Map constructor publicly available.
                Map: Map,
@@ -294,8 +301,6 @@ var mw = ( function ( $, undefined ) {
                 */
                libs: {},
 
-               /* Extension points */
-
                /**
                 * @property
                 */
index ee08b12..75e4c96 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*!
  * Logger for MediaWiki javascript.
  * Implements the stub left by the main 'mediawiki' module.
  *
@@ -8,16 +8,21 @@
 
 ( function ( mw, $ ) {
 
+       /**
+        * @class mw.log
+        * @singleton
+        */
+
        /**
         * Logs a message to the console.
         *
         * In the case the browser does not have a console API, a console is created on-the-fly by appending
-        * a <div id="mw-log-console"> element to the bottom of the body and then appending this and future
+        * a `<div id="mw-log-console">` element to the bottom of the body and then appending this and future
         * messages to that, instead of the console.
         *
-        * @param {String} First in list of variadic messages to output to console.
+        * @param {string...} msg Messages to output to console.
         */
-       mw.log = function ( /* logmsg, logmsg, */ ) {
+       mw.log = function () {
                // Turn arguments into an array
                var     args = Array.prototype.slice.call( arguments ),
                        // Allow log messages to use a configured prefix to identify the source window (ie. frame)
@@ -54,7 +59,7 @@
                                hovzer.update();
                        }
                        $log.append(
-                               $( '<div></div>' )
+                               $( '<div>' )
                                        .css( {
                                                borderBottom: 'solid 1px #DDDDDD',
                                                fontSize: 'small',
                } );
        };
 
+       /**
+        * Write a message the console's warning channel.
+        * Also logs a stacktrace for easier debugging.
+        * Each action is silently ignored if the browser doesn't support it.
+        *
+        * @param {string...} msg Messages to output to console
+        */
+       mw.log.warn = function () {
+               var console = window.console;
+               if ( console && console.warn ) {
+                       console.warn.apply( console, arguments );
+                       if ( console.trace ) {
+                               console.trace();
+                       }
+               }
+       };
+
+       /**
+        * Create a property in a host object that, when accessed, will produce
+        * a deprecation warning in the console with backtrace.
+        *
+        * @param {Object} obj Host object of deprecated property
+        * @param {string} key Name of property to create in `obj`
+        * @param {Mixed} val The value this property should return when accessed
+        * @param {string} [msg] Optional text to include in the deprecation message.
+        */
+       mw.log.deprecate = !Object.defineProperty ? function ( obj, key, val ) {
+               obj[key] = val;
+       } : function ( obj, key, val, msg ) {
+               msg = 'MWDeprecationWarning: Use of "' + key + '" property is deprecated.' +
+                       ( msg ? ( ' ' + msg ) : '' );
+               try {
+                       Object.defineProperty( obj, key, {
+                               configurable: true,
+                               enumerable: true,
+                               get: function () {
+                                       mw.log.warn( msg );
+                                       return val;
+                               },
+                               set: function ( newVal ) {
+                                       mw.log.warn( msg );
+                                       val = newVal;
+                               }
+                       } );
+               } catch ( err ) {
+                       // IE8 can throw on Object.defineProperty
+                       obj[key] = val;
+               }
+       };
+
 }( mediaWiki, jQuery ) );
index 1f7d16d..833ece2 100644 (file)
@@ -162,9 +162,6 @@ img { border: none; }
 }
 
 /* preference page with js-genrated toc */
-#mw-pref-clear {
-       clear: both;
-}
 #preftoc {
        float: left;
        margin: 1em 1em 1em 1em;
index 26a7781..5c1b6b0 100644 (file)
@@ -546,6 +546,7 @@ table.collapsed tr.collapsable {
        float: left;
        margin-bottom: 2em;
        color: #000;
+       font-weight: bold;
 }
 .errorbox {
        border-color: red;
index 709cc33..65042ef 100644 (file)
@@ -113,18 +113,6 @@ window.appendCSS = function( text ) {
        return s;
 };
 
-// Special stylesheet links for Monobook only (see bug 14717)
-var skinpath = mw.config.get( 'stylepath' ) + '/' + mw.config.get( 'skin' );
-if ( mw.config.get( 'skin' ) === 'monobook' ) {
-       if ( opera6_bugs ) {
-               importStylesheetURI( skinpath + '/Opera6Fixes.css' );
-       } else if ( opera7_bugs ) {
-               importStylesheetURI( skinpath + '/Opera7Fixes.css' );
-       } else if ( opera95_bugs ) {
-               importStylesheetURI( skinpath + '/Opera9Fixes.css' );
-       }
-}
-
 if ( mw.config.get( 'wgBreakFrames' ) ) {
        // Un-trap us from framesets
        if ( window.top != window ) {
index f201209..7e7758a 100644 (file)
@@ -412,11 +412,6 @@ h1, h2, h3, h4, h5, h6 {
        text-decoration: none;
        color: white;
 }
-
-#mw-pref-clear {
-       clear: both;
-}
-
 #mw_content a.external,
 #mw_content a.external[href ^="gopher://"] {
        /* @embed */
diff --git a/skins/monobook/Opera6Fixes.css b/skins/monobook/Opera6Fixes.css
deleted file mode 100644 (file)
index 77dec09..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* opera 6 fixes */
-div#column-one {
-       position: relative;
-       max-width: 11.7em;
-}
-#p-personal {
-       width: 45em;
-       margin-left: 8.6em;
-       right: 0;
-}
-#bodyContent a.external {
-       background: url(external.png) center right no-repeat;
-       padding-right: 13px;
-}
-
-.rtl a.feedlink {
-       background-position: right;
-       padding-right: 0;
-       padding-left: 16px;
-}
diff --git a/skins/monobook/Opera7Fixes.css b/skins/monobook/Opera7Fixes.css
deleted file mode 100644 (file)
index 1dcba7c..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/* small tweaks for opera seven */
-#p-cactions {
-       margin-top: .1em;
-}
-#p-cactions li a {
-       top: 2px;
-}
-#bodyContent a.external {
-       background: url(external.png) center right no-repeat;
-       padding-right: 13px;
-}
-.rtl #bodyContent a.external {
-       background-image: url(external-rtl.png);
-       padding-right: 13px;
-}
-
-.rtl a.feedlink {
-       background-position: right;
-       padding-right: 0;
-       padding-left: 16px;
-}
diff --git a/skins/monobook/Opera9Fixes.css b/skins/monobook/Opera9Fixes.css
deleted file mode 100644 (file)
index 9c312a8..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-.rtl #bodyContent a.external {
-       background-image: url(external-rtl.png);
-       padding-right: 13px;
-       padding-left: 0;
-}
-
-.rtl a.feedlink {
-       background-position: right;
-       padding-right: 0;
-       padding-left: 16px;
-}
index 9f34bee..7ae743c 100644 (file)
                $collapsible.find( '.mw-collapsible-toggle' ).trigger( 'click' );
        } );
 
+       QUnit.test( 'premade toggler - options.linksPassthru' , 2, function ( assert ) {
+               var $collapsible, $content;
+
+               $collapsible = prepareCollapsible(
+                       '<div class="mw-collapsible">' +
+                               '<div class="mw-collapsible-toggle">' +
+                                       'Toggle <a href="#top">toggle</a> toggle <b>toggle</b>' +
+                               '</div>' +
+                               '<div class="mw-collapsible-content">' + loremIpsum + '</div>' +
+                       '</div>',
+                       // Can't do asynchronous because we're testing that the event *doesn't* happen
+                       { instantHide: true }
+               );
+               $content = $collapsible.find( '.mw-collapsible-content' );
+
+               $collapsible.find( '.mw-collapsible-toggle a' ).trigger( 'click' );
+               assert.assertTrue( $content.is( ':visible' ), 'click event on link inside toggle passes through (content not toggled)' );
+
+               $collapsible.find( '.mw-collapsible-toggle b' ).trigger( 'click' );
+               assert.assertTrue( $content.is( ':hidden' ), 'click event on non-link inside toggle toggles content' );
+       } );
+
 }( mediaWiki, jQuery ) );