X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/banques/?a=blobdiff_plain;f=includes%2Fspecials%2FSpecialSearch.php;h=74ff8edfc267560e58fa3d8df52f565738d56e4c;hb=937fc3bcfd0f3d1112e528b13c4829816e820045;hp=0a25f244bc5fc0b82d4fbaf04c60f5a1bd31b6d6;hpb=efd835888254cd47389647537d4ba83162ec3bce;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/specials/SpecialSearch.php b/includes/specials/SpecialSearch.php index 0a25f244bc..74ff8edfc2 100644 --- a/includes/specials/SpecialSearch.php +++ b/includes/specials/SpecialSearch.php @@ -23,54 +23,130 @@ * @ingroup SpecialPage */ -/** - * Entry point - * - * @param $par String: (default '') - */ -function wfSpecialSearch( $par = '' ) { - global $wgRequest, $wgUser; - // Strip underscores from title parameter; most of the time we'll want - // text form here. But don't strip underscores from actual text params! - $titleParam = str_replace( '_', ' ', $par ); - // Fetch the search term - $search = str_replace( "\n", " ", $wgRequest->getText( 'search', $titleParam ) ); - $searchPage = new SpecialSearch( $wgRequest, $wgUser ); - if( $wgRequest->getVal( 'fulltext' ) - || !is_null( $wgRequest->getVal( 'offset' )) - || !is_null( $wgRequest->getVal( 'searchx' )) ) - { - $searchPage->showResults( $search ); - } else { - $searchPage->goResult( $search ); - } -} - /** * implements Special:Search - Run text & title search and display the output * @ingroup SpecialPage */ -class SpecialSearch { +class SpecialSearch extends SpecialPage { + /** + * Current search profile. Search profile is just a name that identifies + * the active search tab on the search page (content, help, discussions...) + * For users tt replaces the set of enabled namespaces from the query + * string when applicable. Extensions can add new profiles with hooks + * with custom search options just for that profile. + * null|string + */ + protected $profile; + + /// Search engine + protected $searchEngine; + + /// For links + protected $extraParams = array(); + + /// No idea, apparently used by some other classes + protected $mPrefix; /** - * Set up basic search parameters from the request and user settings. - * Typically you'll pass $wgRequest and $wgUser. + * @var int + */ + protected $limit, $offset; + + /** + * @var array + */ + protected $namespaces; + + /** + * @var bool + */ + protected $searchRedirects; + + /** + * @var string + */ + protected $didYouMeanHtml, $fulltext; + + const NAMESPACES_CURRENT = 'sense'; + + public function __construct() { + parent::__construct( 'Search' ); + } + + /** + * Entry point * - * @param $request WebRequest - * @param $user User + * @param $par String or null */ - public function __construct( &$request, &$user ) { + public function execute( $par ) { + $this->setHeaders(); + $this->outputHeader(); + $out = $this->getOutput(); + $out->allowClickjacking(); + $out->addModuleStyles( 'mediawiki.special' ); + + // Strip underscores from title parameter; most of the time we'll want + // text form here. But don't strip underscores from actual text params! + $titleParam = str_replace( '_', ' ', $par ); + + $request = $this->getRequest(); + + // Fetch the search term + $search = str_replace( "\n", " ", $request->getText( 'search', $titleParam ) ); + + $this->load(); + + if ( $request->getVal( 'fulltext' ) + || !is_null( $request->getVal( 'offset' ) ) + || !is_null( $request->getVal( 'searchx' ) ) ) + { + $this->showResults( $search ); + } else { + $this->goResult( $search ); + } + } + + /** + * Set up basic search parameters from the request and user settings. + */ + public function load() { + $request = $this->getRequest(); list( $this->limit, $this->offset ) = $request->getLimitOffset( 20, 'searchlimit' ); - $this->mPrefix = $request->getVal('prefix', ''); - # Extract requested namespaces - $this->namespaces = $this->powerSearch( $request ); - if( empty( $this->namespaces ) ) { - $this->namespaces = SearchEngine::userNamespaces( $user ); + $this->mPrefix = $request->getVal( 'prefix', '' ); + + $user = $this->getUser(); + # Extract manually requested namespaces + $nslist = $this->powerSearch( $request ); + $this->profile = $profile = $request->getVal( 'profile', null ); + $profiles = $this->getSearchProfiles(); + if ( $profile === null) { + // BC with old request format + $this->profile = 'advanced'; + if ( count( $nslist ) ) { + foreach( $profiles as $key => $data ) { + if ( $nslist === $data['namespaces'] && $key !== 'advanced') { + $this->profile = $key; + } + } + $this->namespaces = $nslist; + } else { + $this->namespaces = SearchEngine::userNamespaces( $user ); + } + } elseif ( $profile === 'advanced' ) { + $this->namespaces = $nslist; + } else { + if ( isset( $profiles[$profile]['namespaces'] ) ) { + $this->namespaces = $profiles[$profile]['namespaces']; + } else { + // Unknown profile requested + $this->profile = 'default'; + $this->namespaces = $profiles['default']['namespaces']; + } } - $this->searchRedirects = $request->getCheck( 'redirs' ); - $this->searchAdvanced = $request->getVal( 'advanced' ); - $this->active = 'advanced'; - $this->sk = $user->getSkin(); + + // Redirects defaults to true, but we don't know whether it was ticked of or just missing + $default = $request->getBool( 'profile' ) ? 0 : 1; + $this->searchRedirects = $request->getBool( 'redirs', $default ) ? 1 : 0; $this->didYouMeanHtml = ''; # html of did you mean... link $this->fulltext = $request->getVal('fulltext'); } @@ -81,7 +157,6 @@ class SpecialSearch { * @param $term String */ public function goResult( $term ) { - global $wgOut; $this->setupPage( $term ); # Try to go to page as entered. $t = Title::newFromText( $term ); @@ -91,9 +166,14 @@ class SpecialSearch { } # If there's an exact or very near match, jump right there. $t = SearchEngine::getNearMatch( $term ); + + if ( !wfRunHooks( 'SpecialSearchGo', array( &$t, &$term ) ) ) { + # Hook requested termination + return; + } + if( !is_null( $t ) ) { - wfRunHooks( 'SpecialSearchGomatch', array( &$t ) ); - $wgOut->redirect( $t->getFullURL() ); + $this->getOutput()->redirect( $t->getFullURL() ); return; } # No match, generate an edit URL @@ -101,9 +181,11 @@ class SpecialSearch { if( !is_null( $t ) ) { global $wgGoToEdit; wfRunHooks( 'SpecialSearchNogomatch', array( &$t ) ); + wfDebugLog( 'nogomatch', $t->getText(), false ); + # If the feature is enabled, go straight to the edit page if( $wgGoToEdit ) { - $wgOut->redirect( $t->getFullURL( array( 'action' => 'edit' ) ) ); + $this->getOutput()->redirect( $t->getFullURL( array( 'action' => 'edit' ) ) ); return; } } @@ -114,41 +196,40 @@ class SpecialSearch { * @param $term String */ public function showResults( $term ) { - global $wgOut, $wgUser, $wgDisableTextSearch, $wgContLang, $wgScript; + global $wgDisableTextSearch, $wgSearchForwardUrl, $wgContLang, $wgScript; wfProfileIn( __METHOD__ ); - $sk = $wgUser->getSkin(); - - $this->searchEngine = SearchEngine::create(); - $search =& $this->searchEngine; + $search = $this->getSearchEngine(); $search->setLimitOffset( $this->limit, $this->offset ); $search->setNamespaces( $this->namespaces ); - $search->showRedirects = $this->searchRedirects; + $search->showRedirects = $this->searchRedirects; // BC + $search->setFeatureData( 'list-redirects', $this->searchRedirects ); $search->prefix = $this->mPrefix; $term = $search->transformSearchTerm($term); + wfRunHooks( 'SpecialSearchSetupEngine', array( $this, $this->profile, $search ) ); + $this->setupPage( $term ); - if( $wgDisableTextSearch ) { - global $wgSearchForwardUrl; - if( $wgSearchForwardUrl ) { + $out = $this->getOutput(); + + if ( $wgDisableTextSearch ) { + if ( $wgSearchForwardUrl ) { $url = str_replace( '$1', urlencode( $term ), $wgSearchForwardUrl ); - $wgOut->redirect( $url ); - wfProfileOut( __METHOD__ ); - return; + $out->redirect( $url ); + } else { + $out->addHTML( + Xml::openElement( 'fieldset' ) . + Xml::element( 'legend', null, wfMsg( 'search-external' ) ) . + Xml::element( 'p', array( 'class' => 'mw-searchdisabled' ), wfMsg( 'searchdisabled' ) ) . + wfMsg( 'googlesearch', + htmlspecialchars( $term ), + htmlspecialchars( 'UTF-8' ), + htmlspecialchars( wfMsg( 'searchbutton' ) ) + ) . + Xml::closeElement( 'fieldset' ) + ); } - global $wgInputEncoding; - $wgOut->addHTML( - Xml::openElement( 'fieldset' ) . - Xml::element( 'legend', null, wfMsg( 'search-external' ) ) . - Xml::element( 'p', array( 'class' => 'mw-searchdisabled' ), wfMsg( 'searchdisabled' ) ) . - wfMsg( 'googlesearch', - htmlspecialchars( $term ), - htmlspecialchars( $wgInputEncoding ), - htmlspecialchars( wfMsg( 'searchbutton' ) ) - ) . - Xml::closeElement( 'fieldset' ) - ); wfProfileOut( __METHOD__ ); return; } @@ -159,8 +240,9 @@ class SpecialSearch { $rewritten = $search->replacePrefixes($term); $titleMatches = $search->searchTitle( $rewritten ); - if( !($titleMatches instanceof SearchResultTooMany)) + if( !( $titleMatches instanceof SearchResultTooMany ) ) { $textMatches = $search->searchText( $rewritten ); + } // did you mean... suggestions if( $textMatches && $textMatches->hasSuggestion() ) { @@ -169,8 +251,9 @@ class SpecialSearch { # mirror Go/Search behaviour of original request .. $didYouMeanParams = array( 'search' => $textMatches->getSuggestionQuery() ); - if($this->fulltext != null) + if( $this->fulltext != null ) { $didYouMeanParams['fulltext'] = $this->fulltext; + } $stParams = array_merge( $didYouMeanParams, @@ -179,10 +262,11 @@ class SpecialSearch { $suggestionSnippet = $textMatches->getSuggestionSnippet(); - if( $suggestionSnippet == '' ) + if( $suggestionSnippet == '' ) { $suggestionSnippet = null; + } - $suggestLink = $sk->linkKnown( + $suggestLink = Linker::linkKnown( $st, $suggestionSnippet, array(), @@ -192,20 +276,20 @@ class SpecialSearch { $this->didYouMeanHtml = '
'.wfMsg('search-suggest',$suggestLink).'
'; } // start rendering the page - $wgOut->addHtml( + $out->addHtml( Xml::openElement( 'form', array( - 'id' => ( $this->searchAdvanced ? 'powersearch' : 'search' ), + 'id' => ( $this->profile === 'advanced' ? 'powersearch' : 'search' ), 'method' => 'get', 'action' => $wgScript ) ) ); - $wgOut->addHtml( + $out->addHtml( Xml::openElement( 'table', array( 'id'=>'mw-search-top-table', 'border'=>0, 'cellpadding'=>0, 'cellspacing'=>0 ) ) . Xml::openElement( 'tr' ) . - Xml::openElement( 'td' ) . "\n" . + Xml::openElement( 'td' ) . "\n" . $this->shortDialog( $term ) . Xml::closeElement('td') . Xml::closeElement('tr') . @@ -214,18 +298,16 @@ class SpecialSearch { // Sometimes the search engine knows there are too many hits if( $titleMatches instanceof SearchResultTooMany ) { - $wgOut->addWikiText( '==' . wfMsg( 'toomanymatches' ) . "==\n" ); + $out->wrapWikiMsg( "==$1==\n", 'toomanymatches' ); wfProfileOut( __METHOD__ ); return; } $filePrefix = $wgContLang->getFormattedNsText(NS_FILE).':'; if( trim( $term ) === '' || $filePrefix === trim( $term ) ) { - $wgOut->addHTML( $this->formHeader($term, 0, 0)); - if( $this->searchAdvanced ) { - $wgOut->addHTML( $this->powerSearchBox( $term ) ); - } - $wgOut->addHTML( '' ); + $out->addHTML( $this->formHeader( $term, 0, 0 ) ); + $out->addHtml( $this->getProfileForm( $this->profile, $term ) ); + $out->addHTML( '' ); // Empty query -- straight view of search form wfProfileOut( __METHOD__ ); return; @@ -236,7 +318,7 @@ class SpecialSearch { $textMatchesNum = $textMatches ? $textMatches->numRows() : 0; // Total initial query matches (possible false positives) $num = $titleMatchesNum + $textMatchesNum; - + // Get total actual results (after second filtering, if any) $numTitleMatches = $titleMatches && !is_null( $titleMatches->getTotalHits() ) ? $titleMatches->getTotalHits() : $titleMatchesNum; @@ -249,15 +331,14 @@ class SpecialSearch { $totalRes += $titleMatches->getTotalHits(); if($textMatches && !is_null( $textMatches->getTotalHits() )) $totalRes += $textMatches->getTotalHits(); - + // show number of results and current offset - $wgOut->addHTML( $this->formHeader($term, $num, $totalRes)); - if( $this->searchAdvanced ) { - $wgOut->addHTML( $this->powerSearchBox( $term ) ); - } - - $wgOut->addHtml( Xml::closeElement( 'form' ) ); - $wgOut->addHtml( "
" ); + $out->addHTML( $this->formHeader( $term, $num, $totalRes ) ); + $out->addHtml( $this->getProfileForm( $this->profile, $term ) ); + + + $out->addHtml( Xml::closeElement( 'form' ) ); + $out->addHtml( "
" ); // prev/next links if( $num || $this->offset ) { @@ -268,16 +349,17 @@ class SpecialSearch { wfArrayToCGI( $this->powerSearchOptions(), array( 'search' => $term ) ), max( $titleMatchesNum, $textMatchesNum ) < $this->limit ); - //$wgOut->addHTML( "

{$prevnext}

\n" ); + //$out->addHTML( "

{$prevnext}

\n" ); wfRunHooks( 'SpecialSearchResults', array( $term, &$titleMatches, &$textMatches ) ); } else { wfRunHooks( 'SpecialSearchNoResults', array( $term ) ); - } + } + $out->parserOptions()->setEditSection( false ); if( $titleMatches ) { if( $numTitleMatches > 0 ) { - $wgOut->wrapWikiMsg( "==$1==\n", 'titlematches' ); - $wgOut->addHTML( $this->showMatches( $titleMatches ) ); + $out->wrapWikiMsg( "==$1==\n", 'titlematches' ); + $out->addHTML( $this->showMatches( $titleMatches ) ); } $titleMatches->free(); } @@ -285,85 +367,80 @@ class SpecialSearch { // output appropriate heading if( $numTextMatches > 0 && $numTitleMatches > 0 ) { // if no title matches the heading is redundant - $wgOut->wrapWikiMsg( "==$1==\n", 'textmatches' ); + $out->wrapWikiMsg( "==$1==\n", 'textmatches' ); } elseif( $totalRes == 0 ) { # Don't show the 'no text matches' if we received title matches - # $wgOut->wrapWikiMsg( "==$1==\n", 'notextmatches' ); + # $out->wrapWikiMsg( "==$1==\n", 'notextmatches' ); } // show interwiki results if any if( $textMatches->hasInterwikiResults() ) { - $wgOut->addHTML( $this->showInterwiki( $textMatches->getInterwikiResults(), $term ) ); + $out->addHTML( $this->showInterwiki( $textMatches->getInterwikiResults(), $term ) ); } // show results if( $numTextMatches > 0 ) { - $wgOut->addHTML( $this->showMatches( $textMatches ) ); + $out->addHTML( $this->showMatches( $textMatches ) ); } $textMatches->free(); } if( $num === 0 ) { - $wgOut->addWikiMsg( 'search-nonefound', wfEscapeWikiText( $term ) ); + $out->wrapWikiMsg( "

\n$1

", array( 'search-nonefound', wfEscapeWikiText( $term ) ) ); $this->showCreateLink( $t ); } - $wgOut->addHtml( "
" ); + $out->addHtml( "
" ); if( $num || $this->offset ) { - $wgOut->addHTML( "

{$prevnext}

\n" ); + $out->addHTML( "

{$prevnext}

\n" ); } wfProfileOut( __METHOD__ ); } - + + /** + * @param $t Title + */ protected function showCreateLink( $t ) { - global $wgOut; - // show direct page/create link if applicable - $messageName = null; - if( !is_null($t) ) { - if( $t->isKnown() ) { - $messageName = 'searchmenu-exists'; - } elseif( $t->userCan( 'create' ) ) { - $messageName = 'searchmenu-new'; - } else { - $messageName = 'searchmenu-new-nocreate'; - } - } + + // Check DBkey !== '' in case of fragment link only. + if( is_null( $t ) || $t->getDBkey() === '' ) { + // invalid title + // preserve the paragraph for margins etc... + $this->getOutput()->addHtml( '

' ); + return; + } + $messageName = ''; + if( $t->isKnown() ) { + $messageName = 'searchmenu-exists'; + } elseif( $t->userCan( 'create' ) ) { + $messageName = 'searchmenu-new'; + } else { + $messageName = 'searchmenu-new-nocreate'; + } + $params = array( $messageName, wfEscapeWikiText( $t->getPrefixedText() ) ); + wfRunHooks( 'SpecialSearchCreateLink', array( $t, &$params ) ); + + // Extensions using the hook might still return an empty $messageName if( $messageName ) { - $wgOut->addWikiMsg( $messageName, wfEscapeWikiText( $t->getPrefixedText() ) ); + $this->getOutput()->wrapWikiMsg( "

\n$1

", $params ); } else { // preserve the paragraph for margins etc... - $wgOut->addHtml( '

' ); + $this->getOutput()->addHtml( '

' ); } } /** - * + * @param $term string */ protected function setupPage( $term ) { - global $wgOut; - // Figure out the active search profile header - $nsAllSet = array_keys( SearchEngine::searchableNamespaces() ); - if( $this->searchAdvanced ) - $this->active = 'advanced'; - else { - $profiles = $this->getSearchProfiles(); - - foreach( $profiles as $key => $data ) { - if ( $this->namespaces == $data['namespaces'] && $key != 'advanced') - $this->active = $key; - } - - } # Should advanced UI be used? - $this->searchAdvanced = ($this->active === 'advanced'); - if( !empty( $term ) ) { - $wgOut->setPageTitle( wfMsg( 'searchresults') ); - $wgOut->setHTMLTitle( wfMsg( 'pagetitle', wfMsg( 'searchresults-title', $term ) ) ); + $this->searchAdvanced = ($this->profile === 'advanced'); + $out = $this->getOutput(); + if( strval( $term ) !== '' ) { + $out->setPageTitle( wfMsg( 'searchresults') ); + $out->setHTMLTitle( wfMsg( 'pagetitle', wfMsg( 'searchresults-title', $term ) ) ); } - $wgOut->setArticleRelated( false ); - $wgOut->setRobotPolicy( 'noindex,nofollow' ); // add javascript specific to special:search - $wgOut->addModules( 'mediawiki.legacy.search' ); - $wgOut->addModules( 'mediawiki.specials.search' ); + $out->addModules( 'mediawiki.special.search' ); } /** @@ -380,6 +457,7 @@ class SpecialSearch { $arr[] = $ns; } } + return $arr; } @@ -390,20 +468,23 @@ class SpecialSearch { */ protected function powerSearchOptions() { $opt = array(); - foreach( $this->namespaces as $n ) { - $opt['ns' . $n] = 1; - } $opt['redirs'] = $this->searchRedirects ? 1 : 0; - if( $this->searchAdvanced ) { - $opt['advanced'] = $this->searchAdvanced; + if( $this->profile !== 'advanced' ) { + $opt['profile'] = $this->profile; + } else { + foreach( $this->namespaces as $n ) { + $opt['ns' . $n] = 1; + } } - return $opt; + return $opt + $this->extraParams; } /** * Show whole set of results * * @param $matches SearchResultSet + * + * @return string */ protected function showMatches( &$matches ) { global $wgContLang; @@ -416,7 +497,6 @@ class SpecialSearch { if( !is_null($infoLine) ) { $out .= "\n\n"; } - $off = $this->offset + 1; $out .= "