Merge "Make DateFormatter::getInstance use APC"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Mon, 26 Oct 2015 17:46:53 +0000 (17:46 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Mon, 26 Oct 2015 17:46:53 +0000 (17:46 +0000)
18 files changed:
autoload.php
includes/Linker.php
includes/User.php
includes/api/ApiQuerySiteinfo.php
includes/exception/ErrorPageError.php
includes/installer/Installer.php
includes/installer/LocalSettingsGenerator.php
includes/installer/WebInstallerPage.php
includes/libs/composer/ComposerInstalled.php [new file with mode: 0644]
includes/media/TransformationalImageHandler.php
includes/page/ImagePage.php
includes/specials/SpecialVersion.php
includes/upload/UploadStash.php
mw-config/config.js
resources/src/mediawiki.special/mediawiki.special.upload.js
resources/src/mediawiki.ui/components/buttons.less
resources/src/mediawiki.widgets/mw.widgets.TitleWidget.less
resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js

index 9b5e10f..731bdaa 100644 (file)
@@ -242,6 +242,7 @@ $wgAutoloadLocalClasses = array(
        'CompareParserCache' => __DIR__ . '/maintenance/compareParserCache.php',
        'CompareParsers' => __DIR__ . '/maintenance/compareParsers.php',
        'ComposerHookHandler' => __DIR__ . '/includes/composer/ComposerHookHandler.php',
+       'ComposerInstalled' => __DIR__ . '/includes/libs/composer/ComposerInstalled.php',
        'ComposerJson' => __DIR__ . '/includes/libs/composer/ComposerJson.php',
        'ComposerLock' => __DIR__ . '/includes/libs/composer/ComposerLock.php',
        'ComposerPackageModifier' => __DIR__ . '/includes/composer/ComposerPackageModifier.php',
index e821004..842d276 100644 (file)
@@ -1469,7 +1469,7 @@ class Linker {
                                                if ( $target->getText() == '' && !$target->isExternal()
                                                        && !$local && $title
                                                ) {
-                                                       $newTarget = clone ( $title );
+                                                       $newTarget = clone $title;
                                                        $newTarget->setFragment( '#' . $target->getFragment() );
                                                        $target = $newTarget;
                                                }
index 6e52a1d..e1c9e35 100644 (file)
@@ -185,21 +185,8 @@ class User implements IDBAccessObject {
        public $mName;
        /** @var string */
        public $mRealName;
-
-       /**
-        * These fields were marked "@private", but were defined as public to
-        * maintain compatibility with PHP4 code since PHP4 didn't support access
-        * restrictions. AuthManager makes password handling pluggable, meaning
-        * these fields don't make sense anymore. If this broke something, see
-        * T89459 for the context of the change.
-        * @deprecated These are mostly unused, but kept for now to raise errors on attempted access.
-        */
-       // @{
+       /** @var Password|null */
        private $mPassword = null;
-       private $mNewpassword;
-       private $mNewpassTime;
-       private $mPasswordExpires;
-       // @}
 
        /** @var string */
        public $mEmail;
@@ -4097,13 +4084,13 @@ class User implements IDBAccessObject {
                        __METHOD__
                );
                try {
-                       $mNewpassword = $passwordFactory->newFromCiphertext( $row->user_newpassword );
+                       $newPassword = $passwordFactory->newFromCiphertext( $row->user_newpassword );
                } catch ( PasswordError $e ) {
                        wfDebug( 'Invalid password hash found in database.' );
-                       $mNewpassword = PasswordFactory::newInvalidPassword();
+                       $newPassword = PasswordFactory::newInvalidPassword();
                }
 
-               if ( $mNewpassword->equals( $plaintext ) ) {
+               if ( $newPassword->equals( $plaintext ) ) {
                        if ( is_null( $row->user_newpass_time ) ) {
                                return true;
                        }
index 1265155..c13b30b 100644 (file)
@@ -540,18 +540,14 @@ class ApiQuerySiteinfo extends ApiQueryBase {
 
        protected function appendInstalledLibraries( $property ) {
                global $IP;
-               $path = "$IP/composer.lock";
+               $path = "$IP/vendor/composer/installed.json";
                if ( !file_exists( $path ) ) {
-                       // Maybe they're using mediawiki/vendor?
-                       $path = "$IP/vendor/composer.lock";
-                       if ( !file_exists( $path ) ) {
-                               return true;
-                       }
+                       return true;
                }
 
                $data = array();
-               $lock = new ComposerLock( $path );
-               foreach ( $lock->getInstalledDependencies() as $name => $info ) {
+               $installed = new ComposerInstalled( $path );
+               foreach ( $installed->getInstalledDependencies() as $name => $info ) {
                        if ( strpos( $info['type'], 'mediawiki-' ) === 0 ) {
                                // Skip any extensions or skins since they'll be listed
                                // in their proper section
index 3631a34..6366c74 100644 (file)
@@ -44,7 +44,7 @@ class ErrorPageError extends MWException {
                // passing to the parent constructor. Our overridden report() below
                // makes sure that the page shown to the user is not forced to English.
                if ( $msg instanceof Message ) {
-                       $enMsg = clone( $msg );
+                       $enMsg = clone $msg;
                } else {
                        $enMsg = wfMessage( $msg, $params );
                }
index 91589e1..ba0e38f 100644 (file)
@@ -164,7 +164,6 @@ abstract class Installer {
                'wgRightsIcon',
                'wgRightsText',
                'wgRightsUrl',
-               'wgMainCacheType',
                'wgEnableEmail',
                'wgEnableUserEmail',
                'wgEnotifUserTalk',
index 526d9b5..b742074 100644 (file)
@@ -62,8 +62,8 @@ class LocalSettingsGenerator {
                                'wgLanguageCode', 'wgEnableEmail', 'wgEnableUserEmail', 'wgDiff3',
                                'wgEnotifUserTalk', 'wgEnotifWatchlist', 'wgEmailAuthentication',
                                'wgDBtype', 'wgSecretKey', 'wgRightsUrl', 'wgSitename', 'wgRightsIcon',
-                               'wgRightsText', 'wgMainCacheType', 'wgEnableUploads',
-                               'wgMainCacheType', '_MemCachedServers', 'wgDBserver', 'wgDBuser',
+                               'wgRightsText', '_MainCacheType', 'wgEnableUploads',
+                               '_MemCachedServers', 'wgDBserver', 'wgDBuser',
                                'wgDBpassword', 'wgUseInstantCommons', 'wgUpgradeKey', 'wgDefaultSkin',
                                'wgMetaNamespace', 'wgLogo',
                        ),
@@ -290,12 +290,12 @@ class LocalSettingsGenerator {
                        $serverSetting .= "\$wgServer = \"{$this->values['wgServer']}\";";
                }
 
-               switch ( $this->values['wgMainCacheType'] ) {
+               switch ( $this->values['_MainCacheType'] ) {
                        case 'anything':
                        case 'db':
                        case 'memcached':
                        case 'accel':
-                               $cacheType = 'CACHE_' . strtoupper( $this->values['wgMainCacheType'] );
+                               $cacheType = 'CACHE_' . strtoupper( $this->values['_MainCacheType'] );
                                break;
                        case 'none':
                        default:
index 0d11463..191c752 100644 (file)
@@ -1131,7 +1131,7 @@ class WebInstallerOptions extends WebInstallerPage {
                $caches[] = 'memcached';
 
                // We'll hide/show this on demand when the value changes, see config.js.
-               $cacheval = $this->getVar( 'wgMainCacheType' );
+               $cacheval = $this->getVar( '_MainCacheType' );
                if ( !$cacheval ) {
                        // We need to set a default here; but don't hardcode it
                        // or we lose it every time we reload the page for validation
@@ -1147,7 +1147,7 @@ class WebInstallerOptions extends WebInstallerPage {
                        // For grep: The following messages are used as the item labels:
                        // config-cache-none, config-cache-accel, config-cache-memcached
                        $this->parent->getRadioSet( array(
-                               'var' => 'wgMainCacheType',
+                               'var' => '_MainCacheType',
                                'label' => 'config-cache-options',
                                'itemLabelPrefix' => 'config-cache-',
                                'values' => $caches,
@@ -1285,7 +1285,7 @@ class WebInstallerOptions extends WebInstallerPage {
                $this->parent->setVarsFromRequest( array( '_RightsProfile', '_LicenseCode',
                        'wgEnableEmail', 'wgPasswordSender', 'wgEnableUploads', 'wgLogo',
                        'wgEnableUserEmail', 'wgEnotifUserTalk', 'wgEnotifWatchlist',
-                       'wgEmailAuthentication', 'wgMainCacheType', '_MemCachedServers',
+                       'wgEmailAuthentication', '_MainCacheType', '_MemCachedServers',
                        'wgUseInstantCommons', 'wgDefaultSkin' ) );
 
                $retVal = true;
@@ -1351,7 +1351,7 @@ class WebInstallerOptions extends WebInstallerPage {
                }
                $this->parent->setVar( '_Extensions', $extsToInstall );
 
-               if ( $this->getVar( 'wgMainCacheType' ) == 'memcached' ) {
+               if ( $this->getVar( '_MainCacheType' ) == 'memcached' ) {
                        $memcServers = explode( "\n", $this->getVar( '_MemCachedServers' ) );
                        if ( !$memcServers ) {
                                $this->parent->showError( 'config-memcache-needservers' );
diff --git a/includes/libs/composer/ComposerInstalled.php b/includes/libs/composer/ComposerInstalled.php
new file mode 100644 (file)
index 0000000..5f87b54
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * Reads an installed.json file and provides accessors to get what is
+ * installed
+ *
+ * @since 1.27
+ */
+class ComposerInstalled {
+
+       /**
+        * @param string $location
+        */
+       public function __construct( $location ) {
+               $this->contents = json_decode( file_get_contents( $location ), true );
+       }
+
+       /**
+        * Dependencies currently installed according to installed.json
+        *
+        * @return array
+        */
+       public function getInstalledDependencies() {
+               $deps = array();
+               foreach ( $this->contents as $installed ) {
+                       $deps[$installed['name']] = array(
+                               'version' => ComposerJson::normalizeVersion( $installed['version'] ),
+                               'type' => $installed['type'],
+                               'licenses' => isset( $installed['license'] ) ? $installed['license'] : array(),
+                               'authors' => isset( $installed['authors'] ) ? $installed['authors'] : array(),
+                               'description' => isset( $installed['description'] ) ? $installed['description']: '',
+                       );
+               }
+
+               ksort( $deps );
+               return $deps;
+       }
+}
index 15753a9..3558149 100644 (file)
@@ -505,30 +505,31 @@ abstract class TransformationalImageHandler extends ImageHandler {
         * Retrieve the version of the installed ImageMagick
         * You can use PHPs version_compare() to use this value
         * Value is cached for one hour.
-        * @return string Representing the IM version.
+        * @return string|bool Representing the IM version; false on error
         */
        protected function getMagickVersion() {
-               global $wgMemc;
-
-               $cache = $wgMemc->get( "imagemagick-version" );
-               if ( !$cache ) {
-                       global $wgImageMagickConvertCommand;
-                       $cmd = wfEscapeShellArg( $wgImageMagickConvertCommand ) . ' -version';
-                       wfDebug( __METHOD__ . ": Running convert -version\n" );
-                       $retval = '';
-                       $return = wfShellExec( $cmd, $retval );
-                       $x = preg_match( '/Version: ImageMagick ([0-9]*\.[0-9]*\.[0-9]*)/', $return, $matches );
-                       if ( $x != 1 ) {
-                               wfDebug( __METHOD__ . ": ImageMagick version check failed\n" );
-
-                               return null;
+               return ObjectCache::newAccelerator( CACHE_NONE )->getWithSetCallback(
+                       "imagemagick-version",
+                       3600,
+                       function () {
+                               global $wgImageMagickConvertCommand;
+
+                               $cmd = wfEscapeShellArg( $wgImageMagickConvertCommand ) . ' -version';
+                               wfDebug( __METHOD__ . ": Running convert -version\n" );
+                               $retval = '';
+                               $return = wfShellExec( $cmd, $retval );
+                               $x = preg_match(
+                                       '/Version: ImageMagick ([0-9]*\.[0-9]*\.[0-9]*)/', $return, $matches
+                               );
+                               if ( $x != 1 ) {
+                                       wfDebug( __METHOD__ . ": ImageMagick version check failed\n" );
+
+                                       return false;
+                               }
+
+                               return $matches[1];
                        }
-                       $wgMemc->set( "imagemagick-version", $matches[1], 3600 );
-
-                       return $matches[1];
-               }
-
-               return $cache;
+               );
        }
 
        /**
index 7957e65..3638aed 100644 (file)
@@ -1533,7 +1533,7 @@ class ImageHistoryPseudoPager extends ReverseChronologicalPager {
        function __construct( $imagePage ) {
                parent::__construct( $imagePage->getContext() );
                $this->mImagePage = $imagePage;
-               $this->mTitle = clone ( $imagePage->getTitle() );
+               $this->mTitle = clone $imagePage->getTitle();
                $this->mTitle->setFragment( '#filehistory' );
                $this->mImg = null;
                $this->mHist = array();
index 38baf5b..7e0f0b2 100644 (file)
@@ -518,16 +518,12 @@ class SpecialVersion extends SpecialPage {
         */
        protected function getExternalLibraries() {
                global $IP;
-               $path = "$IP/composer.lock";
+               $path = "$IP/vendor/composer/installed.json";
                if ( !file_exists( $path ) ) {
-                       // Maybe they're using mediawiki/vendor?
-                       $path = "$IP/vendor/composer.lock";
-                       if ( !file_exists( $path ) ) {
-                               return '';
-                       }
+                       return '';
                }
 
-               $lock = new ComposerLock( $path );
+               $installed = new ComposerInstalled( $path );
                $out = Html::element(
                        'h2',
                        array( 'id' => 'mw-version-libraries' ),
@@ -545,7 +541,7 @@ class SpecialVersion extends SpecialPage {
                        . Html::element( 'th', array(), $this->msg( 'version-libraries-authors' )->text() )
                        . Html::closeElement( 'tr' );
 
-               foreach ( $lock->getInstalledDependencies() as $name => $info ) {
+               foreach ( $installed->getInstalledDependencies() as $name => $info ) {
                        if ( strpos( $info['type'], 'mediawiki-' ) === 0 ) {
                                // Skip any extensions or skins since they'll be listed
                                // in their proper section
index b971c00..e241383 100644 (file)
@@ -54,6 +54,7 @@
 class UploadStash {
        // Format of the key for files -- has to be suitable as a filename itself (e.g. ab12cd34ef.jpg)
        const KEY_FORMAT_REGEX = '/^[\w-\.]+\.\w*$/';
+       const MAX_US_PROPS_SIZE = 65535;
 
        /**
         * repository that this uses to store temp files
@@ -277,13 +278,22 @@ class UploadStash {
                wfDebug( __METHOD__ . " inserting $stashPath under $key\n" );
                $dbw = $this->repo->getMasterDb();
 
+               $serializedFileProps = serialize( $fileProps );
+               if ( strlen( $serializedFileProps ) > self::MAX_US_PROPS_SIZE ) {
+                       // Database is going to truncate this and make the field invalid.
+                       // Prioritize important metadata over file handler metadata.
+                       // File handler should be prepared to regenerate invalid metadata if needed.
+                       $fileProps['metadata'] = false;
+                       $serializedFileProps = serialize( $fileProps );
+               }
+
                $this->fileMetadata[$key] = array(
                        'us_id' => $dbw->nextSequenceValue( 'uploadstash_us_id_seq' ),
                        'us_user' => $this->userId,
                        'us_key' => $key,
                        'us_orig_path' => $path,
                        'us_path' => $stashPath, // virtual URL
-                       'us_props' => $dbw->encodeBlob( serialize( $fileProps ) ),
+                       'us_props' => $dbw->encodeBlob( $serializedFileProps ),
                        'us_size' => $fileProps['size'],
                        'us_sha1' => $fileProps['sha1'],
                        'us_mime' => $fileProps['mime'],
index fb637f7..8b2d6e5 100644 (file)
@@ -96,9 +96,9 @@
                $( '#config_wgSitename' ).on( 'keyup change', syncText ).each( syncText );
 
                // Show/Hide memcached servers when needed
-               $( 'input[name$="config_wgMainCacheType"]' ).change( function () {
+               $( 'input[name$="config__MainCacheType"]' ).change( function () {
                        var $memc = $( '#config-memcachewrapper' );
-                       if ( $( 'input[name$="config_wgMainCacheType"]:checked' ).val() === 'memcached' ) {
+                       if ( $( 'input[name$="config__MainCacheType"]:checked' ).val() === 'memcached' ) {
                                $memc.show( 'slow' );
                        } else {
                                $memc.hide( 'slow' );
index 9fcec02..8c89ed9 100644 (file)
@@ -85,7 +85,9 @@
                },
 
                setWarning: function ( warning ) {
-                       $( '#wpDestFile-warning' ).html( warning );
+                       var $warning = $( $.parseHTML( warning ) );
+                       mw.hook( 'wikipage.content' ).fire( $warning );
+                       $( '#wpDestFile-warning' ).empty().append( $warning );
 
                        // Set a value in the form indicating that the warning is acknowledged and
                        // doesn't need to be redisplayed post-upload
index 77b3f9d..d66973a 100644 (file)
@@ -243,6 +243,12 @@ a.mw-ui-button {
        &:focus {
                text-decoration: none;
        }
+
+       // a-tags behave different to inputs if the line-height attribute is inherited
+       // from another element (e.g. mw-body-content). They appear bigger as input
+       // tags. See Bug T116427. To fix that, apply the correct line-height (used
+       // for inputs) to a-tags, too.
+       line-height: normal;
 }
 
 // Button groups
index 2eb8c55..86d4cfe 100644 (file)
@@ -22,7 +22,7 @@
                        min-height: 3.75em;
                        padding-left: 4.75em;
 
-                       &:not(:last-child) {
+                       &:not( :last-child ) {
                                margin-bottom: 2px;
                        }
 
                        }
 
                        &.oo-ui-iconElement {
-                               >.oo-ui-iconElement-icon {
+                               > .oo-ui-iconElement-icon {
                                        display: block;
                                        width: 3.75em;
                                        height: 3.75em;
                                        left: 0;
-                                       background-color: #ccc;
-                                       opacity: 0.4;
-                               }
-
-                               > .mw-widget-titleOptionWidget-hasImage {
-                                       border: 0;
-                                       background-size: cover;
-                                       opacity: 0.7;
+                                       &:not( .mw-widget-titleOptionWidget-hasImage ) {
+                                               background-color: #ccc;
+                                               opacity: 0.4;
+                                       }
+                                       &.mw-widget-titleOptionWidget-hasImage {
+                                               border: 0;
+                                               background-size: cover;
+                                               opacity: 0.7;
+                                       }
                                }
                        }
-               }
 
-               &.oo-ui-optionWidget-highlighted, &.oo-ui-optionWidget-selected {
-                       &.oo-ui-iconElement > .mw-widget-titleOptionWidget-hasImage {
-                               opacity: 1;
+                       &.oo-ui-optionWidget-highlighted, &.oo-ui-optionWidget-selected {
+                               &.oo-ui-iconElement > .mw-widget-titleOptionWidget-hasImage {
+                                       opacity: 1;
+                               }
                        }
                }
        }
index 86fb91b..01917f8 100644 (file)
         * @inheritdoc
         */
        mw.ForeignStructuredUpload.BookletLayout.prototype.getText = function () {
-               this.upload.addDescription( 'en', this.descriptionWidget.getValue() );
+               var language = mw.config.get( 'wgContentLanguage' );
+               this.upload.addDescription( language, this.descriptionWidget.getValue() );
                this.upload.setDate( this.dateWidget.getValue() );
                this.upload.addCategories( this.categoriesWidget.getItemsData() );
                return this.upload.getText();