X-Git-Url: https://scripts.mit.edu/gitweb/autoinstallsdev/mediawiki.git/blobdiff_plain/19e297c21b10b1b8a3acad5e73fc71dcb35db44a..6932310fd58ebef145fa01eb76edf7150284d8ea:/includes/search/SearchNearMatcher.php diff --git a/includes/search/SearchNearMatcher.php b/includes/search/SearchNearMatcher.php new file mode 100644 index 00000000..27046f31 --- /dev/null +++ b/includes/search/SearchNearMatcher.php @@ -0,0 +1,167 @@ +config = $config; + $this->language = $lang; + } + + /** + * If an exact title match can be found, or a very slightly close match, + * return the title. If no match, returns NULL. + * + * @param string $searchterm + * @return Title + */ + public function getNearMatch( $searchterm ) { + $title = $this->getNearMatchInternal( $searchterm ); + + Hooks::run( 'SearchGetNearMatchComplete', [ $searchterm, &$title ] ); + return $title; + } + + /** + * Do a near match (see SearchEngine::getNearMatch) and wrap it into a + * SearchResultSet. + * + * @param string $searchterm + * @return SearchResultSet + */ + public function getNearMatchResultSet( $searchterm ) { + return new SearchNearMatchResultSet( $this->getNearMatch( $searchterm ) ); + } + + /** + * Really find the title match. + * @param string $searchterm + * @return null|Title + */ + protected function getNearMatchInternal( $searchterm ) { + $lang = $this->language; + + $allSearchTerms = [ $searchterm ]; + + if ( $lang->hasVariants() ) { + $allSearchTerms = array_unique( array_merge( + $allSearchTerms, + $lang->autoConvertToAllVariants( $searchterm ) + ) ); + } + + $titleResult = null; + if ( !Hooks::run( 'SearchGetNearMatchBefore', [ $allSearchTerms, &$titleResult ] ) ) { + return $titleResult; + } + + foreach ( $allSearchTerms as $term ) { + # Exact match? No need to look further. + $title = Title::newFromText( $term ); + if ( is_null( $title ) ) { + return null; + } + + # Try files if searching in the Media: namespace + if ( $title->getNamespace() == NS_MEDIA ) { + $title = Title::makeTitle( NS_FILE, $title->getText() ); + } + + if ( $title->isSpecialPage() || $title->isExternal() || $title->exists() ) { + return $title; + } + + # See if it still otherwise has content is some sane sense + $page = WikiPage::factory( $title ); + if ( $page->hasViewableContent() ) { + return $title; + } + + if ( !Hooks::run( 'SearchAfterNoDirectMatch', [ $term, &$title ] ) ) { + return $title; + } + + # Now try all lower case (i.e. first letter capitalized) + $title = Title::newFromText( $lang->lc( $term ) ); + if ( $title && $title->exists() ) { + return $title; + } + + # Now try capitalized string + $title = Title::newFromText( $lang->ucwords( $term ) ); + if ( $title && $title->exists() ) { + return $title; + } + + # Now try all upper case + $title = Title::newFromText( $lang->uc( $term ) ); + if ( $title && $title->exists() ) { + return $title; + } + + # Now try Word-Caps-Breaking-At-Word-Breaks, for hyphenated names etc + $title = Title::newFromText( $lang->ucwordbreaks( $term ) ); + if ( $title && $title->exists() ) { + return $title; + } + + // Give hooks a chance at better match variants + $title = null; + if ( !Hooks::run( 'SearchGetNearMatch', [ $term, &$title ] ) ) { + return $title; + } + } + + $title = Title::newFromText( $searchterm ); + + # Entering an IP address goes to the contributions page + if ( $this->config->get( 'EnableSearchContributorsByIP' ) ) { + if ( ( $title->getNamespace() == NS_USER && User::isIP( $title->getText() ) ) + || User::isIP( trim( $searchterm ) ) ) { + return SpecialPage::getTitleFor( 'Contributions', $title->getDBkey() ); + } + } + + # Entering a user goes to the user page whether it's there or not + if ( $title->getNamespace() == NS_USER ) { + return $title; + } + + # Go to images that exist even if there's no local page. + # There may have been a funny upload, or it may be on a shared + # file repository such as Wikimedia Commons. + if ( $title->getNamespace() == NS_FILE ) { + $image = wfFindFile( $title ); + if ( $image ) { + return $title; + } + } + + # MediaWiki namespace? Page may be "implied" if not customized. + # Just return it, with caps forced as the message system likes it. + if ( $title->getNamespace() == NS_MEDIAWIKI ) { + return Title::makeTitle( NS_MEDIAWIKI, $lang->ucfirst( $title->getText() ) ); + } + + # Quoted term? Try without the quotes... + $matches = []; + if ( preg_match( '/^"([^"]+)"$/', $searchterm, $matches ) ) { + return self::getNearMatch( $matches[1] ); + } + + return null; + } +}