mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/MinervaNeue
synced 2024-11-24 22:25:27 +00:00
333 lines
11 KiB
PHP
333 lines
11 KiB
PHP
<?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 ExtensionRegistry;
|
|
use Hooks;
|
|
use MediaWiki\Config\ServiceOptions;
|
|
use MediaWiki\Minerva\LanguagesHelper;
|
|
use MediaWiki\Minerva\Menu\Entries\IMenuEntry;
|
|
use MediaWiki\Minerva\Menu\Entries\LanguageSelectorEntry;
|
|
use MediaWiki\Minerva\Menu\Entries\SingleMenuEntry;
|
|
use MediaWiki\Minerva\Menu\Group;
|
|
use MediaWiki\Minerva\Permissions\IMinervaPagePermissions;
|
|
use MediaWiki\Minerva\SkinOptions;
|
|
use MediaWiki\Minerva\Skins\SkinUserPageHelper;
|
|
use MediaWiki\User\UserIdentity;
|
|
use MediaWiki\Watchlist\WatchlistManager;
|
|
use MessageLocalizer;
|
|
use MinervaUI;
|
|
use MWException;
|
|
use SkinMinerva;
|
|
use SpecialMobileHistory;
|
|
use SpecialPage;
|
|
use Title;
|
|
use User;
|
|
|
|
class ToolbarBuilder {
|
|
|
|
/**
|
|
* @var User Currently logged in user
|
|
*/
|
|
private $user;
|
|
/**
|
|
* @var Title Article title user is currently browsing
|
|
*/
|
|
private $title;
|
|
/**
|
|
* @var MessageLocalizer Message localizer to generate localized texts
|
|
*/
|
|
private $messageLocalizer;
|
|
/**
|
|
* @var IMinervaPagePermissions
|
|
*/
|
|
private $permissions;
|
|
|
|
/**
|
|
* @var SkinOptions
|
|
*/
|
|
private $skinOptions;
|
|
|
|
/**
|
|
* @var SkinUserPageHelper
|
|
*/
|
|
private $relevantUserPageHelper;
|
|
|
|
/**
|
|
* @var LanguagesHelper
|
|
*/
|
|
private $languagesHelper;
|
|
|
|
/**
|
|
* @var bool Correlates to $wgWatchlistExpiry feature flag.
|
|
*/
|
|
private $watchlistExpiryEnabled;
|
|
|
|
/**
|
|
* @var WatchlistManager
|
|
*/
|
|
private $watchlistManager;
|
|
|
|
/**
|
|
* ServiceOptions needed.
|
|
*/
|
|
public const CONSTRUCTOR_OPTIONS = [
|
|
'WatchlistExpiry',
|
|
];
|
|
|
|
/**
|
|
* Build Group containing icons for toolbar
|
|
* @param Title $title Article title user is currently browsing
|
|
* @param User $user Currently logged in user
|
|
* @param MessageLocalizer $msgLocalizer Message localizer to generate localized texts
|
|
* @param IMinervaPagePermissions $permissions Minerva permissions system
|
|
* @param SkinOptions $skinOptions
|
|
* @param SkinUserPageHelper $relevantUserPageHelper User Page helper. The
|
|
* UserPageHelper passed should always be specific to the user page Title. If on a
|
|
* user talk page, UserPageHelper should be instantiated with the user page
|
|
* Title and NOT with the user talk page Title.
|
|
* @param LanguagesHelper $languagesHelper Helper to check title languages/variants
|
|
* @param ServiceOptions $options
|
|
* @param WatchlistManager $watchlistManager
|
|
*/
|
|
public function __construct(
|
|
Title $title,
|
|
User $user,
|
|
MessageLocalizer $msgLocalizer,
|
|
IMinervaPagePermissions $permissions,
|
|
SkinOptions $skinOptions,
|
|
SkinUserPageHelper $relevantUserPageHelper,
|
|
LanguagesHelper $languagesHelper,
|
|
ServiceOptions $options,
|
|
WatchlistManager $watchlistManager
|
|
) {
|
|
$this->title = $title;
|
|
$this->user = $user;
|
|
$this->messageLocalizer = $msgLocalizer;
|
|
$this->permissions = $permissions;
|
|
$this->skinOptions = $skinOptions;
|
|
$this->relevantUserPageHelper = $relevantUserPageHelper;
|
|
$this->languagesHelper = $languagesHelper;
|
|
$this->watchlistExpiryEnabled = $options->get( 'WatchlistExpiry' );
|
|
$this->watchlistManager = $watchlistManager;
|
|
}
|
|
|
|
/**
|
|
* @return Group
|
|
* @throws MWException
|
|
*/
|
|
public function getGroup(): Group {
|
|
$group = new Group( 'p-views' );
|
|
$permissions = $this->permissions;
|
|
$userPageOrUserTalkPageWithOverflowMode = $this->skinOptions->get( SkinOptions::TOOLBAR_SUBMENU )
|
|
&& $this->relevantUserPageHelper->isUserPage();
|
|
|
|
if ( !$userPageOrUserTalkPageWithOverflowMode && $permissions->isAllowed(
|
|
IMinervaPagePermissions::SWITCH_LANGUAGE ) ) {
|
|
$group->insertEntry( new LanguageSelectorEntry(
|
|
$this->title,
|
|
$this->languagesHelper->doesTitleHasLanguagesOrVariants( $this->title ),
|
|
$this->messageLocalizer,
|
|
true
|
|
) );
|
|
}
|
|
|
|
if ( $permissions->isAllowed( IMinervaPagePermissions::WATCH ) ) {
|
|
$group->insertEntry( $this->createWatchPageAction() );
|
|
}
|
|
|
|
if ( $permissions->isAllowed( IMinervaPagePermissions::HISTORY ) ) {
|
|
$group->insertEntry( $this->getHistoryPageAction() );
|
|
}
|
|
|
|
$isUserPage = $this->relevantUserPageHelper->isUserPage();
|
|
$isUserPageAccessible = $this->relevantUserPageHelper->isUserPageAccessibleToCurrentUser();
|
|
if ( $isUserPage && $isUserPageAccessible ) {
|
|
// T235681: Contributions icon should be added to toolbar on user pages
|
|
// and user talk pages for all users
|
|
$user = $this->relevantUserPageHelper->getPageUser();
|
|
$group->insertEntry( $this->createContributionsPageAction( $user ) );
|
|
}
|
|
|
|
Hooks::run( 'MobileMenu', [ 'pageactions.toolbar', &$group ] );
|
|
|
|
// We want the edit icon/action always to be the last element on the toolbar list
|
|
if ( $permissions->isAllowed( IMinervaPagePermissions::CONTENT_EDIT ) ) {
|
|
$group->insertEntry( $this->createEditPageAction() );
|
|
}
|
|
return $group;
|
|
}
|
|
|
|
/**
|
|
* Create Contributions page action visible on user pages or user talk pages
|
|
* for given $user
|
|
*
|
|
* @param UserIdentity $user Determines what the contribution page action will link to
|
|
* @return IMenuEntry
|
|
*/
|
|
protected function createContributionsPageAction( UserIdentity $user ): IMenuEntry {
|
|
$label = $this->messageLocalizer->msg( 'mobile-frontend-user-page-contributions' );
|
|
|
|
$entry = new SingleMenuEntry(
|
|
'page-actions-contributions',
|
|
$label->escaped(),
|
|
SpecialPage::getTitleFor( 'Contributions', $user->getName() )->getLocalURL() );
|
|
$entry->setTitle( $label )
|
|
->trackClicks( 'contributions' )
|
|
->setIcon( 'userContributions', 'element',
|
|
// FIXME: mw-ui-icon-minerva-contributions and mw-ui-icon-minerva-userContributions
|
|
// can be removed after cache has cleared (I6c908acd70c0dca5bcb1754d1b25d3da2389feb8)
|
|
'mw-ui-icon-with-label-desktop mw-ui-icon-minerva-contributions '
|
|
. 'mw-ui-icon-minerva-userContributions'
|
|
);
|
|
|
|
return $entry;
|
|
}
|
|
|
|
/**
|
|
* Creates the "edit" page action: the well-known pencil icon that, when tapped, will open an
|
|
* editor with the lead section loaded.
|
|
*
|
|
* @return IMenuEntry An edit page actions menu entry
|
|
* @throws MWException
|
|
* @throws \Exception
|
|
*/
|
|
protected function createEditPageAction(): IMenuEntry {
|
|
$title = $this->title;
|
|
|
|
$editArgs = [ 'action' => 'edit' ];
|
|
if ( $title->isWikitextPage() ) {
|
|
// If the content model is wikitext we'll default to editing the lead section.
|
|
// Full wikitext editing is hard on mobile devices.
|
|
$editArgs['section'] = SkinMinerva::LEAD_SECTION_NUMBER;
|
|
}
|
|
|
|
$editOrCreate = $this->permissions->isAllowed( IMinervaPagePermissions::EDIT_OR_CREATE );
|
|
|
|
$entry = new SingleMenuEntry(
|
|
'page-actions-edit',
|
|
$this->messageLocalizer->msg( 'mobile-frontend-editor-edit' )->escaped(),
|
|
$title->getLocalURL( $editArgs ),
|
|
'edit-page'
|
|
);
|
|
$entry->setIcon( $editOrCreate ? 'edit-base20' : 'editLock-base20',
|
|
'element', 'mw-ui-icon-with-label-desktop', 'wikimedia' )
|
|
->trackClicks( 'edit' )
|
|
->setTitle( $this->messageLocalizer->msg( 'mobile-frontend-pageaction-edit-tooltip' ) )
|
|
->setNodeID( 'ca-edit' );
|
|
return $entry;
|
|
}
|
|
|
|
/**
|
|
* Creates the "watch" or "unwatch" action: the well-known star icon that, when tapped, will
|
|
* 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 IMenuEntry An watch/unwatch page actions menu entry
|
|
* @throws MWException
|
|
*/
|
|
protected function createWatchPageAction(): IMenuEntry {
|
|
$isWatched = $this->user->isRegistered() &&
|
|
$this->watchlistManager->isWatched( $this->user, $this->title );
|
|
$isTempWatched = $this->watchlistExpiryEnabled &&
|
|
$isWatched &&
|
|
$this->watchlistManager->isTempWatched( $this->user, $this->title );
|
|
$newModeToSet = $isWatched ? 'unwatch' : 'watch';
|
|
$href = $this->user->isRegistered()
|
|
? $this->title->getLocalURL( [ 'action' => $newModeToSet ] )
|
|
: $this->getLoginUrl( [ 'returnto' => $this->title ] );
|
|
|
|
if ( $isWatched ) {
|
|
$msg = $this->messageLocalizer->msg( 'unwatch' );
|
|
$icon = $isTempWatched ? 'halfStar-progressive' : 'unStar-progressive';
|
|
} else {
|
|
$msg = $this->messageLocalizer->msg( 'watch' );
|
|
$icon = 'star-base20';
|
|
}
|
|
|
|
$iconClass = MinervaUI::iconClass(
|
|
$icon,
|
|
'element',
|
|
'mw-ui-icon-with-label-desktop watch-this-article',
|
|
'wikimedia'
|
|
);
|
|
|
|
if ( $isTempWatched ) {
|
|
$iconClass .= ' temp-watched';
|
|
} elseif ( $isWatched ) {
|
|
$iconClass .= ' watched';
|
|
}
|
|
|
|
$entry = new SingleMenuEntry(
|
|
'page-actions-watch',
|
|
$msg->text(),
|
|
$href,
|
|
$iconClass . ' mw-watchlink'
|
|
);
|
|
return $entry->trackClicks( $newModeToSet )
|
|
->setTitle( $msg )
|
|
->setNodeID( 'ca-watch' );
|
|
}
|
|
|
|
/**
|
|
* Creates a history action: An icon that links to the mobile history page.
|
|
*
|
|
* @return IMenuEntry A menu entry object that represents a map of HTML attributes
|
|
* and a 'text' property to be used with the pageActionMenu.mustache template.
|
|
* @throws MWException
|
|
*/
|
|
protected function getHistoryPageAction(): IMenuEntry {
|
|
$entry = new SingleMenuEntry(
|
|
'page-actions-history',
|
|
$this->messageLocalizer->msg( 'minerva-page-actions-history' )->escaped(),
|
|
$this->getHistoryUrl( $this->title )
|
|
);
|
|
$entry->setIcon( 'history-base20', 'element', 'mw-ui-icon-with-label-desktop', 'wikimedia' )
|
|
->trackClicks( 'history' );
|
|
return $entry;
|
|
}
|
|
|
|
/**
|
|
* Get the URL for the history page for the given title using Special:History
|
|
* when available.
|
|
* FIXME: temporary duplicated code, same as SkinMinerva::getHistoryUrl()
|
|
* @param Title $title The Title object of the page being viewed
|
|
* @return string
|
|
* @throws MWException
|
|
*/
|
|
protected function getHistoryUrl( Title $title ) {
|
|
return ExtensionRegistry::getInstance()->isLoaded( 'MobileFrontend' ) &&
|
|
SpecialMobileHistory::shouldUseSpecialHistory( $title, $this->user ) ?
|
|
SpecialPage::getTitleFor( 'History', $title )->getLocalURL() :
|
|
$title->getLocalURL( [ 'action' => 'history' ] );
|
|
}
|
|
|
|
/**
|
|
* Prepares a url to the Special:UserLogin with query parameters
|
|
* @param array $query
|
|
* @return string
|
|
* @throws MWException
|
|
*/
|
|
private function getLoginUrl( $query ) {
|
|
return SpecialPage::getTitleFor( 'Userlogin' )->getLocalURL( $query );
|
|
}
|
|
}
|