MediaWiki  master
SearchFormWidget.php
Go to the documentation of this file.
1 <?php
2 
4 
5 use Hooks;
6 use Html;
10 use SpecialSearch;
11 use 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">' .
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>' .
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 }
MediaWiki\Widget\Search\SearchFormWidget\$specialSearch
SpecialSearch $specialSearch
Definition: SearchFormWidget.php:15
MediaWiki\Widget\Search\SearchFormWidget\optionsHtml
optionsHtml( $term, $isPowerSearch, $profile)
Generates HTML for advanced options available with the currently selected search profile.
Definition: SearchFormWidget.php:228
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:130
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:35
MediaWiki\Widget\Search
Definition: BasicSearchResultSetWidget.php:3
NS_FILE
const NS_FILE
Definition: Defines.php:66
MediaWiki\Widget\Search\SearchFormWidget
Definition: SearchFormWidget.php:13
Xml\openElement
static openElement( $element, $attribs=null)
This opens an XML element.
Definition: Xml.php:108
MediaWiki\MediaWikiServices\getInstance
static getInstance()
Returns the global default instance of the top level service locator.
Definition: MediaWikiServices.php:161
wfScript
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
Definition: GlobalFunctions.php:2629
MediaWiki\Widget\Search\SearchFormWidget\powerSearchBox
powerSearchBox( $term, array $opts)
Definition: SearchFormWidget.php:250
MediaWiki\Widget\Search\SearchFormWidget\render
render( $profile, $term, $numResults, $totalResults, $offset, $isPowerSearch, array $options=[])
Definition: SearchFormWidget.php:46
Xml\element
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
Definition: Xml.php:41
MediaWiki\Widget\SearchInputWidget
Search input widget.
Definition: SearchInputWidget.php:11
MediaWiki\Widget\Search\SearchFormWidget\startsWithImage
startsWithImage( $term)
Check if query starts with image: prefix.
Definition: SearchFormWidget.php:186
MediaWiki\Widget\Search\SearchFormWidget\$searchConfig
SearchEngineConfig $searchConfig
Definition: SearchFormWidget.php:17
Xml\tags
static tags( $element, $attribs, $contents)
Same as Xml::element(), but does not escape contents.
Definition: Xml.php:130
SpecialSearch
implements Special:Search - Run text & title search and display the output
Definition: SpecialSearch.php:38
MediaWiki\Widget\Search\SearchFormWidget\__construct
__construct(SpecialSearch $specialSearch, SearchEngineConfig $searchConfig, array $profiles)
Definition: SearchFormWidget.php:26
MediaWiki\Widget\Search\SearchFormWidget\makeSearchLink
makeSearchLink( $term, $label, $tooltip, array $params=[])
Make a search link with some target namespaces.
Definition: SearchFormWidget.php:203
MediaWiki\Widget\Search\SearchFormWidget\$profiles
array $profiles
Definition: SearchFormWidget.php:19
SearchEngineConfig
Configuration handling class for SearchEngine.
Definition: SearchEngineConfig.php:9
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
Xml
Module of static functions for generating XML.
Definition: Xml.php:28
MediaWiki\Widget\Search\SearchFormWidget\shortDialogHtml
shortDialogHtml( $profile, $term, $numResults, $totalResults, $offset, array $options=[])
Definition: SearchFormWidget.php:89
Hooks
Hooks class.
Definition: Hooks.php:34
MediaWiki\Widget\Search\SearchFormWidget\profileTabsHtml
profileTabsHtml( $profile, $term)
Generates HTML for the list of available search profiles.
Definition: SearchFormWidget.php:152
Xml\checkLabel
static checkLabel( $label, $name, $id, $checked=false, $attribs=[])
Convenience function to build an HTML checkbox with a label.
Definition: Xml.php:419