Pull rendering of single result out of SpecialSearch
[lhc/web/wiklou.git] / includes / specials / SpecialSearch.php
index 727179a..255e618 100644 (file)
@@ -740,8 +740,12 @@ class SpecialSearch extends SpecialPage {
                }
 
                $out .= "<ul class='mw-search-results'>\n";
+               $widget = new \MediaWiki\Widget\Search\FullSearchResultWidget(
+                       $this,
+                       $this->getLinkRenderer()
+               );
                while ( $result ) {
-                       $out .= $this->showHit( $result, $terms, $pos++ );
+                       $out .= $widget->render( $result, $terms, $pos++ );
                        $result = $matches->next();
                }
                $out .= "</ul>\n";
@@ -752,181 +756,6 @@ class SpecialSearch extends SpecialPage {
                return $out;
        }
 
-       /**
-        * Format a single hit result
-        *
-        * @param SearchResult $result
-        * @param array $terms Terms to highlight
-        * @param int $position Position within the search results, including offset.
-        *
-        * @return string
-        */
-       protected function showHit( SearchResult $result, $terms, $position ) {
-               if ( $result->isBrokenTitle() ) {
-                       return '';
-               }
-
-               $title = $result->getTitle();
-
-               $titleSnippet = $result->getTitleSnippet();
-
-               if ( $titleSnippet == '' ) {
-                       $titleSnippet = null;
-               }
-
-               $link_t = clone $title;
-               $query = [];
-
-               Hooks::run( 'ShowSearchHitTitle',
-                       [ &$link_t, &$titleSnippet, $result, $terms, $this, &$query ] );
-
-               $linkRenderer = $this->getLinkRenderer();
-
-               if ( $titleSnippet !== null ) {
-                       $titleSnippet = new HtmlArmor( $titleSnippet );
-               }
-
-               $link = $linkRenderer->makeKnownLink(
-                       $link_t,
-                       $titleSnippet,
-                       [ 'data-serp-pos' => $position ], // HTML attributes
-                       $query
-               );
-
-               // 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.
-               if ( !$title->userCan( 'read', $this->getUser() ) ) {
-                       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() ) {
-                       return '';
-               }
-
-               // format redirects / relevant sections
-               $redirectTitle = $result->getRedirectTitle();
-               $redirectText = $result->getRedirectSnippet();
-               $sectionTitle = $result->getSectionTitle();
-               $sectionText = $result->getSectionSnippet();
-               $categorySnippet = $result->getCategorySnippet();
-
-               $redirect = '';
-               if ( !is_null( $redirectTitle ) ) {
-                       if ( $redirectText == '' ) {
-                               $redirectText = null;
-                       }
-
-                       if ( $redirectText !== null ) {
-                               $redirectText = new HtmlArmor( $redirectText );
-                       }
-
-                       $redirect = "<span class='searchalttitle'>" .
-                               $this->msg( 'search-redirect' )->rawParams(
-                                       $linkRenderer->makeKnownLink( $redirectTitle, $redirectText ) )->text() .
-                               "</span>";
-               }
-
-               $section = '';
-               if ( !is_null( $sectionTitle ) ) {
-                       if ( $sectionText == '' ) {
-                               $sectionText = null;
-                       }
-
-                       if ( $sectionText !== null ) {
-                               $sectionText = new HtmlArmor( $sectionText );
-                       }
-
-                       $section = "<span class='searchalttitle'>" .
-                               $this->msg( 'search-section' )->rawParams(
-                                       $linkRenderer->makeKnownLink( $sectionTitle, $sectionText ) )->text() .
-                               "</span>";
-               }
-
-               $category = '';
-               if ( $categorySnippet ) {
-                       $category = "<span class='searchalttitle'>" .
-                               $this->msg( 'search-category' )->rawParams( $categorySnippet )->text() .
-                               "</span>";
-               }
-
-               // format text extract
-               $extract = "<div class='searchresult'>" . $result->getTextSnippet( $terms ) . "</div>";
-
-               $lang = $this->getLanguage();
-
-               // format description
-               $byteSize = $result->getByteSize();
-               $wordCount = $result->getWordCount();
-               $timestamp = $result->getTimestamp();
-               $size = $this->msg( 'search-result-size', $lang->formatSize( $byteSize ) )
-                       ->numParams( $wordCount )->escaped();
-
-               if ( $title->getNamespace() == NS_CATEGORY ) {
-                       $cat = Category::newFromTitle( $title );
-                       $size = $this->msg( 'search-result-category-size' )
-                               ->numParams( $cat->getPageCount(), $cat->getSubcatCount(), $cat->getFileCount() )
-                               ->escaped();
-               }
-
-               $date = $lang->userTimeAndDate( $timestamp, $this->getUser() );
-
-               $fileMatch = '';
-               // Include a thumbnail for media files...
-               if ( $title->getNamespace() == NS_FILE ) {
-                       $img = $result->getFile();
-                       $img = $img ?: wfFindFile( $title );
-                       if ( $result->isFileMatch() ) {
-                               $fileMatch = "<span class='searchalttitle'>" .
-                                       $this->msg( 'search-file-match' )->escaped() . "</span>";
-                       }
-                       if ( $img ) {
-                               $thumb = $img->transform( [ 'width' => 120, 'height' => 120 ] );
-                               if ( $thumb ) {
-                                       $desc = $this->msg( 'parentheses' )->rawParams( $img->getShortDesc() )->escaped();
-                                       // 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 style="width: 120px; text-align: center; vertical-align: top;">' .
-                                               $thumb->toHtml( [ 'desc-link' => true ] ) .
-                                               '</td>' .
-                                               '<td style="vertical-align: top;">' .
-                                               "{$link} {$redirect} {$category} {$section} {$fileMatch}" .
-                                               $extract .
-                                               "<div class='mw-search-result-data'>{$desc} - {$date}</div>" .
-                                               '</td>' .
-                                               '</tr>' .
-                                               '</table>' .
-                                               "</li>\n";
-                               }
-                       }
-               }
-
-               $html = null;
-
-               $score = '';
-               $related = '';
-               if ( Hooks::run( 'ShowSearchHit', [
-                       $this, $result, $terms,
-                       &$link, &$redirect, &$section, &$extract,
-                       &$score, &$size, &$date, &$related,
-                       &$html
-               ] ) ) {
-                       $html = "<li><div class='mw-search-result-heading'>" .
-                               "{$link} {$redirect} {$category} {$section} {$fileMatch}</div> {$extract}\n" .
-                               "<div class='mw-search-result-data'>{$size} - {$date}</div>" .
-                               "</li>\n";
-               }
-
-               return $html;
-       }
-
        /**
         * Extract custom captions from search-interwiki-custom message
         */
@@ -948,17 +777,13 @@ class SpecialSearch extends SpecialPage {
         * Show results from other wikis
         *
         * @param SearchResultSet|array $matches
-        * @param string $query
+        * @param string $terms
         *
         * @return string
         */
-       protected function showInterwiki( $matches, $query ) {
+       protected function showInterwiki( $matches, $terms ) {
                global $wgContLang;
 
-               $out = "<div id='mw-search-interwiki'><div id='mw-search-interwiki-caption'>" .
-                       $this->msg( 'search-interwiki-caption' )->text() . "</div>\n";
-               $out .= "<ul class='mw-search-iwresults'>\n";
-
                // work out custom project captions
                $this->getCustomCaptions();
 
@@ -966,107 +791,72 @@ class SpecialSearch extends SpecialPage {
                        $matches = [ $matches ];
                }
 
+               $iwResults = [];
                foreach ( $matches as $set ) {
-                       $prev = null;
                        $result = $set->next();
                        while ( $result ) {
-                               $out .= $this->showInterwikiHit( $result, $prev, $query );
-                               $prev = $result->getInterwikiPrefix();
+                               if ( !$result->isBrokenTitle() ) {
+                                       $iwResults[$result->getTitle()->getInterwiki()][] = $result;
+                               }
                                $result = $set->next();
                        }
                }
 
-               // @todo Should support paging in a non-confusing way (not sure how though, maybe via ajax)..
-               $out .= "</ul></div>\n";
+               $out = '';
+               $widget = new MediaWiki\Widget\Search\SimpleSearchResultWidget(
+                       $this,
+                       $this->getLinkRenderer()
+               );
+               foreach ( $iwResults as $iwPrefix => $results ) {
+                       $out .= $this->iwHeaderHtml( $iwPrefix, $terms );
+                       $out .= "<ul class='mw-search-iwresults'>";
+                       foreach ( $results as $result ) {
+                               // This makes the bold asumption interwiki results are never paginated.
+                               // That's currently true, but could change at some point?
+                               $out .= $widget->render( $result, $terms, 0 );
+                       }
+                       $out .= "</ul>";
+               }
 
-               // convert the whole thing to desired language variant
-               $out = $wgContLang->convert( $out );
+               $out =
+                       "<div id='mw-search-interwiki'>" .
+                               "<div id='mw-search-interwiki-caption'>" .
+                                       $this->msg( 'search-interwiki-caption' )->escaped() .
+                               "</div>" .
+                               $out .
+                       "</div>";
 
-               return $out;
+               // convert the whole thing to desired language variant
+               return $wgContLang->convert( $out );
        }
 
        /**
-        * Show single interwiki link
-        *
-        * @param SearchResult $result
-        * @param string $lastInterwiki
-        * @param string $query
-        *
-        * @return string
+        * @param string $iwPrefix The interwiki prefix to render a header for
+        * @param string $terms The user-provided search terms
         */
-       protected function showInterwikiHit( $result, $lastInterwiki, $query ) {
-               if ( $result->isBrokenTitle() ) {
-                       return '';
-               }
-
-               $linkRenderer = $this->getLinkRenderer();
-
-               $title = $result->getTitle();
-
-               $titleSnippet = $result->getTitleSnippet();
-
-               if ( $titleSnippet == '' ) {
-                       $titleSnippet = null;
-               }
-
-               if ( $titleSnippet !== null ) {
-                       $titleSnippet = new HtmlArmor( $titleSnippet );
-               }
-
-               $link = $linkRenderer->makeKnownLink(
-                       $title,
-                       $titleSnippet
+       protected function iwHeaderHtml( $iwPrefix, $terms ) {
+               if ( isset( $this->customCaptions[$iwPrefix] ) ) {
+                       $caption = $this->customCaptions[$iwPrefix];
+               } else {
+                       $iwLookup = MediaWiki\MediaWikiServices::getInstance()->getInterwikiLookup();
+                       $interwiki = $iwLookup->fetch( $iwPrefix );
+                       $parsed = wfParseUrl( wfExpandUrl( $interwiki ? $interwiki->getURL() : '/' ) );
+                       $caption = $this->msg( 'search-interwiki-default', $parsed['host'] )->text();
+               }
+               $searchLink = Linker::linkKnown(
+                       Title::newFromText( "$iwPrefix:Special:Search" ),
+                       $this->msg( 'search-interwiki-more' )->text(),
+                       [],
+                       [
+                               'search' => $terms,
+                               'fulltext' => 1,
+                       ]
                );
-
-               // format redirect if any
-               $redirectTitle = $result->getRedirectTitle();
-               $redirectText = $result->getRedirectSnippet();
-               $redirect = '';
-               if ( !is_null( $redirectTitle ) ) {
-                       if ( $redirectText == '' ) {
-                               $redirectText = null;
-                       }
-
-                       if ( $redirectText !== null ) {
-                               $redirectText = new HtmlArmor( $redirectText );
-                       }
-
-                       $redirect = "<span class='searchalttitle'>" .
-                               $this->msg( 'search-redirect' )->rawParams(
-                                       $linkRenderer->makeKnownLink( $redirectTitle, $redirectText ) )->text() .
-                               "</span>";
-               }
-
-               $out = "";
-               // display project name
-               if ( is_null( $lastInterwiki ) || $lastInterwiki != $title->getInterwiki() ) {
-                       if ( array_key_exists( $title->getInterwiki(), $this->customCaptions ) ) {
-                               // captions from 'search-interwiki-custom'
-                               $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
-                               $parsed = wfParseUrl( $title->getFullURL() );
-                               $caption = $this->msg( 'search-interwiki-default', $parsed['host'] )->text();
-                       }
-                       // "more results" link (special page stuff could be localized, but we might not know target lang)
-                       $searchTitle = Title::newFromText( $title->getInterwiki() . ":Special:Search" );
-                       $searchLink = $linkRenderer->makeKnownLink(
-                               $searchTitle,
-                               $this->msg( 'search-interwiki-more' )->text(),
-                               [],
-                               [
-                                       'search' => $query,
-                                       'fulltext' => 'Search'
-                               ]
-                       );
-                       $out .= "</ul><div class='mw-search-interwiki-project'><span class='mw-search-interwiki-more'>
-                               {$searchLink}</span>{$caption}</div>\n<ul>";
-               }
-
-               $out .= "<li>{$link} {$redirect}</li>\n";
-
-               return $out;
+               return
+                       "<div class='mw-search-interwiki-project'>" .
+                               "<span class='mw-search-interwiki-more'>{$searchLink}</span>" .
+                               $caption .
+                       "</div>";
        }
 
        /**