Merge "Generate thumbnails based on buckets"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 9 Jul 2014 14:09:02 +0000 (14:09 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 9 Jul 2014 14:09:02 +0000 (14:09 +0000)
1  2 
includes/DefaultSettings.php
includes/media/Bitmap.php
includes/media/MediaHandler.php

@@@ -1217,6 -1217,33 +1217,33 @@@ $wgThumbLimits = array
        300
  );
  
+ /**
+  * When defined, is an array of image widths used as buckets for thumbnail generation.
+  * The goal is to save resources by generating thumbnails based on reference buckets instead of
+  * always using the original. This will incur a speed gain but cause a quality loss.
+  *
+  * The buckets generation is chained, with each bucket generated based on the above bucket
+  * when possible. File handlers have to opt into using that feature. For now only BitmapHandler
+  * supports it.
+  */
+ $wgThumbnailBuckets = null;
+ /**
+  * When using thumbnail buckets as defined above, this sets the minimum distance with the bucket
+  * above the requested size. The distance represents how pany extra pixels of width the bucket needs
+  * in order to be used as the reference for a given thumbnail. For example, with the following buckets:
+  *
+  * $wgThumbnailBuckets = array ( 128, 256, 512 );
+  *
+  * and a distance of 50:
+  *
+  * $wgThumbnailMinimumBucketDistance = 50;
+  *
+  * If we want to render a thumbnail of width 220px, the 512px bucket will be used,
+  * because 220 + 50 = 270 and the closest bucket bigger than 270px is 512.
+  */
+ $wgThumbnailMinimumBucketDistance = 0;
  /**
   * Default parameters for the "<gallery>" tag
   */
@@@ -1281,7 -1308,7 +1308,7 @@@ $wgDjvuTxt = null
   * Path of the djvutoxml executable
   * This works like djvudump except much, much slower as of version 3.5.
   *
 - * For now we  recommend you use djvudump instead. The djvuxml output is
 + * For now we recommend you use djvudump instead. The djvuxml output is
   * probably more stable, so we'll switch back to it as soon as they fix
   * the efficiency problem.
   * http://sourceforge.net/tracker/index.php?func=detail&aid=1704049&group_id=32953&atid=406583
@@@ -1295,7 -1322,7 +1322,7 @@@ $wgDjvuToXML = null
  
  /**
   * Shell command for the DJVU post processor
 - * Default: pnmtopng, since ddjvu generates ppm output
 + * Default: pnmtojpeg, since ddjvu generates ppm output
   * Set this to false to output the ppm file directly.
   */
  $wgDjvuPostProcessor = 'pnmtojpeg';
@@@ -1514,7 -1541,7 +1541,7 @@@ $wgUsersNotifiedOnAllChanges = array()
  $wgDBserver = 'localhost';
  
  /**
 - * Database port number (for PostgreSQL)
 + * Database port number (for PostgreSQL and Microsoft SQL Server).
   */
  $wgDBport = 5432;
  
@@@ -1540,21 -1567,11 +1567,21 @@@ $wgDBtype = 'mysql'
  
  /**
   * Whether to use SSL in DB connection.
 + *
 + * This setting is only used $wgLBFactoryConf['class'] is set to
 + * 'LBFactorySimple' and $wgDBservers is an empty array; otherwise
 + * the DBO_SSL flag must be set in the 'flags' option of the database
 + * connection to achieve the same functionality.
   */
  $wgDBssl = false;
  
  /**
   * Whether to use compression in DB connection.
 + *
 + * This setting is only used $wgLBFactoryConf['class'] is set to
 + * 'LBFactorySimple' and $wgDBservers is an empty array; otherwise
 + * the DBO_COMPRESS flag must be set in the 'flags' option of the database
 + * connection to achieve the same functionality.
   */
  $wgDBcompress = false;
  
@@@ -1662,7 -1679,7 +1689,7 @@@ $wgSharedTables = array( 'user', 'user_
   *   - dbname:      Default database name
   *   - user:        DB user
   *   - password:    DB password
 - *   - type:        "mysql" or "postgres"
 + *   - type:        DB type
   *
   *   - load:        Ratio of DB_SLAVE load, must be >=0, the sum of all loads must be >0.
   *                  If this is zero for any given server, no normal query traffic will be
@@@ -1720,7 -1737,6 +1747,7 @@@ $wgLBFactoryConf = array( 'class' => 'L
  
  /**
   * How long to wait for a slave to catch up to the master
 + * @deprecated since 1.24
   */
  $wgMasterWaitTimeout = 10;
  
@@@ -1749,6 -1765,11 +1776,6 @@@ $wgDBerrorLog = false
   */
  $wgDBerrorLogTZ = false;
  
 -/**
 - * When to give an error message
 - */
 -$wgDBClusterTimeout = 10;
 -
  /**
   * Scale load balancer polling time so that under overload conditions, the
   * database server receives a SHOW STATUS query at an average interval of this
@@@ -2163,12 -2184,6 +2190,12 @@@ $wgCachePages = true
   */
  $wgCacheEpoch = '20030516000000';
  
 +/**
 + * Directory where GitInfo will look for pre-computed cache files. If false,
 + * $wgCacheDirectory/gitinfo will be used.
 + */
 +$wgGitInfoCacheDirectory = false;
 +
  /**
   * Bump this number when changing the global style sheets and JavaScript.
   *
@@@ -2520,21 -2535,6 +2547,21 @@@ $wgInterwikiMagic = true
   */
  $wgHideInterlanguageLinks = false;
  
 +/**
 + * List of additional interwiki prefixes that should be treated as
 + * interlanguage links (i.e. placed in the sidebar).
 + * Notes:
 + * - This will not do anything unless the prefixes are defined in the interwiki
 + *   map.
 + * - The display text for these custom interlanguage links will be fetched from
 + *   the system message "interlanguage-link-xyz" where xyz is the prefix in
 + *   this array.
 + * - A friendly name for each site, used for tooltip text, may optionally be
 + *   placed in the system message "interlanguage-link-sitename-xyz" where xyz is
 + *   the prefix in this array.
 + */
 +$wgExtraInterlanguageLinkPrefixes = array();
 +
  /**
   * List of language names or overrides for default names in Names.php
   */
@@@ -3248,15 -3248,6 +3275,15 @@@ $wgResourceLoaderMinifierMaxLineLength 
   */
  $wgIncludeLegacyJavaScript = true;
  
 +/**
 + * Whether to include the jQuery Migrate library, which lets legacy JS that
 + * requires jQuery 1.8.x to work and breaks with 1.9.x+.
 + *
 + * @since 1.24
 + * @deprecated since 1.24, to be removed in 1.25
 + */
 +$wgIncludejQueryMigrate = false;
 +
  /**
   * Whether to preload the mediawiki.util module as blocking module in the top
   * queue.
@@@ -4368,7 -4359,6 +4395,7 @@@ $wgGroupPermissions['sysop']['noratelim
  $wgGroupPermissions['sysop']['movefile'] = true;
  $wgGroupPermissions['sysop']['unblockself'] = true;
  $wgGroupPermissions['sysop']['suppressredirect'] = true;
 +#$wgGroupPermissions['sysop']['pagelang'] = true;
  #$wgGroupPermissions['sysop']['upload_by_url'] = true;
  #$wgGroupPermissions['sysop']['mergehistory'] = true;
  
@@@ -4854,6 -4844,11 +4881,6 @@@ $wgSecretKey = false
   */
  $wgProxyList = array();
  
 -/**
 - * @deprecated since 1.14
 - */
 -$wgProxyKey = false;
 -
  /** @} */ # end of proxy scanner settings
  
  /************************************************************************//**
@@@ -4987,12 -4982,7 +5014,12 @@@ $wgDebugComments = false
  $wgDebugDBTransactions = false;
  
  /**
 - * Write SQL queries to the debug log
 + * Write SQL queries to the debug log.
 + *
 + * This setting is only used $wgLBFactoryConf['class'] is set to
 + * 'LBFactorySimple' and $wgDBservers is an empty array; otherwise
 + * the DBO_DEBUG flag must be set in the 'flags' option of the database
 + * connection to achieve the same functionality.
   */
  $wgDebugDumpSql = false;
  
@@@ -5221,6 -5211,21 +5248,6 @@@ $wgParserTestFiles = array
        "$IP/tests/parser/extraParserTests.txt"
  );
  
 -/**
 - * If configured, specifies target CodeReview installation to send test
 - * result data from 'parserTests.php --upload'
 - *
 - * Something like this:
 - * $wgParserTestRemote = array(
 - *     'api-url' => 'https://www.mediawiki.org/w/api.php',
 - *     'repo'    => 'MediaWiki',
 - *     'suite'   => 'ParserTests',
 - *     'path'    => '/trunk/phase3', // not used client-side; for reference
 - *     'secret'  => 'qmoicj3mc4mcklmqw', // Shared secret used in HMAC validation
 - * );
 - */
 -$wgParserTestRemote = false;
 -
  /**
   * Allow running of javascript test suites via [[Special:JavaScriptTest]] (such as QUnit).
   */
@@@ -5284,6 -5289,18 +5311,6 @@@ $wgAdvancedSearchHighlighting = false
   */
  $wgSearchHighlightBoundaries = '[\p{Z}\p{P}\p{C}]';
  
 -/**
 - * Set to true to have the search engine count total
 - * search matches to present in the Special:Search UI.
 - * Not supported by every search engine shipped with MW.
 - *
 - * This could however be slow on larger wikis, and is pretty flaky
 - * with the current title vs content split. Recommend avoiding until
 - * that's been worked out cleanly; but this may aid in testing the
 - * search UI and API to confirm that the result count works.
 - */
 -$wgCountTotalSearchHits = false;
 -
  /**
   * Template for OpenSearch suggestions, defaults to API action=opensearch
   *
@@@ -5595,11 -5612,9 +5622,11 @@@ $wgRC2UDPOmitBots = false
   * Destinations to which notifications about recent changes
   * should be sent.
   *
 - * As of MediaWiki 1.22, the only supported 'engine' parameter option in core
 - * is 'UDPRCFeedEngine', which is used to send recent changes over UDP to the
 - * specified server.
 + * As of MediaWiki 1.22, there are 2 supported 'engine' parameter option in core:
 + *   * 'UDPRCFeedEngine', which is used to send recent changes over UDP to the
 + *      specified server.
 + *   * 'RedisPubSubFeedEngine', which is used to send recent changes to Redis.
 + *
   * The common options are:
   *   * 'uri' -- the address to which the notices are to be sent.
   *   * 'formatter' -- the class name (implementing RCFeedFormatter) which will
   *   * 'omit_user' -- whether edits by registered users should be in the feed
   *   * 'omit_minor' -- whether minor edits should be in the feed
   *   * 'omit_patrolled' -- whether patrolled edits should be in the feed
 + *
   *  The IRC-specific options are:
   *   * 'add_interwiki_prefix' -- whether the titles should be prefixed with
   *     the first entry in the $wgLocalInterwikis array (or the value of
   *     $wgLocalInterwiki, if set)
 + *
   *  The JSON-specific options are:
   *   * 'channel' -- if set, the 'channel' parameter is also set in JSON values.
   *
@@@ -5646,6 -5659,13 +5673,6 @@@ $wgRCEngines = array
        'udp' => 'UDPRCFeedEngine',
  );
  
 -/**
 - * Enable user search in Special:Newpages
 - * This is really a temporary hack around an index install bug on some Wikipedias.
 - * Kill it once fixed.
 - */
 -$wgEnableNewpagesUserFilter = true;
 -
  /**
   * Use RC Patrolling to check for vandalism
   */
@@@ -5779,42 -5799,24 +5806,42 @@@ $wgUnwatchedPageThreshold = false
   * To register a new one:
   * @code
   * $wgRecentChangesFlags['flag'] => array(
 + *   // message for the letter displayed next to rows on changes lists
   *   'letter' => 'letter-msg',
 - *   'title' => 'tooltip-msg'
 + *   // message for the tooltip of the letter
 + *   'title' => 'tooltip-msg',
 + *   // optional (defaults to 'tooltip-msg'), message to use in the legend box
 + *   'legend' => 'legend-msg',
 + *   // optional (defaults to 'flag'), CSS class to put on changes lists rows
 + *   'class' => 'css-class',
   * );
   * @endcode
   *
 - * Optional 'class' allows to set a css class different than the flag name.
 - *
   * @since 1.22
   */
  $wgRecentChangesFlags = array(
 -      'newpage' => array( 'letter' => 'newpageletter',
 -              'title' => 'recentchanges-label-newpage' ),
 -      'minor' => array( 'letter' => 'minoreditletter',
 -              'title' => 'recentchanges-label-minor', 'class' => 'minoredit' ),
 -      'bot' => array( 'letter' => 'boteditletter',
 -              'title' => 'recentchanges-label-bot', 'class' => 'botedit' ),
 -      'unpatrolled' => array( 'letter' => 'unpatrolledletter',
 -              'title' => 'recentchanges-label-unpatrolled' ),
 +      'newpage' => array(
 +              'letter' => 'newpageletter',
 +              'title' => 'recentchanges-label-newpage',
 +              'legend' => 'recentchanges-legend-newpage',
 +      ),
 +      'minor' => array(
 +              'letter' => 'minoreditletter',
 +              'title' => 'recentchanges-label-minor',
 +              'legend' => 'recentchanges-legend-minor',
 +              'class' => 'minoredit',
 +      ),
 +      'bot' => array(
 +              'letter' => 'boteditletter',
 +              'title' => 'recentchanges-label-bot',
 +              'legend' => 'recentchanges-legend-bot',
 +              'class' => 'botedit',
 +      ),
 +      'unpatrolled' => array(
 +              'letter' => 'unpatrolledletter',
 +              'title' => 'recentchanges-label-unpatrolled',
 +              'legend' => 'recentchanges-legend-unpatrolled',
 +      ),
  );
  
  /** @} */ # end RC/watchlist }
@@@ -6082,7 -6084,6 +6109,7 @@@ $wgAutoloadAttemptLowercase = true
   * $wgExtensionCredits[$type][] = array(
   *     'path' => __FILE__,
   *     'name' => 'Example extension',
 + *     'namemsg' => 'exampleextension-name',
   *     'author' => array(
   *         'Foo Barstein',
   *     ),
   *    'skin', 'api', or 'other', or any additional types as specified through the
   *    ExtensionTypes hook as used in SpecialVersion::getExtensionTypes().
   *
 + * - name: Name of extension as an inline string instead of localizable message.
 + *    Do not omit this even if 'namemsg' is provided, as it is used to override
 + *    the path Special:Version uses to find extension's license info, and is
 + *    required for backwards-compatibility with MediaWiki 1.23 and older.
 + *
 + * - namemsg (since MW 1.24): A message key for a message containing the
 + *    extension's name, if the name is localizable. (For example, skin names
 + *    usually are.)
 + *
   * - author: A string or an array of strings. Authors can be linked using
   *    the regular wikitext link syntax. To have an internationalized version of
   *    "and others" show, add an element "...". This element can also be linked,
   *    for instance "[http://example ...]".
   *
   * - descriptionmsg: A message key or an an array with message key and parameters:
 - *    `'descriptionmsg' => array( 'exampleextension-desc', param1, param2, ... ),`
 + *    `'descriptionmsg' => 'exampleextension-desc',`
   *
 - * - description: Description of extension as inline string instead of
 + * - description: Description of extension as an inline string instead of
   *    localizable message (omit in favour of 'descriptionmsg').
   *
   * - license-name: Short name of the license (used as label for the link), such
@@@ -7102,24 -7094,6 +7129,24 @@@ $wgPagePropsHaveSortkey = true
   */
  $wgHttpsPort = 443;
  
 +/**
 + * Secret and algorithm for hmac-based key derivation function (fast,
 + * cryptographically secure random numbers).
 + * This should be set in LocalSettings.php, otherwise wgSecretKey will
 + * be used.
 + * @since 1.24
 + */
 +$wgHKDFSecret = false;
 +$wgHKDFAlgorithm = 'sha256';
 +
 +/**
 + * Enable page language feature
 + * Allows setting page language in database
 + * @var bool
 + * @since 1.24
 + */
 +$wgPageLanguageUseDB = false;
 +
  /**
   * For really cool vim folding this needs to be at the end:
   * vim: foldmarker=@{,@} foldmethod=marker
@@@ -117,6 -117,7 +117,7 @@@ class BitmapHandler extends ImageHandle
                if ( !$this->normaliseParams( $image, $params ) ) {
                        return new TransformParameterError( $params );
                }
                # Create a parameter array to pass to the scaler
                $scalerParams = array(
                        # The size to which the image will be resized
                }
  
                # Transform functions and binaries need a FS source file
-               $scalerParams['srcPath'] = $image->getLocalRefPath();
+               $thumbnailSource = $image->getThumbnailSource( $params );
+               $scalerParams['srcPath'] = $thumbnailSource['path'];
+               $scalerParams['srcWidth'] = $thumbnailSource['width'];
+               $scalerParams['srcHeight'] = $thumbnailSource['height'];
                if ( $scalerParams['srcPath'] === false ) { // Failed to get local copy
                        wfDebugLog( 'thumbnail',
                                sprintf( 'Thumbnail failed on %s: could not get local copy of "%s"',
                                }
                        }
                } elseif ( $params['mimeType'] == 'image/x-xcf' ) {
 -                      $animation_post = array( '-layers', 'merge' );
 +                      // Before merging layers, we need to set the background
 +                      // to be transparent to preserve alpha, as -layers merge
 +                      // merges all layers on to a canvas filled with the
 +                      // background colour. After merging we reset the background
 +                      // to be white for the default background colour setting
 +                      // in the PNG image (which is used in old IE)
 +                      $animation_post = array(
 +                              '-background', 'transparent',
 +                              '-layers', 'merge',
 +                              '-background', 'white',
 +                      );
 +                      wfSuppressWarnings();
 +                      $xcfMeta = unserialize( $image->getMetadata() );
 +                      wfRestoreWarnings();
 +                      if ( $xcfMeta
 +                              && isset( $xcfMeta['colorType'] )
 +                              && $xcfMeta['colorType'] === 'greyscale-alpha'
 +                              && version_compare( $this->getMagickVersion(), "6.8.9-3" ) < 0
 +                      ) {
 +                              // bug 66323 - Greyscale images not rendered properly.
 +                              // So only take the "red" channel.
 +                              $channelOnly = array( '-channel', 'R', '-separate' );
 +                              $animation_post = array_merge( $animation_post, $channelOnly );
 +                      }
                }
  
                // Use one thread only, to avoid deadlock bugs on OOM
        }
  
        /**
-        * Rerurns whether the file needs to be rendered. Returns true if the
+        * Returns whether the file needs to be rendered. Returns true if the
         * file requires rotation and we are able to rotate it.
         *
         * @param File $file
@@@ -108,20 -108,10 +108,20 @@@ abstract class MediaHandler 
         * Get an image size array like that returned by getimagesize(), or false if it
         * can't be determined.
         *
 +       * This function is used for determining the width, height and bitdepth directly
 +       * from an image. The results are stored in the database in the img_width,
 +       * img_height, img_bits fields.
 +       *
 +       * @note If this is a multipage file, return the width and height of the
 +       *  first page.
 +       *
         * @param File $image The image object, or false if there isn't one
         * @param string $path the filename
         * @return array Follow the format of PHP getimagesize() internal function.
 -       *   See http://www.php.net/getimagesize
 +       *   See http://www.php.net/getimagesize. MediaWiki will only ever use the
 +       *   first two array keys (the width and height), and the 'bits' associative
 +       *   key. All other array keys are ignored. Returning a 'bits' key is optional
 +       *   as not all formats have a notion of "bitdepth".
         */
        abstract function getImageSize( $image, $path );
  
         * @param File $image The image object, or false if there isn't one.
         *   Warning, FSFile::getPropsFromPath might pass an (object)array() instead (!)
         * @param string $path The filename
 -       * @return string
 +       * @return string A string of metadata in php serialized form (Run through serialize())
         */
        function getMetadata( $image, $path ) {
                return '';
         *
         * This is not used for validating metadata, this is used for the api when returning
         * metadata, since api content formats should stay the same over time, and so things
 -       * using ForiegnApiRepo can keep backwards compatibility
 +       * using ForeignApiRepo can keep backwards compatibility
         *
         * All core media handlers share a common version number, and extensions can
         * use the GetMetadataVersion hook to append to the array (they should append a unique
  
        /**
         * Get a string describing the type of metadata, for display purposes.
 +       *
 +       * @note This method is currently unused.
         * @param File $image
         * @return string
         */
         * If it returns MediaHandler::METADATA_BAD (or false), Image
         * will reload the metadata from the file and update the database.
         * MediaHandler::METADATA_GOOD for if the metadata is a-ok,
 -       * MediaHanlder::METADATA_COMPATIBLE if metadata is old but backwards
 +       * MediaHandler::METADATA_COMPATIBLE if metadata is old but backwards
         * compatible (which may or may not trigger a metadata reload).
 +       *
 +       * @note Returning self::METADATA_BAD will trigger a metadata reload from
 +       *  file on page view. Always returning this from a broken file, or suddenly
 +       *  triggering as bad metadata for a large number of files can cause
 +       *  performance problems.
         * @param File $image
 -       * @param array $metadata
 +       * @param string $metadata The metadata in serialized form
         * @return bool
         */
        function isMetadataValid( $image, $metadata ) {
        public function isExpensiveToThumbnail( $file ) {
                return false;
        }
+       /**
+        * Returns whether or not this handler supports the chained generation of thumbnails according
+        * to buckets
+        * @return boolean
+        * @since  1.24
+        */
+       public function supportsBucketing() {
+               return false;
+       }
+       /**
+        * Returns a normalised params array for which parameters have been cleaned up for bucketing
+        * purposes
+        * @param array $params
+        * @return array
+        */
+       public function sanitizeParamsForBucketing( $params ) {
+               return $params;
+       }
  }