Current File : /home/jvzmxxx/wiki1/extensions/Wikibase/repo/includes/Specials/SpecialItemDisambiguation.php
<?php

namespace Wikibase\Repo\Specials;

use HTMLForm;
use Html;
use WebRequest;
use Wikibase\ItemDisambiguation;
use Wikibase\Lib\ContentLanguages;
use Wikibase\Lib\Interactors\TermIndexSearchInteractor;
use Wikibase\Lib\Interactors\TermSearchResult;
use Wikibase\Lib\LanguageNameLookup;
use Wikibase\Lib\MediaWikiContentLanguages;
use Wikibase\Repo\WikibaseRepo;
use Wikibase\TermIndexEntry;

/**
 * Enables accessing items by providing the label of the item and the language of the label.
 * A result page is shown, disambiguating between multiple results if necessary.
 *
 * @since 0.1
 *
 * @license GPL-2.0+
 * @author John Erling Blad < jeblad@gmail.com >
 * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 * @author Daniel Kinzler
 * @author Addshore
 */
class SpecialItemDisambiguation extends SpecialWikibasePage {

	/**
	 * @var ItemDisambiguation DO NOT ACCESS DIRECTLY use this->getItemDisambiguation
	 */
	private $itemDisambiguation;

	/**
	 * @var TermIndexSearchInteractor|null DO NOT ACCESS DIRECTLY use this->getSearchInteractor
	 */
	private $searchInteractor = null;

	/**
	 * @var ContentLanguages
	 */
	private $contentLanguages;

	/**
	 * @var LanguageNameLookup
	 */
	private $languageNameLookup;

	/**
	 * @var int
	 */
	private $limit;

	/**
	 * @see SpecialWikibasePage::__construct
	 *
	 * @since 0.1
	 */
	public function __construct() {
		parent::__construct( 'ItemDisambiguation', '', true );

		// @todo inject these
		$this->contentLanguages = new MediaWikiContentLanguages();
		$this->languageNameLookup = new LanguageNameLookup();

		// @todo make this configurable
		$this->limit = 100;
	}

	/**
	 * Set service objects to use. Unit tests may call this to substitute mock
	 * services.
	 *
	 * @param ItemDisambiguation $itemDisambiguation
	 * @param TermIndexSearchInteractor $searchInteractor
	 * @param ContentLanguages $contentLanguages
	 * @param LanguageNameLookup $languageNameLookup
	 */
	public function initServices(
		ItemDisambiguation $itemDisambiguation,
		TermIndexSearchInteractor $searchInteractor,
		ContentLanguages $contentLanguages,
		LanguageNameLookup $languageNameLookup
	) {
		$this->itemDisambiguation = $itemDisambiguation;
		$this->searchInteractor = $searchInteractor;
		$this->contentLanguages = $contentLanguages;
		$this->languageNameLookup = $languageNameLookup;
	}

	/**
	 * @param string $displayLanguageCode Only used if the service does not already exist
	 *
	 * @return TermIndexSearchInteractor
	 */
	private function getSearchInteractor( $displayLanguageCode ) {
		if ( $this->searchInteractor === null ) {
			$this->searchInteractor = WikibaseRepo::getDefaultInstance()->newTermSearchInteractor(
				$displayLanguageCode
			);
		}
		return $this->searchInteractor;
	}

	/**
	 * @return ItemDisambiguation
	 */
	private function getItemDisambiguation() {
		global $wgLang;

		if ( $this->itemDisambiguation === null ) {
			$this->itemDisambiguation = new ItemDisambiguation(
				WikibaseRepo::getDefaultInstance()->getEntityTitleLookup(),
				new LanguageNameLookup( $wgLang->getCode() ),
				$this->getLanguage()->getCode()
			);
		}

		return $this->itemDisambiguation;
	}

	/**
	 * @see SpecialWikibasePage::execute
	 *
	 * @since 0.1
	 *
	 * @param string|null $subPage
	 */
	public function execute( $subPage ) {
		parent::execute( $subPage );

		$request = $this->getRequest();
		$subPageParts = $subPage === '' ? array() : explode( '/', $subPage, 2 );

		$languageCode = $this->extractLanguageCode( $request, $subPageParts );
		$label = $this->extractLabel( $request, $subPageParts );

		$this->switchForm( $languageCode, $label );

		// Display the result set
		if ( isset( $languageCode ) && isset( $label ) && $label !== '' ) {
			// @todo We could have a LanguageCodeValidator or something and handle this
			// in the search interactor or some place else.
			if ( !$this->contentLanguages->hasLanguage( $languageCode ) ) {
				$this->showErrorHTML(
					$this->msg( 'wikibase-itemdisambiguation-invalid-langcode' )->escaped()
				);
			} else {
				$searchResults = $this->getSearchResults( $label, $languageCode );

				if ( !empty( $searchResults ) ) {
					$this->displaySearchResults( $searchResults, $label );
				} else {
					$this->showNothingFound( $languageCode, $label );
				}
			}
		}
	}

	/**
	 * @param WebRequest $request
	 * @param array $subPageParts
	 *
	 * @return string
	 */
	private function extractLanguageCode( WebRequest $request, array $subPageParts ) {
		$languageCode = $request->getVal(
			'language',
			isset( $subPageParts[0] ) ? $subPageParts[0] : ''
		);

		if ( $languageCode === '' ) {
			$languageCode = $this->getLanguage()->getCode();
		}

		return $languageCode;
	}

	/**
	 * @param WebRequest $request
	 * @param array $subPageParts
	 *
	 * @return string
	 */
	private function extractLabel( WebRequest $request, array $subPageParts ) {
		if ( $request->getCheck( 'label' ) ) {
			return $request->getText( 'label' );
		}

		return isset( $subPageParts[1] ) ? str_replace( '_', ' ', $subPageParts[1] ) : '';
	}

	/**
	 * @param TermSearchResult[] $searchResults
	 * @param string $label
	 */
	private function displaySearchResults( array $searchResults, $label ) {
		$this->getOutput()->setPageTitle(
			$this->msg( 'wikibase-disambiguation-title', $label )->escaped()
		);

		$this->displayDisambiguationPage( $searchResults );
	}

	/**
	 * @param string $label
	 * @param string $languageCode
	 *
	 * @return TermSearchResult[]
	 */
	private function getSearchResults( $label, $languageCode ) {
		$searchInteractor = $this->getSearchInteractor( $this->getLanguage()->getCode() );
		$searchInteractor->setLimit( $this->limit );
		$searchInteractor->setIsCaseSensitive( false );
		$searchInteractor->setIsPrefixSearch( false );
		$searchInteractor->setUseLanguageFallback( true );

		return $searchInteractor->searchForEntities(
			$label,
			$languageCode,
			'item',
			array( TermIndexEntry::TYPE_LABEL, TermIndexEntry::TYPE_ALIAS )
		);
	}

	/**
	 * Shows information, assuming no results were found.
	 *
	 * @param string $languageCode
	 * @param string $label
	 */
	private function showNothingFound( $languageCode, $label ) {
		$this->getOutput()->addWikiMsg( 'wikibase-itemdisambiguation-nothing-found' );

		if ( $languageCode === $this->getLanguage()->getCode() ) {
			$searchLink = $this->getTitleFor( 'Search' );
			$this->getOutput()->addWikiMsg(
				'wikibase-itemdisambiguation-search',
				$searchLink->getFullURL( array( 'search' => $label ) )
			);
			$createLink = $this->getTitleFor( 'NewItem' );
			$this->getOutput()->addWikiMsg(
				'wikibase-itemdisambiguation-create',
				$createLink->getFullURL( array( 'label' => $label ) )
			);
		}
	}

	/**
	 * Display disambiguation page.
	 *
	 * @param TermSearchResult[] $searchResults
	 */
	private function displayDisambiguationPage( array $searchResults ) {
		$itemDisambiguation = $this->getItemDisambiguation();
		$html = $itemDisambiguation->getHTML( $searchResults );
		$this->getOutput()->addHTML( $html );
	}

	/**
	 * Return options for the language input field.
	 *
	 * @return array
	 */
	private function getLanguageOptions() {
		$options = array();
		foreach ( $this->contentLanguages->getLanguages() as $languageCode ) {
			$languageName = $this->languageNameLookup->getName( $languageCode );
			$options["$languageName ($languageCode)"] = $languageCode;
		}
		return $options;
	}

	/**
	 * Output a form to allow searching for labels
	 *
	 * @param string|null $languageCode
	 * @param string|null $label
	 */
	private function switchForm( $languageCode, $label ) {
		$formDescriptor = array(
			'language' => array(
				'name' => 'language',
				'default' => $languageCode ?: '',
				'type' => 'combobox',
				'options' => $this->getLanguageOptions(),
				'id' => 'wb-itemdisambiguation-languagename',
				'size' => 12,
				'cssclass' => 'wb-language-suggester',
				'label-message' => 'wikibase-itemdisambiguation-lookup-language'
			),
			'label' => array(
				'name' => 'label',
				'default' => $label ?: '',
				'type' => 'text',
				'id' => 'labelname',
				'size' => 36,
				'autofocus',
				'label-message' => 'wikibase-itemdisambiguation-lookup-label'
			),
			'submit' => array(
				'name' => '',
				'default' => $this->msg( 'wikibase-itemdisambiguation-submit' )->text(),
				'type' => 'submit',
				'id' => 'wb-itembytitle-submit',
			)
		);

		HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
			->setId( 'wb-itemdisambiguation-form1' )
			->setMethod( 'get' )
			->setFooterText( Html::element(
				'p',
				array(),
				$this->msg( 'wikibase-itemdisambiguation-form-hints' )->numParams(
					$this->limit
				)->text()
			) )
			->setWrapperLegendMsg( 'wikibase-itemdisambiguation-lookup-fieldset' )
			->suppressDefaultSubmit()
			->setSubmitCallback( function () {// no-op
			} )->show();
	}

}