Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 50 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
| BasicSearchResultSetWidget | |
0.00% |
0 / 50 |
|
0.00% |
0 / 4 |
462 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
| render | |
0.00% |
0 / 42 |
|
0.00% |
0 / 1 |
306 | |||
| header | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| renderResultSet | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace MediaWiki\Search\SearchWidgets; |
| 4 | |
| 5 | use MediaWiki\MediaWikiServices; |
| 6 | use MediaWiki\Message\Message; |
| 7 | use MediaWiki\Search\ISearchResultSet; |
| 8 | use MediaWiki\Specials\SpecialSearch; |
| 9 | use MediaWiki\Status\Status; |
| 10 | |
| 11 | /** |
| 12 | * Renders the search result area. Handles Title and Full-Text search results, |
| 13 | * along with inline and sidebar secondary (interwiki) results. |
| 14 | */ |
| 15 | class BasicSearchResultSetWidget { |
| 16 | protected SpecialSearch $specialPage; |
| 17 | protected SearchResultWidget $resultWidget; |
| 18 | protected SearchResultSetWidget $sidebarWidget; |
| 19 | |
| 20 | public function __construct( |
| 21 | SpecialSearch $specialPage, |
| 22 | SearchResultWidget $resultWidget, |
| 23 | SearchResultSetWidget $sidebarWidget |
| 24 | ) { |
| 25 | $this->specialPage = $specialPage; |
| 26 | $this->resultWidget = $resultWidget; |
| 27 | $this->sidebarWidget = $sidebarWidget; |
| 28 | } |
| 29 | |
| 30 | /** |
| 31 | * @param string $term The search term to highlight |
| 32 | * @param int $offset The offset of the first result in the result set |
| 33 | * @param ISearchResultSet|null $titleResultSet Results of searching only page titles |
| 34 | * @param ISearchResultSet|null $textResultSet Results of general full text search. |
| 35 | * @return string HTML |
| 36 | */ |
| 37 | public function render( |
| 38 | $term, |
| 39 | $offset, |
| 40 | ?ISearchResultSet $titleResultSet = null, |
| 41 | ?ISearchResultSet $textResultSet = null |
| 42 | ) { |
| 43 | $hasTitle = $titleResultSet && $titleResultSet->numRows() > 0; |
| 44 | $hasText = $textResultSet && $textResultSet->numRows() > 0; |
| 45 | $hasSecondary = |
| 46 | $textResultSet && |
| 47 | $textResultSet->hasInterwikiResults( ISearchResultSet::SECONDARY_RESULTS ); |
| 48 | $hasSecondaryInline = |
| 49 | $textResultSet && |
| 50 | $textResultSet->hasInterwikiResults( ISearchResultSet::INLINE_RESULTS ); |
| 51 | |
| 52 | if ( !$hasTitle && !$hasText && !$hasSecondary && !$hasSecondaryInline ) { |
| 53 | return ''; |
| 54 | } |
| 55 | |
| 56 | $out = '<div class="mw-search-results-container">'; |
| 57 | |
| 58 | if ( $hasTitle ) { |
| 59 | $out .= $this->header( $this->specialPage->msg( 'titlematches' ) ) |
| 60 | // @phan-suppress-next-line PhanTypeMismatchArgumentNullable titleResultSet is set when used here |
| 61 | . $this->renderResultSet( $titleResultSet, $offset ); |
| 62 | } |
| 63 | |
| 64 | if ( $hasText ) { |
| 65 | if ( $hasTitle ) { |
| 66 | $out .= "<div class='mw-search-visualclear'></div>" . |
| 67 | $this->header( $this->specialPage->msg( 'textmatches' ) ); |
| 68 | } |
| 69 | // @phan-suppress-next-line PhanTypeMismatchArgumentNullable textResultSet is set when used |
| 70 | $out .= $this->renderResultSet( $textResultSet, $offset ); |
| 71 | } |
| 72 | |
| 73 | if ( $hasSecondaryInline ) { |
| 74 | $iwResults = $textResultSet->getInterwikiResults( ISearchResultSet::INLINE_RESULTS ); |
| 75 | foreach ( $iwResults as $interwiki => $results ) { |
| 76 | if ( $results instanceof Status || $results->numRows() === 0 ) { |
| 77 | // ignore bad interwikis for now |
| 78 | continue; |
| 79 | } |
| 80 | $out .= |
| 81 | "<h2 class='mw-search-interwiki-header mw-search-visualclear'>" . |
| 82 | $this->specialPage->msg( "search-interwiki-results-{$interwiki}" )->parse() . |
| 83 | "</h2>"; |
| 84 | $out .= |
| 85 | "<div class='mw-search-interwiki-results'>" . |
| 86 | $this->renderResultSet( $results, $offset ) . |
| 87 | "</div>"; |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | // Close <div class='mw-search-results-container'> |
| 92 | $out .= '</div>'; |
| 93 | |
| 94 | if ( $hasSecondary ) { |
| 95 | $out .= $this->sidebarWidget->render( |
| 96 | $term, |
| 97 | $textResultSet->getInterwikiResults( ISearchResultSet::SECONDARY_RESULTS ) |
| 98 | ); |
| 99 | } |
| 100 | |
| 101 | // Convert the whole thing to desired language variant |
| 102 | // TODO: Move this up to Special:Search? |
| 103 | $converter = MediaWikiServices::getInstance()->getLanguageConverterFactory() |
| 104 | ->getLanguageConverter(); |
| 105 | return $converter->convert( $out ); |
| 106 | } |
| 107 | |
| 108 | /** |
| 109 | * Generate a headline for a section of the search results. In prior |
| 110 | * implementations this was rendering wikitext of '==$1==', but seems |
| 111 | * a waste to call the full parser to generate this tiny bit of html |
| 112 | * |
| 113 | * @param Message $msg i18n message to use as header |
| 114 | * @return string HTML |
| 115 | */ |
| 116 | protected function header( Message $msg ) { |
| 117 | return "<h2>" . $msg->escaped() . "</h2>"; |
| 118 | } |
| 119 | |
| 120 | /** |
| 121 | * @param ISearchResultSet $resultSet The search results to render |
| 122 | * @param int $offset Offset of the first result in $resultSet |
| 123 | * @return string HTML |
| 124 | */ |
| 125 | protected function renderResultSet( ISearchResultSet $resultSet, $offset ) { |
| 126 | $hits = []; |
| 127 | foreach ( $resultSet as $result ) { |
| 128 | $hits[] = $this->resultWidget->render( $result, $offset++ ); |
| 129 | } |
| 130 | |
| 131 | return "<ul class='mw-search-results'>" . implode( '', $hits ) . "</ul>"; |
| 132 | } |
| 133 | } |