MediaWiki REL1_34
SearchFormWidget.php
Go to the documentation of this file.
1<?php
2
4
5use Hooks;
6use Html;
11use Xml;
12
15 protected $specialSearch;
17 protected $searchConfig;
19 protected $profiles;
20
26 public function __construct(
29 array $profiles
30 ) {
31 $this->specialSearch = $specialSearch;
32 $this->searchConfig = $searchConfig;
33 $this->profiles = $profiles;
34 }
35
46 public function render(
47 $profile,
48 $term,
49 $numResults,
50 $totalResults,
51 $offset,
52 $isPowerSearch,
53 array $options = []
54 ) {
55 $user = $this->specialSearch->getUser();
56
57 return '<div class="mw-search-form-wrapper">' .
58 Xml::openElement(
59 'form',
60 [
61 'id' => $isPowerSearch ? 'powersearch' : 'search',
62 // T151903: default to POST in case JS is disabled
63 'method' => ( $isPowerSearch && $user->isLoggedIn() ) ? 'post' : 'get',
64 'action' => wfScript(),
65 ]
66 ) .
67 '<div id="mw-search-top-table">' .
68 $this->shortDialogHtml( $profile, $term, $numResults, $totalResults, $offset, $options ) .
69 '</div>' .
70 "<div class='mw-search-visualclear'></div>" .
71 "<div class='mw-search-profile-tabs'>" .
72 $this->profileTabsHtml( $profile, $term ) .
73 "<div style='clear:both'></div>" .
74 "</div>" .
75 $this->optionsHtml( $term, $isPowerSearch, $profile ) .
76 '</form>' .
77 '</div>';
78 }
79
89 protected function shortDialogHtml(
90 $profile,
91 $term,
92 $numResults,
93 $totalResults,
94 $offset,
95 array $options = []
96 ) {
97 $html = '';
98
99 $searchWidget = new SearchInputWidget( $options + [
100 'id' => 'searchText',
101 'name' => 'search',
102 'autofocus' => trim( $term ) === '',
103 'value' => $term,
104 'dataLocation' => 'content',
105 'infusable' => true,
106 ] );
107
108 $layout = new \OOUI\ActionFieldLayout( $searchWidget, new \OOUI\ButtonInputWidget( [
109 'type' => 'submit',
110 'label' => $this->specialSearch->msg( 'searchbutton' )->text(),
111 'flags' => [ 'progressive', 'primary' ],
112 ] ), [
113 'align' => 'top',
114 ] );
115
116 $html .= $layout;
117
118 if ( $this->specialSearch->getPrefix() !== '' ) {
119 $html .= Html::hidden( 'prefix', $this->specialSearch->getPrefix() );
120 }
121
122 if ( $totalResults > 0 && $offset < $totalResults ) {
123 $html .= Xml::tags(
124 'div',
125 [
126 'class' => 'results-info',
127 'data-mw-num-results-offset' => $offset,
128 'data-mw-num-results-total' => $totalResults
129 ],
130 $this->specialSearch->msg( 'search-showingresults' )
131 ->numParams( $offset + 1, $offset + $numResults, $totalResults )
132 ->numParams( $numResults )
133 ->parse()
134 );
135 }
136
137 $html .=
138 Html::hidden( 'title', $this->specialSearch->getPageTitle()->getPrefixedText() ) .
139 Html::hidden( 'profile', $profile ) .
140 Html::hidden( 'fulltext', '1' );
141
142 return $html;
143 }
144
152 protected function profileTabsHtml( $profile, $term ) {
153 $bareterm = $this->startsWithImage( $term )
154 ? substr( $term, strpos( $term, ':' ) + 1 )
155 : $term;
156 $lang = $this->specialSearch->getLanguage();
157 $items = [];
158 foreach ( $this->profiles as $id => $profileConfig ) {
159 $profileConfig['parameters']['profile'] = $id;
160 $tooltipParam = isset( $profileConfig['namespace-messages'] )
161 ? $lang->commaList( $profileConfig['namespace-messages'] )
162 : null;
163 $items[] = Xml::tags(
164 'li',
165 [ 'class' => $profile === $id ? 'current' : 'normal' ],
166 $this->makeSearchLink(
167 $bareterm,
168 $this->specialSearch->msg( $profileConfig['message'] )->text(),
169 $this->specialSearch->msg( $profileConfig['tooltip'], $tooltipParam )->text(),
170 $profileConfig['parameters']
171 )
172 );
173 }
174
175 return "<div class='search-types'>" .
176 "<ul>" . implode( '', $items ) . "</ul>" .
177 "</div>";
178 }
179
186 protected function startsWithImage( $term ) {
187 $parts = explode( ':', $term );
188 return count( $parts ) > 1
189 ? MediaWikiServices::getInstance()->getContentLanguage()->getNsIndex( $parts[0] ) ===
190 NS_FILE
191 : false;
192 }
193
203 protected function makeSearchLink( $term, $label, $tooltip, array $params = [] ) {
204 $params += [
205 'search' => $term,
206 'fulltext' => 1,
207 ];
208
209 return Xml::element(
210 'a',
211 [
212 'href' => $this->specialSearch->getPageTitle()->getLocalURL( $params ),
213 'title' => $tooltip,
214 ],
215 $label
216 );
217 }
218
228 protected function optionsHtml( $term, $isPowerSearch, $profile ) {
229 $html = '';
230
231 if ( $isPowerSearch ) {
232 $html .= $this->powerSearchBox( $term, [] );
233 } else {
234 $form = '';
235 Hooks::run( 'SpecialSearchProfileForm', [
236 $this->specialSearch, &$form, $profile, $term, []
237 ] );
238 $html .= $form;
239 }
240
241 return $html;
242 }
243
250 protected function powerSearchBox( $term, array $opts ) {
251 $rows = [];
252 $activeNamespaces = $this->specialSearch->getNamespaces();
253 $langConverter = $this->specialSearch->getLanguage();
254 foreach ( $this->searchConfig->searchableNamespaces() as $namespace => $name ) {
255 $subject = MediaWikiServices::getInstance()->getNamespaceInfo()->
256 getSubject( $namespace );
257 if ( !isset( $rows[$subject] ) ) {
258 $rows[$subject] = "";
259 }
260
261 $name = $langConverter->convertNamespace( $namespace );
262 if ( $name === '' ) {
263 $name = $this->specialSearch->msg( 'blanknamespace' )->text();
264 }
265
266 $rows[$subject] .=
267 '<td>' .
268 Xml::checkLabel(
269 $name,
270 "ns{$namespace}",
271 "mw-search-ns{$namespace}",
272 in_array( $namespace, $activeNamespaces )
273 ) .
274 '</td>';
275 }
276
277 // Lays out namespaces in multiple floating two-column tables so they'll
278 // be arranged nicely while still accomodating diferent screen widths
279 $tableRows = [];
280 foreach ( $rows as $row ) {
281 $tableRows[] = "<tr>{$row}</tr>";
282 }
283 $namespaceTables = [];
284 foreach ( array_chunk( $tableRows, 4 ) as $chunk ) {
285 $namespaceTables[] = implode( '', $chunk );
286 }
287
288 $showSections = [
289 'namespaceTables' => "<table>" . implode( '</table><table>', $namespaceTables ) . '</table>',
290 ];
291 Hooks::run( 'SpecialSearchPowerBox', [ &$showSections, $term, &$opts ] );
292
293 $hidden = '';
294 foreach ( $opts as $key => $value ) {
295 $hidden .= Html::hidden( $key, $value );
296 }
297
298 $divider = "<div class='divider'></div>";
299
300 // Stuff to feed SpecialSearch::saveNamespaces()
301 $user = $this->specialSearch->getUser();
302 $remember = '';
303 if ( $user->isLoggedIn() ) {
304 $remember = $divider . Xml::checkLabel(
305 $this->specialSearch->msg( 'powersearch-remember' )->text(),
306 'nsRemember',
307 'mw-search-powersearch-remember',
308 false,
309 // The token goes here rather than in a hidden field so it
310 // is only sent when necessary (not every form submission)
311 [ 'value' => $user->getEditToken(
312 'searchnamespace',
313 $this->specialSearch->getRequest()
314 ) ]
315 );
316 }
317
318 return "<fieldset id='mw-searchoptions'>" .
319 "<legend>" . $this->specialSearch->msg( 'powersearch-legend' )->escaped() . '</legend>' .
320 "<h4>" . $this->specialSearch->msg( 'powersearch-ns' )->parse() . '</h4>' .
321 // Handled by JavaScript if available
322 '<div id="mw-search-togglebox">' .
323 '<label>' . $this->specialSearch->msg( 'powersearch-togglelabel' )->escaped() . '</label>' .
324 '<input type="button" id="mw-search-toggleall" value="' .
325 $this->specialSearch->msg( 'powersearch-toggleall' )->escaped() . '"/>' .
326 '<input type="button" id="mw-search-togglenone" value="' .
327 $this->specialSearch->msg( 'powersearch-togglenone' )->escaped() . '"/>' .
328 '</div>' .
329 $divider .
330 implode(
331 $divider,
332 $showSections
333 ) .
334 $hidden .
335 $remember .
336 "</fieldset>";
337 }
338}
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
Hooks class.
Definition Hooks.php:34
This class is a collection of static functions that serve two purposes:
Definition Html.php:49
MediaWikiServices is the service locator for the application scope of MediaWiki.
static getInstance()
Returns the global default instance of the top level service locator.
render( $profile, $term, $numResults, $totalResults, $offset, $isPowerSearch, array $options=[])
profileTabsHtml( $profile, $term)
Generates HTML for the list of available search profiles.
startsWithImage( $term)
Check if query starts with image: prefix.
shortDialogHtml( $profile, $term, $numResults, $totalResults, $offset, array $options=[])
makeSearchLink( $term, $label, $tooltip, array $params=[])
Make a search link with some target namespaces.
__construct(SpecialSearch $specialSearch, SearchEngineConfig $searchConfig, array $profiles)
optionsHtml( $term, $isPowerSearch, $profile)
Generates HTML for advanced options available with the currently selected search profile.
Configuration handling class for SearchEngine.
implements Special:Search - Run text & title search and display the output
Module of static functions for generating XML.
Definition Xml.php:28
const NS_FILE
Definition Defines.php:75
if(!isset( $args[0])) $lang