From b16f897a05907698abb18af037688dde221575df Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Thu, 8 Sep 2016 22:56:07 -0700 Subject: [PATCH] Move Linker::formatTemplates() to separate class, remove global usage Linker::formatTemplates() was a static function that depended upon global state like $wgLang (explicitly), $wgUser & $wgTitle (implicitly). Moving it to a separate class allows us to clean it up a little bit and use modern things like RequestContext and LinkRenderer. Bug: T145177 Change-Id: Icdea8a2b299b4876feb3df3d66df3e4c104dd928 --- autoload.php | 1 + includes/DummyLinker.php | 5 + includes/EditPage.php | 33 +++- includes/Linker.php | 95 ++--------- includes/TemplatesOnThisPageFormatter.php | 183 ++++++++++++++++++++++ includes/actions/InfoAction.php | 22 +-- 6 files changed, 247 insertions(+), 92 deletions(-) create mode 100644 includes/TemplatesOnThisPageFormatter.php diff --git a/autoload.php b/autoload.php index 71f1809db9..ff33cb4493 100644 --- a/autoload.php +++ b/autoload.php @@ -1395,6 +1395,7 @@ $wgAutoloadLocalClasses = [ 'TempFSFile' => __DIR__ . '/includes/filebackend/TempFSFile.php', 'TempFileRepo' => __DIR__ . '/includes/filerepo/FileRepo.php', 'TemplateParser' => __DIR__ . '/includes/TemplateParser.php', + 'TemplatesOnThisPageFormatter' => __DIR__ . '/includes/TemplatesOnThisPageFormatter.php', 'TestFileOpPerformance' => __DIR__ . '/maintenance/fileOpPerfTest.php', 'TextContent' => __DIR__ . '/includes/content/TextContent.php', 'TextContentHandler' => __DIR__ . '/includes/content/TextContentHandler.php', diff --git a/includes/DummyLinker.php b/includes/DummyLinker.php index ba24799818..89a735e73e 100644 --- a/includes/DummyLinker.php +++ b/includes/DummyLinker.php @@ -453,12 +453,17 @@ class DummyLinker { ); } + /** + * @deprecated since 1.28, use TemplatesOnThisPageFormatter directly + */ public function formatTemplates( $templates, $preview = false, $section = false, $more = null ) { + wfDeprecated( __METHOD__, '1.28' ); + return Linker::formatTemplates( $templates, $preview, diff --git a/includes/EditPage.php b/includes/EditPage.php index 7e4e411d5e..777e93a9cd 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -21,6 +21,7 @@ */ use MediaWiki\Logger\LoggerFactory; +use MediaWiki\MediaWikiServices; /** * The edit page/HTML interface (split from Article) @@ -747,8 +748,7 @@ class EditPage { $this->showTextbox( $text, 'wpTextbox1', [ 'readonly' ] ); $wgOut->addHTML( $this->editFormTextAfterContent ); - $wgOut->addHTML( Html::rawElement( 'div', [ 'class' => 'templatesUsed' ], - Linker::formatTemplates( $this->getTemplates() ) ) ); + $wgOut->addHTML( $this->makeTemplatesOnThisPageList( $this->getTemplates() ) ); $wgOut->addModules( 'mediawiki.action.edit.collapsibleFooter' ); @@ -2744,8 +2744,7 @@ class EditPage { $wgOut->addHTML( $this->editFormTextAfterTools . "\n" ); - $wgOut->addHTML( Html::rawElement( 'div', [ 'class' => 'templatesUsed' ], - Linker::formatTemplates( $this->getTemplates(), $this->preview, $this->section != '' ) ) ); + $wgOut->addHTML( $this->makeTemplatesOnThisPageList( $this->getTemplates() ) ); $wgOut->addHTML( Html::rawElement( 'div', [ 'class' => 'hiddencats' ], Linker::formatHiddenCategories( $this->page->getHiddenCategories() ) ) ); @@ -2794,6 +2793,32 @@ class EditPage { } + /** + * Wrapper around TemplatesOnThisPageFormatter to make + * a "templates on this page" list. + * + * @param Title[] $templates + * @return string HTML + */ + protected function makeTemplatesOnThisPageList( array $templates ) { + $templateListFormatter = new TemplatesOnThisPageFormatter( + $this->context, MediaWikiServices::getInstance()->getLinkRenderer() + ); + + // preview if preview, else section if section, else false + $type = false; + if ( $this->preview ) { + $type = 'preview'; + } elseif ( $this->section != '' ) { + $type = 'section'; + } + + return Html::rawElement( 'div', [ 'class' => 'templatesUsed' ], + $templateListFormatter->format( $templates, $type ) + ); + + } + /** * Extract the section title from current section text, if any. * diff --git a/includes/Linker.php b/includes/Linker.php index bcc348e7d6..eae49e7464 100644 --- a/includes/Linker.php +++ b/includes/Linker.php @@ -1919,6 +1919,8 @@ class Linker { } /** + * @deprecated since 1.28, use TemplatesOnThisPageFormatter directly + * * Returns HTML for the "templates used on this page" list. * * Make an HTML list of templates, and then add a "More..." link at @@ -1937,87 +1939,24 @@ class Linker { public static function formatTemplates( $templates, $preview = false, $section = false, $more = null ) { - global $wgLang; - - $outText = ''; - if ( count( $templates ) > 0 ) { - # Do a batch existence check - $batch = new LinkBatch; - foreach ( $templates as $title ) { - $batch->addObj( $title ); - } - $batch->execute(); - - # Construct the HTML - $outText = '
'; - if ( $preview ) { - $outText .= wfMessage( 'templatesusedpreview' )->numParams( count( $templates ) ) - ->parseAsBlock(); - } elseif ( $section ) { - $outText .= wfMessage( 'templatesusedsection' )->numParams( count( $templates ) ) - ->parseAsBlock(); - } else { - $outText .= wfMessage( 'templatesused' )->numParams( count( $templates ) ) - ->parseAsBlock(); - } - $outText .= "
'; + if ( $more instanceof Message ) { + $more = $more->toString(); } - return $outText; + + $formatter = new TemplatesOnThisPageFormatter( + RequestContext::getMain(), + MediaWikiServices::getInstance()->getLinkRenderer() + ); + return $formatter->format( $templates, $type, $more ); } /** diff --git a/includes/TemplatesOnThisPageFormatter.php b/includes/TemplatesOnThisPageFormatter.php new file mode 100644 index 0000000000..c0ae374a05 --- /dev/null +++ b/includes/TemplatesOnThisPageFormatter.php @@ -0,0 +1,183 @@ +context = $context; + $this->linkRenderer = $linkRenderer; + } + + /** + * Make an HTML list of templates, and then add a "More..." link at + * the bottom. If $more is null, do not add a "More..." link. If $more + * is a LinkTarget, make a link to that title and use it. If $more is a string, + * directly paste it in as the link (escaping needs to be done manually). + * + * @param LinkTarget[] $templates + * @param string|bool $type 'preview' if a preview, 'section' if a section edit, false if neither + * @param LinkTarget|string|null $more An escaped link for "More..." of the templates + * @return string HTML output + */ + public function format( array $templates, $type = false, $more = null ) { + if ( !$templates ) { + // No templates + return ''; + } + + # Do a batch existence check + $batch = new LinkBatch; + foreach ( $templates as $title ) { + $batch->addObj( $title ); + } + $batch->execute(); + + # Construct the HTML + $outText = '
'; + $count = count( $templates ); + if ( $type === 'preview' ) { + $outText .= $this->context->msg( 'templatesusedpreview' )->numParams( $count ) + ->parseAsBlock(); + } elseif ( $type === 'section' ) { + $outText .= $this->context->msg( 'templatesusedsection' )->numParams( $count ) + ->parseAsBlock(); + } else { + $outText .= $this->context->msg( 'templatesused' )->numParams( $count ) + ->parseAsBlock(); + } + $outText .= "
'; + return $outText; + } + + /** + * Builds an
  • item for an individual template + * + * @param LinkTarget $target + * @return string + */ + private function formatTemplate( LinkTarget $target ) { + // TODO Would be nice if we didn't have to use Title here + $titleObj = Title::newFromLinkTarget( $target ); + $protected = $this->getRestrictionsText( $titleObj->getRestrictions( 'edit' ) ); + $editLink = $this->buildEditLink( $titleObj ); + return '
  • ' . $this->linkRenderer->makeLink( $target ) + . $this->context->msg( 'word-separator' )->escaped() + . $this->context->msg( 'parentheses' )->rawParams( $editLink )->escaped() + . $this->context->msg( 'word-separator' )->escaped() + . $protected . '
  • '; + } + + /** + * If the page is protected, get the relevant text + * for those restrictions + * + * @param array $restrictions + * @return string + */ + private function getRestrictionsText( array $restrictions ) { + $protected = ''; + if ( !$restrictions ) { + return $protected; + } + + // Check backwards-compatible messages + $msg = null; + if ( $restrictions === [ 'sysop' ] ) { + $msg = $this->context->msg( 'template-protected' ); + } elseif ( $restrictions === [ 'autoconfirmed' ] ) { + $msg = $this->context->msg( 'template-semiprotected' ); + } + if ( $msg && !$msg->isDisabled() ) { + $protected = $msg->parse(); + } else { + // Construct the message from restriction-level-* + // e.g. restriction-level-sysop, restriction-level-autoconfirmed + $msgs = []; + foreach ( $restrictions as $r ) { + $msgs[] = $this->context->msg( "restriction-level-$r" )->parse(); + } + $protected = $this->context->msg( 'parentheses' ) + ->rawParams( $this->context->getLanguage()->commaList( $msgs ) )->escaped(); + } + + return $protected; + } + + /** + * Return a link to the edit page, with the text + * saying "view source" if the user can't edit the page + * + * @param Title $titleObj + * @return string + */ + private function buildEditLink( Title $titleObj ) { + if ( $titleObj->quickUserCan( 'edit', $this->context->getUser() ) ) { + $linkMsg = 'editlink'; + } else { + $linkMsg = 'viewsourcelink'; + } + + return $this->linkRenderer->makeLink( + $titleObj, + $this->context->msg( $linkMsg )->text(), + [], + [ 'action' => 'edit' ] + ); + } + +} diff --git a/includes/actions/InfoAction.php b/includes/actions/InfoAction.php index abc7cb2f46..4d80a1cd33 100644 --- a/includes/actions/InfoAction.php +++ b/includes/actions/InfoAction.php @@ -631,14 +631,15 @@ class InfoAction extends FormlessAction { $more = null; } + $templateListFormatter = new TemplatesOnThisPageFormatter( + $this->getContext(), + $linkRenderer + ); + $pageInfo['header-properties'][] = [ $this->msg( 'pageinfo-templates' ) ->numParams( $pageCounts['transclusion']['from'] ), - Linker::formatTemplates( - $transcludedTemplates, - false, - false, - $more ) + $templateListFormatter->format( $transcludedTemplates, false, $more ) ]; } @@ -654,14 +655,15 @@ class InfoAction extends FormlessAction { $more = null; } + $templateListFormatter = new TemplatesOnThisPageFormatter( + $this->getContext(), + $linkRenderer + ); + $pageInfo['header-properties'][] = [ $this->msg( 'pageinfo-transclusions' ) ->numParams( $pageCounts['transclusion']['to'] ), - Linker::formatTemplates( - $transcludedTargets, - false, - false, - $more ) + $templateListFormatter->format( $transcludedTargets, false, $more ) ]; } } -- 2.20.1