MediaWiki  master
BaseTemplate.php
Go to the documentation of this file.
1 <?php
21 use Wikimedia\WrappedString;
22 use Wikimedia\WrappedStringList;
23 
31 abstract class BaseTemplate extends QuickTemplate {
32 
40  public function getMsg( $name, ...$params ) {
41  return $this->getSkin()->msg( $name, ...$params );
42  }
43 
44  public function msg( $str ) {
45  echo $this->getMsg( $str )->escaped();
46  }
47 
59  public function getToolbox() {
60  wfDeprecated( __METHOD__, '1.35' );
61 
62  $toolbox = $this->getSkin()->makeToolbox(
63  $this->data['nav_urls'],
64  $this->data['feeds']
65  );
66 
67  // Merge content that might be added to the toolbox section by hook
68  if ( isset( $this->data['sidebar']['TOOLBOX'] ) ) {
69  $toolbox = array_merge( $toolbox, $this->data['sidebar']['TOOLBOX'] ?? [] );
70  }
71 
72  return $toolbox;
73  }
74 
79  public function getPersonalTools() {
80  return $this->getSkin()->getPersonalToolsForMakeListItem( $this->get( 'personal_urls' ) );
81  }
82 
88  protected function getSidebar( $options = [] ) {
89  // Force the rendering of the following portals
90  $sidebar = $this->data['sidebar'];
91  if ( !isset( $sidebar['SEARCH'] ) ) {
92  $sidebar['SEARCH'] = true;
93  }
94  if ( !isset( $sidebar['TOOLBOX'] ) ) {
95  $sidebar['TOOLBOX'] = true;
96  }
97  if ( !isset( $sidebar['LANGUAGES'] ) ) {
98  $sidebar['LANGUAGES'] = true;
99  }
100 
101  if ( !isset( $options['search'] ) || $options['search'] !== true ) {
102  unset( $sidebar['SEARCH'] );
103  }
104  if ( isset( $options['toolbox'] ) && $options['toolbox'] === false ) {
105  unset( $sidebar['TOOLBOX'] );
106  }
107  if ( isset( $options['languages'] ) && $options['languages'] === false ) {
108  unset( $sidebar['LANGUAGES'] );
109  }
110 
111  $boxes = [];
112  foreach ( $sidebar as $boxName => $content ) {
113  if ( $content === false ) {
114  continue;
115  }
116  switch ( $boxName ) {
117  case 'SEARCH':
118  // Search is a special case, skins should custom implement this
119  $boxes[$boxName] = [
120  'id' => 'p-search',
121  'header' => $this->getMsg( 'search' )->text(),
122  'generated' => false,
123  'content' => true,
124  ];
125  break;
126  case 'TOOLBOX':
127  $msgObj = $this->getMsg( 'toolbox' );
128  $boxes[$boxName] = [
129  'id' => 'p-tb',
130  'header' => $msgObj->exists() ? $msgObj->text() : 'toolbox',
131  'generated' => false,
132  'content' => $content,
133  ];
134  break;
135  case 'LANGUAGES':
136  if ( $this->data['language_urls'] !== false ) {
137  $msgObj = $this->getMsg( 'otherlanguages' );
138  $boxes[$boxName] = [
139  'id' => 'p-lang',
140  'header' => $msgObj->exists() ? $msgObj->text() : 'otherlanguages',
141  'generated' => false,
142  'content' => $this->data['language_urls'] ?: [],
143  ];
144  }
145  break;
146  default:
147  $msgObj = $this->getMsg( $boxName );
148  $boxes[$boxName] = [
149  'id' => "p-$boxName",
150  'header' => $msgObj->exists() ? $msgObj->text() : $boxName,
151  'generated' => true,
152  'content' => $content,
153  ];
154  break;
155  }
156  }
157 
158  // HACK: Compatibility with extensions still using SkinTemplateToolboxEnd
159  $hookContents = null;
160  if ( isset( $boxes['TOOLBOX'] ) ) {
161  ob_start();
162  // We pass an extra 'true' at the end so extensions using BaseTemplateToolbox
163  // (removed 1.37) can abort and avoid outputting double toolbox links
164  $this->getHookRunner()->onSkinTemplateToolboxEnd( $this, true );
165  $hookContents = ob_get_contents();
166  ob_end_clean();
167  if ( !trim( $hookContents ) ) {
168  $hookContents = null;
169  }
170  }
171  // END hack
172 
173  if ( isset( $options['htmlOnly'] ) && $options['htmlOnly'] === true ) {
174  foreach ( $boxes as $boxName => $box ) {
175  if ( is_array( $box['content'] ) ) {
176  $content = '<ul>';
177  foreach ( $box['content'] as $key => $val ) {
178  $content .= "\n " . $this->getSkin()->makeListItem( $key, $val );
179  }
180  // HACK, shove the toolbox end onto the toolbox if we're rendering itself
181  if ( $hookContents ) {
182  $content .= "\n $hookContents";
183  }
184  // END hack
185  $content .= "\n</ul>\n";
186  $boxes[$boxName]['content'] = $content;
187  }
188  }
189  } elseif ( $hookContents ) {
190  $boxes['TOOLBOXEND'] = [
191  'id' => 'p-toolboxend',
192  'header' => $boxes['TOOLBOX']['header'],
193  'generated' => false,
194  'content' => "<ul>{$hookContents}</ul>",
195  ];
196  // HACK: Make sure that TOOLBOXEND is sorted next to TOOLBOX
197  $boxes2 = [];
198  foreach ( $boxes as $key => $box ) {
199  if ( $key === 'TOOLBOXEND' ) {
200  continue;
201  }
202  $boxes2[$key] = $box;
203  if ( $key === 'TOOLBOX' ) {
204  $boxes2['TOOLBOXEND'] = $boxes['TOOLBOXEND'];
205  }
206  }
207  $boxes = $boxes2;
208  // END hack
209  }
210 
211  return $boxes;
212  }
213 
218  protected function renderAfterPortlet( $name ) {
219  wfDeprecated( __METHOD__, '1.35' );
220  echo $this->getAfterPortlet( $name );
221  }
222 
233  protected function getAfterPortlet( $name ) {
234  wfDeprecated( __METHOD__, '1.35' );
235  $html = '';
236  $content = '';
237  $this->getHookRunner()->onBaseTemplateAfterPortlet( $this, $name, $content );
238  $content .= $this->getSkin()->getAfterPortlet( $name );
239 
240  if ( $content !== '' ) {
241  $html = Html::rawElement(
242  'div',
243  [ 'class' => [ 'after-portlet', 'after-portlet-' . $name ] ],
244  $content
245  );
246  }
247 
248  return $html;
249  }
250 
255  protected function makeLink( $key, $item, $options = [] ) {
256  return $this->getSkin()->makeLink( $key, $item, $options );
257  }
258 
263  public function makeListItem( $key, $item, $options = [] ) {
264  return $this->getSkin()->makeListItem( $key, $item, $options );
265  }
266 
270  protected function makeSearchInput( $attrs = [] ) {
271  return $this->getSkin()->makeSearchInput( $attrs );
272  }
273 
277  protected function makeSearchButton( $mode, $attrs = [] ) {
278  return $this->getSkin()->makeSearchButton( $mode, $attrs );
279  }
280 
290  protected function getFooterLinks( $option = null ) {
291  $footerlinks = $this->get( 'footerlinks' );
292 
293  // Reduce footer links down to only those which are being used
294  $validFooterLinks = [];
295  foreach ( $footerlinks as $category => $links ) {
296  $validFooterLinks[$category] = [];
297  foreach ( $links as $link ) {
298  if ( isset( $this->data[$link] ) && $this->data[$link] ) {
299  $validFooterLinks[$category][] = $link;
300  }
301  }
302  if ( count( $validFooterLinks[$category] ) <= 0 ) {
303  unset( $validFooterLinks[$category] );
304  }
305  }
306 
307  if ( $option == 'flat' && count( $validFooterLinks ) ) {
308  // fold footerlinks into a single array using a bit of trickery
309  $validFooterLinks = array_merge( ...array_values( $validFooterLinks ) );
310  }
311 
312  return $validFooterLinks;
313  }
314 
329  protected function getFooterIcons( $option = null ) {
330  wfDeprecated( __METHOD__, '1.35' );
331  // Generate additional footer icons
332  $footericons = $this->get( 'footericons' );
333 
334  if ( $option == 'icononly' ) {
335  // Unset any icons which don't have an image
336  foreach ( $footericons as $footerIconsKey => &$footerIconsBlock ) {
337  foreach ( $footerIconsBlock as $footerIconKey => $footerIcon ) {
338  if ( !is_string( $footerIcon ) && !isset( $footerIcon['src'] ) ) {
339  unset( $footerIconsBlock[$footerIconKey] );
340  }
341  }
342  if ( $footerIconsBlock === [] ) {
343  unset( $footericons[$footerIconsKey] );
344  }
345  }
346  } elseif ( $option == 'nocopyright' ) {
347  unset( $footericons['copyright'] );
348  }
349 
350  return $footericons;
351  }
352 
362  protected function getFooter( $iconStyle = 'icononly', $linkStyle = 'flat' ) {
363  $validFooterIcons = $this->getFooterIcons( $iconStyle );
364  $validFooterLinks = $this->getFooterLinks( $linkStyle );
365 
366  $html = '';
367 
368  if ( count( $validFooterIcons ) + count( $validFooterLinks ) > 0 ) {
369  $html .= Html::openElement( 'div', [
370  'id' => 'footer-bottom',
371  'class' => 'mw-footer',
372  'role' => 'contentinfo',
373  'lang' => $this->get( 'userlang' ),
374  'dir' => $this->get( 'dir' )
375  ] );
376  $footerEnd = Html::closeElement( 'div' );
377  } else {
378  $footerEnd = '';
379  }
380  foreach ( $validFooterIcons as $blockName => $footerIcons ) {
381  $html .= Html::openElement( 'div', [
382  'id' => Sanitizer::escapeIdForAttribute( "f-{$blockName}ico" ),
383  'class' => 'footer-icons'
384  ] );
385  foreach ( $footerIcons as $icon ) {
386  $html .= $this->getSkin()->makeFooterIcon( $icon );
387  }
388  $html .= Html::closeElement( 'div' );
389  }
390  if ( count( $validFooterLinks ) > 0 ) {
391  $html .= Html::openElement( 'ul', [ 'id' => 'f-list', 'class' => 'footer-places' ] );
392  foreach ( $validFooterLinks as $aLink ) {
393  $html .= Html::rawElement(
394  'li',
395  [ 'id' => Sanitizer::escapeIdForAttribute( $aLink ) ],
396  $this->get( $aLink )
397  );
398  }
399  $html .= Html::closeElement( 'ul' );
400  }
401 
402  $html .= $this->getClear() . $footerEnd;
403 
404  return $html;
405  }
406 
413  protected function getClear() {
414  return Html::element( 'div', [ 'class' => 'visualClear' ] );
415  }
416 
432  public function getIndicators() {
433  $out = "<div class=\"mw-indicators\">\n";
434  foreach ( $this->data['indicators'] as $id => $content ) {
435  $out .= Html::rawElement(
436  'div',
437  [
438  'id' => Sanitizer::escapeIdForAttribute( "mw-indicator-$id" ),
439  'class' => 'mw-indicator',
440  ],
441  $content
442  ) . "\n";
443  }
444  $out .= "</div>\n";
445  return $out;
446  }
447 
451  protected function printTrail() {
452  echo $this->getTrail();
453  }
454 
463  public function getTrail() {
464  return WrappedString::join( "\n", [
466  $this->get( 'bottomscripts' ),
467  $this->get( 'reporttime' )
468  ] );
469  }
470 }
BaseTemplate\getPersonalTools
getPersonalTools()
Definition: BaseTemplate.php:79
BaseTemplate\getFooterLinks
getFooterLinks( $option=null)
Returns an array of footerlinks trimmed down to only those footer links that are valid.
Definition: BaseTemplate.php:290
BaseTemplate\msg
msg( $str)
Definition: BaseTemplate.php:44
MWDebug\getDebugHTML
static getDebugHTML(IContextSource $context)
Returns the HTML to add to the page for the toolbar.
Definition: MWDebug.php:609
BaseTemplate\makeSearchButton
makeSearchButton( $mode, $attrs=[])
Definition: BaseTemplate.php:277
Sanitizer\escapeIdForAttribute
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:811
BaseTemplate\getClear
getClear()
Get a div with the core visualClear class, for clearing floats.
Definition: BaseTemplate.php:413
getContext
getContext()
QuickTemplate\getSkin
getSkin()
Get the Skin object related to this object.
Definition: QuickTemplate.php:139
Html\closeElement
static closeElement( $element)
Returns "</$element>".
Definition: Html.php:316
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
Definition: GlobalFunctions.php:996
BaseTemplate\getAfterPortlet
getAfterPortlet( $name)
Allows extensions to hook into known portlets and add stuff to them.
Definition: BaseTemplate.php:233
BaseTemplate\printTrail
printTrail()
Output getTrail.
Definition: BaseTemplate.php:451
BaseTemplate\makeListItem
makeListItem( $key, $item, $options=[])
Definition: BaseTemplate.php:263
BaseTemplate\getIndicators
getIndicators()
Get the suggested HTML for page status indicators: icons (or short text snippets) usually displayed i...
Definition: BaseTemplate.php:432
BaseTemplate\getFooter
getFooter( $iconStyle='icononly', $linkStyle='flat')
Renderer for getFooterIcons and getFooterLinks.
Definition: BaseTemplate.php:362
$content
$content
Definition: router.php:76
BaseTemplate\renderAfterPortlet
renderAfterPortlet( $name)
Definition: BaseTemplate.php:218
BaseTemplate\makeSearchInput
makeSearchInput( $attrs=[])
Definition: BaseTemplate.php:270
QuickTemplate
Generic wrapper for template functions, with interface compatible with what we use of PHPTAL 0....
Definition: QuickTemplate.php:30
BaseTemplate\getToolbox
getToolbox()
Create an array of common toolbox items from the data in the quicktemplate stored by SkinTemplate and...
Definition: BaseTemplate.php:59
BaseTemplate\getTrail
getTrail()
Get the basic end-page trail including bottomscripts, reporttime, and debug stuff.
Definition: BaseTemplate.php:463
BaseTemplate\getMsg
getMsg( $name,... $params)
Get a Message object with its context set.
Definition: BaseTemplate.php:40
Html\openElement
static openElement( $element, $attribs=[])
Identical to rawElement(), but has no third parameter and omits the end tag (and the self-closing '/'...
Definition: Html.php:252
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:210
BaseTemplate\makeLink
makeLink( $key, $item, $options=[])
Definition: BaseTemplate.php:255
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:232
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:329
BaseTemplate
New base template for a skin's template extended from QuickTemplate this class features helper method...
Definition: BaseTemplate.php:31
BaseTemplate\getSidebar
getSidebar( $options=[])
Definition: BaseTemplate.php:88