PageActions menu elements should be built by using IMenuElement
To simplify and make code reusable all menu elements should be built by using Builder pattern. This a first step, first we the pageActions methods should return Group object/IMenuElement objects, then in the second step we will extract this logic into Director/Builder classes leaving SkinMinerva class much smaller. Bug: T221792 Change-Id: Ic51c4ca4139919fc3c5f3ada8b1b2fe5d23031d7
This commit is contained in:
parent
cb7dfc2dc6
commit
9d1217e13e
|
@ -34,7 +34,7 @@ class Group {
|
|||
/**
|
||||
* Return entries count
|
||||
*
|
||||
* @return int
|
||||
* @return bool
|
||||
*/
|
||||
public function hasEntries() {
|
||||
return count( $this->entries ) > 0;
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
/**
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
namespace MediaWiki\Minerva\Menu\PageActions;
|
||||
|
||||
use Message;
|
||||
use MediaWiki\Minerva\Menu\IMenuEntry;
|
||||
|
||||
class PageActionMenuEntry implements IMenuEntry {
|
||||
|
||||
/**
|
||||
* Menu entry unique identifier
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
/**
|
||||
* A definition of a menu component
|
||||
* An array containing HTML attributes and label for the menu entry
|
||||
* @var array
|
||||
*/
|
||||
private $component;
|
||||
|
||||
/**
|
||||
* PageActionMenuEntry constructor.
|
||||
* @param string $name Unique identifier
|
||||
* @param string $href And URL menu entry points to
|
||||
* @param string $componentClass A CSS class injected to component
|
||||
* @param Message $message Message
|
||||
*/
|
||||
public function __construct( $name, $href, $componentClass, Message $message ) {
|
||||
$this->name = $name;
|
||||
$this->component = [
|
||||
'href' => $href,
|
||||
'class' => $componentClass,
|
||||
'text' => $message->escaped()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Named constructor for easier class creation when we want to additionally set things
|
||||
* like title or nodeId. Mostly a syntax sugar.
|
||||
* @param string $name Unique identifier
|
||||
* @param string $href And URL menu entry points to
|
||||
* @param string $componentClass A CSS class injected to component
|
||||
* @param Message $message Message
|
||||
* @return self
|
||||
*/
|
||||
public static function create( $name, $href, $componentClass, Message $message ) {
|
||||
return new PageActionMenuEntry( $name, $href, $componentClass, $message );
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
*/
|
||||
public function getCSSClasses(): array {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getComponents(): array {
|
||||
return [ $this->component ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the menu entry title
|
||||
* @param Message $message Title message
|
||||
* @return $this
|
||||
*/
|
||||
public function setTitle( \Message $message ) {
|
||||
$this->component['title'] = $message->escaped();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Menu entry ID html attribute
|
||||
* @param string $nodeID
|
||||
* @return $this
|
||||
*/
|
||||
public function setNodeID( $nodeID ) {
|
||||
$this->component['id'] = $nodeID;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use MediaWiki\Minerva\Menu\Main\Director as MainMenuDirector;
|
||||
use MediaWiki\Minerva\Menu\Group;
|
||||
use MediaWiki\Minerva\Menu\PageActions\PageActionMenuEntry;
|
||||
use MediaWiki\Minerva\SkinOptions;
|
||||
use MediaWiki\Minerva\SkinUserPageHelper;
|
||||
|
||||
|
@ -838,23 +840,23 @@ class SkinMinerva extends SkinTemplate {
|
|||
* @param BaseTemplate $tpl
|
||||
*/
|
||||
protected function preparePageActions( BaseTemplate $tpl ) {
|
||||
$toolbar = [];
|
||||
$toolbar = new Group();
|
||||
$overflowMenu = null;
|
||||
|
||||
if ( $this->isAllowedPageAction( 'switch-language' ) ) {
|
||||
$toolbar[] = $this->createSwitchLanguageAction();
|
||||
$toolbar->insertEntry( $this->createSwitchLanguageAction() );
|
||||
}
|
||||
|
||||
if ( $this->isAllowedPageAction( 'watch' ) ) {
|
||||
$toolbar[] = $this->createWatchPageAction();
|
||||
$toolbar->insertEntry( $this->createWatchPageAction() );
|
||||
}
|
||||
|
||||
if ( $this->isAllowedPageAction( 'history' ) ) {
|
||||
$toolbar[] = $this->getHistoryPageAction();
|
||||
$toolbar->insertEntry( $this->getHistoryPageAction() );
|
||||
}
|
||||
|
||||
if ( $this->isAllowedPageAction( 'edit' ) ) {
|
||||
$toolbar[] = $this->createEditPageAction();
|
||||
$toolbar->insertEntry( $this->createEditPageAction() );
|
||||
}
|
||||
|
||||
if ( $this->isAllowedPageAction( SkinOptions::OPTION_OVERFLOW_SUBMENU ) ) {
|
||||
|
@ -862,7 +864,7 @@ class SkinMinerva extends SkinTemplate {
|
|||
}
|
||||
|
||||
$tpl->set( 'page_actions', [
|
||||
'toolbar' => $toolbar,
|
||||
'toolbar' => $toolbar->getEntries(),
|
||||
'overflowMenu' => $overflowMenu
|
||||
] );
|
||||
}
|
||||
|
@ -871,8 +873,7 @@ class SkinMinerva extends SkinTemplate {
|
|||
* Creates the "edit" page action: the well-known pencil icon that, when tapped, will open an
|
||||
* editor with the lead section loaded.
|
||||
*
|
||||
* @return array A map of HTML attributes and a "text" property to be used with the
|
||||
* pageActionMenu.mustache template.
|
||||
* @return PageActionMenuEntry An edit page actions menu entry
|
||||
*/
|
||||
protected function createEditPageAction() {
|
||||
$title = $this->getTitle();
|
||||
|
@ -888,15 +889,15 @@ class SkinMinerva extends SkinTemplate {
|
|||
$userBlockInfo = $user->getId() == 0 ? false : $user->isBlockedFrom( $title, true );
|
||||
$userCanEdit = $userQuickEditCheck && !$userBlockInfo;
|
||||
|
||||
return [
|
||||
'item-id' => 'page-actions-edit',
|
||||
'id' => 'ca-edit',
|
||||
'href' => $title->getLocalURL( $editArgs ),
|
||||
'class' => 'edit-page '
|
||||
. MinervaUI::iconClass( $userCanEdit ? 'edit-enabled' : 'edit', 'element' ),
|
||||
'title' => $this->msg( 'mobile-frontend-pageaction-edit-tooltip' ),
|
||||
'text' => $this->msg( 'mobile-frontend-editor-edit' )
|
||||
];
|
||||
return PageActionMenuEntry::create(
|
||||
'page-actions-edit',
|
||||
$title->getLocalURL( $editArgs ),
|
||||
'edit-page '
|
||||
. MinervaUI::iconClass( $userCanEdit ? 'edit-enabled' : 'edit', 'element' ),
|
||||
$this->msg( 'mobile-frontend-editor-edit' )
|
||||
)
|
||||
->setTitle( $this->msg( 'mobile-frontend-pageaction-edit-tooltip' ) )
|
||||
->setNodeID( 'ca-edit' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -904,8 +905,7 @@ class SkinMinerva extends SkinTemplate {
|
|||
* add the page to or remove the page from the user's watchlist; or, if the user is logged out,
|
||||
* will direct the user's UA to Special:Login.
|
||||
*
|
||||
* @return array A map of HTML attributes and a "text" property to be used with the
|
||||
* pageActionMenu.mustache template.
|
||||
* @return PageActionMenuEntry An watch/unwatch page actions menu entry
|
||||
*/
|
||||
protected function createWatchPageAction() {
|
||||
$title = $this->getTitle();
|
||||
|
@ -925,24 +925,24 @@ class SkinMinerva extends SkinTemplate {
|
|||
$msg = $this->msg( 'watchthispage' );
|
||||
$icon = 'watch';
|
||||
}
|
||||
return [
|
||||
'item-id' => 'page-actions-watch',
|
||||
'id' => 'ca-watch',
|
||||
// Use blank icon to reserve space for watchstar icon once JS loads
|
||||
'class' => MinervaUI::iconClass( $icon, 'element', 'watch-this-article' )
|
||||
. $additionalClassNames,
|
||||
'title' => $msg,
|
||||
'text' => $msg,
|
||||
'href' => $href
|
||||
];
|
||||
$iconClass = MinervaUI::iconClass( $icon, 'element', 'watch-this-article' );
|
||||
|
||||
return PageActionMenuEntry::create(
|
||||
'page-actions-watch',
|
||||
$href,
|
||||
$iconClass . $additionalClassNames,
|
||||
$msg
|
||||
)
|
||||
->setTitle( $msg )
|
||||
->setNodeID( 'ca-watch' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the "switch-language" action: the icon that, when tapped, opens the language
|
||||
* switcher.
|
||||
*
|
||||
* @return array A map of HTML attributes and a 'text' property to be used with the
|
||||
* pageActionMenu.mustache template.
|
||||
* @return PageActionMenuEntry A menu entry object that represents a map of HTML attributes
|
||||
* and a 'text' property to be used with the pageActionMenu.mustache template.
|
||||
*/
|
||||
protected function createSwitchLanguageAction() {
|
||||
$languageSwitcherLink = false;
|
||||
|
@ -956,13 +956,12 @@ class SkinMinerva extends SkinTemplate {
|
|||
} else {
|
||||
$languageSwitcherClasses .= ' disabled';
|
||||
}
|
||||
return [
|
||||
'item-id' => 'page-actions-languages',
|
||||
'class' => MinervaUI::iconClass( 'language-switcher', 'element', $languageSwitcherClasses ),
|
||||
'href' => $languageSwitcherLink,
|
||||
'title' => $this->msg( 'mobile-frontend-language-article-heading' ),
|
||||
'text' => $this->msg( 'mobile-frontend-language-article-heading' )
|
||||
];
|
||||
return PageActionMenuEntry::create(
|
||||
'page-actions-languages',
|
||||
$languageSwitcherLink,
|
||||
MinervaUI::iconClass( 'language-switcher', 'element', $languageSwitcherClasses ),
|
||||
$this->msg( 'mobile-frontend-language-article-heading' )
|
||||
)->setTitle( $this->msg( 'mobile-frontend-language-article-heading' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -976,16 +975,16 @@ class SkinMinerva extends SkinTemplate {
|
|||
/**
|
||||
* Creates a history action: An icon that links to the mobile history page.
|
||||
*
|
||||
* @return array A map of HTML attributes and a 'text' property to be used with the
|
||||
* pageActionMenu.mustache template.
|
||||
* @return PageActionMenuEntry A menu entry object that represents a map of HTML attributes
|
||||
* and a 'text' property to be used with the pageActionMenu.mustache template.
|
||||
*/
|
||||
protected function getHistoryPageAction() {
|
||||
return [
|
||||
'item-id' => 'page-actions-history',
|
||||
'class' => MinervaUI::iconClass( 'clock' ),
|
||||
'text' => $this->msg( 'mobile-frontend-history' ),
|
||||
'href' => $this->getHistoryUrl( $this->getTitle() )
|
||||
];
|
||||
return new PageActionMenuEntry(
|
||||
'page-actions-history',
|
||||
$this->getHistoryUrl( $this->getTitle() ),
|
||||
MinervaUI::iconClass( 'clock' ),
|
||||
$this->msg( 'mobile-frontend-history' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1006,20 +1005,22 @@ class SkinMinerva extends SkinTemplate {
|
|||
$pageActions = $this->getUserPageHelper()->isUserPage()
|
||||
? $this->getUserNamespaceOverflowPageActions( $tpl )
|
||||
: $this->getDefaultOverflowPageActions( $tpl );
|
||||
return empty( $pageActions ) ? null : [
|
||||
return $pageActions->hasEntries() ? [
|
||||
'item-id' => 'page-actions-overflow',
|
||||
'class' => MinervaUI::iconClass( 'page-actions-overflow' ),
|
||||
'text' => $this->msg( 'minerva-page-actions-overflow' ),
|
||||
'pageActions' => $pageActions
|
||||
];
|
||||
'pageActions' => $pageActions->getEntries()
|
||||
] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BaseTemplate $tpl
|
||||
* @return array
|
||||
* @return Group
|
||||
*/
|
||||
private function getDefaultOverflowPageActions( BaseTemplate $tpl ) {
|
||||
return array_values( array_filter( [
|
||||
$group = new Group();
|
||||
|
||||
foreach ( [
|
||||
$this->newOverflowPageAction( 'info', 'info', $tpl->data['nav_urls']['info']['href'] ?? null ),
|
||||
$this->newOverflowPageAction(
|
||||
'permalink', 'link', $tpl->data['nav_urls']['permalink']['href'] ?? null
|
||||
|
@ -1030,7 +1031,12 @@ class SkinMinerva extends SkinTemplate {
|
|||
$this->newOverflowPageAction(
|
||||
'cite', 'quotes', $tpl->data['nav_urls']['citethispage']['href'] ?? null
|
||||
)
|
||||
] ) );
|
||||
] as $menuEntry ) {
|
||||
if ( $menuEntry !== null ) {
|
||||
$group->insertEntry( $menuEntry );
|
||||
}
|
||||
}
|
||||
return $group;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1049,11 +1055,12 @@ class SkinMinerva extends SkinTemplate {
|
|||
|
||||
/**
|
||||
* @param BaseTemplate $tpl
|
||||
* @return array
|
||||
* @return Group
|
||||
*/
|
||||
private function getUserNamespaceOverflowPageActions( BaseTemplate $tpl ) {
|
||||
$pageUser = $this->getUserPageHelper()->getPageUser();
|
||||
return [
|
||||
$group = new Group();
|
||||
foreach ( [
|
||||
$this->newOverflowPageAction(
|
||||
'uploads', 'upload', SpecialPage::getTitleFor( 'Uploads', $pageUser )->getLocalURL()
|
||||
),
|
||||
|
@ -1070,22 +1077,28 @@ class SkinMinerva extends SkinTemplate {
|
|||
$this->newOverflowPageAction(
|
||||
'backlinks', 'articleRedirect', $tpl->data['nav_urls']['whatlinkshere']['href'] ?? null
|
||||
)
|
||||
];
|
||||
] as $menuEntry ) {
|
||||
if ( $menuEntry !== null ) {
|
||||
$group->insertEntry( $menuEntry );
|
||||
}
|
||||
}
|
||||
return $group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $icon Wikimedia UI icon name.
|
||||
* @param string|null $href
|
||||
* @return array
|
||||
* @return PageActionMenuEntry|null
|
||||
*/
|
||||
private function newOverflowPageAction( $name, $icon, $href ) {
|
||||
return $href ? [
|
||||
'item-id' => 'page-actions-overflow-' . $name,
|
||||
'class' => MinervaUI::iconClass( '', 'before', 'wikimedia-ui-' . $icon . '-base20' ),
|
||||
'text' => $this->msg( 'minerva-page-actions-' . $name ),
|
||||
'href' => $href
|
||||
] : null;
|
||||
return $href ?
|
||||
new PageActionMenuEntry(
|
||||
'page-actions-overflow-' . $name,
|
||||
$href,
|
||||
MinervaUI::iconClass( '', 'before', 'wikimedia-ui-' . $icon . '-base20' ),
|
||||
$this->msg( 'minerva-page-actions-' . $name )
|
||||
) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<nav class="page-actions-menu">
|
||||
<ul id="page-actions" class="page-actions-menu__list">
|
||||
{{#toolbar}}
|
||||
<li id="{{item-id}}" class="page-actions-menu__list-item">
|
||||
<a id="{{id}}" href="{{href}}" class="{{class}}" role="button" title="{{title}}">
|
||||
{{text}}
|
||||
</a>
|
||||
<li id="{{name}}" class="page-actions-menu__list-item">
|
||||
{{#components}}
|
||||
<a id="{{id}}" href="{{href}}" class="{{class}}" data-event-name="{{data-event-name}}" role="button" title="{{title}}">
|
||||
{{text}}
|
||||
</a>
|
||||
{{/components}}
|
||||
</li>
|
||||
{{/toolbar}}
|
||||
{{#overflowMenu}}
|
||||
|
@ -15,10 +17,12 @@
|
|||
</label>
|
||||
<ul class="toolbar-overflow-menu__list">
|
||||
{{#pageActions}}
|
||||
<li>
|
||||
<a id="{{id}}" href="{{href}}" class="toolbar-overflow-menu__list-item {{class}}" title="{{title}}">
|
||||
{{text}}
|
||||
</a>
|
||||
<li id="{{name}}">
|
||||
{{#components}}
|
||||
<a id="{{id}}" href="{{href}}" class="toolbar-overflow-menu__list-item {{class}}" title="{{title}}">
|
||||
{{text}}
|
||||
</a>
|
||||
{{/components}}
|
||||
</li>
|
||||
{{/pageActions}}
|
||||
</ul>
|
||||
|
|
Loading…
Reference in New Issue