Current File : /home/jvzmxxx/wiki/extensions/Wikibase/client/includes/Hooks/ChangesListSpecialPageHookHandlers.php
<?php

namespace Wikibase\Client\Hooks;

use ChangesListSpecialPage;
use FormOptions;
use IContextSource;
use LoadBalancer;
use LBFactory;
use RequestContext;
use User;
use WebRequest;
use Wikibase\Client\RecentChanges\RecentChangeFactory;
use Wikibase\Client\WikibaseClient;
use Wikimedia\Assert\Assert;

/**
 * @since 0.5
 *
 * @license GPL-2.0+
 * @author Katie Filbert < aude.wiki@gmail.com >
 */
class ChangesListSpecialPageHookHandlers {

	/**
	 * @var WebRequest
	 */
	private $request;

	/**
	 * @var User
	 */
	private $user;

	/**
	 * @var LoadBalancer
	 */
	private $loadBalancer;

	/**
	 * @var string
	 */
	private $pageName;

	/**
	 * @var bool
	 */
	private $showExternalChanges;

	/**
	 * @var self
	 */
	private static $instance = null;

	/**
	 * @param WebRequest $request
	 * @param User $user
	 * @param LoadBalancer $loadBalancer
	 * @param string $pageName
	 * @param bool $showExternalChanges
	 */
	public function __construct(
		WebRequest $request,
		User $user,
		LoadBalancer $loadBalancer,
		$pageName,
		$showExternalChanges
	) {
		$this->request = $request;
		$this->user = $user;
		$this->loadBalancer = $loadBalancer;
		$this->pageName = $pageName;
		$this->showExternalChanges = $showExternalChanges;
	}

	/**
	 * @param IContextSource $context
	 * @param string $specialPageName
	 *
	 * @return self
	 */
	private static function newFromGlobalState(
		IContextSource $context,
		$specialPageName
	) {
		Assert::parameterType( 'string', $specialPageName, '$specialPageName' );

		$settings = WikibaseClient::getDefaultInstance()->getSettings();

		return new self(
			$context->getRequest(),
			$context->getUser(),
			LBFactory::singleton()->getMainLB(),
			$specialPageName,
			$settings->getSetting( 'showExternalRecentChanges' )
		);
	}

	/**
	 * @param IContextSource $context
	 * @param string $specialPageName
	 *
	 * @return self
	 */
	private static function getInstance(
		IContextSource $context,
		$specialPageName
	) {
		if ( self::$instance === null ) {
			self::$instance = self::newFromGlobalState( $context, $specialPageName );
		}

		return self::$instance;
	}

	/**
	 * Modifies recent changes and watchlist options to show a toggle for Wikibase changes
	 * @see https://www.mediawiki.org/wiki/Manual:Hooks/ChangesListSpecialPageFilters
	 *
	 * @param ChangesListSpecialPage $specialPage
	 * @param array &$filters
	 *
	 * @return bool
	 */
	public static function onChangesListSpecialPageFilters(
		ChangesListSpecialPage $specialPage,
		array &$filters
	) {
		$hookHandler = self::getInstance(
			$specialPage->getContext(),
			$specialPage->getName()
		);

		$hookHandler->addFilterIfEnabled( $filters );

		return true;
	}

	/**
	 * Modifies watchlist and recent changes query to include external changes
	 * @see https://www.mediawiki.org/wiki/Manual:Hooks/ChangesListSpecialPageQuery
	 *
	 * @param string $specialPageName
	 * @param array &$tables
	 * @param array &$fields
	 * @param array &$conds
	 * @param array &$query_options
	 * @param array &$join_conds
	 * @param FormOptions $opts
	 *
	 * @return bool
	 */
	public static function onChangesListSpecialPageQuery(
		$specialPageName,
		array &$tables,
		array &$fields,
		array &$conds,
		array &$query_options,
		array &$join_conds,
		FormOptions $opts
	) {
		$hookHandler = self::getInstance(
			RequestContext::getMain(),
			$specialPageName
		);

		$conds = $hookHandler->addWikibaseConditions( $conds, $opts );

		return true;
	}

	/**
	 * @param array &$filters
	 */
	public function addFilterIfEnabled( array &$filters ) {
		if ( $this->hasWikibaseChangesEnabled() ) {
			$filterName = $this->getFilterName();

			// the toggle needs to be the inverse to invoke the inverse display status.
			// e.g. if Wikibase changes currently hidden, then when the user
			// clicks the toggle, then Wikibase changes are displayed.
			$filters[$filterName] = array(
				'msg' => 'wikibase-rc-hide-wikidata',
				'default' => !$this->hasWikibaseChangesDisplayed()
			);
		}
	}

	/**
	 * @param array &$conds
	 * @param FormOptions $opts
	 *
	 * @return array
	 */
	public function addWikibaseConditions( array &$conds, FormOptions $opts ) {
		// do not include wikibase changes for activated enhanced watchlist
		// since we do not support that format yet
		if ( $this->shouldHideWikibaseChanges( $opts ) ) {
			$dbr = $this->loadBalancer->getConnection( DB_SLAVE );
			$conds[] = 'rc_source != ' . $dbr->addQuotes( RecentChangeFactory::SRC_WIKIBASE );
			$this->loadBalancer->reuseConnection( $dbr );
		}

		return $conds;
	}

	/**
	 * @param FormOptions $opts
	 *
	 * @return boolean
	 */
	private function shouldHideWikibaseChanges( FormOptions $opts ) {
		if ( !$this->hasWikibaseChangesEnabled() ) {
			return true;
		}

		$filterName = $this->getFilterName();

		if ( !$opts->offsetExists( $filterName ) ) {
			return true;
		}

		return $opts->getValue( $filterName ) === true;
	}

	/**
	 * @return bool
	 */
	private function hasWikibaseChangesEnabled() {
		return $this->showExternalChanges && !$this->isEnhancedChangesEnabled();
	}

	/**
	 * @return bool
	 */
	private function hasWikibaseChangesDisplayed() {
		if ( $this->request->getVal( 'action' ) === 'submit' ) {
			return !$this->request->getBool( $this->getFilterName() );
		}

		// if preference enabled, then Wikibase edits are included by default and
		// the toggle default value needs to be the inverse to hide them, and vice versa.
		return $this->hasShowWikibaseEditsPrefEnabled();
	}

	/**
	 * @return bool
	 */
	private function hasShowWikibaseEditsPrefEnabled() {
		return (bool)$this->user->getOption( $this->getOptionName() );
	}

	/**
	 * @return bool
	 */
	private function isEnhancedChangesEnabled() {
		$enhancedChangesUserOption = $this->user->getOption( 'usenewrc' );

		return $this->request->getBool( 'enhanced', $enhancedChangesUserOption );
	}

	/**
	 * @return string
	 */
	private function getFilterName() {
		return 'hideWikibase';
	}

	/**
	 * @return string
	 */
	private function getOptionName() {
		if ( $this->pageName === 'Watchlist' ) {
			return 'wlshowwikibase';
		}

		return 'rcshowwikidata';
	}

}