diff --git a/includes/VisualEditorHooks.php b/includes/VisualEditorHooks.php index 8c7890e8e0..d2d94bafcf 100644 --- a/includes/VisualEditorHooks.php +++ b/includes/VisualEditorHooks.php @@ -228,12 +228,13 @@ class VisualEditorHooks { } if ( $req->getVal( 'wteswitched' ) ) { - return self::isVisualAvailable( $title, $req ); + return self::isVisualAvailable( $title, $req, $user ); } switch ( self::getPreferredEditor( $user, $req ) ) { case 'visualeditor': - return self::isVisualAvailable( $title, $req ) || self::isWikitextAvailable( $title, $user ); + return self::isVisualAvailable( $title, $req, $user ) || + self::isWikitextAvailable( $title, $user ); case 'wikitext': return self::isWikitextAvailable( $title, $user ); } @@ -241,21 +242,40 @@ class VisualEditorHooks { } /** - * @param Title $title - * @param WebRequest $req + * @param User $user * @return bool */ - private static function isVisualAvailable( $title, $req ) { + private static function enabledForUser( $user ) { $veConfig = MediaWikiServices::getInstance()->getConfigFactory() ->makeConfig( 'visualeditor' ); + return $user->getOption( 'visualeditor-enable' ) && + !$user->getOption( 'visualeditor-betatempdisable' ) && + !$user->getOption( 'visualeditor-autodisable' ) && + !( $veConfig->get( 'VisualEditorDisableForAnons' ) && $user->isAnon() ); + } + + /** + * @param Title $title + * @param WebRequest $req + * @param User $user + * @return bool + */ + private static function isVisualAvailable( $title, $req, $user ) { + $veConfig = MediaWikiServices::getInstance()->getConfigFactory() + ->makeConfig( 'visualeditor' ); + return ( + // If forced by the URL parameter, skip the namespace check (T221892) and preference check + $req->getVal( 'veaction' ) === 'edit' || ( // Only in enabled namespaces - ApiVisualEditor::isAllowedNamespace( $veConfig, $title->getNamespace() ) || - // Or if forced by the URL parameter (T221892) - $req->getVal( 'veaction' ) === 'edit' + ApiVisualEditor::isAllowedNamespace( $veConfig, $title->getNamespace() ) && + + // Enabled per user preferences + self::enabledForUser( $user ) ) && // Only for pages with a supported content model - ApiVisualEditor::isAllowedContentType( $veConfig, $title->getContentModel() ); + ApiVisualEditor::isAllowedContentType( $veConfig, $title->getContentModel() ) + ); } /** @@ -282,10 +302,7 @@ class VisualEditorHooks { ->makeConfig( 'visualeditor' ); if ( - !$user->getOption( 'visualeditor-enable' ) || - $user->getOption( 'visualeditor-betatempdisable' ) || - $user->getOption( 'visualeditor-autodisable' ) || - ( $veConfig->get( 'VisualEditorDisableForAnons' ) && $user->isAnon() ) || + !self::enabledForUser( $user ) || self::isUABlacklisted( $req, $veConfig ) ) { return true; @@ -460,7 +477,7 @@ class VisualEditorHooks { $title = $skin->getRelevantTitle(); // Don't exit if this page isn't VE-enabled, since we should still // change "Edit" to "Edit source". - $isAvailable = self::isVisualAvailable( $title, $skin->getRequest() ); + $isAvailable = self::isVisualAvailable( $title, $skin->getRequest(), $user ); $tabMessages = $config->get( 'VisualEditorTabMessages' ); // Rebuild the $links['views'] array and inject the VisualEditor tab before or after @@ -657,7 +674,7 @@ class VisualEditorHooks { } // add VE edit section in VE available namespaces - if ( self::isVisualAvailable( $title, $skin->getRequest() ) ) { + if ( self::isVisualAvailable( $title, $skin->getRequest(), $user ) ) { // @phan-suppress-next-line PhanTypeArraySuspiciousNullable $veEditSection = $tabMessages['editsection']; $veLink = [ diff --git a/modules/ve-mw/preinit/ve.init.mw.DesktopArticleTarget.init.js b/modules/ve-mw/preinit/ve.init.mw.DesktopArticleTarget.init.js index b0905f55b7..bbcf7dbff6 100644 --- a/modules/ve-mw/preinit/ve.init.mw.DesktopArticleTarget.init.js +++ b/modules/ve-mw/preinit/ve.init.mw.DesktopArticleTarget.init.js @@ -587,12 +587,12 @@ // Set up the tabs appropriately if the user has VE on if ( init.isAvailable ) { // … on two-edit-tab wikis, or single-edit-tab wikis, where the user wants both … - if ( !init.isSingleEditTab && init.isVisualAvailable && enabledForUser ) { + if ( !init.isSingleEditTab && init.isVisualAvailable ) { // … set the skin up with both tabs and both section edit links. init.setupMultiTabSkin(); } else if ( pageCanLoadEditor && ( - ( init.isVisualAvailable && enabledForUser && isOnlyTabVE() ) || + ( init.isVisualAvailable && isOnlyTabVE() ) || ( init.isWikitextAvailable && isOnlyTabWikitext() ) ) ) { @@ -679,7 +679,7 @@ } // If the edit tab is hidden, remove it. - if ( !( init.isVisualAvailable && enabledForUser ) ) { + if ( !( init.isVisualAvailable ) ) { $caVeEdit.remove(); } else if ( pageCanLoadEditor ) { // Allow instant switching to edit mode, without refresh @@ -1015,16 +1015,32 @@ mw.config.get( 'wgTwoColConflict' ) !== 'true' ); + enabledForUser = ( + // Allow disabling for anonymous users separately from changing the + // default preference (T52000) + !( conf.disableForAnons && mw.config.get( 'wgUserName' ) === null ) && + + // User has 'visualeditor-enable' preference enabled (for alpha opt-in) + // User has 'visualeditor-betatempdisable' preference disabled + // User has 'visualeditor-autodisable' preference disabled + enable && !tempdisable && !autodisable && + + // Except when single edit tab for old wikitext + !( conf.singleEditTab && tabPreference === 'prefer-wt' && !init.isWikitextAvailable ) + ); + // Duplicated in VisualEditor.hooks.php#isVisualAvailable() init.isVisualAvailable = ( init.isAvailable && - ( + // If forced by the URL parameter, skip the namespace check (T221892) and preference check + ( uri.query.veaction === 'edit' || ( // Only in enabled namespaces - conf.namespaces.indexOf( new mw.Title( mw.config.get( 'wgRelevantPageName' ) ).getNamespaceId() ) !== -1 || - // Or if forced by the URL parameter (T221892) - uri.query.veaction === 'edit' - ) && + conf.namespaces.indexOf( new mw.Title( mw.config.get( 'wgRelevantPageName' ) ).getNamespaceId() ) !== -1 && + + // Enabled per user preferences + enabledForUser + ) ) && // Only for pages with a supported content model Object.prototype.hasOwnProperty.call( conf.contentModels, mw.config.get( 'wgPageContentModel' ) ) @@ -1052,20 +1068,6 @@ availableModes.push( 'source' ); } - enabledForUser = ( - // Allow disabling for anonymous users separately from changing the - // default preference (T52000) - !( conf.disableForAnons && mw.config.get( 'wgUserName' ) === null ) && - - // User has 'visualeditor-enable' preference enabled (for alpha opt-in) - // User has 'visualeditor-betatempdisable' preference disabled - // User has 'visualeditor-autodisable' preference disabled - enable && !tempdisable && !autodisable && - - // Except when single edit tab for old wikitext - !( conf.singleEditTab && tabPreference === 'prefer-wt' && !init.isWikitextAvailable ) - ); - // FIXME: We should do this more elegantly init.setEditorPreference = setEditorPreference; @@ -1081,7 +1083,7 @@ // on this page. See above for why it may be false. mw.libs.ve = $.extend( mw.libs.ve || {}, init ); - if ( init.isVisualAvailable && enabledForUser ) { + if ( init.isVisualAvailable ) { $( 'html' ).addClass( 've-available' ); } else { $( 'html' ).addClass( 've-not-available' );