Merge "phpunit: Avoid use of deprecated getMock for PHPUnit 5 compat"
[lhc/web/wiklou.git] / includes / EditPage.php
index a02392e..2153b8c 100644 (file)
@@ -363,8 +363,8 @@ class EditPage {
        /** @var bool */
        public $bot = true;
 
-       /** @var null|string */
-       public $contentModel = null;
+       /** @var string */
+       public $contentModel;
 
        /** @var null|string */
        public $contentFormat = null;
@@ -1027,7 +1027,7 @@ class EditPage {
                        throw new ErrorPageError(
                                'editpage-invalidcontentmodel-title',
                                'editpage-invalidcontentmodel-text',
-                               [ $this->contentModel ]
+                               [ wfEscapeWikiText( $this->contentModel ) ]
                        );
                }
 
@@ -1035,7 +1035,10 @@ class EditPage {
                        throw new ErrorPageError(
                                'editpage-notsupportedcontentformat-title',
                                'editpage-notsupportedcontentformat-text',
-                               [ $this->contentFormat, ContentHandler::getLocalizedName( $this->contentModel ) ]
+                               [
+                                       wfEscapeWikiText( $this->contentFormat ),
+                                       wfEscapeWikiText( ContentHandler::getLocalizedName( $this->contentModel ) )
+                               ]
                        );
                }
 
@@ -1255,11 +1258,7 @@ class EditPage {
                }
                $revision = $this->mArticle->getRevisionFetched();
                if ( $revision === null ) {
-                       if ( !$this->contentModel ) {
-                               throw new RuntimeException( 'EditPage contentModel was false' );
-                       }
                        $handler = ContentHandler::getForModelID( $this->contentModel );
-
                        return $handler->makeEmptyContent();
                }
                $content = $revision->getContent( Revision::FOR_THIS_USER, $user );
@@ -1299,11 +1298,7 @@ class EditPage {
                $content = $rev ? $rev->getContent( Revision::RAW ) : null;
 
                if ( $content === false || $content === null ) {
-                       if ( !$this->contentModel ) {
-                               throw new RuntimeException( 'EditPage contentModel was false' );
-                       }
                        $handler = ContentHandler::getForModelID( $this->contentModel );
-
                        return $handler->makeEmptyContent();
                } elseif ( !$this->undidRev ) {
                        // Content models should always be the same since we error
@@ -2326,12 +2321,9 @@ class EditPage {
        }
 
        public function setHeaders() {
-               global $wgOut, $wgUser, $wgAjaxEditStash, $wgCookieSetOnAutoblock;
+               global $wgOut, $wgUser, $wgAjaxEditStash;
 
                $wgOut->addModules( 'mediawiki.action.edit' );
-               if ( $wgCookieSetOnAutoblock === true ) {
-                       $wgOut->addModules( 'mediawiki.user.blockcookie' );
-               }
                $wgOut->addModuleStyles( 'mediawiki.action.edit.styles' );
 
                if ( $wgUser->getOption( 'showtoolbar' ) ) {
@@ -2432,7 +2424,7 @@ class EditPage {
                # Show log extract when the user is currently blocked
                if ( $namespace == NS_USER || $namespace == NS_USER_TALK ) {
                        $username = explode( '/', $this->mTitle->getText(), 2 )[0];
-                       $user = User::newFromName( $username, false /* allow IP users*/ );
+                       $user = User::newFromName( $username, false /* allow IP users */ );
                        $ip = User::isIP( $username );
                        $block = Block::newFromTarget( $user, $user );
                        if ( !( $user && $user->isLoggedIn() ) && !$ip ) { # User does not exist
@@ -3069,6 +3061,7 @@ class EditPage {
         */
        protected function showSummaryInput( $isSubjectPreview, $summary = "" ) {
                global $wgOut;
+
                # Add a class if 'missingsummary' is triggered to allow styling of the summary line
                $summaryClass = $this->missingSummary ? 'mw-summarymissed' : 'mw-summary';
                if ( $isSubjectPreview ) {
@@ -3517,12 +3510,12 @@ HTML
 
                $message = $this->context->msg( 'edithelppage' )->inContentLanguage()->text();
                $edithelpurl = Skin::makeInternalOrExternalUrl( $message );
-               $attrs = [
-                       'target' => 'helpwindow',
-                       'href' => $edithelpurl,
-               ];
-               $edithelp = Html::linkButton( $this->context->msg( 'edithelp' )->text(),
-                       $attrs, [ 'mw-ui-quiet' ] ) .
+               $edithelp =
+                       Html::linkButton(
+                               $this->context->msg( 'edithelp' )->text(),
+                               [ 'target' => 'helpwindow', 'href' => $edithelpurl ],
+                               [ 'mw-ui-quiet' ]
+                       ) .
                        $this->context->msg( 'word-separator' )->escaped() .
                        $this->context->msg( 'newwindow' )->parse();
 
@@ -3582,18 +3575,16 @@ HTML
         */
        public function getCancelLink() {
                $cancelParams = [];
-               $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
                if ( !$this->isConflict && $this->oldid > 0 ) {
                        $cancelParams['oldid'] = $this->oldid;
                } elseif ( $this->getContextTitle()->isRedirect() ) {
                        $cancelParams['redirect'] = 'no';
                }
-               $attrs = [ 'id' => 'mw-editform-cancel' ];
 
-               return $linkRenderer->makeKnownLink(
+               return MediaWikiServices::getInstance()->getLinkRenderer()->makeKnownLink(
                        $this->getContextTitle(),
                        new HtmlArmor( $this->context->msg( 'cancel' )->parse() ),
-                       Html::buttonAttributes( $attrs, [ 'mw-ui-quiet' ] ),
+                       Html::buttonAttributes( [ 'id' => 'mw-editform-cancel' ], [ 'mw-ui-quiet' ] ),
                        $cancelParams
                );
        }
@@ -4017,72 +4008,114 @@ HTML
                return $toolbar;
        }
 
+       /**
+        * Return an array of checkbox definitions.
+        *
+        * Array keys correspond to the `<input>` 'name' attribute to use for each checkbox.
+        *
+        * Array values are associative arrays with the following keys:
+        *  - 'label-message' (required): message for label text
+        *  - 'id' (required): 'id' attribute for the `<input>`
+        *  - 'default' (required): default checkedness (true or false)
+        *  - 'title-message' (optional): used to generate 'title' attribute for the `<label>`
+        *  - 'tooltip' (optional): used to generate 'title' and 'accesskey' attributes
+        *    from messages like 'tooltip-foo', 'accesskey-foo'
+        *  - 'label-id' (optional): 'id' attribute for the `<label>`
+        *  - 'legacy-name' (optional): short name for backwards-compatibility
+        * @param array $checked Array of checkbox name (matching the 'legacy-name') => bool,
+        *   where bool indicates the checked status of the checkbox
+        * @return array
+        */
+       protected function getCheckboxesDefinition( $checked ) {
+               global $wgUser;
+               $checkboxes = [];
+
+               // don't show the minor edit checkbox if it's a new page or section
+               if ( !$this->isNew && $wgUser->isAllowed( 'minoredit' ) ) {
+                       $checkboxes['wpMinoredit'] = [
+                               'id' => 'wpMinoredit',
+                               'label-message' => 'minoredit',
+                               // Uses messages: tooltip-minoredit, accesskey-minoredit
+                               'tooltip' => 'minoredit',
+                               'label-id' => 'mw-editpage-minoredit',
+                               'legacy-name' => 'minor',
+                               'default' => $checked['minor'],
+                       ];
+               }
+
+               if ( $wgUser->isLoggedIn() ) {
+                       $checkboxes['wpWatchthis'] = [
+                               'id' => 'wpWatchthis',
+                               'label-message' => 'watchthis',
+                               // Uses messages: tooltip-watch, accesskey-watch
+                               'tooltip' => 'watch',
+                               'label-id' => 'mw-editpage-watch',
+                               'legacy-name' => 'watch',
+                               'default' => $checked['watch'],
+                       ];
+               }
+
+               $editPage = $this;
+               Hooks::run( 'EditPageGetCheckboxesDefinition', [ $editPage, &$checkboxes ] );
+
+               return $checkboxes;
+       }
+
        /**
         * Returns an array of html code of the following checkboxes:
         * minor and watch
         *
         * @param int $tabindex Current tabindex
-        * @param array $checked Array of checkbox => bool, where bool indicates the checked
-        *                 status of the checkbox
-        *
+        * @param array $checked See getCheckboxesDefinition()
         * @return array
         */
        public function getCheckboxes( &$tabindex, $checked ) {
-               global $wgUser, $wgUseMediaWikiUIEverywhere;
+               global $wgUseMediaWikiUIEverywhere;
 
                $checkboxes = [];
+               $checkboxesDef = $this->getCheckboxesDefinition( $checked );
 
-               // don't show the minor edit checkbox if it's a new page or section
+               // Backwards-compatibility for the EditPageBeforeEditChecks hook
                if ( !$this->isNew ) {
                        $checkboxes['minor'] = '';
-                       $minorLabel = $this->context->msg( 'minoredit' )->parse();
-                       if ( $wgUser->isAllowed( 'minoredit' ) ) {
-                               $attribs = [
-                                       'tabindex' => ++$tabindex,
-                                       'accesskey' => $this->context->msg( 'accesskey-minoredit' )->text(),
-                                       'id' => 'wpMinoredit',
-                               ];
-                               $minorEditHtml =
-                                       Xml::check( 'wpMinoredit', $checked['minor'], $attribs ) .
-                                       "&#160;<label for='wpMinoredit' id='mw-editpage-minoredit'" .
-                                       Xml::expandAttributes( [ 'title' => Linker::titleAttrib( 'minoredit', 'withaccess' ) ] ) .
-                                       ">{$minorLabel}</label>";
-
-                               if ( $wgUseMediaWikiUIEverywhere ) {
-                                       $checkboxes['minor'] = Html::openElement( 'div', [ 'class' => 'mw-ui-checkbox' ] ) .
-                                               $minorEditHtml .
-                                       Html::closeElement( 'div' );
-                               } else {
-                                       $checkboxes['minor'] = $minorEditHtml;
-                               }
-                       }
                }
-
-               $watchLabel = $this->context->msg( 'watchthis' )->parse();
                $checkboxes['watch'] = '';
-               if ( $wgUser->isLoggedIn() ) {
+
+               foreach ( $checkboxesDef as $name => $options ) {
+                       $legacyName = isset( $options['legacy-name'] ) ? $options['legacy-name'] : $name;
+                       $label = $this->context->msg( $options['label-message'] )->parse();
                        $attribs = [
                                'tabindex' => ++$tabindex,
-                               'accesskey' => $this->context->msg( 'accesskey-watch' )->text(),
-                               'id' => 'wpWatchthis',
+                               'id' => $options['id'],
                        ];
-                       $watchThisHtml =
-                               Xml::check( 'wpWatchthis', $checked['watch'], $attribs ) .
-                               "&#160;<label for='wpWatchthis' id='mw-editpage-watch'" .
-                               Xml::expandAttributes( [ 'title' => Linker::titleAttrib( 'watch', 'withaccess' ) ] ) .
-                               ">{$watchLabel}</label>";
+                       $labelAttribs = [
+                               'for' => $options['id'],
+                       ];
+                       if ( isset( $options['tooltip'] ) ) {
+                               $attribs['accesskey'] = $this->context->msg( "accesskey-{$options['tooltip']}" )->text();
+                               $labelAttribs['title'] = Linker::titleAttrib( $options['tooltip'], 'withaccess' );
+                       }
+                       if ( isset( $options['title-message'] ) ) {
+                               $labelAttribs['title'] = $this->context->msg( $options['title-message'] )->text();
+                       }
+                       if ( isset( $options['label-id'] ) ) {
+                               $labelAttribs['id'] = $options['label-id'];
+                       }
+                       $checkboxHtml =
+                               Xml::check( $name, $options['default'], $attribs ) .
+                               '&#160;' .
+                               Xml::tags( 'label', $labelAttribs, $label );
+
                        if ( $wgUseMediaWikiUIEverywhere ) {
-                               $checkboxes['watch'] = Html::openElement( 'div', [ 'class' => 'mw-ui-checkbox' ] ) .
-                                       $watchThisHtml .
-                                       Html::closeElement( 'div' );
-                       } else {
-                               $checkboxes['watch'] = $watchThisHtml;
+                               $checkboxHtml = Html::rawElement( 'div', [ 'class' => 'mw-ui-checkbox' ], $checkboxHtml );
                        }
+
+                       $checkboxes[ $legacyName ] = $checkboxHtml;
                }
 
                // Avoid PHP 7.1 warning of passing $this by reference
                $editPage = $this;
-               Hooks::run( 'EditPageBeforeEditChecks', [ &$editPage, &$checkboxes, &$tabindex ] );
+               Hooks::run( 'EditPageBeforeEditChecks', [ &$editPage, &$checkboxes, &$tabindex ], '1.29' );
                return $checkboxes;
        }
 
@@ -4106,34 +4139,41 @@ HTML
                } else {
                        $buttonLabelKey = !$this->mTitle->exists() ? 'savearticle' : 'savechanges';
                }
-               $buttonLabel = $this->context->msg( $buttonLabelKey )->text();
                $attribs = [
                        'id' => 'wpSave',
                        'name' => 'wpSave',
                        'tabindex' => ++$tabindex,
                ] + Linker::tooltipAndAccesskeyAttribs( 'save' );
-               $buttons['save'] = Html::submitButton( $buttonLabel, $attribs, [ 'mw-ui-progressive' ] );
+               $buttons['save'] = Html::submitButton(
+                       $this->context->msg( $buttonLabelKey )->text(),
+                       $attribs,
+                       [ 'mw-ui-progressive' ]
+               );
 
-               ++$tabindex; // use the same for preview and live preview
                $attribs = [
                        'id' => 'wpPreview',
                        'name' => 'wpPreview',
-                       'tabindex' => $tabindex,
+                       'tabindex' => ++$tabindex,
                ] + Linker::tooltipAndAccesskeyAttribs( 'preview' );
-               $buttons['preview'] = Html::submitButton( $this->context->msg( 'showpreview' )->text(),
-                       $attribs );
+               $buttons['preview'] = Html::submitButton(
+                       $this->context->msg( 'showpreview' )->text(),
+                       $attribs
+               );
 
                $attribs = [
                        'id' => 'wpDiff',
                        'name' => 'wpDiff',
                        'tabindex' => ++$tabindex,
                ] + Linker::tooltipAndAccesskeyAttribs( 'diff' );
-               $buttons['diff'] = Html::submitButton( $this->context->msg( 'showdiff' )->text(),
-                       $attribs );
+               $buttons['diff'] = Html::submitButton(
+                       $this->context->msg( 'showdiff' )->text(),
+                       $attribs
+               );
 
                // Avoid PHP 7.1 warning of passing $this by reference
                $editPage = $this;
                Hooks::run( 'EditPageBeforeEditButtons', [ &$editPage, &$buttons, &$tabindex ] );
+
                return $buttons;
        }