skinOptions = $skinOptions; $this->languagesHelper = $languagesHelper; $this->permissionManager = $permissionManager; } /** * @param IContextSource $context * @param ContentHandler|null $contentHandler (for unit tests only) * @return $this */ public function setContext( IContextSource $context, ContentHandler $contentHandler = null ) { $this->title = $context->getTitle(); $this->config = $context->getConfig(); $this->user = $context->getUser(); // 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 = $contentHandler ?: ContentHandler::getForTitle( $this->title ); } return $this; } /** * Gets whether or not the action is allowed. * * Actions isn't allowed when: * * * The "edit" action is not allowed if editing is not possible on the page * @see method isCurrentPageContentModelEditable * * The "switch-language" is allowed if there are interlanguage links on the page, * or $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 ( !in_array( $action, $this->config->get( 'MinervaPageActions' ) ) ) { return false; } if ( $action === self::SWITCH_LANGUAGE ) { return !$wgHideInterlanguageLinks; } return $action === self::TALK; } 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 ( !in_array( $action, $this->config->get( 'MinervaPageActions' ) ) ) { return false; } if ( $action === self::CONTENT_EDIT ) { return $this->isCurrentPageContentModelEditable(); } if ( $action === self::WATCH ) { return $this->title->isWatchable() ? $this->user->isAllowedAll( 'viewmywatchlist', 'editmywatchlist' ) : false; } if ( $action === self::SWITCH_LANGUAGE ) { if ( $wgHideInterlanguageLinks ) { return false; } return $this->languagesHelper->doesTitleHasLanguagesOrVariants( $this->title ) || $this->config->get( 'MinervaAlwaysShowLanguageButton' ); } return true; } /** * @inheritDoc */ public function isTalkAllowed() { if ( !$this->title ) { return false; } return $this->isAllowed( self::TALK ) && ( $this->title->isTalkPage() || $this->title->canHaveTalkPage() ) && $this->user->isLoggedIn(); } /** * Checks whether the editor can handle the existing content handler type. * * @return bool */ protected function isCurrentPageContentModelEditable() { return $this->contentHandler && $this->contentHandler->supportsDirectEditing() && $this->contentHandler->supportsDirectApiEditing(); } /** * 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->permissionManager->userCan( 'edit', $this->user, $this->title, PermissionManager::RIGOR_QUICK ) && ( $this->title->exists() || $this->permissionManager->userCan( 'create', $this->user, $this->title, PermissionManager::RIGOR_QUICK ) ); $blocked = $this->user->isAnon() ? false : $this->permissionManager->isBlockedFrom( $this->user, $this->title, true ); return $this->isCurrentPageContentModelEditable() && $userQuickEditCheck && !$blocked; } }