Merge "Allow extension of the Special:Upload form"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 17 Jan 2018 16:35:02 +0000 (16:35 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 17 Jan 2018 16:35:02 +0000 (16:35 +0000)
1  2 
RELEASE-NOTES-1.31
docs/hooks.txt
includes/specials/formfields/Licenses.php
resources/src/mediawiki.special/mediawiki.special.upload.js

diff --combined RELEASE-NOTES-1.31
@@@ -37,6 -37,8 +37,8 @@@ production
    users during an import.
  * Added a hook, ParserOutputPostCacheTransform, to allow extensions to affect
    the ParserOutput::getText() post-cache transformations.
+ * Added a hook, UploadForm:getInitialPageText, to allow extensions to alter the
+   initial page text for file uploads.
  
  === External library changes in 1.31 ===
  
@@@ -65,9 -67,7 +67,9 @@@
  * (T90902) Non-breaking space in header ID breaks anchor
  
  === Action API changes in 1.31 ===
 -* …
 +* (T185058) The 'name' value to tgprop for action=query&list=tags has been
 +  removed. It has never made a difference in the output, the name was always
 +  returned regardless.
  
  === Action API internal changes in 1.31 ===
  * …
@@@ -78,7 -78,6 +80,7 @@@ regularly. Below only new and removed l
  changes to languages because of Phabricator reports.
  
  * (T180052) Mirandese (mwl) now supports gendered NS_USER/NS_USER_TALK namespaces.
 +* (T182305) New language support: Nyungar (nys).
  
  === Other changes in 1.31 ===
  * Introducing multi-content-revision capability into the storage layer. For details,
    has been deprecated since 1.27 and was removed as well.
  * The HtmlFormatter class was removed (deprecated in 1.27). The namespaced
    HtmlFormatter\HtmlFormatter class should be used instead.
+ * License::getLicenses has been deprecated; use License::getLines instead.
  
  == Compatibility ==
 -MediaWiki 1.31 requires PHP 5.5.9 or later. There is experimental support for
 -HHVM 3.6.5 or later.
 +MediaWiki 1.31 requires PHP 5.5.9 or later. Although HHVM 3.18.5 or later is supported,
 +it is generally advised to use PHP 5.5.9 or later for long term support.
  
  MySQL/MariaDB is the recommended DBMS. PostgreSQL or SQLite can also be used,
  but support for them is somewhat less mature. There is experimental support for
diff --combined docs/hooks.txt
@@@ -3521,6 -3521,12 +3521,12 @@@ blank form with no error message; use U
  instead.
  &$form: UploadForm object
  
+ 'UploadForm:getInitialPageText': After the initial page text for file uploads
+ is generated, to allow it to be altered.
+ &$pageText: the page text
+ $msg: array of header messages
+ $config: Config object
  'UploadForm:initial': Before the upload form is generated. You might set the
  member-variables $uploadFormTextTop and $uploadFormTextAfterSummary to inject
  text (HTML) either before or after the editform.
@@@ -3917,15 -3923,14 +3923,15 @@@ dumps. One, and only one hook should se
  &$opts: Options to use for the query
  &$join: Join conditions
  
 -'WikiPageDeletionUpdates': manipulate the list of DataUpdates to be applied when
 +'WikiPageDeletionUpdates': manipulate the list of DeferrableUpdates to be applied when
  a page is deleted. Called in WikiPage::getDeletionUpdates(). Note that updates
  specific to a content model should be provided by the respective Content's
  getDeletionUpdates() method.
  $page: the WikiPage
 -$content: the Content to generate updates for (or null, if the Content could not be loaded
 -due to an error)
 -&$updates: the array of DataUpdate objects. Hook function may want to add to it.
 +$content: the Content to generate updates for, or null in case the page revision could not be
 +  loaded. The delete will succeed despite this.
 +&$updates: the array of objects that implement DeferrableUpdate. Hook function may want to add to
 +  it.
  
  'WikiPageFactory': Override WikiPage class used for a title
  $title: Title of the page
@@@ -21,6 -21,7 +21,6 @@@
   * @ingroup SpecialPage
   * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
   * @copyright Copyright © 2005, Ævar Arnfjörð Bjarmason
 - * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later
   */
  
  /**
@@@ -31,10 -32,13 +31,13 @@@ class Licenses extends HTMLFormField 
        protected $msg;
  
        /** @var array */
-       protected $licenses = [];
+       protected $lines = [];
  
        /** @var string */
        protected $html;
+       /** @var string|null */
+       protected $selected;
        /**#@-*/
  
        /**
        public function __construct( $params ) {
                parent::__construct( $params );
  
-               $this->msg = empty( $params['licenses'] )
+               $this->msg = static::getMessageFromParams( $params );
+               $this->selected = null;
+               $this->makeLines();
+       }
+       /**
+        * @param array $params
+        * @return string
+        */
+       protected static function getMessageFromParams( $params ) {
+               return empty( $params['licenses'] )
                        ? wfMessage( 'licenses' )->inContentLanguage()->plain()
                        : $params['licenses'];
-               $this->selected = null;
+       }
  
-               $this->makeLicenses();
+       /**
+        * @param string $line
+        * @return License
+        */
+       protected function buildLine( $line ) {
+               return new License( $line );
        }
  
        /**
         * @private
         */
-       protected function makeLicenses() {
+       protected function makeLines() {
                $levels = [];
                $lines = explode( "\n", $this->msg );
  
@@@ -65,8 -85,8 +84,8 @@@
                                list( $level, $line ) = $this->trimStars( $line );
  
                                if ( strpos( $line, '|' ) !== false ) {
-                                       $obj = new License( $line );
-                                       $this->stackItem( $this->licenses, $levels, $obj );
+                                       $obj = $this->buildLine( $line );
+                                       $this->stackItem( $this->lines, $levels, $obj );
                                } else {
                                        if ( $level < count( $levels ) ) {
                                                $levels = array_slice( $levels, 0, $level );
        /**
         * @param array $tagset
         * @param int $depth
+        * @return string
         */
        protected function makeHtml( $tagset, $depth = 0 ) {
+               $html = '';
                foreach ( $tagset as $key => $val ) {
                        if ( is_array( $val ) ) {
-                               $this->html .= $this->outputOption(
+                               $html .= $this->outputOption(
                                        $key, '',
                                        [
                                                'disabled' => 'disabled',
                                        ],
                                        $depth
                                );
-                               $this->makeHtml( $val, $depth + 1 );
+                               $html .= $this->makeHtml( $val, $depth + 1 );
                        } else {
-                               $this->html .= $this->outputOption(
+                               $html .= $this->outputOption(
                                        $val->text, $val->template,
                                        [ 'title' => '{{' . $val->template . '}}' ],
                                        $depth
                                );
                        }
                }
+               return $html;
        }
  
        /**
        /**#@-*/
  
        /**
-        *  Accessor for $this->licenses
+        * Accessor for $this->lines
         *
         * @return array
         */
-       public function getLicenses() {
-               return $this->licenses;
+       public function getLines() {
+               return $this->lines;
        }
  
        /**
-        * Accessor for $this->html
+        * Accessor for $this->lines
         *
-        * @param bool $value
+        * @return array
         *
-        * @return string
+        * @deprecated since 1.31 Use getLines() instead
+        */
+       public function getLicenses() {
+               return $this->getLines();
+       }
+       /**
+        * {@inheritdoc}
         */
        public function getInputHTML( $value ) {
                $this->selected = $value;
  
-               $this->html = $this->outputOption( wfMessage( 'nolicense' )->text(), '',
-                       (bool)$this->selected ? null : [ 'selected' => 'selected' ] );
-               $this->makeHtml( $this->getLicenses() );
+               // add a default "no license selected" option
+               $default = $this->buildLine( '|nolicense' );
+               array_unshift( $this->lines, $default );
+               $html = $this->makeHtml( $this->getLines() );
  
                $attribs = [
                        'name' => $this->mName,
                        'id' => $this->mID
                ];
                if ( !empty( $this->mParams['disabled'] ) ) {
-                       $attibs['disabled'] = 'disabled';
+                       $attribs['disabled'] = 'disabled';
                }
  
-               return Html::rawElement( 'select', $attribs, $this->html );
+               $html = Html::rawElement( 'select', $attribs, $html );
+               // remove default "no license selected" from lines again
+               array_shift( $this->lines );
+               return $html;
        }
  }
@@@ -10,7 -10,7 +10,7 @@@
  /* global Uint8Array */
  
  ( function ( mw, $ ) {
-       var uploadWarning, uploadLicense,
+       var uploadWarning, uploadTemplatePreview,
                ajaxUploadDestCheck = mw.config.get( 'wgAjaxUploadDestCheck' ),
                $license = $( '#wpLicense' );
  
                }
        };
  
-       uploadLicense = {
+       window.wgUploadTemplatePreviewObj = uploadTemplatePreview = {
  
                responseCache: { '': '' },
  
-               fetchPreview: function ( license ) {
-                       var $spinnerLicense;
-                       if ( !mw.config.get( 'wgAjaxLicensePreview' ) ) {
-                               return;
-                       }
-                       if ( this.responseCache.hasOwnProperty( license ) ) {
-                               this.showPreview( this.responseCache[ license ] );
+               /**
+                * @param {jQuery} $element The element whose .val() will be previewed
+                * @param {jQuery} $previewContainer The container to display the preview in
+                */
+               getPreview: function ( $element, $previewContainer ) {
+                       var template = $element.val(),
+                               $spinner;
+                       if ( this.responseCache.hasOwnProperty( template ) ) {
+                               this.showPreview( this.responseCache[ template ], $previewContainer );
                                return;
                        }
  
-                       $spinnerLicense = $.createSpinner().insertAfter( '#wpLicense' );
+                       $spinner = $.createSpinner().insertAfter( $element );
  
                        ( new mw.Api() ).get( {
                                formatversion: 2,
                                action: 'parse',
-                               text: '{{' + license + '}}',
+                               text: '{{' + template + '}}',
                                title: $( '#wpDestFile' ).val() || 'File:Sample.jpg',
                                prop: 'text',
 -                              pst: true
 +                              pst: true,
 +                              uselang: mw.config.get( 'wgUserLanguage' )
                        } ).done( function ( result ) {
-                               uploadLicense.processResult( result, license );
+                               uploadTemplatePreview.processResult( result, template, $previewContainer );
                        } ).always( function () {
-                               $spinnerLicense.remove();
+                               $spinner.remove();
                        } );
                },
  
-               processResult: function ( result, license ) {
-                       this.responseCache[ license ] = result.parse.text;
-                       this.showPreview( this.responseCache[ license ] );
+               processResult: function ( result, template, $previewContainer ) {
+                       this.responseCache[ template ] = result.parse.text;
+                       this.showPreview( this.responseCache[ template ], $previewContainer );
                },
  
-               showPreview: function ( preview ) {
-                       $( '#mw-license-preview' ).html( preview );
+               showPreview: function ( preview, $previewContainer ) {
+                       $previewContainer.html( preview );
                }
  
        };
                        // License selector check
                        $license.change( function () {
                                // We might show a preview
-                               uploadLicense.fetchPreview( $license.val() );
+                               uploadTemplatePreview.getPreview( $license, $( '#mw-license-preview' ) );
                        } );
  
                        // License selector table row
                                if (
                                        mw.config.get( 'wgCheckFileExtensions' ) &&
                                        mw.config.get( 'wgStrictFileExtensions' ) &&
 -                                      mw.config.get( 'wgFileExtensions' ) &&
 +                                      Array.isArray( mw.config.get( 'wgFileExtensions' ) ) &&
                                        $( this ).attr( 'id' ) !== 'wpUploadFileURL'
                                ) {
                                        if (
                                                fname.lastIndexOf( '.' ) === -1 ||
 -                                              $.inArray(
 -                                                      fname.slice( fname.lastIndexOf( '.' ) + 1 ).toLowerCase(),
 -                                                      $.map( mw.config.get( 'wgFileExtensions' ), function ( element ) {
 -                                                              return element.toLowerCase();
 -                                                      } )
 -                                              ) === -1
 +                                              mw.config.get( 'wgFileExtensions' ).map( function ( element ) {
 +                                                      return element.toLowerCase();
 +                                              } ).indexOf( fname.slice( fname.lastIndexOf( '.' ) + 1 ).toLowerCase() ) === -1
                                        ) {
                                                // Not a valid extension
                                                // Clear the upload and set mw-upload-permitted to error
                function fileIsPreviewable( file ) {
                        var known = [ 'image/png', 'image/gif', 'image/jpeg', 'image/svg+xml' ],
                                tooHuge = 10 * 1024 * 1024;
 -                      return ( $.inArray( file.type, known ) !== -1 ) && file.size > 0 && file.size < tooHuge;
 +                      return ( known.indexOf( file.type ) !== -1 ) && file.size > 0 && file.size < tooHuge;
                }
  
                /**