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...)
+ * the active search tab on the search page (content, 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.
$profile = new ProfileSection( __METHOD__ );
$search = $this->getSearchEngine();
- $search->setLimitOffset( $this->limit, $this->offset );
+ // Request an extra result to determine whether a "next page" link is useful
+ $search->setLimitOffset( $this->limit + 1, $this->offset );
$search->setNamespaces( $this->namespaces );
+ $this->saveNamespaces();
$search->prefix = $this->mPrefix;
$term = $search->transformSearchTerm( $term );
$out->addHTML(
Xml::openElement( 'fieldset' ) .
Xml::element( 'legend', null, $this->msg( 'search-external' )->text() ) .
- Xml::element( 'p', array( 'class' => 'mw-searchdisabled' ), $this->msg( 'searchdisabled' )->text() ) .
+ Xml::element(
+ 'p',
+ array( 'class' => 'mw-searchdisabled' ),
+ $this->msg( 'searchdisabled' )->text()
+ ) .
$this->msg( 'googlesearch' )->rawParams(
htmlspecialchars( $term ),
'UTF-8',
$stParams
);
- $this->didYouMeanHtml = '<div class="searchdidyoumean">' . $this->msg( 'search-suggest' )->rawParams( $suggestLink )->text() . '</div>';
+ $this->didYouMeanHtml = '<div class="searchdidyoumean">'
+ . $this->msg( 'search-suggest' )->rawParams( $suggestLink )->text() . '</div>';
}
if ( !wfRunHooks( 'SpecialSearchResultsPrepend', array( $this, $out, $term ) ) ) {
// Show the create link ahead
$this->showCreateLink( $title, $num, $titleMatches, $textMatches );
if ( $totalRes > $this->limit || $this->offset ) {
- $prevnext = $this->getLanguage()->viewPrevNext( $this->getPageTitle(), $this->offset, $this->limit,
+ $prevnext = $this->getLanguage()->viewPrevNext(
+ $this->getPageTitle(),
+ $this->offset,
+ $this->limit,
$this->powerSearchOptions() + array( 'search' => $term ),
- max( $titleMatchesNum, $textMatchesNum ) < $this->limit
+ max( $titleMatchesNum, $textMatchesNum ) <= $this->limit
);
}
wfRunHooks( 'SpecialSearchResults', array( $term, &$titleMatches, &$textMatches ) );
if ( $num === 0 ) {
if ( $textStatus ) {
$out->addHTML( '<div class="error">' .
- htmlspecialchars( $textStatus->getWikiText( 'search-error' ) ) . '</div>' );
+ $textStatus->getMessage( 'search-error' ) . '</div>' );
} else {
$out->wrapWikiMsg( "<p class=\"mw-search-nonefound\">\n$1</p>",
array( 'search-nonefound', wfEscapeWikiText( $term ) ) );
if ( $title->isKnown() ) {
$messageName = 'searchmenu-exists';
- } elseif ( $title->userCan( 'create', $this->getUser() ) ) {
+ } elseif ( $title->quickUserCan( 'create', $this->getUser() ) ) {
$messageName = 'searchmenu-new';
} else {
$messageName = 'searchmenu-new-nocreate';
}
- $params = array( $messageName, wfEscapeWikiText( $title->getPrefixedText() ), Message::numParam( $num ) );
+ $params = array(
+ $messageName,
+ wfEscapeWikiText( $title->getPrefixedText() ),
+ Message::numParam( $num )
+ );
wfRunHooks( 'SpecialSearchCreateLink', array( $title, &$params ) );
// Extensions using the hook might still return an empty $messageName
return $opt + $this->extraParams;
}
+ /**
+ * Save namespace preferences when we're supposed to
+ *
+ * @return bool Whether we wrote something
+ */
+ protected function saveNamespaces() {
+ $user = $this->getUser();
+ $request = $this->getRequest();
+
+ if ( $user->isLoggedIn() &&
+ !is_null( $request->getVal( 'nsRemember' ) ) &&
+ $user->matchEditToken( $request->getVal( 'nsToken' ) )
+ ) {
+ // Reset namespace preferences: namespaces are not searched
+ // when they're not mentioned in the URL parameters.
+ foreach ( MWNamespace::getValidNamespaces() as $n ) {
+ $user->setOption( 'searchNs' . $n, false );
+ }
+ // The request parameters include all the namespaces we just searched.
+ // Even if they're the same as an existing profile, they're not eaten.
+ foreach ( $this->namespaces as $n ) {
+ $user->setOption( 'searchNs' . $n, true );
+ }
+
+ $user->saveSettings();
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Show whole set of results
*
$out = "<ul class='mw-search-results'>\n";
$result = $matches->next();
- while ( $result ) {
+ $count = 0;
+ while ( $result && $count < $this->limit ) {
$out .= $this->showHit( $result, $terms );
$result = $matches->next();
+ $count++;
}
$out .= "</ul>\n";
&$score, &$size, &$date, &$related,
&$html
) ) ) {
- $html = "<li><div class='mw-search-result-heading'>{$link} {$redirect} {$section} {$fileMatch}</div> {$extract}\n" .
+ $html = "<li><div class='mw-search-result-heading'>" .
+ "{$link} {$redirect} {$section} {$fileMatch}</div> {$extract}\n" .
"<div class='mw-search-result-data'>{$score}{$size} - {$date}{$related}</div>" .
"</li>\n";
}
// work out custom project captions
$customCaptions = array();
- $customLines = explode( "\n", $this->msg( 'search-interwiki-custom' )->text() ); // format per line <iwprefix>:<caption>
+ // format per line <iwprefix>:<caption>
+ $customLines = explode( "\n", $this->msg( 'search-interwiki-custom' )->text() );
foreach ( $customLines as $line ) {
$parts = explode( ":", $line, 2 );
if ( count( $parts ) == 2 ) { // validate line
}
}
-
- // TODO: should support paging in a non-confusing way (not sure how though, maybe via ajax)..
+ // @todo Should support paging in a non-confusing way (not sure how though, maybe via ajax)..
$out .= "</ul></div>\n";
// convert the whole thing to desired language variant
$hidden .= Html::hidden( $key, $value );
}
+ # Stuff to feed saveNamespaces()
+ $remember = '';
+ $user = $this->getUser();
+ if ( $user->isLoggedIn() ) {
+ $remember .= Html::hidden( 'nsToken', $user->getEditToken() ) .
+ Xml::checkLabel(
+ wfMessage( 'powersearch-remember' )->text(),
+ 'nsRemember',
+ 'mw-search-powersearch-remember',
+ false
+ );
+ }
+
// Return final output
return Xml::openElement(
'fieldset',
Xml::element( 'div', array( 'class' => 'divider' ), '', false ) .
implode( Xml::element( 'div', array( 'class' => 'divider' ), '', false ), $showSections ) .
$hidden .
+ Xml::element( 'div', array( 'class' => 'divider' ), '', false ) .
+ $remember .
Xml::closeElement( 'fieldset' );
}
'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',