X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FSpecialSearch.php;h=b58f91d0305e22b5c58b560b7abc781084b5d448;hb=3de6fd8c819d21bb3814a6f97d429c1912f5c048;hp=ad3600eb3c06c2752ac5b8a5a4d08773bcedfd7f;hpb=8ffff3e2e073ee4ce13e35799cbec94997b65a20;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/SpecialSearch.php b/includes/SpecialSearch.php index ad3600eb3c..b58f91d030 100644 --- a/includes/SpecialSearch.php +++ b/includes/SpecialSearch.php @@ -1,33 +1,35 @@ # http://www.mediawiki.org/ -# +# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # http://www.gnu.org/copyleft/gpl.html /** * Run text & title search and display the output - * @package MediaWiki - * @subpackage SpecialPage + * @addtogroup SpecialPage */ -require_once( 'SearchEngine.php' ); - -function wfSpecialSearch( $par='' ) { +/** + * Entry point + * + * @param $par String: (default '') + */ +function wfSpecialSearch( $par = '' ) { global $wgRequest, $wgUser; - + $search = $wgRequest->getText( 'search', $par ); $searchPage = new SpecialSearch( $wgRequest, $wgUser ); if( $wgRequest->getVal( 'fulltext' ) || @@ -39,45 +41,48 @@ function wfSpecialSearch( $par='' ) { } } - +/** + * @todo document + * @addtogroup SpecialPage + */ class SpecialSearch { + /** * Set up basic search parameters from the request and user settings. * Typically you'll pass $wgRequest and $wgUser. * * @param WebRequest $request * @param User $user - * @access public + * @public */ function SpecialSearch( &$request, &$user ) { list( $this->limit, $this->offset ) = $request->getLimitOffset( 20, 'searchlimit' ); - + if( $request->getCheck( 'searchx' ) ) { $this->namespaces = $this->powerSearch( $request ); } else { $this->namespaces = $this->userNamespaces( $user ); } - - $this->searchRedirects = false; + + $this->searchRedirects = $request->getcheck( 'redirs' ) ? true : false; } - + /** - * If an exact title match can be found, jump straight ahead to + * If an exact title match can be found, jump straight ahead to it. * @param string $term - * @access public + * @public */ function goResult( $term ) { global $wgOut; global $wgGoToEdit; - + $this->setupPage( $term ); # Try to go to page as entered. - # $t = Title::newFromText( $term ); # If the string cannot be used to create a title - if( is_null( $t ) ){ + if( is_null( $t ) ){ return $this->showResults( $term ); } @@ -87,60 +92,73 @@ class SpecialSearch { $wgOut->redirect( $t->getFullURL() ); return; } - + # No match, generate an edit URL $t = Title::newFromText( $term ); - if( is_null( $t ) ) { - $editurl = ''; # hrm... - } else { + if( ! is_null( $t ) ) { + wfRunHooks( 'SpecialSearchNogomatch', array( &$t ) ); # If the feature is enabled, go straight to the edit page if ( $wgGoToEdit ) { $wgOut->redirect( $t->getFullURL( 'action=edit' ) ); return; - } else { - $editurl = $t->escapeLocalURL( 'action=edit' ); - } + } } - # FIXME: HTML in wiki message - $wgOut->addHTML( '

' . wfMsg('nogomatch', $editurl, htmlspecialchars( $term ) ) . "

\n" ); + $wgOut->addWikiText( wfMsg( 'noexactmatch', wfEscapeWikiText( $term ) ) ); return $this->showResults( $term ); } - + /** * @param string $term - * @access public + * @public */ function showResults( $term ) { + $fname = 'SpecialSearch::showResults'; + wfProfileIn( $fname ); + $this->setupPage( $term ); - - global $wgUser, $wgOut; - $sk = $wgUser->getSkin(); + + global $wgOut; $wgOut->addWikiText( wfMsg( 'searchresulttext' ) ); - + #if ( !$this->parseQuery() ) { if( '' === trim( $term ) ) { - $wgOut->addWikiText( - '==' . wfMsg( 'badquery' ) . "==\n" . - wfMsg( 'badquerytext' ) ); + $wgOut->setSubtitle( '' ); + $wgOut->addHTML( $this->powerSearchBox( $term ) ); + wfProfileOut( $fname ); return; } - + global $wgDisableTextSearch; if ( $wgDisableTextSearch ) { + global $wgForwardSearchUrl; + if( $wgForwardSearchUrl ) { + $url = str_replace( '$1', urlencode( $term ), $wgForwardSearchUrl ); + $wgOut->redirect( $url ); + return; + } global $wgInputEncoding; $wgOut->addHTML( wfMsg( 'searchdisabled' ) ); - $wgOut->addHTML( wfMsg( 'googlesearch', - htmlspecialchars( $term ), - htmlspecialchars( $wgInputEncoding ) ) ); + $wgOut->addHTML( + wfMsg( 'googlesearch', + htmlspecialchars( $term ), + htmlspecialchars( $wgInputEncoding ), + htmlspecialchars( wfMsg( 'searchbutton' ) ) + ) + ); + wfProfileOut( $fname ); return; } - $search =& $this->getSearchEngine(); + $search = SearchEngine::create(); + $search->setLimitOffset( $this->limit, $this->offset ); + $search->setNamespaces( $this->namespaces ); + $search->showRedirects = $this->searchRedirects; $titleMatches = $search->searchTitle( $term ); $textMatches = $search->searchText( $term ); - - $num = $titleMatches->numRows() + $textMatches->numRows(); + + $num = ( $titleMatches ? $titleMatches->numRows() : 0 ) + + ( $textMatches ? $textMatches->numRows() : 0); if ( $num >= $this->limit ) { $top = wfShowingResults( $this->offset, $this->limit ); } else { @@ -150,30 +168,32 @@ class SpecialSearch { if( $num || $this->offset ) { $prevnext = wfViewPrevNext( $this->offset, $this->limit, - 'Special:Search', + SpecialPage::getTitleFor( 'Search' ), wfArrayToCGI( $this->powerSearchOptions(), array( 'search' => $term ) ) ); $wgOut->addHTML( "
{$prevnext}\n" ); } - $terms = implode( '|', $search->termMatches() ); - - if( $titleMatches->numRows() ) { - $wgOut->addWikiText( '==' . wfMsg( 'titlematches' ) . "==\n" ); - $wgOut->addHTML( $this->showMatches( $titleMatches, $terms ) ); - } else { - $wgOut->addWikiText( '==' . wfMsg( 'notitlematches' ) . "==\n" ); + if( $titleMatches ) { + if( $titleMatches->numRows() ) { + $wgOut->addWikiText( '==' . wfMsg( 'titlematches' ) . "==\n" ); + $wgOut->addHTML( $this->showMatches( $titleMatches ) ); + } else { + $wgOut->addWikiText( '==' . wfMsg( 'notitlematches' ) . "==\n" ); + } } - - if( $textMatches->numRows() ) { - $wgOut->addWikiText( '==' . wfMsg( 'textmatches' ) . "==\n" ); - $wgOut->addHTML( $this->showMatches( $textMatches, $terms ) ); - } elseif( $num == 0 ) { - # Don't show the 'no text matches' if we received title matches - $wgOut->addWikiText( '==' . wfMsg( 'notextmatches' ) . "==\n" ); + + if( $textMatches ) { + if( $textMatches->numRows() ) { + $wgOut->addWikiText( '==' . wfMsg( 'textmatches' ) . "==\n" ); + $wgOut->addHTML( $this->showMatches( $textMatches ) ); + } elseif( $num == 0 ) { + # Don't show the 'no text matches' if we received title matches + $wgOut->addWikiText( '==' . wfMsg( 'notextmatches' ) . "==\n" ); + } } - + if ( $num == 0 ) { $wgOut->addWikiText( wfMsg( 'nonefound' ) ); } @@ -181,55 +201,31 @@ class SpecialSearch { $wgOut->addHTML( "

{$prevnext}

\n" ); } $wgOut->addHTML( $this->powerSearchBox( $term ) ); + wfProfileOut( $fname ); } - + #------------------------------------------------------------------ # Private methods below this line - + /** - * + * */ function setupPage( $term ) { global $wgOut; $wgOut->setPageTitle( wfMsg( 'searchresults' ) ); - $wgOut->setSubtitle( wfMsg( 'searchquery', htmlspecialchars( $term ) ) ); + $subtitlemsg = ( Title::newFromText($term) ? 'searchsubtitle' : 'searchsubtitleinvalid' ); + $wgOut->setSubtitle( $wgOut->parse( wfMsg( $subtitlemsg, wfEscapeWikiText($term) ) ) ); $wgOut->setArticleRelated( false ); $wgOut->setRobotpolicy( 'noindex,nofollow' ); } - /** - * Load up the appropriate search engine class for the currently - * active database backend, and return a configured instance. - * - * @return SearchEngine - * @access private - */ - function &getSearchEngine() { - global $wgDBtype, $wgDBmysql4, $wgSearchType; - if( $wgDBtype == 'mysql' ) { - if( $wgDBmysql4 ) { - $class = 'SearchMySQL4'; - require_once( 'SearchMySQL4.php' ); - } else { - $class = 'SearchMysql3'; - require_once( 'SearchMySQL3.php' ); - } - } else { - $class = 'SearchEngineDummy'; - } - $search = new $class( wfGetDB( DB_SLAVE ) ); - $search->setLimitOffset( $this->limit, $this->offset ); - $search->setNamespaces( $this->namespaces ); - return $search; - } - /** * Extract default namespaces to search from the given user's * settings, returning a list of index numbers. * * @param User $user * @return array - * @access private + * @private */ function userNamespaces( &$user ) { $arr = array(); @@ -240,14 +236,14 @@ class SpecialSearch { } return $arr; } - + /** * Extract "power search" namespace settings from the request object, * returning a list of index numbers to search. * * @param WebRequest $request * @return array - * @access private + * @private */ function powerSearch( &$request ) { $arr = array(); @@ -258,11 +254,11 @@ class SpecialSearch { } return $arr; } - + /** * Reconstruct the 'power search' options for links * @return array - * @access private + * @private */ function powerSearchOptions() { $opt = array(); @@ -273,60 +269,79 @@ class SpecialSearch { $opt['searchx'] = 1; return $opt; } - + /** - * @param ResultWrapper $matches + * @param SearchResultSet $matches * @param string $terms partial regexp for highlighting terms */ - function showMatches( &$matches, $terms ) { - global $wgOut; + function showMatches( &$matches ) { + $fname = 'SpecialSearch::showMatches'; + wfProfileIn( $fname ); + + global $wgContLang; + $tm = $wgContLang->convertForSearchResult( $matches->termMatches() ); + $terms = implode( '|', $tm ); + $off = $this->offset + 1; $out = "
    \n"; - while( $row = $matches->fetchObject() ) { - $out .= $this->showHit( $row, $terms ); + while( $result = $matches->next() ) { + $out .= $this->showHit( $result, $terms ); } $out .= "
\n"; + + // convert the whole thing to desired language variant + global $wgContLang; + $out = $wgContLang->convert( $out ); + wfProfileOut( $fname ); return $out; } - + /** * Format a single hit result - * @param object $row + * @param SearchResult $result * @param string $terms partial regexp for highlighting terms */ - function showHit( $row, $terms ) { - global $wgUser, $wgContLang; + function showHit( $result, $terms ) { + $fname = 'SpecialSearch::showHit'; + wfProfileIn( $fname ); + global $wgUser, $wgContLang, $wgLang; - $t = Title::makeName( $row->cur_namespace, $row->cur_title ); + $t = $result->getTitle(); if( is_null( $t ) ) { + wfProfileOut( $fname ); return "\n"; } $sk = $wgUser->getSkin(); - $contextlines = $wgUser->getOption( 'contextlines' ); - if ( '' == $contextlines ) { $contextlines = 5; } - $contextchars = $wgUser->getOption( 'contextchars' ); - if ( '' == $contextchars ) { $contextchars = 50; } + $contextlines = $wgUser->getOption( 'contextlines', 5 ); + $contextchars = $wgUser->getOption( 'contextchars', 50 ); - $link = $sk->makeKnownLink( $t, '' ); - $size = wfMsg( 'nbytes', strlen( $row->cur_text ) ); + $link = $sk->makeKnownLinkObj( $t ); + $revision = Revision::newFromTitle( $t ); + $text = $revision->getText(); + $size = wfMsgExt( 'nbytes', array( 'parsemag', 'escape'), + $wgLang->formatNum( strlen( $text ) ) ); + + $lines = explode( "\n", $text ); + + $max = intval( $contextchars ) + 1; + $pat1 = "/(.*)($terms)(.{0,$max})/i"; - $lines = explode( "\n", $row->cur_text ); - $pat1 = "/(.*)($terms)(.*)/i"; $lineno = 0; - + $extract = ''; + wfProfileIn( "$fname-extract" ); foreach ( $lines as $line ) { if ( 0 == $contextlines ) { break; } - --$contextlines; ++$lineno; + $m = array(); if ( ! preg_match( $pat1, $line, $m ) ) { continue; } - + --$contextlines; $pre = $wgContLang->truncate( $m[1], -$contextchars, '...' ); if ( count( $m ) < 3 ) { @@ -344,9 +359,11 @@ class SpecialSearch { $extract .= "
{$lineno}: {$line}\n"; } + wfProfileOut( "$fname-extract" ); + wfProfileOut( $fname ); return "
  • {$link} ({$size}){$extract}
  • \n"; } - + function powerSearchBox( $term ) { $namespaces = ''; foreach( SearchEngine::searchableNamespaces() as $ns => $name ) { @@ -360,24 +377,24 @@ class SpecialSearch { $namespaces .= " \n"; } - + $checked = $this->searchRedirects ? ' checked="checked"' : ''; $redirect = "\n"; - - $searchField = "\n"; - + + $searchField = '\n"; + $searchButton = '\n"; - + $ret = wfMsg( 'powersearchtext', $namespaces, $redirect, $searchField, '', '', '', '', '', # Dummy placeholders $searchButton ); - - $title = Title::makeTitle( NS_SPECIAL, 'Search' ); + + $title = SpecialPage::getTitleFor( 'Search' ); $action = $title->escapeLocalURL(); return "

    \n
    \n{$ret}\n
    \n";