Merge "Move TOC metadata generation to a post-processing step"

This commit is contained in:
jenkins-bot 2023-02-12 01:06:57 +00:00 committed by Gerrit Code Review
commit 5a9cb0c358
4 changed files with 59 additions and 43 deletions

View file

@ -403,6 +403,7 @@
"BeforePageDisplay": "page",
"GetActionName": "page",
"OutputPageBeforeHTML": "page",
"OutputPageParserOutput": "page",
"TitleGetEditNotices": "page",
"ResourceLoaderGetConfigVars": "resourceloader",
"GetBetaFeaturePreferences": "\\MediaWiki\\Extension\\DiscussionTools\\Hooks\\PreferenceHooks::onGetBetaFeaturePreferences",

View file

@ -57,45 +57,7 @@ class CommentFormatter {
$requestId = null;
try {
[ 'html' => $text, 'tocInfo' => $tocInfo ] =
static::addDiscussionToolsInternal( $text, $pout, $title );
// Enhance the table of contents in supporting skins (vector-2022)
// Only do the work if the ToC is present
// (Note that skins may decide to show the ToC even if
// "not recommended" (ie, the SHOW_TOC flag is false); see
// T315862.
if ( $pout->getTOCData() != null ) {
// The TOC generation no longer splits the parser cache
// by user language, but the call below to
// getUserLangObj() will do so.
// FIXME: change this to happen in a post-processing
// step (like all other transformations) to avoid
// splitting the cache.
$lang = $parser->getOptions()->getUserLangObj();
$sections = $pout->getTOCData()->getSections();
foreach ( $sections as $item ) {
$key = str_replace( '_', ' ', $item->anchor );
// Unset if we did not format this section as a topic container
if ( isset( $tocInfo[$key] ) ) {
$count = $lang->formatNum( $tocInfo[$key]['commentCount'] );
$commentCount = wfMessage(
'discussiontools-topicheader-commentcount',
$count
)->inLanguage( $lang )->text();
$summary = Html::element( 'span', [
'class' => 'ext-discussiontools-init-sidebar-meta'
], $commentCount );
} else {
$summary = '';
}
// This also shows up in API action=parse&prop=sections output.
$item->setExtensionData( 'DiscussionTools-html-summary', $summary );
}
}
$text = static::addDiscussionToolsInternal( $text, $pout, $title );
} catch ( Throwable $e ) {
// Catch errors, so that they don't cause the entire page to not display.
@ -232,9 +194,9 @@ class CommentFormatter {
* @param string $html HTML
* @param ParserOutput $pout
* @param Title $title
* @return array HTML with discussion tools and TOC info
* @return string HTML with discussion tools
*/
protected static function addDiscussionToolsInternal( string $html, ParserOutput $pout, Title $title ): array {
protected static function addDiscussionToolsInternal( string $html, ParserOutput $pout, Title $title ): string {
// The output of this method can end up in the HTTP cache (Varnish). Avoid changing it;
// and when doing so, ensure that frontend code can handle both the old and new outputs.
// See controller#init in JS.
@ -315,6 +277,8 @@ class CommentFormatter {
}
}
$pout->setExtensionData( 'DiscussionTools-tocInfo', $tocInfo );
if ( $newestCommentJSON ) {
$newestCommentMarker = $doc->createComment(
'__DTLATESTCOMMENTPAGE__' . htmlspecialchars( $newestCommentJSON, ENT_NOQUOTES ) . '__'
@ -369,7 +333,7 @@ class CommentFormatter {
// ParserOutput::EDITSECTION_REGEX matching 'mw:editsection' tags (T274709)
$html = XMLSerializer::serialize( $container, [ 'innerXML' => true, 'smartQuote' => false ] )['html'];
return [ 'html' => $html, 'tocInfo' => $tocInfo ];
return $html;
}
/**
@ -787,6 +751,42 @@ class CommentFormatter {
return null;
}
/**
* Post-process visual enhancements features for table of contents
*
* @param ParserOutput $pout
* @param Language $lang
*/
public static function postprocessTableOfContents(
ParserOutput $pout, Language $lang
): void {
$tocInfo = $pout->getExtensionData( 'DiscussionTools-tocInfo' );
if ( $tocInfo && $pout->getTOCData() ) {
$sections = $pout->getTOCData()->getSections();
foreach ( $sections as $item ) {
$key = str_replace( '_', ' ', $item->anchor );
// Unset if we did not format this section as a topic container
if ( isset( $tocInfo[$key] ) ) {
$count = $lang->formatNum( $tocInfo[$key]['commentCount'] );
$commentCount = wfMessage(
'discussiontools-topicheader-commentcount',
$count
)->inLanguage( $lang )->text();
$summary = Html::element( 'span', [
'class' => 'ext-discussiontools-init-sidebar-meta'
], $commentCount );
} else {
$summary = '';
}
// This also shows up in API action=parse&prop=sections output.
$item->setExtensionData( 'DiscussionTools-html-summary', $summary );
}
}
}
/**
* Check if the talk page had no comments or headings.
*

View file

@ -21,6 +21,7 @@ use MediaWiki\Extension\DiscussionTools\SubscriptionStore;
use MediaWiki\Extension\VisualEditor\Hooks as VisualEditorHooks;
use MediaWiki\Hook\BeforePageDisplayHook;
use MediaWiki\Hook\OutputPageBeforeHTMLHook;
use MediaWiki\Hook\OutputPageParserOutputHook;
use MediaWiki\Hook\TitleGetEditNoticesHook;
use MediaWiki\MediaWikiServices;
use MediaWiki\Page\Hook\BeforeDisplayNoArticleTextHook;
@ -30,6 +31,7 @@ use OOUI\ButtonWidget;
use OOUI\HtmlSnippet;
use OOUI\MessageWidget;
use OutputPage;
use ParserOutput;
use RequestContext;
use Skin;
use SpecialPage;
@ -40,6 +42,7 @@ class PageHooks implements
BeforePageDisplayHook,
GetActionNameHook,
OutputPageBeforeHTMLHook,
OutputPageParserOutputHook,
TitleGetEditNoticesHook
{
@ -335,6 +338,18 @@ class PageHooks implements
return true;
}
/**
* OutputPageParserOutput hook handler
* @see https://www.mediawiki.org/wiki/Manual:Hooks/OutputPageParserOutput
*
* @param OutputPage $output
* @param ParserOutput $pout ParserOutput instance being added in $output
* @return void This hook must not abort, it must return no value
*/
public function onOutputPageParserOutput( $output, $pout ): void {
CommentFormatter::postprocessTableOfContents( $pout, $output->getLanguage() );
}
/**
* GetActionName hook handler
*

View file

@ -33,7 +33,7 @@ class CommentFormatterTest extends IntegrationTestCase {
$commentFormatter = TestingAccessWrapper::newFromClass( MockCommentFormatter::class );
$pout = new ParserOutput();
[ 'html' => $preprocessed ] = $commentFormatter->addDiscussionToolsInternal( $dom, $pout, $title );
$preprocessed = $commentFormatter->addDiscussionToolsInternal( $dom, $pout, $title );
$preprocessed .= "\n<pre>\n" .
FormatJson::encode( $pout->getJsConfigVars(), "\t", FormatJson::ALL_OK ) .
"\n</pre>";