Allow the new topic tool to handle URLs like action=edit&section=new

Depends-On: Ib9302e2fda7dadf1edc43c0107db7234eb4bdf7a
Depends-On: Ic7dd677ea219938969f60bab91387c2e03ebdbe6
Bug: T282204
Change-Id: I2e7b2682da7beb3c1c469bb784a9a8ec3998aeb9
This commit is contained in:
Bartosz Dziewoński 2021-07-28 12:36:58 +02:00
parent 3ccfa56d8f
commit cfbf437d9d
6 changed files with 107 additions and 3 deletions

View file

@ -7,7 +7,7 @@
"descriptionmsg": "discussiontools-desc",
"manifest_version": 2,
"requires": {
"MediaWiki": ">= 1.36.0",
"MediaWiki": ">= 1.37.0",
"extensions": {
"VisualEditor": ">= 0.1.2",
"Linter": "*"
@ -381,6 +381,7 @@
"ParserAfterTidy": "parser",
"ParserOptionsRegister": "parser",
"BeforePageDisplay": "page",
"GetActionName": "page",
"OutputPageBeforeHTML": "page",
"ResourceLoaderGetConfigVars": "resourceloader",
"GetBetaFeaturePreferences": "\\MediaWiki\\Extension\\DiscussionTools\\Hooks\\PreferenceHooks::onGetBetaFeaturePreferences",

View file

@ -11,6 +11,7 @@ namespace MediaWiki\Extension\DiscussionTools\Hooks;
use Action;
use ExtensionRegistry;
use IContextSource;
use MediaWiki\MediaWikiServices;
use OutputPage;
use PageProps;
@ -203,7 +204,7 @@ class HookUtils {
*/
public static function isFeatureEnabledForOutput( OutputPage $output, ?string $feature = null ): bool {
// Don't show on edit pages, history, etc.
if ( Action::getActionName( $output->getContext() ) !== 'view' ) {
if ( $feature !== self::NEWTOPICTOOL && Action::getActionName( $output->getContext() ) !== 'view' ) {
return false;
}
@ -256,4 +257,32 @@ class HookUtils {
return static::isAvailableForTitle( $title ) &&
static::isFeatureEnabledForUser( $output->getUser(), $feature );
}
/**
* Check if this page view should open the new topic tool on page load.
*
* @param IContextSource $context
* @return bool
*/
public static function shouldUseNewTopicTool( IContextSource $context ): bool {
$req = $context->getRequest();
$out = $context->getOutput();
return (
// ?title=...&action=edit&section=new
// ?title=...&veaction=editsource&section=new
( $req->getVal( 'action' ) === 'edit' || $req->getVal( 'veaction' ) === 'editsource' ) &&
$req->getVal( 'section' ) === 'new' &&
// Adding a new topic with preloaded text is not supported yet (T269310)
!(
$req->getVal( 'editintro' ) || $req->getVal( 'preload' ) ||
$req->getVal( 'preloadparams' ) || $req->getVal( 'preloadtitle' )
) &&
// TODO If the page doesn't exist yet, we'll need to handle the interface differently,
// for now just don't enable the tool there
$context->getTitle()->exists() &&
// User has new topic tool enabled (and not using &dtenable=0)
self::isFeatureEnabledForOutput( $out, self::NEWTOPICTOOL )
);
}
}

View file

@ -9,6 +9,9 @@
namespace MediaWiki\Extension\DiscussionTools\Hooks;
use Html;
use IContextSource;
use MediaWiki\Actions\Hook\GetActionNameHook;
use MediaWiki\Extension\DiscussionTools\CommentFormatter;
use MediaWiki\Extension\DiscussionTools\SubscriptionStore;
use MediaWiki\Hook\BeforePageDisplayHook;
@ -20,6 +23,7 @@ use VisualEditorHooks;
class PageHooks implements
BeforePageDisplayHook,
GetActionNameHook,
OutputPageBeforeHTMLHook
{
/** @var SubscriptionStore */
@ -90,6 +94,34 @@ class PageHooks implements
);
}
}
// Replace the action=edit&section=new form with the new topic tool.
if ( HookUtils::shouldUseNewTopicTool( $output->getContext() ) ) {
$output->addJsConfigVars( 'wgDiscussionToolsStartNewTopicTool', true );
// For no-JS compatibility, redirect to the old new section editor if JS is unavailable.
// This isn't great, because the user has to load the page twice. But making a page that is
// both a view mode and an edit mode seems difficult, so I'm cutting some corners here.
// (Code below adapted from VisualEditor.)
$params = $output->getRequest()->getValues();
$params['dtenable'] = '0';
$url = wfScript() . '?' . wfArrayToCgi( $params );
$escapedUrl = htmlspecialchars( $url );
// Redirect if the user has no JS (<noscript>)
$output->addHeadItem(
'dt-noscript-fallback',
"<noscript><meta http-equiv=\"refresh\" content=\"0; url=$escapedUrl\"></noscript>"
);
// Redirect if the user has no ResourceLoader
$output->addScript( Html::inlineScript(
"(window.NORLQ=window.NORLQ||[]).push(" .
"function(){" .
"location.href=\"$url\";" .
"}" .
");"
) );
}
}
/**
@ -133,4 +165,17 @@ class PageHooks implements
return true;
}
/**
* GetActionName hook handler
*
* @param IContextSource $context Request context
* @param string &$action Default action name, reassign to change it
* @return void This hook must not abort, it must return no value
*/
public function onGetActionName( IContextSource $context, string &$action ): void {
if ( $action === 'edit' && HookUtils::shouldUseNewTopicTool( $context ) ) {
$action = 'view';
}
}
}

View file

@ -118,6 +118,21 @@ NewTopicController.prototype.teardown = function ( abandoned ) {
this.sectionTitle.setValue( '' );
this.sectionTitleField.setWarnings( [] );
this.container.$element.detach();
if ( mw.config.get( 'wgDiscussionToolsStartNewTopicTool' ) ) {
var uri;
try {
uri = new mw.Uri();
} catch ( err ) {
// T106244: URL encoded values using fallback 8-bit encoding (invalid UTF-8) cause mediawiki.Uri to crash
return;
}
delete uri.query.action;
delete uri.query.veaction;
delete uri.query.section;
history.replaceState( null, document.title, uri.toString() );
mw.config.set( 'wgDiscussionToolsStartNewTopicTool', false );
}
};
/**

View file

@ -125,6 +125,11 @@ ReplyLinksController.prototype.setActiveLink = function ( $link ) {
if ( this.$activeLink.is( this.$replyLinks ) ) {
this.$activeLink.closest( '.ext-discussiontools-init-replylink-buttons' )
.addClass( 'ext-discussiontools-init-replylink-active' );
} else if ( this.$addSectionLink && this.$activeLink.is( this.$addSectionLink ) ) {
// eslint-disable-next-line no-jquery/no-global-selector
$( '#ca-addsection' ).addClass( 'selected' );
// eslint-disable-next-line no-jquery/no-global-selector
$( '#ca-view' ).removeClass( 'selected' );
}
this.$pageContainer.addClass( 'ext-discussiontools-init-replylink-open' );
@ -142,6 +147,11 @@ ReplyLinksController.prototype.clearActiveLink = function () {
if ( this.$activeLink.is( this.$replyLinks ) ) {
this.$activeLink.closest( '.ext-discussiontools-init-replylink-buttons' )
.removeClass( 'ext-discussiontools-init-replylink-active' );
} else if ( this.$addSectionLink && this.$activeLink.is( this.$addSectionLink ) ) {
// eslint-disable-next-line no-jquery/no-global-selector
$( '#ca-addsection' ).removeClass( 'selected' );
// eslint-disable-next-line no-jquery/no-global-selector
$( '#ca-view' ).addClass( 'selected' );
}
this.$pageContainer.removeClass( 'ext-discussiontools-init-replylink-open' );

View file

@ -472,8 +472,12 @@ function init( $container, state ) {
if ( storage.get( 'reply/' + utils.NEW_TOPIC_COMMENT_ID + '/saveable' ) ) {
mode = storage.get( 'reply/' + utils.NEW_TOPIC_COMMENT_ID + '/mode' );
// eslint-disable-next-line no-jquery/no-global-selector
$link = $( '#ca-addsection' );
$link = $( '#ca-addsection a' );
setupController( utils.NEW_TOPIC_COMMENT_ID, $link, mode, true );
} else if ( mw.config.get( 'wgDiscussionToolsStartNewTopicTool' ) ) {
// eslint-disable-next-line no-jquery/no-global-selector
$link = $( '#ca-addsection a' );
setupController( utils.NEW_TOPIC_COMMENT_ID, $link );
}
// For debugging (now unused in the code)