Displaying search results for multiple wikis
authorStanislav Malyshev <smalyshev@gmail.com>
Fri, 18 Sep 2015 19:30:30 +0000 (12:30 -0700)
committerStanislav Malyshev <smalyshev@gmail.com>
Thu, 22 Oct 2015 21:34:41 +0000 (14:34 -0700)
Uses fully translated string like search-interwiki-results-abwiki
which should be present in WikimediaMessages.

Requires Ic4bdd9462f844febea2e402e4b89d9dcc4c836b6
Supports I0d0efacf3066b3b5fe0bfcb058dd0b0f9988ccae

Bug: T112349
Change-Id: Ib6524bc79e1648ccf6adc5745f0dbc4c26dcb0d2

includes/search/SearchResultSet.php
includes/specials/SpecialSearch.php
languages/i18n/en.json
languages/i18n/qqq.json

index 6178756..8fb04e4 100644 (file)
  * @ingroup Search
  */
 class SearchResultSet {
+
+       /**
+        * Types of interwiki results
+        */
+       /**
+        * Results that are displayed only together with existing main wiki results
+        * @var int
+        */
+       const SECONDARY_RESULTS = 0;
+       /**
+        * Results that can displayed even if no existing main wiki results exist
+        * @var int
+        */
+       const INLINE_RESULTS = 1;
+
        protected $containedSyntax = false;
 
        public function __construct( $containedSyntax = false ) {
@@ -116,7 +131,7 @@ class SearchResultSet {
         *
         * @return SearchResultSet
         */
-       function getInterwikiResults() {
+       function getInterwikiResults( $type = self::SECONDARY_RESULTS ) {
                return null;
        }
 
@@ -125,8 +140,8 @@ class SearchResultSet {
         *
         * @return bool
         */
-       function hasInterwikiResults() {
-               return $this->getInterwikiResults() != null;
+       function hasInterwikiResults( $type = self::SECONDARY_RESULTS ) {
+               return false;
        }
 
        /**
index fc7eeb1..d6ce6a4 100644 (file)
@@ -73,6 +73,12 @@ class SpecialSearch extends SpecialPage {
         */
        protected $runSuggestion = true;
 
+       /**
+        * Names of the wikis, in format: Interwiki prefix -> caption
+        * @var array
+        */
+       protected $customCaptions;
+
        const NAMESPACES_CURRENT = 'sense';
 
        public function __construct() {
@@ -371,25 +377,45 @@ class SpecialSearch extends SpecialPage {
                        if ( $numTextMatches > 0 ) {
                                $out->addHTML( $this->showMatches( $textMatches ) );
                        }
-                       // show interwiki results if any
-                       if ( $textMatches->hasInterwikiResults() ) {
-                               $out->addHTML( $this->showInterwiki( $textMatches->getInterwikiResults(), $term ) );
+
+                       // show secondary interwiki results if any
+                       if ( $textMatches->hasInterwikiResults( SearchResultSet::SECONDARY_RESULTS ) ) {
+                               $out->addHTML( $this->showInterwiki( $textMatches->getInterwikiResults(
+                                               SearchResultSet::SECONDARY_RESULTS ), $term ) );
                        }
 
                        $textMatches->free();
                }
+
+               $hasOtherResults = $textMatches->hasInterwikiResults( SearchResultSet::INLINE_RESULTS );
+
                if ( $num === 0 ) {
                        if ( $textStatus ) {
                                $out->addHTML( '<div class="error">' .
                                        $textStatus->getMessage( 'search-error' ) . '</div>' );
                        } else {
-                               $out->wrapWikiMsg( "<p class=\"mw-search-nonefound\">\n$1</p>",
-                                       array( 'search-nonefound', wfEscapeWikiText( $term ) ) );
                                $this->showCreateLink( $title, $num, $titleMatches, $textMatches );
+                               $out->wrapWikiMsg( "<p class=\"mw-search-nonefound\">\n$1</p>",
+                                       array( $hasOtherResults ? 'search-nonefound-thiswiki' : 'search-nonefound',
+                                                       wfEscapeWikiText( $term )
+                                       ) );
+                       }
+               }
+
+               if ( $hasOtherResults ) {
+                       foreach ( $textMatches->getInterwikiResults( SearchResultSet::INLINE_RESULTS )
+                                               as $interwiki => $interwikiResult ) {
+                               if ( $interwikiResult instanceof Status || $interwikiResult->numRows() == 0 ) {
+                                       // ignore bad interwikis for now
+                                       continue;
+                               }
+                               // TODO: wiki header
+                               $out->addHTML( $this->showMatches( $interwikiResult, $interwiki ) );
                        }
                }
 
                $out->addHTML( '<div class="visualClear"></div>' );
+
                if ( $prevnext ) {
                        $out->addHTML( "<p class='mw-search-pager-bottom'>{$prevnext}</p>\n" );
                }
@@ -400,6 +426,17 @@ class SpecialSearch extends SpecialPage {
 
        }
 
+       /**
+        * Produce wiki header for interwiki results
+        * @param string $interwiki Interwiki name
+        * @param SearchResultSet $interwikiResult The result set
+        */
+       protected function interwikiHeader( $interwiki, $interwikiResult ) {
+               // TODO: we need to figure out how to name wikis correctly
+               $wikiMsg = $this->msg( 'search-interwiki-results-' . $interwiki )->parse();
+               return "<p class=\"mw-search-interwiki-header\">\n$wikiMsg</p>";
+       }
+
        /**
         * Decide if the suggested query should be run, and it's results returned
         * instead of the provided $textMatches
@@ -636,17 +673,23 @@ class SpecialSearch extends SpecialPage {
         * Show whole set of results
         *
         * @param SearchResultSet $matches
+        * @param string $interwiki Interwiki name
         *
         * @return string
         */
-       protected function showMatches( &$matches ) {
+       protected function showMatches( &$matches, $interwiki = null ) {
                global $wgContLang;
 
                $terms = $wgContLang->convertForSearchResult( $matches->termMatches() );
-
-               $out = "<ul class='mw-search-results'>\n";
+               $out = '';
                $result = $matches->next();
                $pos = $this->offset;
+
+               if ( $result && $interwiki ) {
+                       $out .= $this->interwikiHeader( $interwiki, $result );
+               }
+
+               $out .= "<ul class='mw-search-results'>\n";
                while ( $result ) {
                        $out .= $this->showHit( $result, $terms, ++$pos );
                        $result = $matches->next();
@@ -683,14 +726,16 @@ class SpecialSearch extends SpecialPage {
                }
 
                $link_t = clone $title;
+               $query = array();
 
                Hooks::run( 'ShowSearchHitTitle',
-                       array( &$link_t, &$titleSnippet, $result, $terms, $this ) );
+                       array( &$link_t, &$titleSnippet, $result, $terms, $this, &$query ) );
 
                $link = Linker::linkKnown(
                        $link_t,
                        $titleSnippet,
-                       array( 'data-serp-pos' => $position ) // HTML attributes
+                       array( 'data-serp-pos' => $position ), // HTML attributes
+                       $query
                );
 
                // If page content is not readable, just return the title.
@@ -818,6 +863,23 @@ class SpecialSearch extends SpecialPage {
                return $html;
        }
 
+       /**
+        * Extract custom captions from search-interwiki-custom message
+        */
+       protected function getCustomCaptions() {
+               if ( is_null( $this->customCaptions ) ) {
+                       $this->customCaptions = array();
+                       // 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
+                                       $this->customCaptions[$parts[0]] = $parts[1];
+                               }
+                       }
+               }
+       }
+
        /**
         * Show results from other wikis
         *
@@ -834,15 +896,7 @@ class SpecialSearch extends SpecialPage {
                $out .= "<ul class='mw-search-iwresults'>\n";
 
                // work out custom project captions
-               $customCaptions = array();
-               // 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
-                               $customCaptions[$parts[0]] = $parts[1];
-                       }
-               }
+               $this->getCustomCaptions();
 
                if ( !is_array( $matches ) ) {
                        $matches = array( $matches );
@@ -852,7 +906,7 @@ class SpecialSearch extends SpecialPage {
                        $prev = null;
                        $result = $set->next();
                        while ( $result ) {
-                               $out .= $this->showInterwikiHit( $result, $prev, $query, $customCaptions );
+                               $out .= $this->showInterwikiHit( $result, $prev, $query );
                                $prev = $result->getInterwikiPrefix();
                                $result = $set->next();
                        }
@@ -873,11 +927,10 @@ class SpecialSearch extends SpecialPage {
         * @param SearchResult $result
         * @param string $lastInterwiki
         * @param string $query
-        * @param array $customCaptions Interwiki prefix -> caption
         *
         * @return string
         */
-       protected function showInterwikiHit( $result, $lastInterwiki, $query, $customCaptions ) {
+       protected function showInterwikiHit( $result, $lastInterwiki, $query ) {
 
                if ( $result->isBrokenTitle() ) {
                        return '';
@@ -914,9 +967,9 @@ class SpecialSearch extends SpecialPage {
                $out = "";
                // display project name
                if ( is_null( $lastInterwiki ) || $lastInterwiki != $title->getInterwiki() ) {
-                       if ( array_key_exists( $title->getInterwiki(), $customCaptions ) ) {
+                       if ( array_key_exists( $title->getInterwiki(), $this->customCaptions ) ) {
                                // captions from 'search-interwiki-custom'
-                               $caption = $customCaptions[$title->getInterwiki()];
+                               $caption = $this->customCaptions[$title->getInterwiki()];
                        } else {
                                // default is to show the hostname of the other wiki which might suck
                                // if there are many wikis on one hostname
index 3e545d2..5f38d3f 100644 (file)
        "showingresultsinrange": "Showing below up to {{PLURAL:$1|<strong>1</strong> result|<strong>$1</strong> results}} in range #<strong>$2</strong> to #<strong>$3</strong>.",
        "search-showingresults": "{{PLURAL:$4|Result <strong>$1</strong> of <strong>$3</strong>|Results <strong>$1 - $2</strong> of <strong>$3</strong>}}",
        "search-nonefound": "There were no results matching the query.",
+       "search-nonefound-thiswiki": "There were no results matching the query in this site.",
        "powersearch-legend": "Advanced search",
        "powersearch-ns": "Search in namespaces:",
        "powersearch-togglelabel": "Check:",
index 3592562..ea88cd5 100644 (file)
        "showingresultsinrange": "Used in pagination of [[Special:MostLinkedCategories]]. Parameters:\n* $1 - the total number of results in the batch shown\n* $2 - the number of the first item listed\n* $3 - the number of last item in the batch shown\n\nSee also {{msg-mw|Showingresults}}",
        "search-showingresults": "Used in search results of [[Special:Search]]. Parameters:\n* $1 - minimum offset\n* $2 - maximum offset\n* $3 - total number of results\n* $4 - number of results",
        "search-nonefound": "Message shown when a search returned no results (when using the default MediaWiki search engine).",
+       "search-nonefound-thiswiki": "Message shown when a search in current wiki returned no results (when using the default MediaWiki search engine) but search in other wikis did return results.",
        "powersearch-legend": "Advanced search\n\n{{Identical|Advanced search}}",
        "powersearch-ns": "Used in the extended search form at [[Special:Search]]",
        "powersearch-togglelabel": "Used in [{{canonicalurl:Special:Search|advanced=1}} Advanced search]. Synonym: \"Select\" as verb.\n{{Identical|Check}}",