skinOptions = $skinOptions; $this->languagesHelper = $languagesHelper; $this->permissionManager = $permissionManager; $this->contentHandlerFactory = $contentHandlerFactory; $this->userFactory = $userFactory; } /** * @param IContextSource $context * @return $this */ public function setContext( IContextSource $context ) { $this->title = $context->getTitle(); $this->config = $context->getConfig(); $this->performer = $context->getAuthority(); // Title may be undefined in certain contexts (T179833) // TODO: Check if this is still true if we always pass a context instead of using global one if ( $this->title ) { $this->contentHandler = $this->contentHandlerFactory->getContentHandler( $this->title->getContentModel() ); } return $this; } /** * Gets whether or not the action is allowed. * * Actions isn't allowed when: *
$wgMinervaAlwaysShowLanguageButton
is truthy.
*
* @inheritDoc
* @throws ConfigException
*/
public function isAllowed( $action ) {
global $wgHideInterlanguageLinks;
if ( !$this->title ) {
return false;
}
// T206406: Enable "Talk" or "Discussion" button on Main page, also, not forgetting
// the "switch-language" button. But disable "edit" and "watch" actions.
if ( $this->title->isMainPage() ) {
if ( $action === self::SWITCH_LANGUAGE ) {
return !$wgHideInterlanguageLinks;
}
// Only the talk page is allowed on the main page provided user is registered.
// talk page permission is disabled on mobile for anons
// https://phabricator.wikimedia.org/T54165
return $action === self::TALK && $this->performer->isRegistered();
}
if ( $action === self::TALK ) {
return (
$this->title->isTalkPage() ||
$this->title->canHaveTalkPage()
);
}
if ( $action === self::HISTORY && $this->title->exists() ) {
return $this->skinOptions->get( SkinOptions::HISTORY_IN_PAGE_ACTIONS );
}
if ( $action === SkinOptions::TOOLBAR_SUBMENU ) {
return $this->skinOptions->get( SkinOptions::TOOLBAR_SUBMENU );
}
if ( $action === self::EDIT_OR_CREATE ) {
return $this->canEditOrCreate();
}
if ( $action === self::CONTENT_EDIT ) {
return $this->isCurrentPageContentModelEditable();
}
if ( $action === self::WATCH ) {
return MediaWikiServices::getInstance()->getWatchlistManager()->isWatchable( $this->title )
? $this->performer->isAllowedAll( 'viewmywatchlist', 'editmywatchlist' )
: false;
}
if ( $action === self::SWITCH_LANGUAGE ) {
if ( $wgHideInterlanguageLinks ) {
return false;
}
return $this->languagesHelper->doesTitleHasLanguagesOrVariants( $this->title ) ||
$this->config->get( 'MinervaAlwaysShowLanguageButton' );
}
if ( $action === self::MOVE ) {
return $this->canMove();
}
if ( $action === self::DELETE ) {
return $this->canDelete();
}
if ( $action === self::PROTECT ) {
return $this->canProtect();
}
// Unknown action has been passed.
return false;
}
/**
* @inheritDoc
*/
public function isTalkAllowed() {
return $this->isAllowed( self::TALK );
}
/**
* Checks whether the editor can handle the existing content handler type.
*
* @return bool
*/
protected function isCurrentPageContentModelEditable() {
if ( !$this->contentHandler ) {
return false;
}
if (
$this->contentHandler->supportsDirectEditing() &&
$this->contentHandler->supportsDirectApiEditing()
) {
return true;
}
// For content types with custom action=edit handlers, let them do their thing
if ( array_key_exists( 'edit', $this->contentHandler->getActionOverrides() ?? [] ) ) {
return true;
}
return false;
}
/**
* Returns true if $title page exists and is editable or is creatable by $user as determined by
* quick checks.
* @return bool
*/
private function canEditOrCreate() {
if ( !$this->title ) {
return false;
}
$userQuickEditCheck =
$this->performer->probablyCan( 'edit', $this->title ) && (
$this->title->exists() ||
$this->performer->probablyCan( 'create', $this->title )
);
if ( $this->performer->isRegistered() ) {
$legacyUser = $this->userFactory->newFromAuthority( $this->performer );
$blocked = $this->permissionManager->isBlockedFrom(
$legacyUser, $this->title, true
);
} else {
$blocked = false;
}
return $this->isCurrentPageContentModelEditable() && $userQuickEditCheck && !$blocked;
}
/**
* Checks whether the user has the permissions to move the current page.
*
* @return bool
*/
private function canMove() {
if ( !$this->title ) {
return false;
}
return $this->performer->probablyCan( 'move', $this->title )
&& $this->title->exists();
}
/**
* Checks whether the user has the permissions to delete the current page.
*
* @return bool
*/
private function canDelete() {
if ( !$this->title ) {
return false;
}
return $this->performer->probablyCan( 'delete', $this->title )
&& $this->title->exists();
}
/**
* Checks whether the user has the permissions to change the protections status of the current page.
*
* @return bool
*/
private function canProtect() {
if ( !$this->title ) {
return false;
}
return $this->performer->probablyCan( 'protect', $this->title )
&& $this->title->exists();
}
}