summaryrefslogtreecommitdiff
path: root/www/wiki/includes/widget/search/BasicSearchResultSetWidget.php
blob: e23664050fd093fa969acefcbba55654a8ec5d67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<?php

namespace MediaWiki\Widget\Search;

use Message;
use SearchResultSet;
use SpecialSearch;
use Status;

/**
 * Renders the search result area. Handles Title and Full-Text search results,
 * along with inline and sidebar secondary (interwiki) results.
 */
class BasicSearchResultSetWidget {
	/** @var SpecialSearch */
	protected $specialPage;
	/** @var SearchResultWidget */
	protected $resultWidget;
	/** @var InterwikiSearchResultSetWidget */
	protected $sidebarWidget;

	public function __construct(
		SpecialSearch $specialPage,
		SearchResultWidget $resultWidget,
		SearchResultSetWidget $sidebarWidget
	) {
		$this->specialPage = $specialPage;
		$this->resultWidget = $resultWidget;
		$this->sidebarWidget = $sidebarWidget;
	}

	/**
	 * @param string $term The search term to highlight
	 * @param int $offset The offset of the first result in the result set
	 * @param SearchResultSet|null $titleResultSet Results of searching only page titles
	 * @param SearchResultSet|null $textResultSet Results of general full text search.
	 * @return string HTML
	 */
	public function render(
		$term,
		$offset,
		SearchResultSet $titleResultSet = null,
		SearchResultSet $textResultSet = null
	) {
		global $wgContLang;

		$hasTitle = $titleResultSet ? $titleResultSet->numRows() > 0 : false;
		$hasText = $textResultSet ? $textResultSet->numRows() > 0 : false;
		$hasSecondary = $textResultSet
			? $textResultSet->hasInterwikiResults( SearchResultSet::SECONDARY_RESULTS )
			: false;
		$hasSecondaryInline = $textResultSet
			? $textResultSet->hasInterwikiResults( SearchResultSet::INLINE_RESULTS )
			: false;

		if ( !$hasTitle && !$hasText && !$hasSecondary && !$hasSecondaryInline ) {
			return '';
		}

		$out = '';
		if ( $hasTitle ) {
			$out .= $this->header( $this->specialPage->msg( 'titlematches' ) )
				. $this->renderResultSet( $titleResultSet, $offset );
		}

		if ( $hasText ) {
			if ( $hasTitle ) {
				$out .= "<div class='mw-search-visualclear'></div>" .
					$this->header( $this->specialPage->msg( 'textmatches' ) );
			}
			$out .= $this->renderResultSet( $textResultSet, $offset );
		}

		if ( $hasSecondaryInline ) {
			$iwResults = $textResultSet->getInterwikiResults( SearchResultSet::INLINE_RESULTS );
			foreach ( $iwResults as $interwiki => $results ) {
				if ( $results instanceof Status || $results->numRows() === 0 ) {
					// ignore bad interwikis for now
					continue;
				}
				$out .=
					"<h2 class='mw-search-interwiki-header mw-search-visualclear'>" .
						$this->specialPage->msg( "search-interwiki-results-{$interwiki}" )->parse() .
					"</h2>";
				$out .= $this->renderResultSet( $results, $offset );
			}
		}

		if ( $hasSecondary ) {
			$out .= $this->sidebarWidget->render(
				$term,
				$textResultSet->getInterwikiResults( SearchResultSet::SECONDARY_RESULTS )
			);
		}

		// Convert the whole thing to desired language variant
		// TODO: Move this up to Special:Search?
		return $wgContLang->convert( $out );
	}

	/**
	 * Generate a headline for a section of the search results. In prior
	 * implementations this was rendering wikitext of '==$1==', but seems
	 * a waste to call the full parser to generate this tiny bit of html
	 *
	 * @param Message $msg i18n message to use as header
	 * @return string HTML
	 */
	protected function header( Message $msg ) {
		return "<h2>" .
			"<span class='mw-headline'>" . $msg->escaped() . "</span>" .
		"</h2>";
	}

	/**
	 * @param SearchResultSet $resultSet The search results to render
	 * @param int $offset Offset of the first result in $resultSet
	 * @return string HTML
	 */
	protected function renderResultSet( SearchResultSet $resultSet, $offset ) {
		global $wgContLang;

		$terms = $wgContLang->convertForSearchResult( $resultSet->termMatches() );

		$hits = [];
		$result = $resultSet->next();
		while ( $result ) {
			$hits[] .= $this->resultWidget->render( $result, $terms, $offset++ );
			$result = $resultSet->next();
		}

		return "<ul class='mw-search-results'>" . implode( '', $hits ) . "</ul>";
	}
}