diff options
-rw-r--r-- | includes/OutputPage.php | 1 | ||||
-rw-r--r-- | includes/skins/Skin.php | 8 | ||||
-rw-r--r-- | includes/skins/SkinTemplate.php | 51 | ||||
-rw-r--r-- | tests/phpunit/includes/skins/SkinMustacheTest.php | 2 |
4 files changed, 56 insertions, 6 deletions
diff --git a/includes/OutputPage.php b/includes/OutputPage.php index 5d09168f0452..2b8567175469 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -1483,6 +1483,7 @@ class OutputPage extends ContextSource { * page * * @return string[][] + * @return-taint none */ public function getCategoryLinks() { return $this->mCategoryLinks; diff --git a/includes/skins/Skin.php b/includes/skins/Skin.php index 0ff6011a085d..6c40766c34f0 100644 --- a/includes/skins/Skin.php +++ b/includes/skins/Skin.php @@ -2124,6 +2124,8 @@ abstract class Skin extends ContextSource { * link from. * @param array $item Contains some of a specific set of keys. * + * If "html" key is present, this will be returned. All other keys will be ignored. + * * The text of the link will be generated either from the contents of the * "text" key in the $item array, if a "msg" key is present a message by * that name will be used, and if neither of those are set the $key will be @@ -2176,6 +2178,10 @@ abstract class Skin extends ContextSource { */ final public function makeLink( $key, $item, $linkOptions = [] ) { $options = $linkOptions + $this->defaultLinkOptions; + $html = $item['html'] ?? null; + if ( $html ) { + return $html; + } $text = $item['text'] ?? $this->msg( $item['msg'] ?? $key )->text(); $html = htmlspecialchars( $text ); @@ -2263,7 +2269,7 @@ abstract class Skin extends ContextSource { * if "active" contains a value of true a "active" class will also be appended to class. * The "class" key currently accepts both a string and an array of classes, but this will be * changed to only accept an array in the future. - * @phan-param array{id?:string,class?:string|string[],itemtitle?:string,active?:bool} $item + * @phan-param array{id?:string,html?:string,class?:string|string[],itemtitle?:string,active?:bool} $item * * @param array $options * @phan-param array{tag?:string} $options diff --git a/includes/skins/SkinTemplate.php b/includes/skins/SkinTemplate.php index c5810680022f..a90a2876eda7 100644 --- a/includes/skins/SkinTemplate.php +++ b/includes/skins/SkinTemplate.php @@ -648,6 +648,25 @@ class SkinTemplate extends Skin { } /** + * @param array $links return value from OutputPage::getCategoryLinks + * @return array of data + */ + private function getCategoryPortletsData( array $links ): array { + $categories = []; + foreach ( $links as $group => $links ) { + $allLinks = []; + $groupName = 'category-' . $group; + foreach ( $links as $i => $link ) { + $allLinks[$groupName . '-' . $i] = [ + 'html' => $link, + ]; + } + $categories[ $groupName ] = $allLinks; + } + return $categories; + } + + /** * @since 1.37 for non-SkinMustache base classes. Available since 1.36 for SkinMustache * @stable to override * @param string $name of the portal e.g. p-personal the name is personal. @@ -671,10 +690,22 @@ class SkinTemplate extends Skin { $name = 'personal'; } - $id = Sanitizer::escapeIdForAttribute( "p-$name" ); + $legacyClasses = ''; + if ( $name === 'category-normal' ) { + // retain historic category IDs and classes + $id = 'mw-normal-catlinks'; + $legacyClasses .= ' mw-normal-catlinks'; + } elseif ( $name === 'category-hidden' ) { + // retain historic category IDs and classes + $id = 'mw-hidden-catlinks'; + $legacyClasses .= ' mw-hidden-catlinks mw-hidden-cats-hidden'; + } else { + $id = Sanitizer::escapeIdForAttribute( "p-$name" ); + } + $data = [ 'id' => $id, - 'class' => 'mw-portlet ' . Sanitizer::escapeClass( "mw-portlet-$name" ), + 'class' => 'mw-portlet ' . Sanitizer::escapeClass( "mw-portlet-$name" ) . $legacyClasses, 'html-tooltip' => Linker::tooltip( $id ), 'html-items' => '', // Will be populated by SkinAfterPortlet hook. @@ -710,6 +741,16 @@ class SkinTemplate extends Skin { } /** + * Extends category links with Skin::getAfterPortlet functionality. + * @return string HTML + */ + public function getCategoryLinks() { + $afterPortlet = $this->getPortletsTemplateData()['data-portlets']['data-category-normal']['html-after-portal'] + ?? ''; + return parent::getCategoryLinks() . $afterPortlet; + } + + /** * @param string $name of the portal e.g. p-personal the name is personal. * @return string that is human readable corresponding to the menu */ @@ -1193,8 +1234,8 @@ class SkinTemplate extends Skin { $performer = $this->getAuthority(); $action = $this->getAction(); $permissionManager = MediaWikiServices::getInstance()->getPermissionManager(); - - $content_navigation = [ + $categoriesData = $this->getCategoryPortletsData( $this->getOutput()->getCategoryLinks() ); + $content_navigation = $categoriesData + [ // Modern keys: Please ensure these get unset inside Skin::prepareQuickTemplate 'user-interface-preferences' => [], 'user-page' => $this->loggedin ? [ @@ -1480,7 +1521,7 @@ class SkinTemplate extends Skin { foreach ( $content_navigation as $section => &$links ) { foreach ( $links as $key => &$link ) { // Allow links to set their own id for backwards compatibility reasons. - if ( isset( $link['id'] ) ) { + if ( isset( $link['id'] ) || isset( $link['html' ] ) ) { continue; } $xmlID = $key; diff --git a/tests/phpunit/includes/skins/SkinMustacheTest.php b/tests/phpunit/includes/skins/SkinMustacheTest.php index af624c05b53a..6e2ac4b3461b 100644 --- a/tests/phpunit/includes/skins/SkinMustacheTest.php +++ b/tests/phpunit/includes/skins/SkinMustacheTest.php @@ -26,6 +26,8 @@ class SkinMustacheTest extends MediaWikiIntegrationTestCase { $mock = $this->createMock( OutputPage::class ); $mock->method( 'getHTML' ) ->willReturn( $html ); + $mock->method( 'getCategoryLinks' ) + ->willReturn( [] ); $mock->method( 'getIndicators' ) ->willReturn( [ 'id' => '<a>indicator</a>' |