MediaWiki  master
BaseTemplate.php
Go to the documentation of this file.
1 <?php
21 use Wikimedia\WrappedString;
22 use Wikimedia\WrappedStringList;
23 
33 abstract class BaseTemplate extends QuickTemplate {
34 
42  public function getMsg( $name, ...$params ) {
43  return $this->getSkin()->msg( $name, ...$params );
44  }
45 
46  public function msg( $str ) {
47  echo $this->getMsg( $str )->escaped();
48  }
49 
61  public function getToolbox() {
62  wfDeprecated( __METHOD__, '1.35' );
63 
64  $toolbox = $this->getSkin()->makeToolbox(
65  $this->data['nav_urls'],
66  $this->data['feeds']
67  );
68 
69  // Merge content that might be added to the toolbox section by hook
70  if ( isset( $this->data['sidebar']['TOOLBOX'] ) ) {
71  $toolbox = array_merge( $toolbox, $this->data['sidebar']['TOOLBOX'] ?? [] );
72  }
73 
74  return $toolbox;
75  }
76 
81  public function getPersonalTools() {
82  return $this->getSkin()->getPersonalToolsForMakeListItem( $this->get( 'personal_urls' ) );
83  }
84 
90  protected function getSidebar( $options = [] ) {
91  // Force the rendering of the following portals
92  $sidebar = $this->data['sidebar'];
93  if ( !isset( $sidebar['SEARCH'] ) ) {
94  $sidebar['SEARCH'] = true;
95  }
96  if ( !isset( $sidebar['TOOLBOX'] ) ) {
97  $sidebar['TOOLBOX'] = true;
98  }
99  if ( !isset( $sidebar['LANGUAGES'] ) ) {
100  $sidebar['LANGUAGES'] = true;
101  }
102 
103  if ( !isset( $options['search'] ) || $options['search'] !== true ) {
104  unset( $sidebar['SEARCH'] );
105  }
106  if ( isset( $options['toolbox'] ) && $options['toolbox'] === false ) {
107  unset( $sidebar['TOOLBOX'] );
108  }
109  if ( isset( $options['languages'] ) && $options['languages'] === false ) {
110  unset( $sidebar['LANGUAGES'] );
111  }
112 
113  $boxes = [];
114  foreach ( $sidebar as $boxName => $content ) {
115  if ( $content === false ) {
116  continue;
117  }
118  switch ( $boxName ) {
119  case 'SEARCH':
120  // Search is a special case, skins should custom implement this
121  $boxes[$boxName] = [
122  'id' => 'p-search',
123  'header' => $this->getMsg( 'search' )->text(),
124  'generated' => false,
125  'content' => true,
126  ];
127  break;
128  case 'TOOLBOX':
129  $msgObj = $this->getMsg( 'toolbox' );
130  $boxes[$boxName] = [
131  'id' => 'p-tb',
132  'header' => $msgObj->exists() ? $msgObj->text() : 'toolbox',
133  'generated' => false,
134  'content' => $content,
135  ];
136  break;
137  case 'LANGUAGES':
138  if ( $this->data['language_urls'] !== false ) {
139  $msgObj = $this->getMsg( 'otherlanguages' );
140  $boxes[$boxName] = [
141  'id' => 'p-lang',
142  'header' => $msgObj->exists() ? $msgObj->text() : 'otherlanguages',
143  'generated' => false,
144  'content' => $this->data['language_urls'] ?: [],
145  ];
146  }
147  break;
148  default:
149  $msgObj = $this->getMsg( $boxName );
150  $boxes[$boxName] = [
151  'id' => "p-$boxName",
152  'header' => $msgObj->exists() ? $msgObj->text() : $boxName,
153  'generated' => true,
154  'content' => $content,
155  ];
156  break;
157  }
158  }
159 
160  if ( isset( $options['htmlOnly'] ) && $options['htmlOnly'] === true ) {
161  foreach ( $boxes as $boxName => $box ) {
162  if ( is_array( $box['content'] ) ) {
163  $content = '<ul>';
164  foreach ( $box['content'] as $key => $val ) {
165  $content .= "\n " . $this->getSkin()->makeListItem( $key, $val );
166  }
167  $content .= "\n</ul>\n";
168  $boxes[$boxName]['content'] = $content;
169  }
170  }
171  }
172 
173  return $boxes;
174  }
175 
180  protected function renderAfterPortlet( $name ) {
181  wfDeprecated( __METHOD__, '1.35' );
182  echo $this->getAfterPortlet( $name );
183  }
184 
195  protected function getAfterPortlet( $name ) {
196  wfDeprecated( __METHOD__, '1.35' );
197  $html = '';
198  $content = '';
199  $this->getHookRunner()->onBaseTemplateAfterPortlet( $this, $name, $content );
200  $content .= $this->getSkin()->getAfterPortlet( $name );
201 
202  if ( $content !== '' ) {
203  $html = Html::rawElement(
204  'div',
205  [ 'class' => [ 'after-portlet', 'after-portlet-' . $name ] ],
206  $content
207  );
208  }
209 
210  return $html;
211  }
212 
217  protected function makeLink( $key, $item, $options = [] ) {
218  return $this->getSkin()->makeLink( $key, $item, $options );
219  }
220 
225  public function makeListItem( $key, $item, $options = [] ) {
226  return $this->getSkin()->makeListItem( $key, $item, $options );
227  }
228 
232  protected function makeSearchInput( $attrs = [] ) {
233  return $this->getSkin()->makeSearchInput( $attrs );
234  }
235 
239  protected function makeSearchButton( $mode, $attrs = [] ) {
240  return $this->getSkin()->makeSearchButton( $mode, $attrs );
241  }
242 
252  protected function getFooterLinks( $option = null ) {
253  $footerlinks = $this->get( 'footerlinks' );
254 
255  // Reduce footer links down to only those which are being used
256  $validFooterLinks = [];
257  foreach ( $footerlinks as $category => $links ) {
258  $validFooterLinks[$category] = [];
259  foreach ( $links as $link ) {
260  if ( isset( $this->data[$link] ) && $this->data[$link] ) {
261  $validFooterLinks[$category][] = $link;
262  }
263  }
264  if ( count( $validFooterLinks[$category] ) <= 0 ) {
265  unset( $validFooterLinks[$category] );
266  }
267  }
268 
269  if ( $option == 'flat' && count( $validFooterLinks ) ) {
270  // fold footerlinks into a single array using a bit of trickery
271  $validFooterLinks = array_merge( ...array_values( $validFooterLinks ) );
272  }
273 
274  return $validFooterLinks;
275  }
276 
291  protected function getFooterIcons( $option = null ) {
292  wfDeprecated( __METHOD__, '1.35' );
293  // Generate additional footer icons
294  $footericons = $this->get( 'footericons' );
295 
296  if ( $option == 'icononly' ) {
297  // Unset any icons which don't have an image
298  $this->unsetIconsWithoutImages( $footericons );
299  } elseif ( $option == 'nocopyright' ) {
300  unset( $footericons['copyright'] );
301  }
302 
303  return $footericons;
304  }
305 
312  private function unsetIconsWithoutImages( array &$icons ) {
313  // Unset any icons which don't have an image
314  foreach ( $icons as $iconsKey => &$iconsBlock ) {
315  foreach ( $iconsBlock as $iconKey => $icon ) {
316  if ( !is_string( $icon ) && !isset( $icon['src'] ) ) {
317  unset( $iconsBlock[$iconKey] );
318  }
319  }
320  if ( $iconsBlock === [] ) {
321  unset( $icons[$iconsKey] );
322  }
323  }
324  }
325 
336  protected function getFooter( $iconStyle = 'icononly', $linkStyle = 'flat' ) {
337  $validFooterIcons = $this->get( 'footericons' );
338  if ( $iconStyle === 'icononly' ) {
339  $this->unsetIconsWithoutImages( $validFooterIcons );
340  } else {
341  // take a deprecated unsupported path
342  $validFooterIcons = $this->getFooterIcons( $iconStyle );
343  }
344  $validFooterLinks = $this->getFooterLinks( $linkStyle );
345 
346  $html = '';
347 
348  if ( count( $validFooterIcons ) + count( $validFooterLinks ) > 0 ) {
349  $html .= Html::openElement( 'div', [
350  'id' => 'footer-bottom',
351  'class' => 'mw-footer',
352  'role' => 'contentinfo',
353  'lang' => $this->get( 'userlang' ),
354  'dir' => $this->get( 'dir' )
355  ] );
356  $footerEnd = Html::closeElement( 'div' );
357  } else {
358  $footerEnd = '';
359  }
360  foreach ( $validFooterIcons as $blockName => $footerIcons ) {
361  $html .= Html::openElement( 'div', [
362  'id' => Sanitizer::escapeIdForAttribute( "f-{$blockName}ico" ),
363  'class' => 'footer-icons'
364  ] );
365  foreach ( $footerIcons as $icon ) {
366  $html .= $this->getSkin()->makeFooterIcon( $icon );
367  }
368  $html .= Html::closeElement( 'div' );
369  }
370  if ( count( $validFooterLinks ) > 0 ) {
371  $html .= Html::openElement( 'ul', [ 'id' => 'f-list', 'class' => 'footer-places' ] );
372  foreach ( $validFooterLinks as $aLink ) {
373  $html .= Html::rawElement(
374  'li',
375  [ 'id' => Sanitizer::escapeIdForAttribute( $aLink ) ],
376  $this->get( $aLink )
377  );
378  }
379  $html .= Html::closeElement( 'ul' );
380  }
381 
382  $html .= $this->getClear() . $footerEnd;
383 
384  return $html;
385  }
386 
393  protected function getClear() {
394  return Html::element( 'div', [ 'class' => 'visualClear' ] );
395  }
396 
412  public function getIndicators() {
413  $out = "<div class=\"mw-indicators\">\n";
414  foreach ( $this->data['indicators'] as $id => $content ) {
415  $out .= Html::rawElement(
416  'div',
417  [
418  'id' => Sanitizer::escapeIdForAttribute( "mw-indicator-$id" ),
419  'class' => 'mw-indicator',
420  ],
421  $content
422  ) .
423  // Add whitespace between the <div>s because
424  // they get displayed with display: inline-block
425  "\n";
426  }
427  $out .= "</div>\n";
428  return $out;
429  }
430 
435  protected function printTrail() {
436  wfDeprecated( __METHOD__, '1.39' );
437  echo $this->getTrail();
438  }
439 
449  public function getTrail() {
450  wfDeprecated( __METHOD__, '1.39' );
451  $skin = $this->getSkin();
452  $options = $skin->getOptions();
453 
454  return $options['bodyOnly'] ? '' : WrappedString::join( "\n", [
455  MWDebug::getDebugHTML( $skin->getContext() ),
456  $this->get( 'bottomscripts' ),
457  $this->get( 'reporttime' )
458  ] );
459  }
460 }
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
Extended QuickTemplate with additional MediaWiki-specific helper methods.
getFooterLinks( $option=null)
Returns an array of footerlinks trimmed down to only those footer links that are valid.
makeSearchButton( $mode, $attrs=[])
renderAfterPortlet( $name)
getToolbox()
Create an array of common toolbox items from the data in the quicktemplate stored by SkinTemplate and...
getTrail()
Get the basic end-page trail including bottomscripts, reporttime, and debug stuff.
printTrail()
Output getTrail.
makeLink( $key, $item, $options=[])
getSidebar( $options=[])
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=[])
getMsg( $name,... $params)
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=[])
getFooter( $iconStyle='icononly', $linkStyle='flat')
Renderer for getFooterIcons and getFooterLinks.
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 element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:236
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:214
static openElement( $element, $attribs=[])
Identical to rawElement(), but has no third parameter and omits the end tag (and the self-closing '/'...
Definition: Html.php:256
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:320
static getDebugHTML(IContextSource $context)
Returns the HTML to add to the page for the toolbar.
Definition: MWDebug.php:618
PHP-based skin template that holds data.
getSkin()
Get the Skin object related to this object.
static escapeIdForAttribute( $id, $mode=self::ID_PRIMARY)
Given a section name or other user-generated or otherwise unsafe string, escapes it to be a valid HTM...
Definition: Sanitizer.php:945
$content
Definition: router.php:76