X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Fsearch%2FSearchEngine.php;h=ea86a4b580687a478dde9d4102acd0b7d1b37281;hb=46c17ddb1ff10a1e073742c9d8b831cd915802f3;hp=7e6e8e6d0db6d1e14a7f651e611e7aa394a3312e;hpb=dd942172f81013f0866370b2acb1eee829de19d3;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/search/SearchEngine.php b/includes/search/SearchEngine.php index 7e6e8e6d0d..ea86a4b580 100644 --- a/includes/search/SearchEngine.php +++ b/includes/search/SearchEngine.php @@ -69,12 +69,27 @@ abstract class SearchEngine { /** * Perform a full text search query and return a result set. * If full text searches are not supported or disabled, return null. - * STUB + * + * As of 1.32 overriding this function is deprecated. It will + * be converted to final in 1.34. Override self::doSearchText(). * * @param string $term Raw search term * @return SearchResultSet|Status|null */ - function searchText( $term ) { + public function searchText( $term ) { + return $this->maybePaginate( function () use ( $term ) { + return $this->doSearchText( $term ); + } ); + } + + /** + * Perform a full text search query and return a result set. + * + * @param string $term Raw search term + * @return SearchResultSet|Status|null + * @since 1.32 + */ + protected function doSearchText( $term ) { return null; } @@ -85,11 +100,25 @@ abstract class SearchEngine { * The results returned by this methods are only sugegstions and * may not end up being shown to the user. * + * As of 1.32 overriding this function is deprecated. It will + * be converted to final in 1.34. Override self::doSearchArchiveTitle(). + * * @param string $term Raw search term * @return Status * @since 1.29 */ - function searchArchiveTitle( $term ) { + public function searchArchiveTitle( $term ) { + return $this->doSearchArchiveTitle( $term ); + } + + /** + * Perform a title search in the article archive. + * + * @param string $term Raw search term + * @return Status + * @since 1.32 + */ + protected function doSearchArchiveTitle( $term ) { return Status::newGood( [] ); } @@ -98,13 +127,63 @@ abstract class SearchEngine { * If title searches are not supported or disabled, return null. * STUB * + * As of 1.32 overriding this function is deprecated. It will + * be converted to final in 1.34. Override self::doSearchTitle(). + * + * @param string $term Raw search term + * @return SearchResultSet|null + */ + public function searchTitle( $term ) { + return $this->maybePaginate( function () use ( $term ) { + return $this->doSearchTitle( $term ); + } ); + } + + /** + * Perform a title-only search query and return a result set. + * * @param string $term Raw search term * @return SearchResultSet|null + * @since 1.32 */ - function searchTitle( $term ) { + protected function doSearchTitle( $term ) { return null; } + /** + * Performs an overfetch and shrink operation to determine if + * the next page is available for search engines that do not + * explicitly implement their own pagination. + * + * @param Closure $fn Takes no arguments + * @return SearchResultSet|Status|null Result of calling $fn + */ + private function maybePaginate( Closure $fn ) { + if ( $this instanceof PaginatingSearchEngine ) { + return $fn(); + } + $this->limit++; + try { + $resultSetOrStatus = $fn(); + } finally { + $this->limit--; + } + + $resultSet = null; + if ( $resultSetOrStatus instanceof SearchResultSet ) { + $resultSet = $resultSetOrStatus; + } elseif ( $resultSetOrStatus instanceof Status && + $resultSetOrStatus->getValue() instanceof SearchResultSet + ) { + $resultSet = $resultSetOrStatus->getValue(); + } + if ( $resultSet ) { + $resultSet->shrink( $this->limit ); + } + + return $resultSetOrStatus; + } + /** * @since 1.18 * @param string $feature @@ -165,6 +244,8 @@ abstract class SearchEngine { * search=test&prefix=Main_Page/Archive -> test prefix:Main Page/Archive * @param string $term * @return string + * @deprecated since 1.32 this should now be handled internally by the + * search engine */ public function transformSearchTerm( $term ) { return $term; @@ -335,12 +416,25 @@ abstract class SearchEngine { return false; } $extractedNamespace = null; + $allkeywords = []; + + $allkeywords[] = wfMessage( 'searchall' )->inContentLanguage()->text() . ":"; + // force all: so that we have a common syntax for all the wikis + if ( !in_array( 'all:', $allkeywords ) ) { + $allkeywords[] = 'all:'; + } + + $allQuery = false; + foreach ( $allkeywords as $kw ) { + if ( strncmp( $query, $kw, strlen( $kw ) ) == 0 ) { + $extractedNamespace = null; + $parsed = substr( $query, strlen( $kw ) ); + $allQuery = true; + break; + } + } - $allkeyword = wfMessage( 'searchall' )->inContentLanguage()->text() . ":"; - if ( strncmp( $query, $allkeyword, strlen( $allkeyword ) ) == 0 ) { - $extractedNamespace = null; - $parsed = substr( $query, strlen( $allkeyword ) ); - } elseif ( strpos( $query, ':' ) !== false ) { + if ( !$allQuery && strpos( $query, ':' ) !== false ) { // TODO: should we unify with PrefixSearch::extractNamespace ? $prefix = str_replace( ' ', '_', substr( $query, 0, strpos( $query, ':' ) ) ); $index = $wgContLang->getNsIndex( $prefix ); @@ -413,7 +507,7 @@ abstract class SearchEngine { * * @todo This isn't ideal, we'd really like to have content-specific handling here * @param Title $t Title we're indexing - * @param Content $c Content of the page to index + * @param Content|null $c Content of the page to index * @return string */ public function getTextFromContent( Title $t, Content $c = null ) { @@ -469,6 +563,22 @@ abstract class SearchEngine { return $search; } + /** + * Perform an overfetch of completion search results. This allows + * determining if another page of results is available. + * + * @param string $search + * @return SearchSuggestionSet + */ + protected function completionSearchBackendOverfetch( $search ) { + $this->limit++; + try { + return $this->completionSearchBackend( $search ); + } finally { + $this->limit--; + } + } + /** * Perform a completion search. * Does not resolve namespaces and does not check variants. @@ -506,7 +616,8 @@ abstract class SearchEngine { return SearchSuggestionSet::emptySuggestionSet(); // Return empty result } $search = $this->normalizeNamespaces( $search ); - return $this->processCompletionResults( $search, $this->completionSearchBackend( $search ) ); + $suggestions = $this->completionSearchBackendOverfetch( $search ); + return $this->processCompletionResults( $search, $suggestions ); } /** @@ -520,8 +631,8 @@ abstract class SearchEngine { } $search = $this->normalizeNamespaces( $search ); - $results = $this->completionSearchBackend( $search ); - $fallbackLimit = $this->limit - $results->getSize(); + $results = $this->completionSearchBackendOverfetch( $search ); + $fallbackLimit = 1 + $this->limit - $results->getSize(); if ( $fallbackLimit > 0 ) { global $wgContLang; @@ -560,15 +671,26 @@ abstract class SearchEngine { * @return SearchSuggestionSet */ protected function processCompletionResults( $search, SearchSuggestionSet $suggestions ) { + // We over-fetched to determine pagination. Shrink back down if we have extra results + // and mark if pagination is possible + $suggestions->shrink( $this->limit ); + $search = trim( $search ); // preload the titles with LinkBatch - $titles = $suggestions->map( function ( SearchSuggestion $sugg ) { + $lb = new LinkBatch( $suggestions->map( function ( SearchSuggestion $sugg ) { return $sugg->getSuggestedTitle(); - } ); - $lb = new LinkBatch( $titles ); + } ) ); $lb->setCaller( __METHOD__ ); $lb->execute(); + $diff = $suggestions->filter( function ( SearchSuggestion $sugg ) { + return $sugg->getSuggestedTitle()->isKnown(); + } ); + if ( $diff > 0 ) { + MediaWikiServices::getInstance()->getStatsdDataFactory() + ->updateCount( 'search.completion.missing', $diff ); + } + $results = $suggestions->map( function ( SearchSuggestion $sugg ) { return $sugg->getSuggestedTitle()->getPrefixedText(); } ); @@ -776,7 +898,6 @@ abstract class SearchEngine { $setAugmentors = []; $rowAugmentors = []; Hooks::run( "SearchResultsAugment", [ &$setAugmentors, &$rowAugmentors ] ); - if ( !$setAugmentors && !$rowAugmentors ) { // We're done here return;