MediaWiki  1.34.0
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::element( 'div', [ 'id' => 'jump-to-nav' ] ) .
74  Html::element( 'a', [ 'href' => '#column-one', 'class' => 'mw-jump-link' ],
75  $this->getMsg( 'monobook-jumptonavigation' )->text()
76  ) .
77  Html::element( 'a', [ 'href' => '#searchInput', 'class' => 'mw-jump-link' ],
78  $this->getMsg( 'monobook-jumptosearch' )->text()
79  ) .
80  '<!-- start content -->' .
81 
82  $this->get( 'bodytext' ) .
83  $this->getIfExists( 'catlinks' ) .
84 
85  '<!-- end content -->' .
86  $this->getClear()
87  )
88  );
89  $html .= $this->deprecatedHookHack( 'MonoBookAfterContent' );
90  $html .= $this->getIfExists( 'dataAfterContent' ) . $this->getClear();
91  $html .= Html::closeElement( 'div' );
92 
93  $html .= Html::rawElement( 'div',
94  [
95  'id' => 'column-one',
96  'lang' => $this->get( 'userlang' ),
97  'dir' => $this->get( 'dir' )
98  ],
99  Html::element( 'h2', [], $this->getMsg( 'navigation-heading' )->text() ) .
100  $this->getCactions() .
101  $this->getBox( 'personal', $this->getPersonalTools(), 'personaltools' ) .
102  Html::rawElement( 'div', [ 'class' => 'portlet', 'id' => 'p-logo', 'role' => 'banner' ],
103  Html::element( 'a',
104  [
105  'href' => $this->data['nav_urls']['mainpage']['href'],
106  'class' => 'mw-wiki-logo',
107  ]
109  )
110  ) .
111  Html::rawElement( 'div', [ 'id' => 'sidebar' ], $this->getRenderedSidebar() ) .
113  'sidebar',
114  $this->getMsg( 'jumptonavigation' )->text()
115  ) .
117  'p-personal',
118  $this->getMsg( 'monobook-jumptopersonal' )->text()
119  ) .
121  'globalWrapper',
122  $this->getMsg( 'monobook-jumptotop' )->text()
123  )
124  );
125  $html .= '<!-- end of the left (by default at least) column -->';
126 
127  $html .= $this->getClear();
128  $html .= $this->getSimpleFooter();
129  $html .= Html::closeElement( 'div' );
130 
131  $html .= $this->getTrail();
132 
133  $html .= Html::closeElement( 'body' );
134  $html .= Html::closeElement( 'html' );
135 
136  // The unholy echo
137  echo $html;
138  }
139 
150  protected function getMobileNavigationIcon( $target, $title ) {
151  return Html::element( 'a', [
152  'href' => "#$target",
153  'title' => $title,
154  'class' => 'menu-toggle',
155  'id' => "$target-toggle"
156  ] );
157  }
158 
164  protected function getCactions() {
165  $html = '';
166  $allTabs = $this->data['content_actions'];
167  $tabCount = count( $allTabs );
168 
169  // Normal cactions
170  if ( $tabCount > 2 ) {
171  $html .= $this->getBox( 'cactions', $allTabs, 'monobook-cactions-label' );
172  } else {
173  // Is redundant with spoof, hide normal cactions entirely in mobile
174  $html .= $this->getBox( 'cactions', $allTabs, 'monobook-cactions-label',
175  [ 'extra-classes' => 'nomobile' ]
176  );
177  }
178 
179  // Mobile cactions tabs
180  $tabs = $this->data['content_navigation']['namespaces'];
181  foreach ( $tabs as $tab => $attribs ) {
182  $tabs[$tab]['id'] = $attribs['id'] . '-mobile';
183  $tabs[$tab]['title'] = $attribs['text'];
184  }
185 
186  if ( $tabCount !== 1 ) {
187  // Is not special page or stuff, append a 'more'
188  $tabs['more'] = [
189  'text' => $this->getMsg( 'monobook-more-actions' )->text(),
190  'href' => '#p-cactions',
191  'id' => 'ca-more'
192  ];
193  }
194  $tabs['toolbox'] = [
195  'text' => $this->getMsg( 'toolbox' )->text(),
196  'href' => '#p-tb',
197  'id' => 'ca-tools',
198  'title' => $this->getMsg( 'toolbox' )->text()
199  ];
200  if ( $this->data['language_urls'] !== false ) {
201  $tabs['languages'] = [
202  'text' => $this->getMsg( 'otherlanguages' )->text(),
203  'href' => '#p-lang',
204  'id' => 'ca-languages',
205  'title' => $this->getMsg( 'otherlanguages' )->text()
206  ];
207  }
208 
209  $html .= $this->getBox( 'cactions-mobile', $tabs, 'monobook-cactions-label' );
210 
211  return $html;
212  }
213 
219  protected function getRenderedSidebar() {
220  $sidebar = $this->data['sidebar'];
221  $html = '';
222 
223  if ( !isset( $sidebar['SEARCH'] ) ) {
224  $sidebar['SEARCH'] = true;
225  }
226  if ( !isset( $sidebar['TOOLBOX'] ) ) {
227  $sidebar['TOOLBOX'] = true;
228  }
229  if ( !isset( $sidebar['LANGUAGES'] ) ) {
230  $sidebar['LANGUAGES'] = true;
231  }
232 
233  foreach ( $sidebar as $boxName => $content ) {
234  if ( $content === false ) {
235  continue;
236  }
237 
238  // Numeric strings gets an integer when set as key, cast back - T73639
239  $boxName = (string)$boxName;
240 
241  if ( $boxName == 'SEARCH' ) {
242  $html .= $this->getSearchBox();
243  } elseif ( $boxName == 'TOOLBOX' ) {
244  $html .= $this->getToolboxBox();
245  } elseif ( $boxName == 'LANGUAGES' ) {
246  $html .= $this->getLanguageBox();
247  } else {
248  $html .= $this->getBox(
249  $boxName,
250  $content,
251  null,
252  [ 'extra-classes' => 'generated-sidebar' ]
253  );
254  }
255  }
256 
257  return $html;
258  }
259 
265  protected function getSearchBox() {
266  $html = '';
267 
268  if ( $this->config->get( 'UseTwoButtonsSearchForm' ) ) {
269  $optionButtons = "\u{00A0} " . $this->makeSearchButton(
270  'fulltext',
271  [ 'id' => 'mw-searchButton', 'class' => 'searchButton' ]
272  );
273  } else {
274  $optionButtons = Html::rawElement( 'div', [],
275  Html::rawElement( 'a', [ 'href' => $this->get( 'searchaction' ), 'rel' => 'search' ],
276  $this->getMsg( 'powersearch-legend' )->escaped()
277  )
278  );
279  }
280  $searchInputId = 'searchInput';
281  $searchForm = Html::rawElement( 'form', [
282  'action' => $this->get( 'wgScript' ),
283  'id' => 'searchform'
284  ],
285  Html::hidden( 'title', $this->get( 'searchtitle' ) ) .
286  $this->makeSearchInput( [ 'id' => $searchInputId ] ) .
287  $this->makeSearchButton( 'go', [ 'id' => 'searchGoButton', 'class' => 'searchButton' ] ) .
288  $optionButtons
289  );
290 
291  $html .= $this->getBox( 'search', $searchForm, null, [
292  'search-input-id' => $searchInputId,
293  'role' => 'search',
294  'body-id' => 'searchBody'
295  ] );
296 
297  return $html;
298  }
299 
305  protected function getToolboxBox() {
306  $html = '';
307  $template = $this;
308 
309  $html .= $this->getBox( 'tb', $this->getToolbox(), 'toolbox', [ 'hooks' => [
310  // Deprecated hooks
311  'MonoBookTemplateToolboxEnd' => [ &$template ],
312  'SkinTemplateToolboxEnd' => [ &$template, true ]
313  ] ] );
314 
315  $html .= $this->deprecatedHookHack( 'MonoBookAfterToolbox', [ $template ] );
316 
317  return $html;
318  }
319 
325  protected function getLanguageBox() {
326  $html = '';
327 
328  if ( $this->data['language_urls'] !== false ) {
329  $html .= $this->getBox( 'lang', $this->data['language_urls'], 'otherlanguages' );
330  }
331 
332  return $html;
333  }
334 
346  protected function getBox( $name, $contents, $msg = null, $setOptions = [] ) {
347  $options = array_merge( [
348  'class' => 'portlet',
349  'body-class' => 'pBody',
350  'text-wrapper' => ''
351  ], $setOptions );
352 
353  // Do some special stuff for the personal menu
354  if ( $name == 'personal' ) {
355  $prependiture = '';
356 
357  // Extension:UniversalLanguageSelector order - T121793
358  if ( array_key_exists( 'uls', $contents ) ) {
359  $prependiture .= $this->makeListItem( 'uls', $contents['uls'] );
360  unset( $contents['uls'] );
361  }
362  if ( !$this->getSkin()->getUser()->isLoggedIn() &&
363  User::groupHasPermission( '*', 'edit' )
364  ) {
365  $prependiture .= Html::rawElement(
366  'li',
367  [ 'id' => 'pt-anonuserpage' ],
368  $this->getMsg( 'notloggedin' )->escaped()
369  );
370  }
371  $options['list-prepend'] = $prependiture;
372  }
373 
374  return $this->getPortlet( $name, $contents, $msg, $options );
375  }
376 
387  protected function getPortlet( $name, $content, $msg = null, $setOptions = [] ) {
388  // random stuff to override with any provided options
389  $options = array_merge( [
390  // handle role=search a little differently
391  'role' => 'navigation',
392  'search-input-id' => 'searchInput',
393  // extra classes/ids
394  'id' => 'p-' . $name,
395  'class' => 'mw-portlet',
396  'extra-classes' => '',
397  'body-id' => null,
398  'body-class' => 'mw-portlet-body',
399  'body-extra-classes' => '',
400  // wrapper for individual list items
401  'text-wrapper' => [ 'tag' => 'span' ],
402  // old toolbox hook support (use: [ 'SkinTemplateToolboxEnd' => [ &$skin, true ] ])
403  'hooks' => '',
404  // option to stick arbitrary stuff at the beginning of the ul
405  'list-prepend' => ''
406  ], $setOptions );
407 
408  // Handle the different $msg possibilities
409  if ( $msg === null ) {
410  $msg = $name;
411  $msgParams = [];
412  } elseif ( is_array( $msg ) ) {
413  $msgString = array_shift( $msg );
414  $msgParams = $msg;
415  $msg = $msgString;
416  } else {
417  $msgParams = [];
418  }
419  $msgObj = $this->getMsg( $msg, $msgParams );
420  if ( $msgObj->exists() ) {
421  $msgString = $msgObj->parse();
422  } else {
423  $msgString = htmlspecialchars( $msg );
424  }
425 
426  $labelId = Sanitizer::escapeIdForAttribute( "p-$name-label" );
427 
428  if ( is_array( $content ) ) {
429  $contentText = Html::openElement( 'ul',
430  [ 'lang' => $this->get( 'userlang' ), 'dir' => $this->get( 'dir' ) ]
431  );
432  $contentText .= $options['list-prepend'];
433  foreach ( $content as $key => $item ) {
434  if ( is_array( $options['text-wrapper'] ) ) {
435  $contentText .= $this->makeListItem(
436  $key,
437  $item,
438  [ 'text-wrapper' => $options['text-wrapper'] ]
439  );
440  } else {
441  $contentText .= $this->makeListItem(
442  $key,
443  $item
444  );
445  }
446  }
447  // Compatibility with extensions still using SkinTemplateToolboxEnd or similar
448  if ( is_array( $options['hooks'] ) ) {
449  foreach ( $options['hooks'] as $hook => $hookOptions ) {
450  $contentText .= $this->deprecatedHookHack( $hook, $hookOptions );
451  }
452  }
453 
454  $contentText .= Html::closeElement( 'ul' );
455  } else {
456  $contentText = $content;
457  }
458 
459  // Special handling for role=search
460  $divOptions = [
461  'role' => $options['role'],
462  'class' => $this->mergeClasses( $options['class'], $options['extra-classes'] ),
463  'id' => Sanitizer::escapeIdForAttribute( $options['id'] ),
464  'title' => Linker::titleAttrib( $options['id'] )
465  ];
466  if ( $options['role'] !== 'search' ) {
467  $divOptions['aria-labelledby'] = $labelId;
468  }
469  $labelOptions = [
470  'id' => $labelId,
471  'lang' => $this->get( 'userlang' ),
472  'dir' => $this->get( 'dir' )
473  ];
474  if ( $options['role'] == 'search' ) {
475  $msgString = Html::rawElement( 'label', [ 'for' => $options['search-input-id'] ], $msgString );
476  }
477 
478  $bodyDivOptions = [
479  'class' => $this->mergeClasses( $options['body-class'], $options['body-extra-classes'] )
480  ];
481  if ( is_string( $options['body-id'] ) ) {
482  $bodyDivOptions['id'] = $options['body-id'];
483  }
484 
485  $html = Html::rawElement( 'div', $divOptions,
486  Html::rawElement( 'h3', $labelOptions, $msgString ) .
487  Html::rawElement( 'div', $bodyDivOptions,
488  $contentText .
489  $this->getAfterPortlet( $name )
490  )
491  );
492 
493  return $html;
494  }
495 
507  protected function mergeClasses( $class, $extraClasses ) {
508  if ( !is_array( $class ) ) {
509  $class = [ $class ];
510  }
511  if ( !is_array( $extraClasses ) ) {
512  $extraClasses = [ $extraClasses ];
513  }
514 
515  return array_merge( $class, $extraClasses );
516  }
517 
527  protected function deprecatedHookHack( $hook, $hookOptions = [] ) {
528  $hookContents = '';
529  ob_start();
530  Hooks::run( $hook, $hookOptions );
531  $hookContents = ob_get_contents();
532  ob_end_clean();
533  if ( !trim( $hookContents ) ) {
534  $hookContents = '';
535  }
536 
537  return $hookContents;
538  }
539 
548  protected function getIfExists( $object, $setOptions = [] ) {
549  $options = [
550  'loose' => false,
551  'wrapper' => 'none',
552  'parameters' => []
553  ];
554  foreach ( $setOptions as $key => $value ) {
555  $options[$key] = $value;
556  }
557 
558  $html = '';
559 
560  if ( ( $options['loose'] && $this->data[$object] != '' ) ||
561  ( !$options['loose'] && $this->data[$object] ) ) {
562  if ( $options['wrapper'] == 'none' ) {
563  $html .= $this->get( $object );
564  } else {
565  $html .= Html::rawElement(
566  $options['wrapper'],
567  $options['parameters'],
568  $this->get( $object )
569  );
570  }
571  }
572 
573  return $html;
574  }
575 
581  protected function getSimpleFooter() {
582  $validFooterIcons = $this->getFooterIcons( 'icononly' );
583  $validFooterLinks = $this->getFooterLinks( 'flat' );
584 
585  $html = '';
586 
587  $html .= Html::openElement( 'div', [
588  'id' => 'footer',
589  'role' => 'contentinfo',
590  'lang' => $this->get( 'userlang' ),
591  'dir' => $this->get( 'dir' )
592  ] );
593 
594  foreach ( $validFooterIcons as $blockName => $footerIcons ) {
595  $html .= Html::openElement( 'div', [
596  'id' => Sanitizer::escapeIdForAttribute( "f-{$blockName}ico" ),
597  'class' => 'footer-icons'
598  ] );
599  foreach ( $footerIcons as $icon ) {
600  $html .= $this->getSkin()->makeFooterIcon( $icon );
601  }
602  $html .= Html::closeElement( 'div' );
603  }
604  if ( count( $validFooterLinks ) > 0 ) {
605  $html .= Html::openElement( 'ul', [ 'id' => 'f-list' ] );
606  foreach ( $validFooterLinks as $aLink ) {
607  $html .= Html::rawElement(
608  'li',
609  [ 'id' => Sanitizer::escapeIdForAttribute( $aLink ) ],
610  $this->get( $aLink )
611  );
612  }
613  $html .= Html::closeElement( 'ul' );
614  }
615  $html .= Html::closeElement( 'div' );
616 
617  return $html;
618  }
619 }
BaseTemplate\getPersonalTools
getPersonalTools()
Create an array of personal tools items from the data in the quicktemplate stored by SkinTemplate.
Definition: BaseTemplate.php:127
BaseTemplate\getFooterLinks
getFooterLinks( $option=null)
Returns an array of footerlinks trimmed down to only those footer links that are valid.
Definition: BaseTemplate.php:581
MonoBookTemplate\mergeClasses
mergeClasses( $class, $extraClasses)
Helper function for getPortlet.
Definition: MonoBookTemplate.php:507
BaseTemplate\makeSearchButton
makeSearchButton( $mode, $attrs=[])
Definition: BaseTemplate.php:531
MonoBookTemplate\execute
execute()
Template filter callback for MonoBook skin.
Definition: MonoBookTemplate.php:38
MonoBookTemplate\getBox
getBox( $name, $contents, $msg=null, $setOptions=[])
Generate a sidebar box using getPortlet(); prefill some common stuff.
Definition: MonoBookTemplate.php:346
getUser
getUser()
BaseTemplate\getClear
getClear()
Get a div with the core visualClear class, for clearing floats.
Definition: BaseTemplate.php:706
MonoBookTemplate\getToolboxBox
getToolboxBox()
Generate the toolbox, complete with all three old hooks.
Definition: MonoBookTemplate.php:305
MonoBookTemplate\getPortlet
getPortlet( $name, $content, $msg=null, $setOptions=[])
Generates a block of navigation links with a header.
Definition: MonoBookTemplate.php:387
User\groupHasPermission
static groupHasPermission( $group, $role)
Check, if the given group has the given permission.
Definition: User.php:4775
QuickTemplate\getSkin
getSkin()
Get the Skin object related to this object.
Definition: QuickTemplate.php:166
Linker\tooltipAndAccesskeyAttribs
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[], $options=null)
Returns the attributes for the tooltip and access key.
Definition: Linker.php:2195
MonoBookTemplate\getCactions
getCactions()
Generate the cactions (content actions) tabs, as well as a second set of spoof tabs for mobile.
Definition: MonoBookTemplate.php:164
BaseTemplate\getAfterPortlet
getAfterPortlet( $name)
Allows extensions to hook into known portlets and add stuff to them.
Definition: BaseTemplate.php:295
BaseTemplate\makeListItem
makeListItem( $key, $item, $options=[])
Generates a list item for a navigation, portlet, portal, sidebar...
Definition: BaseTemplate.php:470
MonoBookTemplate\getSimpleFooter
getSimpleFooter()
Renderer for getFooterIcons and getFooterLinks as a generic footer block.
Definition: MonoBookTemplate.php:581
$title
$title
Definition: testCompression.php:34
BaseTemplate\getIndicators
getIndicators()
Get the suggested HTML for page status indicators: icons (or short text snippets) usually displayed i...
Definition: BaseTemplate.php:725
QuickTemplate\text
text( $str)
Definition: QuickTemplate.php:107
$content
$content
Definition: router.php:78
MonoBookTemplate\getMobileNavigationIcon
getMobileNavigationIcon( $target, $title)
Create a wrapped link to create a mobile toggle/jump icon Needs to be an on-page link (as opposed to ...
Definition: MonoBookTemplate.php:150
BaseTemplate\makeSearchInput
makeSearchInput( $attrs=[])
Definition: BaseTemplate.php:521
MonoBookTemplate\getLanguageBox
getLanguageBox()
Generate the languages box.
Definition: MonoBookTemplate.php:325
MonoBookTemplate
Definition: MonoBookTemplate.php:30
MonoBookTemplate\getSearchBox
getSearchBox()
Generate the search, using config options for buttons (?)
Definition: MonoBookTemplate.php:265
Linker\titleAttrib
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:2026
MonoBookTemplate\getRenderedSidebar
getRenderedSidebar()
Generate the full sidebar.
Definition: MonoBookTemplate.php:219
BaseTemplate\getToolbox
getToolbox()
Create an array of common toolbox items from the data in the quicktemplate stored by SkinTemplate.
Definition: BaseTemplate.php:61
MonoBookTemplate\getIfExists
getIfExists( $object, $setOptions=[])
Simple wrapper for random if-statement-wrapped $this->data things.
Definition: MonoBookTemplate.php:548
BaseTemplate\getTrail
getTrail()
Get the basic end-page trail including bottomscripts, reporttime, and debug stuff.
Definition: BaseTemplate.php:756
BaseTemplate\getMsg
getMsg( $name,... $params)
Get a Message object with its context set.
Definition: BaseTemplate.php:38
getTitle
getTitle()
Definition: RevisionSearchResultTrait.php:74
MonoBookTemplate\deprecatedHookHack
deprecatedHookHack( $hook, $hookOptions=[])
Wrapper to catch output of old hooks expecting to write directly to page We no longer do things that ...
Definition: MonoBookTemplate.php:527
BaseTemplate\getFooterIcons
getFooterIcons( $option=null)
Returns an array of footer icons filtered down by options relevant to how the skin wishes to display ...
Definition: BaseTemplate.php:618
Hooks\run
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
BaseTemplate
New base template for a skin's template extended from QuickTemplate this class features helper method...
Definition: BaseTemplate.php:29