Current File : /home/jvzmxxx/wiki/extensions/Wikibase/repo/includes/Api/ItemByTitleHelper.php
<?php

namespace Wikibase\Repo\Api;

use Profiler;
use Site;
use SiteStore;
use UsageException;
use Wikibase\DataModel\Entity\ItemId;
use Wikibase\Lib\Store\SiteLinkLookup;
use Wikibase\StringNormalizer;

/**
 * Helper class for api modules to resolve page+title pairs into items.
 *
 * @since 0.4
 *
 * @license GPL-2.0+
 * @author Marius Hoch < hoo@online.de >
 * @author Addshore
 */
class ItemByTitleHelper {

	/**
	 * @var ResultBuilder
	 */
	private $resultBuilder;

	/**
	 * @var SiteLinkLookup
	 */
	private $siteLinkLookup;

	/**
	 * @var SiteStore
	 */
	private $siteStore;

	/**
	 * @var StringNormalizer
	 */
	private $stringNormalizer;

	/**
	 * @param ResultBuilder $resultBuilder
	 * @param SiteLinkLookup $siteLinkLookup
	 * @param SiteStore $siteStore
	 * @param StringNormalizer $stringNormalizer
	 */
	public function __construct(
		ResultBuilder $resultBuilder,
		SiteLinkLookup $siteLinkLookup,
		SiteStore $siteStore,
		StringNormalizer $stringNormalizer
	) {
		$this->resultBuilder = $resultBuilder;
		$this->siteLinkLookup = $siteLinkLookup;
		$this->siteStore = $siteStore;
		$this->stringNormalizer = $stringNormalizer;
	}

	/**
	 * Tries to find item ids for given client pages.
	 *
	 * @param array $sites
	 * @param array $titles
	 * @param bool $normalize
	 *
	 * @throws UsageException
	 * @return array( ItemId[], array[] )
	 *         List containing valid ItemIds and MissingItem site title combinations
	 */
	public function getItemIds( array $sites, array $titles, $normalize ) {
		$ids = array();
		$numSites = count( $sites );
		$numTitles = count( $titles );

		// Make sure the arrays of sites and titles are not empty
		if ( $numSites === 0 || $numTitles === 0 ) {
			$this->throwUsageException(
				'Must request one site, one title, or an equal number of sites and titles',
				'param-missing'
			);
		}

		if ( $normalize && max( $numSites, $numTitles ) > 1 ) {
			// For performance reasons we only do this if the user asked for it and only for one title!
			$this->throwUsageException(
				'Normalize is only allowed if exactly one site and one page have been given',
				'params-illegal'
			);
		}

		// Restrict the crazy combinations of sites and titles that can be used
		if ( $numSites !== 1 && $numTitles !== 1 && $numSites !== $numTitles ) {
			$this->throwUsageException(
				'Must request one site, one title, or an equal number of sites and titles',
				'params-illegal'
			);
		}

		$missingItems = array();
		foreach ( $sites as $siteId ) {
			foreach ( $titles as $title ) {
				$itemId = $this->getItemId( $siteId, $title, $normalize );
				if ( !is_null( $itemId ) ) {
					$ids[] = $itemId;
				} else {
					$missingItems[] = array( 'site' => $siteId, 'title' => $title );
				}
			}
		}

		return array( $ids, $missingItems );
	}

	/**
	 * Tries to find item id for given siteId and title combination
	 *
	 * @param string $siteId
	 * @param string $title
	 * @param bool $normalize
	 *
	 * @return ItemId|null
	 */
	private function getItemId( $siteId, $title, $normalize ) {
		// FIXME: This code is duplicated in SpecialItemByTitle::execute!
		$title = $this->stringNormalizer->trimToNFC( $title );
		$id = $this->siteLinkLookup->getItemIdForLink( $siteId, $title );

		// Try harder by requesting normalization on the external site.
		if ( $id === null && $normalize === true ) {
			$siteObj = $this->siteStore->getSite( $siteId );
			//XXX: this passes the normalized title back into $title by reference...
			$this->normalizeTitle( $title, $siteObj );
			$id = $this->siteLinkLookup->getItemIdForLink( $siteObj->getGlobalId(), $title );
		}

		return $id;
	}

	/**
	 * Tries to normalize the given page title against the given client site.
	 * Updates $title accordingly and adds the normalization to the API output.
	 *
	 * @param string &$title
	 * @param Site $site
	 */
	public function normalizeTitle( &$title, Site $site ) {
		$normalizedTitle = $site->normalizePageName( $title );
		if ( $normalizedTitle !== false && $normalizedTitle !== $title ) {
			// @todo this should not be in the helper but in the module itself...
			$this->resultBuilder->addNormalizedTitle( $title, $normalizedTitle );
			//XXX: the below is an ugly hack as we pass title by reference...
			$title = $normalizedTitle;
		}
	}

	/**
	 * @param string $message
	 * @param string $code
	 *
	 * @throws UsageException always
	 */
	private function throwUsageException( $message, $code ) {
		Profiler::instance()->close();
		throw new UsageException( $message, $code );
	}

}