TemplatesOnThisPageFormatter.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <?php
  2. /**
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, write to the Free Software Foundation, Inc.,
  15. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. * http://www.gnu.org/copyleft/gpl.html
  17. *
  18. * @file
  19. */
  20. use MediaWiki\Linker\LinkRenderer;
  21. use MediaWiki\Linker\LinkTarget;
  22. use MediaWiki\MediaWikiServices;
  23. /**
  24. * Handles formatting for the "templates used on this page"
  25. * lists. Formerly known as Linker::formatTemplates()
  26. *
  27. * @since 1.28
  28. */
  29. class TemplatesOnThisPageFormatter {
  30. /**
  31. * @var IContextSource
  32. */
  33. private $context;
  34. /**
  35. * @var LinkRenderer
  36. */
  37. private $linkRenderer;
  38. /**
  39. * @param IContextSource $context
  40. * @param LinkRenderer $linkRenderer
  41. */
  42. public function __construct( IContextSource $context, LinkRenderer $linkRenderer ) {
  43. $this->context = $context;
  44. $this->linkRenderer = $linkRenderer;
  45. }
  46. /**
  47. * Make an HTML list of templates, and then add a "More..." link at
  48. * the bottom. If $more is null, do not add a "More..." link. If $more
  49. * is a LinkTarget, make a link to that title and use it. If $more is a string,
  50. * directly paste it in as the link (escaping needs to be done manually).
  51. *
  52. * @param LinkTarget[] $templates
  53. * @param string|bool $type 'preview' if a preview, 'section' if a section edit, false if neither
  54. * @param LinkTarget|string|null $more An escaped link for "More..." of the templates
  55. * @return string HTML output
  56. */
  57. public function format( array $templates, $type = false, $more = null ) {
  58. if ( !$templates ) {
  59. // No templates
  60. return '';
  61. }
  62. # Do a batch existence check
  63. ( new LinkBatch( $templates ) )->execute();
  64. # Construct the HTML
  65. $outText = '<div class="mw-templatesUsedExplanation">';
  66. $count = count( $templates );
  67. if ( $type === 'preview' ) {
  68. $outText .= $this->context->msg( 'templatesusedpreview' )->numParams( $count )
  69. ->parseAsBlock();
  70. } elseif ( $type === 'section' ) {
  71. $outText .= $this->context->msg( 'templatesusedsection' )->numParams( $count )
  72. ->parseAsBlock();
  73. } else {
  74. $outText .= $this->context->msg( 'templatesused' )->numParams( $count )
  75. ->parseAsBlock();
  76. }
  77. $outText .= "</div><ul>\n";
  78. usort( $templates, 'Title::compare' );
  79. foreach ( $templates as $template ) {
  80. $outText .= $this->formatTemplate( $template );
  81. }
  82. if ( $more instanceof LinkTarget ) {
  83. $outText .= Html::rawElement( 'li', [], $this->linkRenderer->makeLink(
  84. $more, $this->context->msg( 'moredotdotdot' )->text() ) );
  85. } elseif ( $more ) {
  86. // Documented as should already be escaped
  87. $outText .= Html::rawElement( 'li', [], $more );
  88. }
  89. $outText .= '</ul>';
  90. return $outText;
  91. }
  92. /**
  93. * Builds an <li> item for an individual template
  94. *
  95. * @param LinkTarget $target
  96. * @return string
  97. */
  98. private function formatTemplate( LinkTarget $target ) {
  99. // TODO Would be nice if we didn't have to use Title here
  100. $titleObj = Title::newFromLinkTarget( $target );
  101. $protected = $this->getRestrictionsText( $titleObj->getRestrictions( 'edit' ) );
  102. $editLink = $this->buildEditLink( $titleObj );
  103. return '<li>' . $this->linkRenderer->makeLink( $target )
  104. . $this->context->msg( 'word-separator' )->escaped()
  105. . $this->context->msg( 'parentheses' )->rawParams( $editLink )->escaped()
  106. . $this->context->msg( 'word-separator' )->escaped()
  107. . $protected . '</li>';
  108. }
  109. /**
  110. * If the page is protected, get the relevant text
  111. * for those restrictions
  112. *
  113. * @param array $restrictions
  114. * @return string
  115. */
  116. private function getRestrictionsText( array $restrictions ) {
  117. $protected = '';
  118. if ( !$restrictions ) {
  119. return $protected;
  120. }
  121. // Check backwards-compatible messages
  122. $msg = null;
  123. if ( $restrictions === [ 'sysop' ] ) {
  124. $msg = $this->context->msg( 'template-protected' );
  125. } elseif ( $restrictions === [ 'autoconfirmed' ] ) {
  126. $msg = $this->context->msg( 'template-semiprotected' );
  127. }
  128. if ( $msg && !$msg->isDisabled() ) {
  129. $protected = $msg->parse();
  130. } else {
  131. // Construct the message from restriction-level-*
  132. // e.g. restriction-level-sysop, restriction-level-autoconfirmed
  133. $msgs = [];
  134. foreach ( $restrictions as $r ) {
  135. $msgs[] = $this->context->msg( "restriction-level-$r" )->parse();
  136. }
  137. $protected = $this->context->msg( 'parentheses' )
  138. ->rawParams( $this->context->getLanguage()->commaList( $msgs ) )->escaped();
  139. }
  140. return $protected;
  141. }
  142. /**
  143. * Return a link to the edit page, with the text
  144. * saying "view source" if the user can't edit the page
  145. *
  146. * @param LinkTarget $titleObj
  147. * @return string
  148. */
  149. private function buildEditLink( LinkTarget $titleObj ) {
  150. if ( MediaWikiServices::getInstance()->getPermissionManager()
  151. ->quickUserCan( 'edit', $this->context->getUser(), $titleObj )
  152. ) {
  153. $linkMsg = 'editlink';
  154. } else {
  155. $linkMsg = 'viewsourcelink';
  156. }
  157. return $this->linkRenderer->makeLink(
  158. $titleObj,
  159. $this->context->msg( $linkMsg )->text(),
  160. [],
  161. [ 'action' => 'edit' ]
  162. );
  163. }
  164. }