X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FSearchEngine.php;h=e5392f7c43cbf51a23703986548f263dcd5cafa8;hb=221967100c4eeb3c126acc0000f0e7d2250a38d0;hp=04fa906a003fe8a4f102dc6818197bb4ddb836c6;hpb=6ca27fc95fa6519aacee7ea880f0ad3b5342b884;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/SearchEngine.php b/includes/SearchEngine.php index 04fa906a00..e5392f7c43 100644 --- a/includes/SearchEngine.php +++ b/includes/SearchEngine.php @@ -13,6 +13,7 @@ class SearchEngine { var $limit = 10; var $offset = 0; + var $prefix = ''; var $searchTerms = array(); var $namespaces = array( NS_MAIN ); var $showRedirects = false; @@ -43,6 +44,19 @@ class SearchEngine { return null; } + /** If this search backend can list/unlist redirects */ + function acceptListRedirects() { + return true; + } + + /** + * Transform search term in cases when parts of the query came as different GET params (when supported) + * e.g. for prefix queries: search=test&prefix=Main_Page/Archive -> test prefix:Main Page/Archive + */ + function transformSearchTerm( $term ) { + return $term; + } + /** * If an exact title match can be find, or a very slightly close match, * return the title. If no match, returns NULL. @@ -66,8 +80,13 @@ class SearchEngine { if (is_null($title)) return NULL; - if ( $title->getNamespace() == NS_SPECIAL || $title->isExternal() - || $title->exists() ) { + if ( $title->getNamespace() == NS_SPECIAL || $title->isExternal() || $title->exists() ) { + return $title; + } + + # See if it still otherwise has content is some sane sense + $article = MediaWiki::articleFromTitle( $title ); + if( $article->hasViewableContent() ) { return $title; } @@ -98,19 +117,6 @@ class SearchEngine { return $title; } - global $wgCapitalLinks, $wgContLang; - if( !$wgCapitalLinks ) { - // Catch differs-by-first-letter-case-only - $title = Title::newFromText( $wgContLang->ucfirst( $term ) ); - if ( $title && $title->exists() ) { - return $title; - } - $title = Title::newFromText( $wgContLang->lcfirst( $term ) ); - if ( $title && $title->exists() ) { - return $title; - } - } - // Give hooks a chance at better match variants $title = null; if( !wfRunHooks( 'SearchGetNearMatch', array( $term, &$title ) ) ) { @@ -135,7 +141,7 @@ class SearchEngine { # 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_IMAGE ) { + if( $title->getNamespace() == NS_FILE ) { $image = wfFindFile( $title ); if( $image ) { return $title; @@ -158,7 +164,7 @@ class SearchEngine { } public static function legalSearchChars() { - return "A-Za-z_'0-9\\x80-\\xFF\\-"; + return "A-Za-z_'.0-9\\x80-\\xFF\\-"; } /** @@ -275,7 +281,51 @@ class SearchEngine { return array_keys($wgNamespacesToBeSearchedDefault, true); } - + + /** + * Get a list of namespace names useful for showing in tooltips + * and preferences + * + * @param unknown_type $namespaces + */ + public static function namespacesAsText( $namespaces ){ + global $wgContLang; + + $formatted = array_map( array($wgContLang,'getFormattedNsText'), $namespaces ); + foreach( $formatted as $key => $ns ){ + if ( empty($ns) ) + $formatted[$key] = wfMsg( 'blanknamespace' ); + } + return $formatted; + } + + /** + * An array of "project" namespaces indexes typically searched + * by logged-in users + * + * @return array + * @static + */ + public static function projectNamespaces() { + global $wgNamespacesToBeSearchedDefault, $wgNamespacesToBeSearchedProject; + + return array_keys( $wgNamespacesToBeSearchedProject, true ); + } + + /** + * An array of "project" namespaces indexes typically searched + * by logged-in users in addition to the default namespaces + * + * @return array + * @static + */ + public static function defaultAndProjectNamespaces() { + global $wgNamespacesToBeSearchedDefault, $wgNamespacesToBeSearchedProject; + + return array_keys( $wgNamespacesToBeSearchedDefault + + $wgNamespacesToBeSearchedProject, true); + } + /** * Return a 'cleaned up' search string * @@ -293,19 +343,14 @@ class SearchEngine { * @return SearchEngine */ public static function create() { - global $wgDBtype, $wgSearchType; + global $wgSearchType; + $dbr = wfGetDB( DB_SLAVE ); if( $wgSearchType ) { $class = $wgSearchType; - } elseif( $wgDBtype == 'mysql' ) { - $class = 'SearchMySQL'; - } else if ( $wgDBtype == 'postgres' ) { - $class = 'SearchPostgres'; - } else if ( $wgDBtype == 'oracle' ) { - $class = 'SearchOracle'; } else { - $class = 'SearchEngineDummy'; + $class = $dbr->getSearchEngine(); } - $search = new $class( wfGetDB( DB_SLAVE ) ); + $search = new $class( $dbr ); $search->setLimitOffset(0,0); return $search; } @@ -343,11 +388,11 @@ class SearchEngine { */ public static function getOpenSearchTemplate() { global $wgOpenSearchTemplate, $wgServer, $wgScriptPath; - if($wgOpenSearchTemplate) + if( $wgOpenSearchTemplate ) { return $wgOpenSearchTemplate; - else{ - $ns = implode(',',SearchEngine::defaultNamespaces()); - if(!$ns) $ns = "0"; + } else { + $ns = implode( '|', SearchEngine::defaultNamespaces() ); + if( !$ns ) $ns = "0"; return $wgServer . $wgScriptPath . '/api.php?action=opensearch&search={searchTerms}&namespace='.$ns; } } @@ -363,7 +408,7 @@ class SearchEngine { if($wgMWSuggestTemplate) return $wgMWSuggestTemplate; else - return $wgServer . $wgScriptPath . '/api.php?action=opensearch&search={searchTerms}&namespace={namespaces}'; + return $wgServer . $wgScriptPath . '/api.php?action=opensearch&search={searchTerms}&namespace={namespaces}&suggest'; } } @@ -430,7 +475,7 @@ class SearchResultSet { } /** - * @return string highlighted suggested query, '' if none + * @return string HTML highlighted suggested query, '' if none */ function getSuggestionSnippet(){ return ''; @@ -494,15 +539,22 @@ class SearchResultTooMany { /** + * @fixme This class is horribly factored. It would probably be better to have + * a useful base class to which you pass some standard information, then let + * the fancy self-highlighters extend that. * @ingroup Search */ class SearchResult { var $mRevision = null; + var $mImage = null; - function SearchResult( $row ) { + function __construct( $row ) { $this->mTitle = Title::makeTitle( $row->page_namespace, $row->page_title ); - if( !is_null($this->mTitle) ) + if( !is_null($this->mTitle) ){ $this->mRevision = Revision::newFromTitle( $this->mTitle ); + if( $this->mTitle->getNamespace() === NS_FILE ) + $this->mImage = wfFindFile( $this->mTitle ); + } } /** @@ -524,9 +576,7 @@ class SearchResult { * @access public */ function isMissingRevision(){ - if( !$this->mRevision ) - return true; - return false; + return !$this->mRevision && !$this->mImage; } /** @@ -549,7 +599,11 @@ class SearchResult { */ protected function initText(){ if( !isset($this->mText) ){ - $this->mText = $this->mRevision->getText(); + if($this->mRevision != null) + $this->mText = $this->mRevision->getText(); + else // TODO: can we fetch raw wikitext for commons images? + $this->mText = ''; + } } @@ -609,7 +663,11 @@ class SearchResult { * @return string timestamp */ function getTimestamp(){ - return $this->mRevision->getTimestamp(); + if( $this->mRevision ) + return $this->mRevision->getTimestamp(); + else if( $this->mImage ) + return $this->mImage->getTimestamp(); + return ''; } /** @@ -701,7 +759,7 @@ class SearchHighlighter { if($key == 2){ // see if this is an image link $ns = substr($val[0],2,-1); - if( $wgContLang->getNsIndex($ns) != NS_IMAGE ) + if( $wgContLang->getNsIndex($ns) != NS_FILE ) break; } @@ -756,13 +814,12 @@ class SearchHighlighter { // prepare regexps foreach( $terms as $index => $term ) { - $terms[$index] = preg_quote( $term, '/' ); // manually do upper/lowercase stuff for utf-8 since PHP won't do it if(preg_match('/[\x80-\xff]/', $term) ){ $terms[$index] = preg_replace_callback('/./us',array($this,'caseCallback'),$terms[$index]); + } else { + $terms[$index] = $term; } - - } $anyterm = implode( '|', $terms ); $phrase = implode("$wgSearchHighlightBoundaries+", $terms ); @@ -1072,7 +1129,7 @@ class SearchHighlighter { global $wgContLang; $ns = substr( $matches[1], 0, $colon ); $index = $wgContLang->getNsIndex($ns); - if( $index !== false && ($index == NS_IMAGE || $index == NS_CATEGORY) ) + if( $index !== false && ($index == NS_FILE || $index == NS_CATEGORY) ) return $matches[0]; // return the whole thing else return $matches[2]; @@ -1092,11 +1149,10 @@ class SearchHighlighter { public function highlightSimple( $text, $terms, $contextlines, $contextchars ) { global $wgLang, $wgContLang; $fname = __METHOD__; - + $lines = explode( "\n", $text ); $terms = implode( '|', $terms ); - $terms = str_replace( '/', "\\/", $terms); $max = intval( $contextchars ) + 1; $pat1 = "/(.*)($terms)(.{0,$max})/i"; @@ -1114,12 +1170,12 @@ class SearchHighlighter { continue; } --$contextlines; - $pre = $wgContLang->truncate( $m[1], -$contextchars, ' ... ' ); + $pre = $wgContLang->truncate( $m[1], -$contextchars ); if ( count( $m ) < 3 ) { $post = ''; } else { - $post = $wgContLang->truncate( $m[3], $contextchars, ' ... ' ); + $post = $wgContLang->truncate( $m[3], $contextchars ); } $found = $m[2]; @@ -1139,16 +1195,11 @@ class SearchHighlighter { } /** + * Dummy class to be used when non-supported Database engine is present. + * @fixme Dummy class should probably try something at least mildly useful, + * such as a LIKE search through titles. * @ingroup Search */ -class SearchEngineDummy { - function search( $term ) { - return null; - } - function setLimitOffset($l, $o) {} - function legalSearchChars() {} - function update() {} - function setnamespaces() {} - function searchtitle() {} - function searchtext() {} +class SearchEngineDummy extends SearchEngine { + // no-op }