%PDF- %PDF-
Direktori : /www/varak.net/wiki.varak.net/extensions/CirrusSearch/includes/ |
Current File : /www/varak.net/wiki.varak.net/extensions/CirrusSearch/includes/SearchConfig.php |
<?php namespace CirrusSearch; use Config; use RequestContext; /** * Configuration class encapsulating Searcher environment. * This config class can import settings from the environment globals, * or from specific wiki configuration. */ class SearchConfig implements \Config { // Constants for referring to various config values. Helps prevent fat-fingers const INDEX_BASE_NAME = 'CirrusSearchIndexBaseName'; const PREFIX_IDS = 'CirrusSearchPrefixIds'; /** * Override settings * @var Config */ private $source; /** * Wiki variables prefix. * @var string */ private $prefix = ''; /** * Interwiki name for this wiki * @var string */ private $interwiki; /** * Wiki id or null for current wiki * @var string|null */ private $wikiId; /** * @var string[]|null writable clusters (lazy loaded, call * getWritableClusters() instead of direct access) */ private $writableClusters; /** * @var string[]|null clusters available (lazy loaded, call * getAvailableClusters() instead of direct access) */ private $availableClusters; /** * Create new search config for current or other wiki. * @param string|null $overrideWiki Interwiki link name for wiki * @param string|null $overrideName DB name for the wiki */ public function __construct( $overrideWiki = null, $overrideName = null ) { $this->interwiki = $overrideWiki; if ( $overrideWiki && $overrideName ) { $this->wikiId = $overrideName; if ( $this->wikiId != wfWikiID() ) { $this->source = new \HashConfig( $this->getConfigVars( $overrideName, 'wgCirrus' ) ); $this->prefix = 'wg'; // Re-create language object $this->source->set( 'wgContLang', \Language::factory( $this->source->get( 'wgLanguageCode' ) ) ); return; } } $this->source = new \GlobalVarConfig(); $this->wikiId = wfWikiID(); } /** * Get search config vars from other wiki's config * @param string $wiki Target wiki * @param string $prefix Cirrus variables prefix * @return array */ private function getConfigVars( $wiki, $prefix ) { global $wgConf; $cirrusVars = array_filter( array_keys($GLOBALS), function($key) use($prefix) { if ( !isset( $GLOBALS[$key] ) || is_object( $GLOBALS[$key] ) ) { return false; } return strncmp( $key, $prefix, strlen($prefix) ) === 0; } ); $cirrusVars[] = 'wgLanguageCode'; // Hack to work around https://phabricator.wikimedia.org/T111441 putenv( 'REQUEST_METHOD' ); return $wgConf->getConfig( $wiki, $cirrusVars ); } /** * @param string $name * @return bool */ public function has($name) { return $this->source->has( $this->prefix . $name ); } /** * @param string $name * @return mixed */ public function get($name) { if ( !$this->source->has( $this->prefix . $name ) ) { return null; } return $this->source->get( $this->prefix . $name ); } /** * Produce new configuration from globals * @return SearchConfig */ public static function newFromGlobals() { return new self(); } /** * Return configured Wiki ID * @return string */ public function getWikiId() { return $this->wikiId; } /** * @todo * The indices have to be rebuilt with new id's and we have to know when * generating queries if new style id's are being used, or old style. It * could plausibly be done with the metastore index, but that seems like * overkill because the knowledge is only necessary during transition, and * not post-transition. Additionally this function would then need to know * the name of the index being queried, and that isn't always known when * building. * * @param string|int $pageId * @return string */ public function makeId( $pageId ) { $prefix = $this->get( self::PREFIX_IDS ) ? $this->getWikiId() : null; if ( $prefix === null ) { return (string) $pageId; } else { return "{$prefix}|{$pageId}"; } } /** * There are times, such as when using the Reindexer, when we aren't completely * sure if these are old style numeric page id's, or new style prefixed id's. * Do some magic to decide and self::makeId() when necessary. * * @param string|int $pageOrDocId * @return string */ public function maybeMakeId( $pageOrDocId ) { if ( !is_string( $pageOrDocId ) || ctype_digit( $pageOrDocId ) ) { return $this->makeId( $pageOrDocId ); } else { return $pageOrDocId; } } /** * Convert an elasticsearch document id back into a mediawiki page id. * * @param string $docId Elasticsearch document id * @return int Related mediawiki page id */ public function makePageId( $docId ) { if ( !$this->get( self::PREFIX_IDS ) ) { return (int)$docId; } $pieces = explode( '|', $docId ); switch( count( $pieces ) ) { case 2: return (int)$pieces[1]; case 1: // Broken doc id...assume somehow this didn't get prefixed. // Attempt to continue on...but maybe should throw exception // instead? return (int)$docId; default: throw new \Exception( "Invalid document id: $docId" ); } } /** * Get user's language * @return string User's language code */ public function getUserLanguage() { // I suppose using $wgLang would've been more evil than this, but // only marginally so. Find some real context to use here. return RequestContext::getMain()->getLanguage()->getCode(); } /** * Get wiki's interwiki code * @return string */ public function getWikiCode() { return $this->interwiki; } /** * Get chain of elements from config array * @param string $configName * @param string ... list of path elements * @return mixed Returns value or null if not present */ public function getElement($configName) { if( !$this->has( $configName ) ) { return null; } $data = $this->get( $configName ); $path = func_get_args(); array_shift( $path ); foreach( $path as $el ) { if( !isset( $data[$el] ) ) { return null; } $data = $data[$el]; } return $data; } /** * For Unit tests * @param Config $source Config override source */ protected function setSource( Config $source ) { $this->source = $source; } /** * @return string[] array of all the cluster names defined in this config */ public function getAvailableClusters() { if ( $this->availableClusters === null ) { $this->initClusterConfig(); } return $this->availableClusters; } /** * @return string[] array of all the clusters allowed to receive write operations */ public function getWritableClusters() { if ( $this->writableClusters === null ) { $this->initClusterConfig(); } return $this->writableClusters; } /** * Check if a cluster is declared "writable". * NOTE: a cluster is considered writable even if one of its index is * frozen. * Before sending any writes in this cluster, the forzen index status * must be checked fr the target index. * @see DataSender::areIndexesAvailableForWrites() * * @param string $cluster * @retirn bool true is the cluster is writable */ public function canWriteToCluster( $cluster ) { return in_array( $cluster, $this->getWritableClusters() ); } /** * Check if this cluster is defined. * NOTE: this cluster may not be available for writes. * * @param string $cluster * @retirn bool true is the cluster is writable */ public function clusterExists( $cluster ) { return in_array( $cluster, $this->getAvailableClusters() ); } /** * Initialization of availableClusters and writableClusters */ private function initClusterConfig() { $this->availableClusters = array_keys( $this->get( 'CirrusSearchClusters' ) ); if( $this->has( 'CirrusSearchWriteClusters' ) ) { $this->writableClusters = $this->get( 'CirrusSearchWriteClusters' ); if( is_null( $this->writableClusters ) ) { $this->writableClusters = array_keys( $this->get( 'CirrusSearchClusters' ) ); } } else { $this->writableClusters = $this->availableClusters; } } }