2004-04-24 06:27:16 +00:00
|
|
|
<?php
|
2010-06-21 12:59:04 +00:00
|
|
|
/**
|
2010-08-15 07:16:58 +00:00
|
|
|
* Implements Special:Search
|
|
|
|
|
*
|
|
|
|
|
* Copyright © 2004 Brion Vibber <brion@pobox.com>
|
2010-06-21 12:59:04 +00:00
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
* (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.,
|
2010-06-21 13:16:32 +00:00
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2010-06-21 12:59:04 +00:00
|
|
|
* http://www.gnu.org/copyleft/gpl.html
|
2010-08-15 07:16:58 +00:00
|
|
|
*
|
WARNING: HUGE COMMIT
Doxygen documentation update:
* Changed alls @addtogroup to @ingroup. @addtogroup adds the comment to the group description, but doesn't add the file, class, function, ... to the group like @ingroup does. See for example http://svn.wikimedia.org/doc/group__SpecialPage.html where it's impossible to see related files, classes, ... that should belong to that group.
* Added @file to file description, it seems that it should be explicitely decalred for file descriptions, otherwise doxygen will think that the comment document the first class, variabled, function, ... that is in that file.
* Removed some empty comments
* Removed some ?>
Added following groups:
* ExternalStorage
* JobQueue
* MaintenanceLanguage
One more thing: there are still a lot of warnings when generating the doc.
2008-05-20 17:13:28 +00:00
|
|
|
* @file
|
|
|
|
|
* @ingroup SpecialPage
|
2004-09-02 23:28:24 +00:00
|
|
|
*/
|
|
|
|
|
|
2005-01-27 19:51:47 +00:00
|
|
|
/**
|
2007-04-20 08:55:14 +00:00
|
|
|
* implements Special:Search - Run text & title search and display the output
|
WARNING: HUGE COMMIT
Doxygen documentation update:
* Changed alls @addtogroup to @ingroup. @addtogroup adds the comment to the group description, but doesn't add the file, class, function, ... to the group like @ingroup does. See for example http://svn.wikimedia.org/doc/group__SpecialPage.html where it's impossible to see related files, classes, ... that should belong to that group.
* Added @file to file description, it seems that it should be explicitely decalred for file descriptions, otherwise doxygen will think that the comment document the first class, variabled, function, ... that is in that file.
* Removed some empty comments
* Removed some ?>
Added following groups:
* ExternalStorage
* JobQueue
* MaintenanceLanguage
One more thing: there are still a lot of warnings when generating the doc.
2008-05-20 17:13:28 +00:00
|
|
|
* @ingroup SpecialPage
|
2005-01-27 19:51:47 +00:00
|
|
|
*/
|
2010-12-10 20:51:06 +00:00
|
|
|
class SpecialSearch extends SpecialPage {
|
2011-08-17 09:50:54 +00:00
|
|
|
/**
|
|
|
|
|
* 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.
|
2011-09-29 22:08:00 +00:00
|
|
|
* null|string
|
2011-10-16 03:27:12 +00:00
|
|
|
*/
|
2011-04-22 16:13:58 +00:00
|
|
|
protected $profile;
|
2012-01-09 11:41:13 +00:00
|
|
|
function getProfile() { return $this->profile; }
|
2011-04-22 16:13:58 +00:00
|
|
|
|
|
|
|
|
/// Search engine
|
|
|
|
|
protected $searchEngine;
|
|
|
|
|
|
2011-04-22 20:25:21 +00:00
|
|
|
/// For links
|
|
|
|
|
protected $extraParams = array();
|
|
|
|
|
|
2011-06-20 09:35:44 +00:00
|
|
|
/// No idea, apparently used by some other classes
|
|
|
|
|
protected $mPrefix;
|
|
|
|
|
|
2011-08-16 00:41:50 +00:00
|
|
|
/**
|
|
|
|
|
* @var int
|
|
|
|
|
*/
|
|
|
|
|
protected $limit, $offset;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
|
|
|
|
protected $namespaces;
|
2012-01-09 11:41:13 +00:00
|
|
|
function getNamespaces() { return $this->namespaces; }
|
2011-08-16 00:41:50 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var bool
|
|
|
|
|
*/
|
|
|
|
|
protected $searchRedirects;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
|
|
|
|
protected $didYouMeanHtml, $fulltext;
|
|
|
|
|
|
2011-04-22 16:13:58 +00:00
|
|
|
const NAMESPACES_CURRENT = 'sense';
|
2010-12-10 20:51:06 +00:00
|
|
|
|
|
|
|
|
public function __construct() {
|
|
|
|
|
parent::__construct( 'Search' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Entry point
|
|
|
|
|
*
|
|
|
|
|
* @param $par String or null
|
|
|
|
|
*/
|
|
|
|
|
public function execute( $par ) {
|
|
|
|
|
$this->setHeaders();
|
|
|
|
|
$this->outputHeader();
|
2011-08-11 21:10:30 +00:00
|
|
|
$out = $this->getOutput();
|
|
|
|
|
$out->allowClickjacking();
|
|
|
|
|
$out->addModuleStyles( 'mediawiki.special' );
|
2010-12-10 20:51:06 +00:00
|
|
|
|
|
|
|
|
// 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 );
|
|
|
|
|
|
2011-08-11 21:10:30 +00:00
|
|
|
$request = $this->getRequest();
|
|
|
|
|
|
2010-12-10 20:51:06 +00:00
|
|
|
// Fetch the search term
|
2011-08-11 21:10:30 +00:00
|
|
|
$search = str_replace( "\n", " ", $request->getText( 'search', $titleParam ) );
|
2010-12-10 20:51:06 +00:00
|
|
|
|
2011-08-11 21:10:30 +00:00
|
|
|
$this->load();
|
2010-12-10 20:51:06 +00:00
|
|
|
|
2011-08-11 21:10:30 +00:00
|
|
|
if ( $request->getVal( 'fulltext' )
|
|
|
|
|
|| !is_null( $request->getVal( 'offset' ) )
|
|
|
|
|
|| !is_null( $request->getVal( 'searchx' ) ) )
|
2010-12-10 20:51:06 +00:00
|
|
|
{
|
|
|
|
|
$this->showResults( $search );
|
|
|
|
|
} else {
|
|
|
|
|
$this->goResult( $search );
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-01-27 19:51:47 +00:00
|
|
|
|
2004-10-20 09:56:34 +00:00
|
|
|
/**
|
|
|
|
|
* Set up basic search parameters from the request and user settings.
|
2012-01-12 09:03:38 +00:00
|
|
|
*
|
|
|
|
|
* @see tests/phpunit/includes/specials/SpecialSearchTest.php
|
2004-10-20 09:56:34 +00:00
|
|
|
*/
|
2011-08-11 21:10:30 +00:00
|
|
|
public function load() {
|
|
|
|
|
$request = $this->getRequest();
|
2008-11-17 04:56:14 +00:00
|
|
|
list( $this->limit, $this->offset ) = $request->getLimitOffset( 20, 'searchlimit' );
|
2011-06-20 09:35:44 +00:00
|
|
|
$this->mPrefix = $request->getVal( 'prefix', '' );
|
2011-04-22 16:13:58 +00:00
|
|
|
|
2011-08-11 21:10:30 +00:00
|
|
|
$user = $this->getUser();
|
2012-01-12 09:03:38 +00:00
|
|
|
|
2011-04-22 16:13:58 +00:00
|
|
|
# Extract manually requested namespaces
|
|
|
|
|
$nslist = $this->powerSearch( $request );
|
2012-01-12 09:03:38 +00:00
|
|
|
if ( !count( $nslist ) ) {
|
|
|
|
|
# Fallback to user preference
|
|
|
|
|
$nslist = SearchEngine::userNamespaces( $user );
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-20 11:17:36 +00:00
|
|
|
$profile = null;
|
|
|
|
|
if ( !count( $nslist ) ) {
|
|
|
|
|
$profile = 'default';
|
|
|
|
|
}
|
2012-01-12 09:03:38 +00:00
|
|
|
|
2011-12-20 11:17:36 +00:00
|
|
|
$profile = $request->getVal( 'profile', $profile );
|
2011-04-22 16:13:58 +00:00
|
|
|
$profiles = $this->getSearchProfiles();
|
2011-12-20 11:17:36 +00:00
|
|
|
if ( $profile === null ) {
|
2011-04-22 16:13:58 +00:00
|
|
|
// BC with old request format
|
2011-12-20 11:17:36 +00:00
|
|
|
$profile = 'advanced';
|
2012-01-12 09:03:38 +00:00
|
|
|
foreach( $profiles as $key => $data ) {
|
|
|
|
|
if ( $nslist === $data['namespaces'] && $key !== 'advanced') {
|
|
|
|
|
$profile = $key;
|
2011-04-22 16:13:58 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-01-12 09:03:38 +00:00
|
|
|
$this->namespaces = $nslist;
|
2011-04-22 16:13:58 +00:00
|
|
|
} elseif ( $profile === 'advanced' ) {
|
|
|
|
|
$this->namespaces = $nslist;
|
|
|
|
|
} else {
|
|
|
|
|
if ( isset( $profiles[$profile]['namespaces'] ) ) {
|
|
|
|
|
$this->namespaces = $profiles[$profile]['namespaces'];
|
|
|
|
|
} else {
|
|
|
|
|
// Unknown profile requested
|
2011-12-20 11:17:36 +00:00
|
|
|
$profile = 'default';
|
2011-04-22 16:13:58 +00:00
|
|
|
$this->namespaces = $profiles['default']['namespaces'];
|
|
|
|
|
}
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
2011-04-22 16:13:58 +00:00
|
|
|
|
|
|
|
|
// 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;
|
2008-12-18 18:01:06 +00:00
|
|
|
$this->didYouMeanHtml = ''; # html of did you mean... link
|
2009-04-27 07:25:51 +00:00
|
|
|
$this->fulltext = $request->getVal('fulltext');
|
2011-12-20 11:17:36 +00:00
|
|
|
$this->profile = $profile;
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If an exact title match can be found, jump straight ahead to it.
|
2010-05-02 20:34:40 +00:00
|
|
|
*
|
|
|
|
|
* @param $term String
|
2008-11-17 04:56:14 +00:00
|
|
|
*/
|
2008-11-19 08:35:04 +00:00
|
|
|
public function goResult( $term ) {
|
2008-11-17 04:56:14 +00:00
|
|
|
$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 ) ) {
|
2012-04-27 15:40:14 +00:00
|
|
|
$this->showResults( $term );
|
|
|
|
|
return;
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
|
|
|
|
# If there's an exact or very near match, jump right there.
|
|
|
|
|
$t = SearchEngine::getNearMatch( $term );
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2010-12-13 20:00:43 +00:00
|
|
|
if ( !wfRunHooks( 'SpecialSearchGo', array( &$t, &$term ) ) ) {
|
|
|
|
|
# Hook requested termination
|
|
|
|
|
return;
|
|
|
|
|
}
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
if( !is_null( $t ) ) {
|
2011-08-11 21:10:30 +00:00
|
|
|
$this->getOutput()->redirect( $t->getFullURL() );
|
2008-11-17 04:56:14 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
# No match, generate an edit URL
|
|
|
|
|
$t = Title::newFromText( $term );
|
2008-11-19 08:35:04 +00:00
|
|
|
if( !is_null( $t ) ) {
|
|
|
|
|
global $wgGoToEdit;
|
2008-11-17 04:56:14 +00:00
|
|
|
wfRunHooks( 'SpecialSearchNogomatch', array( &$t ) );
|
2011-01-21 19:02:17 +00:00
|
|
|
wfDebugLog( 'nogomatch', $t->getText(), false );
|
|
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
# If the feature is enabled, go straight to the edit page
|
|
|
|
|
if( $wgGoToEdit ) {
|
2011-08-11 21:10:30 +00:00
|
|
|
$this->getOutput()->redirect( $t->getFullURL( array( 'action' => 'edit' ) ) );
|
2008-11-17 04:56:14 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-04-27 15:40:14 +00:00
|
|
|
$this->showResults( $term );
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2010-05-02 20:34:40 +00:00
|
|
|
* @param $term String
|
2008-11-17 04:56:14 +00:00
|
|
|
*/
|
2008-11-19 08:35:04 +00:00
|
|
|
public function showResults( $term ) {
|
2011-08-11 21:10:30 +00:00
|
|
|
global $wgDisableTextSearch, $wgSearchForwardUrl, $wgContLang, $wgScript;
|
2008-11-17 04:56:14 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2011-04-22 16:13:58 +00:00
|
|
|
$search = $this->getSearchEngine();
|
2008-12-31 04:48:23 +00:00
|
|
|
$search->setLimitOffset( $this->limit, $this->offset );
|
|
|
|
|
$search->setNamespaces( $this->namespaces );
|
2011-04-22 16:13:58 +00:00
|
|
|
$search->showRedirects = $this->searchRedirects; // BC
|
|
|
|
|
$search->setFeatureData( 'list-redirects', $this->searchRedirects );
|
2011-06-20 09:35:44 +00:00
|
|
|
$search->prefix = $this->mPrefix;
|
2008-12-31 04:48:23 +00:00
|
|
|
$term = $search->transformSearchTerm($term);
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2011-04-22 16:13:58 +00:00
|
|
|
wfRunHooks( 'SpecialSearchSetupEngine', array( $this, $this->profile, $search ) );
|
|
|
|
|
|
2008-12-31 04:48:23 +00:00
|
|
|
$this->setupPage( $term );
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2011-08-11 21:10:30 +00:00
|
|
|
$out = $this->getOutput();
|
|
|
|
|
|
|
|
|
|
if ( $wgDisableTextSearch ) {
|
|
|
|
|
if ( $wgSearchForwardUrl ) {
|
2008-11-17 04:56:14 +00:00
|
|
|
$url = str_replace( '$1', urlencode( $term ), $wgSearchForwardUrl );
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->redirect( $url );
|
|
|
|
|
} else {
|
|
|
|
|
$out->addHTML(
|
|
|
|
|
Xml::openElement( 'fieldset' ) .
|
2012-05-07 04:38:51 +00:00
|
|
|
Xml::element( 'legend', null, $this->msg( 'search-external' )->text() ) .
|
|
|
|
|
Xml::element( 'p', array( 'class' => 'mw-searchdisabled' ), $this->msg( 'searchdisabled' )->text() ) .
|
|
|
|
|
$this->msg( 'googlesearch' )->rawParams(
|
2011-08-11 21:10:30 +00:00
|
|
|
htmlspecialchars( $term ),
|
2012-05-07 04:38:51 +00:00
|
|
|
'UTF-8',
|
|
|
|
|
$this->msg( 'searchbutton' )->escaped()
|
|
|
|
|
)->text() .
|
2011-08-11 21:10:30 +00:00
|
|
|
Xml::closeElement( 'fieldset' )
|
|
|
|
|
);
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
return;
|
|
|
|
|
}
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2008-12-18 18:01:06 +00:00
|
|
|
$t = Title::newFromText( $term );
|
2009-04-27 07:25:51 +00:00
|
|
|
|
|
|
|
|
// fetch search results
|
2008-11-17 04:56:14 +00:00
|
|
|
$rewritten = $search->replacePrefixes($term);
|
|
|
|
|
|
|
|
|
|
$titleMatches = $search->searchTitle( $rewritten );
|
2011-08-16 00:41:50 +00:00
|
|
|
if( !( $titleMatches instanceof SearchResultTooMany ) ) {
|
2008-12-18 18:01:06 +00:00
|
|
|
$textMatches = $search->searchText( $rewritten );
|
2011-08-16 00:41:50 +00:00
|
|
|
}
|
2008-11-19 08:35:04 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
// did you mean... suggestions
|
|
|
|
|
if( $textMatches && $textMatches->hasSuggestion() ) {
|
2009-03-21 10:51:08 +00:00
|
|
|
$st = SpecialPage::getTitleFor( 'Search' );
|
2009-06-07 18:45:52 +00:00
|
|
|
|
2009-03-21 10:51:08 +00:00
|
|
|
# mirror Go/Search behaviour of original request ..
|
|
|
|
|
$didYouMeanParams = array( 'search' => $textMatches->getSuggestionQuery() );
|
2009-06-07 18:45:52 +00:00
|
|
|
|
2011-08-16 00:41:50 +00:00
|
|
|
if( $this->fulltext != null ) {
|
2009-04-27 07:25:51 +00:00
|
|
|
$didYouMeanParams['fulltext'] = $this->fulltext;
|
2011-08-16 00:41:50 +00:00
|
|
|
}
|
2009-06-07 18:45:52 +00:00
|
|
|
|
|
|
|
|
$stParams = array_merge(
|
2009-03-21 10:51:08 +00:00
|
|
|
$didYouMeanParams,
|
2008-11-17 04:56:14 +00:00
|
|
|
$this->powerSearchOptions()
|
|
|
|
|
);
|
2009-06-07 18:45:52 +00:00
|
|
|
|
2009-06-07 19:49:56 +00:00
|
|
|
$suggestionSnippet = $textMatches->getSuggestionSnippet();
|
|
|
|
|
|
2011-08-16 00:41:50 +00:00
|
|
|
if( $suggestionSnippet == '' ) {
|
2009-06-07 19:49:56 +00:00
|
|
|
$suggestionSnippet = null;
|
2011-08-16 00:41:50 +00:00
|
|
|
}
|
2009-06-07 19:49:56 +00:00
|
|
|
|
2011-08-11 21:10:30 +00:00
|
|
|
$suggestLink = Linker::linkKnown(
|
2009-06-07 18:45:52 +00:00
|
|
|
$st,
|
2009-06-07 19:49:56 +00:00
|
|
|
$suggestionSnippet,
|
2009-06-07 18:45:52 +00:00
|
|
|
array(),
|
|
|
|
|
$stParams
|
|
|
|
|
);
|
2008-11-17 04:56:14 +00:00
|
|
|
|
2012-05-07 04:38:51 +00:00
|
|
|
$this->didYouMeanHtml = '<div class="searchdidyoumean">' . $this->msg( 'search-suggest' )->rawParams( $suggestLink )->text() . '</div>';
|
2008-12-18 18:01:06 +00:00
|
|
|
}
|
2009-04-27 07:25:51 +00:00
|
|
|
// start rendering the page
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->addHtml(
|
2010-08-07 12:45:10 +00:00
|
|
|
Xml::openElement(
|
|
|
|
|
'form',
|
|
|
|
|
array(
|
2011-04-22 16:13:58 +00:00
|
|
|
'id' => ( $this->profile === 'advanced' ? 'powersearch' : 'search' ),
|
2010-08-07 12:45:10 +00:00
|
|
|
'method' => 'get',
|
|
|
|
|
'action' => $wgScript
|
|
|
|
|
)
|
|
|
|
|
)
|
2009-06-12 22:45:13 +00:00
|
|
|
);
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->addHtml(
|
2010-08-07 12:45:10 +00:00
|
|
|
Xml::openElement( 'table', array( 'id'=>'mw-search-top-table', 'border'=>0, 'cellpadding'=>0, 'cellspacing'=>0 ) ) .
|
|
|
|
|
Xml::openElement( 'tr' ) .
|
2011-04-22 16:13:58 +00:00
|
|
|
Xml::openElement( 'td' ) . "\n" .
|
2010-08-07 12:45:10 +00:00
|
|
|
$this->shortDialog( $term ) .
|
|
|
|
|
Xml::closeElement('td') .
|
|
|
|
|
Xml::closeElement('tr') .
|
|
|
|
|
Xml::closeElement('table')
|
2008-12-18 18:01:06 +00:00
|
|
|
);
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2008-12-18 18:01:06 +00:00
|
|
|
// Sometimes the search engine knows there are too many hits
|
|
|
|
|
if( $titleMatches instanceof SearchResultTooMany ) {
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->wrapWikiMsg( "==$1==\n", 'toomanymatches' );
|
2008-12-18 18:01:06 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
return;
|
|
|
|
|
}
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2010-08-07 12:45:10 +00:00
|
|
|
$filePrefix = $wgContLang->getFormattedNsText(NS_FILE).':';
|
|
|
|
|
if( trim( $term ) === '' || $filePrefix === trim( $term ) ) {
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->addHTML( $this->formHeader( $term, 0, 0 ) );
|
|
|
|
|
$out->addHtml( $this->getProfileForm( $this->profile, $term ) );
|
|
|
|
|
$out->addHTML( '</form>' );
|
2010-08-07 12:45:10 +00:00
|
|
|
// Empty query -- straight view of search form
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-19 09:08:49 +00:00
|
|
|
// Get number of results
|
2009-05-06 21:05:52 +00:00
|
|
|
$titleMatchesNum = $titleMatches ? $titleMatches->numRows() : 0;
|
|
|
|
|
$textMatchesNum = $textMatches ? $textMatches->numRows() : 0;
|
2008-11-19 09:08:49 +00:00
|
|
|
// Total initial query matches (possible false positives)
|
2009-05-06 21:05:52 +00:00
|
|
|
$num = $titleMatchesNum + $textMatchesNum;
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2008-11-19 09:08:49 +00:00
|
|
|
// Get total actual results (after second filtering, if any)
|
|
|
|
|
$numTitleMatches = $titleMatches && !is_null( $titleMatches->getTotalHits() ) ?
|
2009-05-06 21:05:52 +00:00
|
|
|
$titleMatches->getTotalHits() : $titleMatchesNum;
|
2008-11-19 09:08:49 +00:00
|
|
|
$numTextMatches = $textMatches && !is_null( $textMatches->getTotalHits() ) ?
|
2009-05-06 21:05:52 +00:00
|
|
|
$textMatches->getTotalHits() : $textMatchesNum;
|
|
|
|
|
|
|
|
|
|
// get total number of results if backend can calculate it
|
|
|
|
|
$totalRes = 0;
|
|
|
|
|
if($titleMatches && !is_null( $titleMatches->getTotalHits() ) )
|
|
|
|
|
$totalRes += $titleMatches->getTotalHits();
|
|
|
|
|
if($textMatches && !is_null( $textMatches->getTotalHits() ))
|
|
|
|
|
$totalRes += $textMatches->getTotalHits();
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2008-11-19 09:08:49 +00:00
|
|
|
// show number of results and current offset
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->addHTML( $this->formHeader( $term, $num, $totalRes ) );
|
|
|
|
|
$out->addHtml( $this->getProfileForm( $this->profile, $term ) );
|
2011-04-22 16:13:58 +00:00
|
|
|
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->addHtml( Xml::closeElement( 'form' ) );
|
|
|
|
|
$out->addHtml( "<div class='searchresults'>" );
|
2008-11-17 04:56:14 +00:00
|
|
|
|
|
|
|
|
// prev/next links
|
2009-05-06 21:05:52 +00:00
|
|
|
if( $num || $this->offset ) {
|
2009-09-17 17:23:26 +00:00
|
|
|
// Show the create link ahead
|
|
|
|
|
$this->showCreateLink( $t );
|
2011-11-21 16:13:21 +00:00
|
|
|
$prevnext = $this->getLanguage()->viewPrevNext( $this->getTitle(), $this->offset, $this->limit,
|
2011-10-14 14:57:06 +00:00
|
|
|
$this->powerSearchOptions() + array( 'search' => $term ),
|
2009-05-06 21:05:52 +00:00
|
|
|
max( $titleMatchesNum, $textMatchesNum ) < $this->limit
|
2008-11-17 04:56:14 +00:00
|
|
|
);
|
2011-08-11 21:10:30 +00:00
|
|
|
//$out->addHTML( "<p class='mw-search-pager-top'>{$prevnext}</p>\n" );
|
2008-11-17 04:56:14 +00:00
|
|
|
wfRunHooks( 'SpecialSearchResults', array( $term, &$titleMatches, &$textMatches ) );
|
|
|
|
|
} else {
|
|
|
|
|
wfRunHooks( 'SpecialSearchNoResults', array( $term ) );
|
2011-01-22 14:36:11 +00:00
|
|
|
}
|
2008-11-17 04:56:14 +00:00
|
|
|
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->parserOptions()->setEditSection( false );
|
2008-11-17 04:56:14 +00:00
|
|
|
if( $titleMatches ) {
|
2008-11-19 00:19:25 +00:00
|
|
|
if( $numTitleMatches > 0 ) {
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->wrapWikiMsg( "==$1==\n", 'titlematches' );
|
|
|
|
|
$out->addHTML( $this->showMatches( $titleMatches ) );
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
|
|
|
|
$titleMatches->free();
|
|
|
|
|
}
|
|
|
|
|
if( $textMatches ) {
|
|
|
|
|
// output appropriate heading
|
2008-11-19 00:19:25 +00:00
|
|
|
if( $numTextMatches > 0 && $numTitleMatches > 0 ) {
|
|
|
|
|
// if no title matches the heading is redundant
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->wrapWikiMsg( "==$1==\n", 'textmatches' );
|
2008-11-19 09:08:49 +00:00
|
|
|
} elseif( $totalRes == 0 ) {
|
2008-11-17 04:56:14 +00:00
|
|
|
# Don't show the 'no text matches' if we received title matches
|
2011-08-11 21:10:30 +00:00
|
|
|
# $out->wrapWikiMsg( "==$1==\n", 'notextmatches' );
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
|
|
|
|
// show interwiki results if any
|
2008-11-19 09:08:49 +00:00
|
|
|
if( $textMatches->hasInterwikiResults() ) {
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->addHTML( $this->showInterwiki( $textMatches->getInterwikiResults(), $term ) );
|
2008-11-19 09:08:49 +00:00
|
|
|
}
|
2008-11-17 04:56:14 +00:00
|
|
|
// show results
|
2008-11-19 09:08:49 +00:00
|
|
|
if( $numTextMatches > 0 ) {
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->addHTML( $this->showMatches( $textMatches ) );
|
2008-11-19 09:08:49 +00:00
|
|
|
}
|
2008-11-17 04:56:14 +00:00
|
|
|
|
|
|
|
|
$textMatches->free();
|
|
|
|
|
}
|
2009-05-06 21:05:52 +00:00
|
|
|
if( $num === 0 ) {
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->wrapWikiMsg( "<p class=\"mw-search-nonefound\">\n$1</p>", array( 'search-nonefound', wfEscapeWikiText( $term ) ) );
|
2009-09-17 17:23:26 +00:00
|
|
|
$this->showCreateLink( $t );
|
|
|
|
|
}
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->addHtml( "</div>" );
|
2009-08-26 14:34:28 +00:00
|
|
|
|
2009-09-17 17:23:26 +00:00
|
|
|
if( $num || $this->offset ) {
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->addHTML( "<p class='mw-search-pager-bottom'>{$prevnext}</p>\n" );
|
2009-09-17 17:23:26 +00:00
|
|
|
}
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
}
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2011-08-16 00:41:50 +00:00
|
|
|
/**
|
|
|
|
|
* @param $t Title
|
|
|
|
|
*/
|
2009-09-17 17:23:26 +00:00
|
|
|
protected function showCreateLink( $t ) {
|
2010-01-27 03:06:56 +00:00
|
|
|
// show direct page/create link if applicable
|
2011-09-15 16:26:35 +00:00
|
|
|
|
2011-05-10 06:20:13 +00:00
|
|
|
// Check DBkey !== '' in case of fragment link only.
|
2011-09-15 16:26:35 +00:00
|
|
|
if( is_null( $t ) || $t->getDBkey() === '' ) {
|
|
|
|
|
// invalid title
|
|
|
|
|
// preserve the paragraph for margins etc...
|
|
|
|
|
$this->getOutput()->addHtml( '<p></p>' );
|
|
|
|
|
return;
|
2011-01-22 14:36:11 +00:00
|
|
|
}
|
2011-10-29 01:17:26 +00:00
|
|
|
|
2011-09-15 16:26:35 +00:00
|
|
|
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
|
2010-01-27 03:06:56 +00:00
|
|
|
if( $messageName ) {
|
2011-09-15 16:26:35 +00:00
|
|
|
$this->getOutput()->wrapWikiMsg( "<p class=\"mw-search-createlink\">\n$1</p>", $params );
|
2009-08-26 14:34:28 +00:00
|
|
|
} else {
|
|
|
|
|
// preserve the paragraph for margins etc...
|
2011-08-11 21:10:30 +00:00
|
|
|
$this->getOutput()->addHtml( '<p></p>' );
|
2009-08-26 14:34:28 +00:00
|
|
|
}
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
/**
|
2011-08-16 00:41:50 +00:00
|
|
|
* @param $term string
|
2008-11-17 04:56:14 +00:00
|
|
|
*/
|
|
|
|
|
protected function setupPage( $term ) {
|
2008-11-19 08:35:04 +00:00
|
|
|
# Should advanced UI be used?
|
2011-04-22 16:13:58 +00:00
|
|
|
$this->searchAdvanced = ($this->profile === 'advanced');
|
2011-08-11 21:10:30 +00:00
|
|
|
$out = $this->getOutput();
|
2011-04-22 16:13:58 +00:00
|
|
|
if( strval( $term ) !== '' ) {
|
2011-10-27 20:23:16 +00:00
|
|
|
$out->setPageTitle( $this->msg( 'searchresults' ) );
|
|
|
|
|
$out->setHTMLTitle( $this->msg( 'pagetitle', $this->msg( 'searchresults-title', $term )->plain() ) );
|
2009-04-27 07:25:51 +00:00
|
|
|
}
|
2009-05-31 13:22:35 +00:00
|
|
|
// add javascript specific to special:search
|
2011-08-11 21:10:30 +00:00
|
|
|
$out->addModules( 'mediawiki.special.search' );
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Extract "power search" namespace settings from the request object,
|
|
|
|
|
* returning a list of index numbers to search.
|
|
|
|
|
*
|
2010-05-02 20:34:40 +00:00
|
|
|
* @param $request WebRequest
|
|
|
|
|
* @return Array
|
2008-11-17 04:56:14 +00:00
|
|
|
*/
|
|
|
|
|
protected function powerSearch( &$request ) {
|
|
|
|
|
$arr = array();
|
|
|
|
|
foreach( SearchEngine::searchableNamespaces() as $ns => $name ) {
|
|
|
|
|
if( $request->getCheck( 'ns' . $ns ) ) {
|
|
|
|
|
$arr[] = $ns;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-04-22 16:13:58 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
return $arr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reconstruct the 'power search' options for links
|
2010-05-02 20:34:40 +00:00
|
|
|
*
|
|
|
|
|
* @return Array
|
2008-11-17 04:56:14 +00:00
|
|
|
*/
|
|
|
|
|
protected function powerSearchOptions() {
|
|
|
|
|
$opt = array();
|
|
|
|
|
$opt['redirs'] = $this->searchRedirects ? 1 : 0;
|
2011-04-22 20:12:29 +00:00
|
|
|
if( $this->profile !== 'advanced' ) {
|
2011-04-22 16:13:58 +00:00
|
|
|
$opt['profile'] = $this->profile;
|
2011-04-22 20:12:29 +00:00
|
|
|
} else {
|
|
|
|
|
foreach( $this->namespaces as $n ) {
|
|
|
|
|
$opt['ns' . $n] = 1;
|
|
|
|
|
}
|
2008-11-19 08:35:04 +00:00
|
|
|
}
|
2011-04-22 20:25:21 +00:00
|
|
|
return $opt + $this->extraParams;
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2009-04-27 07:25:51 +00:00
|
|
|
* Show whole set of results
|
|
|
|
|
*
|
2010-05-02 20:34:40 +00:00
|
|
|
* @param $matches SearchResultSet
|
2011-08-16 00:41:50 +00:00
|
|
|
*
|
|
|
|
|
* @return string
|
2008-11-17 04:56:14 +00:00
|
|
|
*/
|
|
|
|
|
protected function showMatches( &$matches ) {
|
|
|
|
|
global $wgContLang;
|
|
|
|
|
wfProfileIn( __METHOD__ );
|
|
|
|
|
|
|
|
|
|
$terms = $wgContLang->convertForSearchResult( $matches->termMatches() );
|
|
|
|
|
|
|
|
|
|
$out = "";
|
|
|
|
|
$infoLine = $matches->getInfo();
|
2008-11-19 08:35:04 +00:00
|
|
|
if( !is_null($infoLine) ) {
|
2008-11-17 04:56:14 +00:00
|
|
|
$out .= "\n<!-- {$infoLine} -->\n";
|
2008-11-19 08:35:04 +00:00
|
|
|
}
|
2008-11-17 04:56:14 +00:00
|
|
|
$out .= "<ul class='mw-search-results'>\n";
|
2011-10-16 03:27:12 +00:00
|
|
|
$result = $matches->next();
|
|
|
|
|
while( $result ) {
|
2008-11-17 04:56:14 +00:00
|
|
|
$out .= $this->showHit( $result, $terms );
|
2011-10-16 03:27:12 +00:00
|
|
|
$result = $matches->next();
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
|
|
|
|
$out .= "</ul>\n";
|
|
|
|
|
|
|
|
|
|
// convert the whole thing to desired language variant
|
|
|
|
|
$out = $wgContLang->convert( $out );
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
return $out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Format a single hit result
|
2010-05-02 20:34:40 +00:00
|
|
|
*
|
|
|
|
|
* @param $result SearchResult
|
|
|
|
|
* @param $terms Array: terms to highlight
|
2011-08-16 00:41:50 +00:00
|
|
|
*
|
|
|
|
|
* @return string
|
2008-11-17 04:56:14 +00:00
|
|
|
*/
|
|
|
|
|
protected function showHit( $result, $terms ) {
|
|
|
|
|
wfProfileIn( __METHOD__ );
|
2008-11-19 08:35:04 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
if( $result->isBrokenTitle() ) {
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
return "<!-- Broken link in search result -->\n";
|
|
|
|
|
}
|
2008-11-19 08:35:04 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
$t = $result->getTitle();
|
|
|
|
|
|
2009-06-07 19:49:56 +00:00
|
|
|
$titleSnippet = $result->getTitleSnippet($terms);
|
|
|
|
|
|
|
|
|
|
if( $titleSnippet == '' )
|
|
|
|
|
$titleSnippet = null;
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2009-08-14 16:06:11 +00:00
|
|
|
$link_t = clone $t;
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2009-08-14 16:06:11 +00:00
|
|
|
wfRunHooks( 'ShowSearchHitTitle',
|
|
|
|
|
array( &$link_t, &$titleSnippet, $result, $terms, $this ) );
|
2009-06-07 19:49:56 +00:00
|
|
|
|
2011-08-11 21:10:30 +00:00
|
|
|
$link = Linker::linkKnown(
|
2009-08-14 16:06:11 +00:00
|
|
|
$link_t,
|
2009-06-07 19:49:56 +00:00
|
|
|
$titleSnippet
|
2009-06-07 18:45:52 +00:00
|
|
|
);
|
2008-11-17 04:56:14 +00:00
|
|
|
|
|
|
|
|
//If page content is not readable, just return the title.
|
|
|
|
|
//This is not quite safe, but better than showing excerpts from non-readable pages
|
|
|
|
|
//Note that hiding the entry entirely would screw up paging.
|
2011-12-13 10:47:31 +00:00
|
|
|
if( !$t->userCan( 'read' ) ) {
|
2008-11-17 04:56:14 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
return "<li>{$link}</li>\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the page doesn't *exist*... our search index is out of date.
|
|
|
|
|
// The least confusing at this point is to drop the result.
|
|
|
|
|
// You may get less results, but... oh well. :P
|
|
|
|
|
if( $result->isMissingRevision() ) {
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
2008-11-19 08:35:04 +00:00
|
|
|
return "<!-- missing page " . htmlspecialchars( $t->getPrefixedText() ) . "-->\n";
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// format redirects / relevant sections
|
|
|
|
|
$redirectTitle = $result->getRedirectTitle();
|
|
|
|
|
$redirectText = $result->getRedirectSnippet($terms);
|
|
|
|
|
$sectionTitle = $result->getSectionTitle();
|
|
|
|
|
$sectionText = $result->getSectionSnippet($terms);
|
|
|
|
|
$redirect = '';
|
2009-06-07 18:45:52 +00:00
|
|
|
|
2009-06-07 19:49:56 +00:00
|
|
|
if( !is_null($redirectTitle) ) {
|
|
|
|
|
if( $redirectText == '' )
|
|
|
|
|
$redirectText = null;
|
|
|
|
|
|
2009-06-07 18:45:52 +00:00
|
|
|
$redirect = "<span class='searchalttitle'>" .
|
2012-05-07 04:38:51 +00:00
|
|
|
$this->msg( 'search-redirect' )->rawParams(
|
|
|
|
|
Linker::linkKnown( $redirectTitle, $redirectText ) )->text() .
|
2009-06-07 18:45:52 +00:00
|
|
|
"</span>";
|
2009-06-07 19:49:56 +00:00
|
|
|
}
|
2009-06-07 18:45:52 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
$section = '';
|
2009-06-07 18:45:52 +00:00
|
|
|
|
2009-06-07 19:49:56 +00:00
|
|
|
if( !is_null($sectionTitle) ) {
|
|
|
|
|
if( $sectionText == '' )
|
|
|
|
|
$sectionText = null;
|
|
|
|
|
|
2009-06-07 18:45:52 +00:00
|
|
|
$section = "<span class='searchalttitle'>" .
|
2012-05-07 04:38:51 +00:00
|
|
|
$this->msg( 'search-section' )->rawParams(
|
|
|
|
|
Linker::linkKnown( $sectionTitle, $sectionText ) )->text() .
|
2009-06-07 18:45:52 +00:00
|
|
|
"</span>";
|
2009-06-07 19:49:56 +00:00
|
|
|
}
|
2008-11-17 04:56:14 +00:00
|
|
|
|
|
|
|
|
// format text extract
|
|
|
|
|
$extract = "<div class='searchresult'>".$result->getTextSnippet($terms)."</div>";
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2011-11-21 16:13:21 +00:00
|
|
|
$lang = $this->getLanguage();
|
2011-08-11 21:10:30 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
// format score
|
|
|
|
|
if( is_null( $result->getScore() ) ) {
|
|
|
|
|
// Search engine doesn't report scoring info
|
|
|
|
|
$score = '';
|
|
|
|
|
} else {
|
|
|
|
|
$percent = sprintf( '%2.1f', $result->getScore() * 100 );
|
2012-05-07 04:38:51 +00:00
|
|
|
$score = $this->msg( 'search-result-score' )->numParams( $percent )->text()
|
2008-11-17 04:56:14 +00:00
|
|
|
. ' - ';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// format description
|
|
|
|
|
$byteSize = $result->getByteSize();
|
|
|
|
|
$wordCount = $result->getWordCount();
|
|
|
|
|
$timestamp = $result->getTimestamp();
|
2012-05-07 04:38:51 +00:00
|
|
|
$size = $this->msg( 'search-result-size', $lang->formatSize( $byteSize ) )
|
|
|
|
|
->numParams( $wordCount )->escaped();
|
2010-04-20 23:06:59 +00:00
|
|
|
|
|
|
|
|
if( $t->getNamespace() == NS_CATEGORY ) {
|
|
|
|
|
$cat = Category::newFromTitle( $t );
|
2012-05-07 04:38:51 +00:00
|
|
|
$size = $this->msg( 'search-result-category-size' )
|
|
|
|
|
->numParams( $cat->getPageCount(), $cat->getSubcatCount(), $cat->getFileCount() )
|
|
|
|
|
->escaped();
|
2010-04-20 23:06:59 +00:00
|
|
|
}
|
|
|
|
|
|
2012-05-07 04:38:51 +00:00
|
|
|
$date = $lang->userTimeAndDate( $timestamp, $this->getUser() );
|
2008-11-17 04:56:14 +00:00
|
|
|
|
|
|
|
|
// link to related articles if supported
|
|
|
|
|
$related = '';
|
|
|
|
|
if( $result->hasRelated() ) {
|
|
|
|
|
$st = SpecialPage::getTitleFor( 'Search' );
|
2009-06-07 18:45:52 +00:00
|
|
|
$stParams = array_merge(
|
|
|
|
|
$this->powerSearchOptions(),
|
|
|
|
|
array(
|
2012-05-07 04:38:51 +00:00
|
|
|
'search' => $this->msg( 'searchrelated' )->inContentLanguage()->text() .
|
|
|
|
|
':' . $t->getPrefixedText(),
|
|
|
|
|
'fulltext' => $this->msg( 'search' )->text()
|
2009-06-07 18:45:52 +00:00
|
|
|
)
|
|
|
|
|
);
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2011-08-11 21:10:30 +00:00
|
|
|
$related = ' -- ' . Linker::linkKnown(
|
2009-06-07 18:45:52 +00:00
|
|
|
$st,
|
2012-05-07 04:38:51 +00:00
|
|
|
$this->msg( 'search-relatedarticle' )->text(),
|
2009-06-07 18:45:52 +00:00
|
|
|
array(),
|
|
|
|
|
$stParams
|
|
|
|
|
);
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
2008-11-19 08:35:04 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
// Include a thumbnail for media files...
|
2008-12-01 17:14:30 +00:00
|
|
|
if( $t->getNamespace() == NS_FILE ) {
|
2008-11-17 04:56:14 +00:00
|
|
|
$img = wfFindFile( $t );
|
|
|
|
|
if( $img ) {
|
|
|
|
|
$thumb = $img->transform( array( 'width' => 120, 'height' => 120 ) );
|
|
|
|
|
if( $thumb ) {
|
2012-05-07 04:38:51 +00:00
|
|
|
$desc = $this->msg( 'parentheses' )->rawParams( $img->getShortDesc() )->escaped();
|
2008-11-17 04:56:14 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
// Float doesn't seem to interact well with the bullets.
|
|
|
|
|
// Table messes up vertical alignment of the bullets.
|
|
|
|
|
// Bullets are therefore disabled (didn't look great anyway).
|
|
|
|
|
return "<li>" .
|
|
|
|
|
'<table class="searchResultImage">' .
|
|
|
|
|
'<tr>' .
|
|
|
|
|
'<td width="120" align="center" valign="top">' .
|
|
|
|
|
$thumb->toHtml( array( 'desc-link' => true ) ) .
|
|
|
|
|
'</td>' .
|
|
|
|
|
'<td valign="top">' .
|
|
|
|
|
$link .
|
|
|
|
|
$extract .
|
|
|
|
|
"<div class='mw-search-result-data'>{$score}{$desc} - {$date}{$related}</div>" .
|
|
|
|
|
'</td>' .
|
|
|
|
|
'</tr>' .
|
|
|
|
|
'</table>' .
|
|
|
|
|
"</li>\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
2010-07-01 09:48:53 +00:00
|
|
|
return "<li><div class='mw-search-result-heading'>{$link} {$redirect} {$section}</div> {$extract}\n" .
|
2008-11-17 04:56:14 +00:00
|
|
|
"<div class='mw-search-result-data'>{$score}{$size} - {$date}{$related}</div>" .
|
|
|
|
|
"</li>\n";
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Show results from other wikis
|
2009-04-27 07:25:51 +00:00
|
|
|
*
|
2010-05-02 20:34:40 +00:00
|
|
|
* @param $matches SearchResultSet
|
|
|
|
|
* @param $query String
|
2011-08-16 00:41:50 +00:00
|
|
|
*
|
|
|
|
|
* @return string
|
2008-11-17 04:56:14 +00:00
|
|
|
*/
|
|
|
|
|
protected function showInterwiki( &$matches, $query ) {
|
|
|
|
|
global $wgContLang;
|
2008-11-19 08:35:04 +00:00
|
|
|
wfProfileIn( __METHOD__ );
|
2008-11-17 04:56:14 +00:00
|
|
|
$terms = $wgContLang->convertForSearchResult( $matches->termMatches() );
|
|
|
|
|
|
|
|
|
|
$out = "<div id='mw-search-interwiki'><div id='mw-search-interwiki-caption'>".
|
2012-05-07 04:38:51 +00:00
|
|
|
$this->msg( 'search-interwiki-caption' )->text() . "</div>\n";
|
2008-12-18 18:01:06 +00:00
|
|
|
$out .= "<ul class='mw-search-iwresults'>\n";
|
2008-11-17 04:56:14 +00:00
|
|
|
|
|
|
|
|
// work out custom project captions
|
|
|
|
|
$customCaptions = array();
|
2012-05-07 04:38:51 +00:00
|
|
|
$customLines = explode( "\n", $this->msg( 'search-interwiki-custom' )->text() ); // format per line <iwprefix>:<caption>
|
2008-11-17 04:56:14 +00:00
|
|
|
foreach($customLines as $line) {
|
|
|
|
|
$parts = explode(":",$line,2);
|
|
|
|
|
if(count($parts) == 2) // validate line
|
2009-04-27 07:25:51 +00:00
|
|
|
$customCaptions[$parts[0]] = $parts[1];
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
$prev = null;
|
2011-10-16 03:27:12 +00:00
|
|
|
$result = $matches->next();
|
|
|
|
|
while( $result ) {
|
2008-11-17 04:56:14 +00:00
|
|
|
$out .= $this->showInterwikiHit( $result, $prev, $terms, $query, $customCaptions );
|
|
|
|
|
$prev = $result->getInterwikiPrefix();
|
2011-10-16 03:27:12 +00:00
|
|
|
$result = $matches->next();
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
2009-05-31 13:22:35 +00:00
|
|
|
// TODO: should support paging in a non-confusing way (not sure how though, maybe via ajax)..
|
2008-11-17 04:56:14 +00:00
|
|
|
$out .= "</ul></div>\n";
|
|
|
|
|
|
|
|
|
|
// convert the whole thing to desired language variant
|
|
|
|
|
$out = $wgContLang->convert( $out );
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
return $out;
|
|
|
|
|
}
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
/**
|
|
|
|
|
* Show single interwiki link
|
|
|
|
|
*
|
2010-05-02 20:34:40 +00:00
|
|
|
* @param $result SearchResult
|
|
|
|
|
* @param $lastInterwiki String
|
|
|
|
|
* @param $terms Array
|
|
|
|
|
* @param $query String
|
|
|
|
|
* @param $customCaptions Array: iw prefix -> caption
|
2011-08-16 00:41:50 +00:00
|
|
|
*
|
|
|
|
|
* @return string
|
2008-11-17 04:56:14 +00:00
|
|
|
*/
|
|
|
|
|
protected function showInterwikiHit( $result, $lastInterwiki, $terms, $query, $customCaptions) {
|
|
|
|
|
wfProfileIn( __METHOD__ );
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
if( $result->isBrokenTitle() ) {
|
|
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
return "<!-- Broken link in search result -->\n";
|
|
|
|
|
}
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
$t = $result->getTitle();
|
2008-11-19 08:35:04 +00:00
|
|
|
|
2009-06-07 19:49:56 +00:00
|
|
|
$titleSnippet = $result->getTitleSnippet($terms);
|
|
|
|
|
|
|
|
|
|
if( $titleSnippet == '' )
|
|
|
|
|
$titleSnippet = null;
|
|
|
|
|
|
2011-08-11 21:10:30 +00:00
|
|
|
$link = Linker::linkKnown(
|
2009-06-07 18:45:52 +00:00
|
|
|
$t,
|
2009-06-07 19:49:56 +00:00
|
|
|
$titleSnippet
|
2009-06-07 18:45:52 +00:00
|
|
|
);
|
2008-11-19 08:35:04 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
// format redirect if any
|
|
|
|
|
$redirectTitle = $result->getRedirectTitle();
|
|
|
|
|
$redirectText = $result->getRedirectSnippet($terms);
|
|
|
|
|
$redirect = '';
|
2009-06-07 19:49:56 +00:00
|
|
|
if( !is_null($redirectTitle) ) {
|
|
|
|
|
if( $redirectText == '' )
|
|
|
|
|
$redirectText = null;
|
|
|
|
|
|
2009-06-07 18:45:52 +00:00
|
|
|
$redirect = "<span class='searchalttitle'>" .
|
2012-05-07 04:38:51 +00:00
|
|
|
$this->msg( 'search-redirect' )->rawParams(
|
|
|
|
|
Linker::linkKnown( $redirectTitle, $redirectText ) )->text() .
|
2009-06-07 18:45:52 +00:00
|
|
|
"</span>";
|
2009-06-07 19:49:56 +00:00
|
|
|
}
|
2008-11-17 04:56:14 +00:00
|
|
|
|
|
|
|
|
$out = "";
|
2009-04-27 07:25:51 +00:00
|
|
|
// display project name
|
2008-11-17 04:56:14 +00:00
|
|
|
if(is_null($lastInterwiki) || $lastInterwiki != $t->getInterwiki()) {
|
2011-08-19 15:56:59 +00:00
|
|
|
if( array_key_exists($t->getInterwiki(),$customCaptions) ) {
|
2008-11-17 04:56:14 +00:00
|
|
|
// captions from 'search-interwiki-custom'
|
|
|
|
|
$caption = $customCaptions[$t->getInterwiki()];
|
2011-08-16 00:41:50 +00:00
|
|
|
} else {
|
2009-04-27 07:25:51 +00:00
|
|
|
// default is to show the hostname of the other wiki which might suck
|
2008-11-17 04:56:14 +00:00
|
|
|
// if there are many wikis on one hostname
|
2011-08-19 15:56:59 +00:00
|
|
|
$parsed = wfParseUrl( $t->getFullURL() );
|
2012-05-07 04:38:51 +00:00
|
|
|
$caption = $this->msg( 'search-interwiki-default', $parsed['host'] )->text();
|
2009-04-27 07:25:51 +00:00
|
|
|
}
|
2008-11-17 04:56:14 +00:00
|
|
|
// "more results" link (special page stuff could be localized, but we might not know target lang)
|
2009-04-27 07:25:51 +00:00
|
|
|
$searchTitle = Title::newFromText($t->getInterwiki().":Special:Search");
|
2011-08-11 21:10:30 +00:00
|
|
|
$searchLink = Linker::linkKnown(
|
2009-06-07 18:45:52 +00:00
|
|
|
$searchTitle,
|
2012-05-07 04:38:51 +00:00
|
|
|
$this->msg( 'search-interwiki-more' )->text(),
|
2009-06-07 18:45:52 +00:00
|
|
|
array(),
|
|
|
|
|
array(
|
|
|
|
|
'search' => $query,
|
|
|
|
|
'fulltext' => 'Search'
|
|
|
|
|
)
|
|
|
|
|
);
|
2008-11-17 04:56:14 +00:00
|
|
|
$out .= "</ul><div class='mw-search-interwiki-project'><span class='mw-search-interwiki-more'>
|
|
|
|
|
{$searchLink}</span>{$caption}</div>\n<ul>";
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-27 07:25:51 +00:00
|
|
|
$out .= "<li>{$link} {$redirect}</li>\n";
|
2008-11-17 04:56:14 +00:00
|
|
|
wfProfileOut( __METHOD__ );
|
|
|
|
|
return $out;
|
|
|
|
|
}
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2011-08-16 00:41:50 +00:00
|
|
|
/**
|
|
|
|
|
* @param $profile
|
|
|
|
|
* @param $term
|
|
|
|
|
* @return String
|
|
|
|
|
*/
|
2011-04-22 16:13:58 +00:00
|
|
|
protected function getProfileForm( $profile, $term ) {
|
|
|
|
|
// Hidden stuff
|
|
|
|
|
$opts = array();
|
|
|
|
|
$opts['redirs'] = $this->searchRedirects;
|
|
|
|
|
$opts['profile'] = $this->profile;
|
|
|
|
|
|
|
|
|
|
if ( $profile === 'advanced' ) {
|
|
|
|
|
return $this->powerSearchBox( $term, $opts );
|
|
|
|
|
} else {
|
|
|
|
|
$form = '';
|
|
|
|
|
wfRunHooks( 'SpecialSearchProfileForm', array( $this, &$form, $profile, $term, $opts ) );
|
|
|
|
|
return $form;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-11-17 04:56:14 +00:00
|
|
|
|
|
|
|
|
/**
|
2011-04-22 16:13:58 +00:00
|
|
|
* Generates the power search box at [[Special:Search]]
|
2010-05-02 20:34:40 +00:00
|
|
|
*
|
|
|
|
|
* @param $term String: search term
|
2011-08-16 00:41:50 +00:00
|
|
|
* @param $opts array
|
2010-05-02 20:34:40 +00:00
|
|
|
* @return String: HTML form
|
2008-11-17 04:56:14 +00:00
|
|
|
*/
|
2011-04-22 16:13:58 +00:00
|
|
|
protected function powerSearchBox( $term, $opts ) {
|
2009-06-12 22:45:13 +00:00
|
|
|
// Groups namespaces into rows according to subject
|
|
|
|
|
$rows = array();
|
|
|
|
|
foreach( SearchEngine::searchableNamespaces() as $namespace => $name ) {
|
|
|
|
|
$subject = MWNamespace::getSubject( $namespace );
|
|
|
|
|
if( !array_key_exists( $subject, $rows ) ) {
|
|
|
|
|
$rows[$subject] = "";
|
|
|
|
|
}
|
|
|
|
|
$name = str_replace( '_', ' ', $name );
|
|
|
|
|
if( $name == '' ) {
|
2012-05-07 04:38:51 +00:00
|
|
|
$name = $this->msg( 'blanknamespace' )->text();
|
2009-06-12 22:45:13 +00:00
|
|
|
}
|
|
|
|
|
$rows[$subject] .=
|
|
|
|
|
Xml::openElement(
|
|
|
|
|
'td', array( 'style' => 'white-space: nowrap' )
|
|
|
|
|
) .
|
|
|
|
|
Xml::checkLabel(
|
|
|
|
|
$name,
|
|
|
|
|
"ns{$namespace}",
|
|
|
|
|
"mw-search-ns{$namespace}",
|
|
|
|
|
in_array( $namespace, $this->namespaces )
|
|
|
|
|
) .
|
|
|
|
|
Xml::closeElement( 'td' );
|
2008-12-18 18:01:06 +00:00
|
|
|
}
|
2009-06-12 22:45:13 +00:00
|
|
|
$rows = array_values( $rows );
|
|
|
|
|
$numRows = count( $rows );
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2009-06-12 22:45:13 +00:00
|
|
|
// Lays out namespaces in multiple floating two-column tables so they'll
|
|
|
|
|
// be arranged nicely while still accommodating different screen widths
|
|
|
|
|
$namespaceTables = '';
|
|
|
|
|
for( $i = 0; $i < $numRows; $i += 4 ) {
|
|
|
|
|
$namespaceTables .= Xml::openElement(
|
|
|
|
|
'table',
|
|
|
|
|
array( 'cellpadding' => 0, 'cellspacing' => 0, 'border' => 0 )
|
|
|
|
|
);
|
|
|
|
|
for( $j = $i; $j < $i + 4 && $j < $numRows; $j++ ) {
|
|
|
|
|
$namespaceTables .= Xml::tags( 'tr', null, $rows[$j] );
|
|
|
|
|
}
|
|
|
|
|
$namespaceTables .= Xml::closeElement( 'table' );
|
|
|
|
|
}
|
2011-09-15 16:26:35 +00:00
|
|
|
|
|
|
|
|
$showSections = array( 'namespaceTables' => $namespaceTables );
|
|
|
|
|
|
2009-06-12 22:45:13 +00:00
|
|
|
// Show redirects check only if backend supports it
|
2011-04-22 16:13:58 +00:00
|
|
|
if( $this->getSearchEngine()->supports( 'list-redirects' ) ) {
|
2011-09-15 16:26:35 +00:00
|
|
|
$showSections['redirects'] =
|
2012-05-07 04:38:51 +00:00
|
|
|
Xml::checkLabel( $this->msg( 'powersearch-redir' )->text(), 'redirs', 'redirs', $this->searchRedirects );
|
2011-04-22 16:13:58 +00:00
|
|
|
}
|
|
|
|
|
|
2011-09-15 16:26:35 +00:00
|
|
|
wfRunHooks( 'SpecialSearchPowerBox', array( &$showSections, $term, $opts ) );
|
|
|
|
|
|
2011-04-22 16:13:58 +00:00
|
|
|
$hidden = '';
|
|
|
|
|
unset( $opts['redirs'] );
|
|
|
|
|
foreach( $opts as $key => $value ) {
|
|
|
|
|
$hidden .= Html::hidden( $key, $value );
|
2009-06-12 22:45:13 +00:00
|
|
|
}
|
|
|
|
|
// Return final output
|
|
|
|
|
return
|
|
|
|
|
Xml::openElement(
|
|
|
|
|
'fieldset',
|
|
|
|
|
array( 'id' => 'mw-searchoptions', 'style' => 'margin:0em;' )
|
|
|
|
|
) .
|
2012-05-07 04:38:51 +00:00
|
|
|
Xml::element( 'legend', null, $this->msg('powersearch-legend' )->text() ) .
|
|
|
|
|
Xml::tags( 'h4', null, $this->msg( 'powersearch-ns' )->parse() ) .
|
2009-06-12 22:45:13 +00:00
|
|
|
Xml::tags(
|
|
|
|
|
'div',
|
|
|
|
|
array( 'id' => 'mw-search-togglebox' ),
|
2012-05-07 04:38:51 +00:00
|
|
|
Xml::label( $this->msg( 'powersearch-togglelabel' )->text(), 'mw-search-togglelabel' ) .
|
2009-06-12 22:45:13 +00:00
|
|
|
Xml::element(
|
|
|
|
|
'input',
|
|
|
|
|
array(
|
|
|
|
|
'type'=>'button',
|
|
|
|
|
'id' => 'mw-search-toggleall',
|
2012-05-07 04:38:51 +00:00
|
|
|
'value' => $this->msg( 'powersearch-toggleall' )->text()
|
2009-06-12 22:45:13 +00:00
|
|
|
)
|
|
|
|
|
) .
|
|
|
|
|
Xml::element(
|
|
|
|
|
'input',
|
|
|
|
|
array(
|
|
|
|
|
'type'=>'button',
|
|
|
|
|
'id' => 'mw-search-togglenone',
|
2012-05-07 04:38:51 +00:00
|
|
|
'value' => $this->msg( 'powersearch-togglenone' )->text()
|
2009-06-12 22:45:13 +00:00
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
) .
|
|
|
|
|
Xml::element( 'div', array( 'class' => 'divider' ), '', false ) .
|
2011-09-15 16:26:35 +00:00
|
|
|
implode( Xml::element( 'div', array( 'class' => 'divider' ), '', false ), $showSections ) .
|
|
|
|
|
$hidden .
|
2008-11-17 04:56:14 +00:00
|
|
|
Xml::closeElement( 'fieldset' );
|
|
|
|
|
}
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2011-08-16 00:41:50 +00:00
|
|
|
/**
|
|
|
|
|
* @return array
|
|
|
|
|
*/
|
2009-09-08 11:50:31 +00:00
|
|
|
protected function getSearchProfiles() {
|
|
|
|
|
// Builds list of Search Types (profiles)
|
2009-06-12 22:45:13 +00:00
|
|
|
$nsAllSet = array_keys( SearchEngine::searchableNamespaces() );
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2009-06-12 22:45:13 +00:00
|
|
|
$profiles = array(
|
|
|
|
|
'default' => array(
|
|
|
|
|
'message' => 'searchprofile-articles',
|
|
|
|
|
'tooltip' => 'searchprofile-articles-tooltip',
|
|
|
|
|
'namespaces' => SearchEngine::defaultNamespaces(),
|
|
|
|
|
'namespace-messages' => SearchEngine::namespacesAsText(
|
|
|
|
|
SearchEngine::defaultNamespaces()
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
'images' => array(
|
|
|
|
|
'message' => 'searchprofile-images',
|
|
|
|
|
'tooltip' => 'searchprofile-images-tooltip',
|
|
|
|
|
'namespaces' => array( NS_FILE ),
|
|
|
|
|
),
|
|
|
|
|
'help' => array(
|
|
|
|
|
'message' => 'searchprofile-project',
|
|
|
|
|
'tooltip' => 'searchprofile-project-tooltip',
|
|
|
|
|
'namespaces' => SearchEngine::helpNamespaces(),
|
|
|
|
|
'namespace-messages' => SearchEngine::namespacesAsText(
|
|
|
|
|
SearchEngine::helpNamespaces()
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
'all' => array(
|
|
|
|
|
'message' => 'searchprofile-everything',
|
|
|
|
|
'tooltip' => 'searchprofile-everything-tooltip',
|
|
|
|
|
'namespaces' => $nsAllSet,
|
|
|
|
|
),
|
|
|
|
|
'advanced' => array(
|
|
|
|
|
'message' => 'searchprofile-advanced',
|
|
|
|
|
'tooltip' => 'searchprofile-advanced-tooltip',
|
2011-04-22 16:13:58 +00:00
|
|
|
'namespaces' => self::NAMESPACES_CURRENT,
|
2009-06-12 22:45:13 +00:00
|
|
|
)
|
|
|
|
|
);
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2009-09-08 11:50:31 +00:00
|
|
|
wfRunHooks( 'SpecialSearchProfiles', array( &$profiles ) );
|
|
|
|
|
|
2010-10-14 20:53:04 +00:00
|
|
|
foreach( $profiles as &$data ) {
|
2011-04-22 16:13:58 +00:00
|
|
|
if ( !is_array( $data['namespaces'] ) ) continue;
|
|
|
|
|
sort( $data['namespaces'] );
|
2009-09-08 11:50:31 +00:00
|
|
|
}
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2009-09-08 11:50:31 +00:00
|
|
|
return $profiles;
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-16 00:41:50 +00:00
|
|
|
/**
|
|
|
|
|
* @param $term
|
|
|
|
|
* @param $resultsShown
|
|
|
|
|
* @param $totalNum
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2009-09-08 11:50:31 +00:00
|
|
|
protected function formHeader( $term, $resultsShown, $totalNum ) {
|
|
|
|
|
$out = Xml::openElement('div', array( 'class' => 'mw-search-formheader' ) );
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2009-09-08 11:50:31 +00:00
|
|
|
$bareterm = $term;
|
|
|
|
|
if( $this->startsWithImage( $term ) ) {
|
|
|
|
|
// Deletes prefixes
|
|
|
|
|
$bareterm = substr( $term, strpos( $term, ':' ) + 1 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$profiles = $this->getSearchProfiles();
|
2011-11-21 16:13:21 +00:00
|
|
|
$lang = $this->getLanguage();
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2009-06-12 22:45:13 +00:00
|
|
|
// Outputs XML for Search Types
|
|
|
|
|
$out .= Xml::openElement( 'div', array( 'class' => 'search-types' ) );
|
|
|
|
|
$out .= Xml::openElement( 'ul' );
|
|
|
|
|
foreach ( $profiles as $id => $profile ) {
|
2011-04-22 16:13:58 +00:00
|
|
|
if ( !isset( $profile['parameters'] ) ) {
|
|
|
|
|
$profile['parameters'] = array();
|
|
|
|
|
}
|
|
|
|
|
$profile['parameters']['profile'] = $id;
|
|
|
|
|
|
2009-06-12 22:45:13 +00:00
|
|
|
$tooltipParam = isset( $profile['namespace-messages'] ) ?
|
2011-08-11 21:10:30 +00:00
|
|
|
$lang->commaList( $profile['namespace-messages'] ) : null;
|
2009-06-12 22:45:13 +00:00
|
|
|
$out .= Xml::tags(
|
|
|
|
|
'li',
|
|
|
|
|
array(
|
2011-04-22 16:13:58 +00:00
|
|
|
'class' => $this->profile === $id ? 'current' : 'normal'
|
2009-06-12 22:45:13 +00:00
|
|
|
),
|
|
|
|
|
$this->makeSearchLink(
|
|
|
|
|
$bareterm,
|
2011-04-22 16:13:58 +00:00
|
|
|
array(),
|
2012-05-07 04:38:51 +00:00
|
|
|
$this->msg( $profile['message'] )->text(),
|
|
|
|
|
$this->msg( $profile['tooltip'], $tooltipParam )->text(),
|
2011-04-22 16:13:58 +00:00
|
|
|
$profile['parameters']
|
2009-06-12 22:45:13 +00:00
|
|
|
)
|
|
|
|
|
);
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
2009-06-12 22:45:13 +00:00
|
|
|
$out .= Xml::closeElement( 'ul' );
|
2008-11-17 04:56:14 +00:00
|
|
|
$out .= Xml::closeElement('div') ;
|
2009-08-17 09:45:39 +00:00
|
|
|
|
2009-06-12 22:45:13 +00:00
|
|
|
// Results-info
|
2009-05-06 21:05:52 +00:00
|
|
|
if ( $resultsShown > 0 ) {
|
|
|
|
|
if ( $totalNum > 0 ){
|
2012-05-07 04:38:51 +00:00
|
|
|
$top = $this->msg( 'showingresultsheader' )
|
|
|
|
|
->numParams( $this->offset + 1, $this->offset + $resultsShown, $totalNum )
|
|
|
|
|
->params( wfEscapeWikiText( $term ) )
|
|
|
|
|
->numParams( $resultsShown )
|
|
|
|
|
->parse();
|
2009-05-06 21:05:52 +00:00
|
|
|
} elseif ( $resultsShown >= $this->limit ) {
|
2012-05-07 04:38:51 +00:00
|
|
|
$top = $this->msg( 'showingresults' )
|
|
|
|
|
->numParams( $this->limit, $this->offset + 1 )
|
|
|
|
|
->parse();
|
2009-05-06 21:05:52 +00:00
|
|
|
} else {
|
2012-05-07 04:38:51 +00:00
|
|
|
$top = $this->msg( 'showingresultsnum' )
|
|
|
|
|
->numParams( $this->limit, $this->offset + 1, $resultsShown )
|
|
|
|
|
->parse();
|
2009-05-06 21:05:52 +00:00
|
|
|
}
|
2009-06-12 22:45:13 +00:00
|
|
|
$out .= Xml::tags( 'div', array( 'class' => 'results-info' ),
|
|
|
|
|
Xml::tags( 'ul', null, Xml::tags( 'li', null, $top ) )
|
|
|
|
|
);
|
|
|
|
|
}
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2009-06-12 22:45:13 +00:00
|
|
|
$out .= Xml::element( 'div', array( 'style' => 'clear:both' ), '', false );
|
|
|
|
|
$out .= Xml::closeElement('div');
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
return $out;
|
|
|
|
|
}
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2011-08-16 00:41:50 +00:00
|
|
|
/**
|
|
|
|
|
* @param $term string
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
2008-11-17 04:56:14 +00:00
|
|
|
protected function shortDialog( $term ) {
|
2011-11-19 17:27:34 +00:00
|
|
|
$out = Html::hidden( 'title', $this->getTitle()->getPrefixedText() );
|
|
|
|
|
$out .= Html::hidden( 'profile', $this->profile ) . "\n";
|
2008-11-19 09:08:49 +00:00
|
|
|
// Term box
|
2009-08-21 21:57:26 +00:00
|
|
|
$out .= Html::input( 'search', $term, 'search', array(
|
2011-04-22 16:13:58 +00:00
|
|
|
'id' => $this->profile === 'advanced' ? 'powerSearchText' : 'searchText',
|
2009-08-21 21:57:26 +00:00
|
|
|
'size' => '50',
|
|
|
|
|
'autofocus'
|
|
|
|
|
) ) . "\n";
|
|
|
|
|
$out .= Html::hidden( 'fulltext', 'Search' ) . "\n";
|
2012-05-07 04:38:51 +00:00
|
|
|
$out .= Xml::submitButton( $this->msg( 'searchbutton' )->text() ) . "\n";
|
2011-01-22 14:36:11 +00:00
|
|
|
return $out . $this->didYouMeanHtml;
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2010-05-02 20:34:40 +00:00
|
|
|
/**
|
|
|
|
|
* Make a search link with some target namespaces
|
|
|
|
|
*
|
|
|
|
|
* @param $term String
|
2011-04-22 16:13:58 +00:00
|
|
|
* @param $namespaces Array ignored
|
2010-05-02 20:34:40 +00:00
|
|
|
* @param $label String: link's text
|
|
|
|
|
* @param $tooltip String: link's tooltip
|
|
|
|
|
* @param $params Array: query string parameters
|
|
|
|
|
* @return String: HTML fragment
|
|
|
|
|
*/
|
2011-04-22 16:13:58 +00:00
|
|
|
protected function makeSearchLink( $term, $namespaces, $label, $tooltip, $params = array() ) {
|
2008-11-19 01:45:32 +00:00
|
|
|
$opt = $params;
|
|
|
|
|
foreach( $namespaces as $n ) {
|
|
|
|
|
$opt['ns' . $n] = 1;
|
|
|
|
|
}
|
2011-04-22 16:13:58 +00:00
|
|
|
$opt['redirs'] = $this->searchRedirects;
|
2008-11-19 01:45:32 +00:00
|
|
|
|
2009-06-07 18:45:52 +00:00
|
|
|
$stParams = array_merge(
|
|
|
|
|
array(
|
|
|
|
|
'search' => $term,
|
2012-05-07 04:38:51 +00:00
|
|
|
'fulltext' => $this->msg( 'search' )->text()
|
2009-06-07 18:45:52 +00:00
|
|
|
),
|
|
|
|
|
$opt
|
|
|
|
|
);
|
2008-11-19 01:45:32 +00:00
|
|
|
|
2009-06-07 18:45:52 +00:00
|
|
|
return Xml::element(
|
|
|
|
|
'a',
|
|
|
|
|
array(
|
2011-04-22 16:13:58 +00:00
|
|
|
'href' => $this->getTitle()->getLocalURL( $stParams ),
|
2011-07-08 17:07:11 +00:00
|
|
|
'title' => $tooltip),
|
2009-06-07 18:45:52 +00:00
|
|
|
$label
|
|
|
|
|
);
|
2008-11-19 01:45:32 +00:00
|
|
|
}
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2010-05-02 20:34:40 +00:00
|
|
|
/**
|
|
|
|
|
* Check if query starts with image: prefix
|
|
|
|
|
*
|
|
|
|
|
* @param $term String: the string to check
|
|
|
|
|
* @return Boolean
|
|
|
|
|
*/
|
2008-11-19 01:45:32 +00:00
|
|
|
protected function startsWithImage( $term ) {
|
|
|
|
|
global $wgContLang;
|
2009-04-27 07:25:51 +00:00
|
|
|
|
2008-11-19 01:45:32 +00:00
|
|
|
$p = explode( ':', $term );
|
|
|
|
|
if( count( $p ) > 1 ) {
|
2008-12-01 17:14:30 +00:00
|
|
|
return $wgContLang->getNsIndex( $p[0] ) == NS_FILE;
|
2008-11-19 01:45:32 +00:00
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2010-05-02 20:34:40 +00:00
|
|
|
/**
|
|
|
|
|
* Check if query starts with all: prefix
|
|
|
|
|
*
|
|
|
|
|
* @param $term String: the string to check
|
|
|
|
|
* @return Boolean
|
|
|
|
|
*/
|
2009-05-04 23:07:19 +00:00
|
|
|
protected function startsWithAll( $term ) {
|
|
|
|
|
|
2012-05-07 04:38:51 +00:00
|
|
|
$allkeyword = $this->msg( 'searchall' )->inContentLanguage()->text();
|
2011-01-22 14:36:11 +00:00
|
|
|
|
2009-05-04 23:07:19 +00:00
|
|
|
$p = explode( ':', $term );
|
|
|
|
|
if( count( $p ) > 1 ) {
|
|
|
|
|
return $p[0] == $allkeyword;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2011-04-22 16:13:58 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @since 1.18
|
2011-08-16 00:41:50 +00:00
|
|
|
*
|
|
|
|
|
* @return SearchEngine
|
2011-04-22 16:13:58 +00:00
|
|
|
*/
|
|
|
|
|
public function getSearchEngine() {
|
|
|
|
|
if ( $this->searchEngine === null ) {
|
|
|
|
|
$this->searchEngine = SearchEngine::create();
|
|
|
|
|
}
|
|
|
|
|
return $this->searchEngine;
|
|
|
|
|
}
|
2011-04-22 20:25:21 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Users of hook SpecialSearchSetupEngine can use this to
|
|
|
|
|
* add more params to links to not lose selection when
|
|
|
|
|
* user navigates search results.
|
|
|
|
|
* @since 1.18
|
2011-08-16 00:41:50 +00:00
|
|
|
*
|
|
|
|
|
* @param $key
|
|
|
|
|
* @param $value
|
2011-04-22 20:25:21 +00:00
|
|
|
*/
|
|
|
|
|
public function setExtraParam( $key, $value ) {
|
|
|
|
|
$this->extraParams[$key] = $value;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-17 04:56:14 +00:00
|
|
|
}
|