MediaWiki REL1_31
MonoBookTemplate.php
Go to the documentation of this file.
1<?php
31
38 public function execute() {
39 // Open html, body elements, etc
40 $html = $this->get( 'headelement' );
41 $html .= Html::openElement( 'div', [ 'id' => 'globalWrapper' ] );
42
43 $html .= Html::openElement( 'div', [ 'id' => 'column-content' ] );
44 $html .= Html::rawElement( 'div', [ 'id' => 'content', 'class' => 'mw-body', 'role' => 'main' ],
45 Html::element( 'a', [ 'id' => 'top' ] ) .
46 $this->getIfExists( 'sitenotice', [
47 'wrapper' => 'div',
48 'parameters' => [ 'id' => 'siteNotice', 'class' => 'mw-body-content' ]
49 ] ) .
50 $this->getIndicators() .
51 $this->getIfExists( 'title', [
52 'loose' => true,
53 'wrapper' => 'h1',
54 'parameters' => [
55 'id' => 'firstHeading',
56 'class' => 'firstHeading',
57 'lang' => $this->getSkin()->getTitle()->getPageViewLanguage()->getHtmlCode()
58 ]
59 ] ) .
60 Html::rawElement( 'div', [ 'id' => 'bodyContent', 'class' => 'mw-body-content' ],
61 Html::rawElement( 'div', [ 'id' => 'siteSub' ], $this->getMsg( 'tagline' )->parse() ) .
62 Html::rawElement(
63 'div',
64 [ 'id' => 'contentSub', 'lang' => $this->get( 'userlang' ), 'dir' => $this->get( 'dir' ) ],
65 $this->get( 'subtitle' )
66 ) .
67 $this->getIfExists( 'undelete', [ 'wrapper' => 'div', 'parameters' => [
68 'id' => 'contentSub2'
69 ] ] ) .
70 $this->getIfExists( 'newtalk', [ 'wrapper' => 'div', 'parameters' => [
71 'class' => 'usermessage'
72 ] ] ) .
73 Html::rawElement( 'div', [ 'id' => 'jump-to-nav', 'class' => 'mw-jump' ],
74 $this->getMsg( 'jumpto' )->escaped() .
75 Html::element( 'a', [ 'href' => '#column-one' ],
76 $this->getMsg( 'jumptonavigation' )->text()
77 ) .
78 $this->getMsg( 'comma-separator' )->escaped() .
79 Html::element( 'a', [ 'href' => '#searchInput' ],
80 $this->getMsg( 'jumptosearch' )->text()
81 )
82 ) .
83 '<!-- start content -->' .
84
85 $this->get( 'bodytext' ) .
86 $this->getIfExists( 'catlinks' ) .
87
88 '<!-- end content -->' .
89 $this->getIfExists( 'dataAfterContent' ) .
90 $this->getClear()
91 )
92 );
93 $html .= $this->deprecatedHookHack( 'MonoBookAfterContent' );
94 $html .= Html::closeElement( 'div' );
95
96 $html .= Html::rawElement( 'div',
97 [
98 'id' => 'column-one',
99 'lang' => $this->get( 'userlang' ),
100 'dir' => $this->get( 'dir' )
101 ],
102 Html::element( 'h2', [], $this->getMsg( 'navigation-heading' )->text() ) .
103 $this->getBox( 'cactions', $this->data['content_actions'], 'views' ) .
104 $this->getBox( 'personal', $this->getPersonalTools(), 'personaltools' ) .
105 Html::rawElement( 'div', [ 'class' => 'portlet', 'id' => 'p-logo', 'role' => 'banner' ],
106 Html::element( 'a',
107 [
108 'href' => $this->data['nav_urls']['mainpage']['href'],
109 'class' => 'mw-wiki-logo',
110 ]
112 )
113 ) .
114 $this->getRenderedSidebar()
115 );
116 $html .= '<!-- end of the left (by default at least) column -->';
117
118 $html .= $this->getClear();
119 $html .= $this->getSimpleFooter();
120 $html .= Html::closeElement( 'div' );
121
122 $html .= $this->getTrail();
123
124 $html .= Html::closeElement( 'body' );
125 $html .= Html::closeElement( 'html' );
126
127 // The unholy echo
128 echo $html;
129 }
130
136 protected function getRenderedSidebar() {
137 $sidebar = $this->data['sidebar'];
138 $html = '';
139
140 if ( !isset( $sidebar['SEARCH'] ) ) {
141 $sidebar['SEARCH'] = true;
142 }
143 if ( !isset( $sidebar['TOOLBOX'] ) ) {
144 $sidebar['TOOLBOX'] = true;
145 }
146 if ( !isset( $sidebar['LANGUAGES'] ) ) {
147 $sidebar['LANGUAGES'] = true;
148 }
149
150 foreach ( $sidebar as $boxName => $content ) {
151 if ( $content === false ) {
152 continue;
153 }
154
155 // Numeric strings gets an integer when set as key, cast back - T73639
156 $boxName = (string)$boxName;
157
158 if ( $boxName == 'SEARCH' ) {
159 $html .= $this->getSearchBox();
160 } elseif ( $boxName == 'TOOLBOX' ) {
161 $html .= $this->getToolboxBox();
162 } elseif ( $boxName == 'LANGUAGES' ) {
163 $html .= $this->getLanguageBox();
164 } else {
165 $html .= $this->getBox(
166 $boxName,
167 $content,
168 null,
169 [ 'extra-classes' => 'generated-sidebar' ]
170 );
171 }
172 }
173
174 return $html;
175 }
176
182 protected function getSearchBox() {
183 $html = '';
184
185 if ( $this->config->get( 'UseTwoButtonsSearchForm' ) ) {
186 $optionButtons = '&#160; ' . $this->makeSearchButton(
187 'fulltext',
188 [ 'id' => 'mw-searchButton', 'class' => 'searchButton' ]
189 );
190 } else {
191 $optionButtons = Html::rawElement( 'div', [],
192 Html::rawElement( 'a', [ 'href' => $this->get( 'searchaction' ), 'rel' => 'search' ],
193 $this->getMsg( 'powersearch-legend' )->escaped()
194 )
195 );
196 }
197 $searchInputId = 'searchInput';
198 $searchForm = Html::rawElement( 'form', [
199 'action' => $this->get( 'wgScript' ),
200 'id' => 'searchform'
201 ],
202 Html::hidden( 'title', $this->get( 'searchtitle' ) ) .
203 $this->makeSearchInput( [ 'id' => $searchInputId ] ) .
204 $this->makeSearchButton( 'go', [ 'id' => 'searchGoButton', 'class' => 'searchButton' ] ) .
205 $optionButtons
206 );
207
208 $html .= $this->getBox( 'search', $searchForm, null, [
209 'search-input-id' => $searchInputId,
210 'role' => 'search',
211 'body-id' => 'searchBody'
212 ] );
213
214 return $html;
215 }
216
222 protected function getToolboxBox() {
223 $html = '';
224 $skin = $this;
225
226 $html .= $this->getBox( 'tb', $this->getToolbox(), 'toolbox', [ 'hooks' => [
227 // Deprecated hooks
228 'MonoBookTemplateToolboxEnd' => [ &$skin ],
229 'SkinTemplateToolboxEnd' => [ &$skin, true ]
230 ] ] );
231
232 $html .= $this->deprecatedHookHack( 'MonoBookAfterToolbox' );
233
234 return $html;
235 }
236
242 protected function getLanguageBox() {
243 $html = '';
244
245 if ( $this->data['language_urls'] !== false ) {
246 $html .= $this->getBox( 'lang', $this->data['language_urls'], 'otherlanguages' );
247 }
248
249 return $html;
250 }
251
262 protected function getBox( $name, $contents, $msg = null, $setOptions = [] ) {
263 $options = [
264 'class' => 'portlet',
265 'body-class' => 'pBody',
266 'text-wrapper' => ''
267 ];
268 foreach ( $setOptions as $key => $value ) {
269 $options[$key] = $value;
270 }
271
272 // Do some special stuff for the personal menu
273 if ( $name == 'personal' ) {
274 $prependiture = '';
275
276 // Extension:UniversalLanguageSelector order - T121793
277 if ( array_key_exists( 'uls', $contents ) ) {
278 $prependiture .= $this->makeListItem( 'uls', $contents['uls'] );
279 unset( $contents['uls'] );
280 }
281 if ( !$this->getSkin()->getUser()->isLoggedIn() &&
282 User::groupHasPermission( '*', 'edit' )
283 ) {
284 $prependiture .= Html::rawElement(
285 'li',
286 [ 'id' => 'pt-anonuserpage' ],
287 $this->getMsg( 'notloggedin' )->escaped()
288 );
289 }
290 $options['list-prepend'] = $prependiture;
291 }
292
293 return $this->getPortlet( $name, $contents, $msg, $options );
294 }
295
306 protected function getPortlet( $name, $content, $msg = null, $setOptions = [] ) {
307 // random stuff to override with any provided options
308 $options = [
309 // handle role=search a little differently
310 'role' => 'navigation',
311 'search-input-id' => 'searchInput',
312 // extra classes/ids
313 'id' => 'p-' . $name,
314 'class' => 'mw-portlet',
315 'extra-classes' => '',
316 'body-id' => null,
317 'body-class' => 'mw-portlet-body',
318 'body-extra-classes' => '',
319 // wrapper for individual list items
320 'text-wrapper' => [ 'tag' => 'span' ],
321 // old toolbox hook support (use: [ 'SkinTemplateToolboxEnd' => [ &$skin, true ] ])
322 'hooks' => '',
323 // option to stick arbitrary stuff at the beginning of the ul
324 'list-prepend' => ''
325 ];
326 // set options based on input
327 foreach ( $setOptions as $key => $value ) {
328 $options[$key] = $value;
329 }
330
331 // Handle the different $msg possibilities
332 if ( $msg === null ) {
333 $msg = $name;
334 $msgParams = [];
335 } elseif ( is_array( $msg ) ) {
336 $msgString = array_shift( $msg );
337 $msgParams = $msg;
338 $msg = $msgString;
339 } else {
340 $msgParams = [];
341 }
342 $msgObj = $this->getMsg( $msg, $msgParams );
343 if ( $msgObj->exists() ) {
344 $msgString = $msgObj->parse();
345 } else {
346 $msgString = htmlspecialchars( $msg );
347 }
348
349 $labelId = Sanitizer::escapeIdForAttribute( "p-$name-label" );
350
351 if ( is_array( $content ) ) {
352 $contentText = Html::openElement( 'ul',
353 [ 'lang' => $this->get( 'userlang' ), 'dir' => $this->get( 'dir' ) ]
354 );
355 $contentText .= $options['list-prepend'];
356 foreach ( $content as $key => $item ) {
357 if ( is_array( $options['text-wrapper'] ) ) {
358 $contentText .= $this->makeListItem(
359 $key,
360 $item,
361 [ 'text-wrapper' => $options['text-wrapper'] ]
362 );
363 } else {
364 $contentText .= $this->makeListItem(
365 $key,
366 $item
367 );
368 }
369 }
370 // Compatibility with extensions still using SkinTemplateToolboxEnd or similar
371 if ( is_array( $options['hooks'] ) ) {
372 foreach ( $options['hooks'] as $hook => $hookOptions ) {
373 $contentText .= $this->deprecatedHookHack( $hook, $hookOptions );
374 }
375 }
376
377 $contentText .= Html::closeElement( 'ul' );
378 } else {
379 $contentText = $content;
380 }
381
382 // Special handling for role=search
383 $divOptions = [
384 'role' => $options['role'],
385 'class' => $this->mergeClasses( $options['class'], $options['extra-classes'] ),
386 'id' => Sanitizer::escapeIdForAttribute( $options['id'] ),
387 'title' => Linker::titleAttrib( $options['id'] )
388 ];
389 if ( $options['role'] !== 'search' ) {
390 $divOptions['aria-labelledby'] = $labelId;
391 }
392 $labelOptions = [
393 'id' => $labelId,
394 'lang' => $this->get( 'userlang' ),
395 'dir' => $this->get( 'dir' )
396 ];
397 if ( $options['role'] == 'search' ) {
398 $msgString = Html::rawElement( 'label', [ 'for' => $options['search-input-id'] ], $msgString );
399 }
400
401 $bodyDivOptions = [
402 'class' => $this->mergeClasses( $options['body-class'], $options['body-extra-classes'] )
403 ];
404 if ( is_string( $options['body-id'] ) ) {
405 $bodyDivOptions['id'] = $options['body-id'];
406 }
407
408 $html = Html::rawElement( 'div', $divOptions,
409 Html::rawElement( 'h3', $labelOptions, $msgString ) .
410 Html::rawElement( 'div', $bodyDivOptions,
411 $contentText .
412 $this->getAfterPortlet( $name )
413 )
414 );
415
416 return $html;
417 }
418
430 protected function mergeClasses( $class, $extraClasses ) {
431 if ( !is_array( $class ) ) {
432 $class = [ $class ];
433 }
434 if ( !is_array( $extraClasses ) ) {
435 $extraClasses = [ $extraClasses ];
436 }
437
438 return array_merge( $class, $extraClasses );
439 }
440
450 protected function deprecatedHookHack( $hook, $hookOptions = [] ) {
451 $hookContents = '';
452 ob_start();
453 Hooks::run( $hook, $hookOptions );
454 $hookContents = ob_get_contents();
455 ob_end_clean();
456 if ( !trim( $hookContents ) ) {
457 $hookContents = '';
458 }
459
460 return $hookContents;
461 }
462
471 protected function getIfExists( $object, $setOptions = [] ) {
472 $options = [
473 'loose' => false,
474 'wrapper' => 'none',
475 'parameters' => []
476 ];
477 foreach ( $setOptions as $key => $value ) {
478 $options[$key] = $value;
479 }
480
481 $html = '';
482
483 if ( ( $options['loose'] && $this->data[$object] != '' ) ||
484 ( !$options['loose'] && $this->data[$object] ) ) {
485 if ( $options['wrapper'] == 'none' ) {
486 $html .= $this->get( $object );
487 } else {
488 $html .= Html::rawElement(
489 $options['wrapper'],
490 $options['parameters'],
491 $this->get( $object )
492 );
493 }
494 }
495
496 return $html;
497 }
498
504 protected function getSimpleFooter() {
505 $validFooterIcons = $this->getFooterIcons( 'icononly' );
506 $validFooterLinks = $this->getFooterLinks( 'flat' );
507
508 $html = '';
509
510 $html .= Html::openElement( 'div', [
511 'id' => 'footer',
512 'role' => 'contentinfo',
513 'lang' => $this->get( 'userlang' ),
514 'dir' => $this->get( 'dir' )
515 ] );
516
517 foreach ( $validFooterIcons as $blockName => $footerIcons ) {
518 $html .= Html::openElement( 'div', [
519 'id' => Sanitizer::escapeIdForAttribute( "f-{$blockName}ico" ),
520 'class' => 'footer-icons'
521 ] );
522 foreach ( $footerIcons as $icon ) {
523 $html .= $this->getSkin()->makeFooterIcon( $icon );
524 }
525 $html .= Html::closeElement( 'div' );
526 }
527 if ( count( $validFooterLinks ) > 0 ) {
528 $html .= Html::openElement( 'ul', [ 'id' => 'f-list' ] );
529 foreach ( $validFooterLinks as $aLink ) {
530 $html .= Html::rawElement(
531 'li',
532 [ 'id' => Sanitizer::escapeIdForAttribute( $aLink ) ],
533 $this->get( $aLink )
534 );
535 }
536 $html .= Html::closeElement( 'ul' );
537 }
538 $html .= Html::closeElement( 'div' );
539
540 return $html;
541 }
542}
New base template for a skin's template extended from QuickTemplate this class features helper method...
getFooterLinks( $option=null)
Returns an array of footerlinks trimmed down to only those footer links that are valid.
makeSearchButton( $mode, $attrs=[])
getToolbox()
Create an array of common toolbox items from the data in the quicktemplate stored by SkinTemplate.
getTrail()
Get the basic end-page trail including bottomscripts, reporttime, and debug stuff.
getPersonalTools()
Create an array of personal tools items from the data in the quicktemplate stored by SkinTemplate.
getFooterIcons( $option=null)
Returns an array of footer icons filtered down by options relevant to how the skin wishes to display ...
makeListItem( $key, $item, $options=[])
Generates a list item for a navigation, portlet, portal, sidebar... list.
getMsg( $name)
Get a Message object with its context set.
getIndicators()
Get the suggested HTML for page status indicators: icons (or short text snippets) usually displayed i...
makeSearchInput( $attrs=[])
getClear()
Get a div with the core visualClear class, for clearing floats.
getAfterPortlet( $name)
Allows extensions to hook into known portlets and add stuff to them.
static titleAttrib( $name, $options=null, array $msgParams=[])
Given the id of an interface element, constructs the appropriate title attribute from the system mess...
Definition Linker.php:1969
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[], $options=null)
Returns the attributes for the tooltip and access key.
Definition Linker.php:2135
execute()
Template filter callback for MonoBook skin.
getBox( $name, $contents, $msg=null, $setOptions=[])
Generate a sidebar box using getPortlet(); prefill some common stuff.
getSimpleFooter()
Renderer for getFooterIcons and getFooterLinks as a generic footer block.
getSearchBox()
Generate the search, using config options for buttons (?)
getPortlet( $name, $content, $msg=null, $setOptions=[])
Generates a block of navigation links with a header.
getRenderedSidebar()
Generate the full sidebar.
getLanguageBox()
Generate the languages box.
getIfExists( $object, $setOptions=[])
Simple wrapper for random if-statement-wrapped $this->data things.
mergeClasses( $class, $extraClasses)
Helper function for getPortlet.
getToolboxBox()
Generate the toolbox, complete with all three old hooks.
deprecatedHookHack( $hook, $hookOptions=[])
Wrapper to catch output of old hooks expecting to write directly to page We no longer do things that ...
getSkin()
Get the Skin object related to this object.
static groupHasPermission( $group, $role)
Check, if the given group has the given permission.
Definition User.php:5005
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add text
Definition design.txt:18
This code would result in ircNotify being run twice when an article is and once for brion Hooks can return three possible true was required This is the default since MediaWiki *some string
Definition hooks.txt:181
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
Definition hooks.txt:2001
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses & $html
Definition hooks.txt:2013
Allows to change the fields on the form that will be generated $name
Definition hooks.txt:302