MediaWiki master
BaseTemplate.php
Go to the documentation of this file.
1<?php
7namespace MediaWiki\Skin;
8
14
24abstract class BaseTemplate extends QuickTemplate {
25
35 public function getMsg( $name, ...$params ) {
36 return $this->getSkin()->msg( $name, ...$params );
37 }
38
42 public function msg( $str ) {
43 echo $this->getMsg( $str )->escaped();
44 }
45
49 public function getPersonalTools() {
50 return $this->getSkin()->getPersonalToolsForMakeListItem( $this->get( 'personal_urls' ) );
51 }
52
58 protected function getSidebar( $options = [] ) {
59 // Force the rendering of the following portals
60 $sidebar = $this->data['sidebar'];
61 if ( !isset( $sidebar['SEARCH'] ) ) {
62 // @phan-suppress-next-line PhanTypeMismatchDimAssignment False positive
63 $sidebar['SEARCH'] = true;
64 }
65 if ( !isset( $sidebar['TOOLBOX'] ) ) {
66 $sidebar['TOOLBOX'] = true;
67 }
68 if ( !isset( $sidebar['LANGUAGES'] ) ) {
69 $sidebar['LANGUAGES'] = true;
70 }
71
72 if ( !isset( $options['search'] ) || $options['search'] !== true ) {
73 unset( $sidebar['SEARCH'] );
74 }
75 if ( isset( $options['toolbox'] ) && $options['toolbox'] === false ) {
76 unset( $sidebar['TOOLBOX'] );
77 }
78 if ( isset( $options['languages'] ) && $options['languages'] === false ) {
79 unset( $sidebar['LANGUAGES'] );
80 }
81
82 $boxes = [];
83 foreach ( $sidebar as $boxName => $content ) {
84 if ( $content === false ) {
85 continue;
86 }
87 switch ( $boxName ) {
88 case 'SEARCH':
89 // Search is a special case, skins should custom implement this
90 $boxes[$boxName] = [
91 'id' => 'p-search',
92 'header' => $this->getMsg( 'search' )->text(),
93 'generated' => false,
94 'content' => true,
95 ];
96 break;
97 case 'TOOLBOX':
98 $msgObj = $this->getMsg( 'toolbox' );
99 $boxes[$boxName] = [
100 'id' => 'p-tb',
101 'header' => $msgObj->exists() ? $msgObj->text() : 'toolbox',
102 'generated' => false,
103 'content' => $content,
104 ];
105 break;
106 case 'LANGUAGES':
107 if ( $this->data['language_urls'] !== false ) {
108 $msgObj = $this->getMsg( 'otherlanguages' );
109 $boxes[$boxName] = [
110 'id' => 'p-lang',
111 'header' => $msgObj->exists() ? $msgObj->text() : 'otherlanguages',
112 'generated' => false,
113 'content' => $this->data['language_urls'] ?: [],
114 ];
115 }
116 break;
117 default:
118 $msgObj = $this->getMsg( $boxName );
119 $boxes[$boxName] = [
120 'id' => "p-$boxName",
121 'header' => $msgObj->exists() ? $msgObj->text() : $boxName,
122 'generated' => true,
123 'content' => $content,
124 ];
125 break;
126 }
127 }
128
129 if ( isset( $options['htmlOnly'] ) && $options['htmlOnly'] === true ) {
130 foreach ( $boxes as $boxName => $box ) {
131 if ( is_array( $box['content'] ) ) {
132 $content = '<ul>';
133 foreach ( $box['content'] as $key => $val ) {
134 $content .= "\n " . $this->getSkin()->makeListItem( $key, $val );
135 }
136 $content .= "\n</ul>\n";
137 $boxes[$boxName]['content'] = $content;
138 }
139 }
140 }
141
142 return $boxes;
143 }
144
153 protected function makeLink( $key, $item, $options = [] ) {
154 return $this->getSkin()->makeLink( $key, $item, $options );
155 }
156
165 public function makeListItem( $key, $item, $options = [] ) {
166 return $this->getSkin()->makeListItem( $key, $item, $options );
167 }
168
175 protected function makeSearchInput( $attrs = [] ) {
176 return $this->getSkin()->makeSearchInput( $attrs );
177 }
178
186 protected function makeSearchButton( $mode, $attrs = [] ) {
187 return $this->getSkin()->makeSearchButton( $mode, $attrs );
188 }
189
199 protected function getFooterLinks( $option = null ) {
200 $footerlinks = $this->get( 'footerlinks' );
201
202 // Reduce footer links down to only those which are being used
203 $validFooterLinks = [];
204 foreach ( $footerlinks as $category => $links ) {
205 $validFooterLinks[$category] = [];
206 foreach ( $links as $link ) {
207 if ( isset( $this->data[$link] ) && $this->data[$link] ) {
208 $validFooterLinks[$category][] = $link;
209 }
210 }
211 if ( count( $validFooterLinks[$category] ) <= 0 ) {
212 unset( $validFooterLinks[$category] );
213 }
214 }
215
216 if ( $option == 'flat' && count( $validFooterLinks ) ) {
217 // fold footerlinks into a single array using a bit of trickery
218 $validFooterLinks = array_merge( ...array_values( $validFooterLinks ) );
219 }
220
221 return $validFooterLinks;
222 }
223
228 private function unsetIconsWithoutImages( array &$icons ) {
229 // Unset any icons which don't have an image
230 foreach ( $icons as $iconsKey => &$iconsBlock ) {
231 foreach ( $iconsBlock as $iconKey => $icon ) {
232 if ( !is_string( $icon ) && !isset( $icon['src'] ) ) {
233 unset( $iconsBlock[$iconKey] );
234 }
235 }
236 if ( $iconsBlock === [] ) {
237 unset( $icons[$iconsKey] );
238 }
239 }
240 }
241
252 protected function getFooter( $iconStyle = 'icononly', $linkStyle = 'flat' ) {
253 $validFooterIcons = $this->get( 'footericons' );
254 if ( $iconStyle === 'icononly' ) {
255 $this->unsetIconsWithoutImages( $validFooterIcons );
256 }
257 $validFooterLinks = $this->getFooterLinks( $linkStyle );
258
259 $html = '';
260
261 if ( count( $validFooterIcons ) + count( $validFooterLinks ) > 0 ) {
262 $html .= Html::openElement( 'div', [
263 'id' => 'footer-bottom',
264 'class' => 'mw-footer',
265 'role' => 'contentinfo',
266 'lang' => $this->get( 'userlang' ),
267 'dir' => $this->get( 'dir' )
268 ] );
269 $footerEnd = Html::closeElement( 'div' );
270 } else {
271 $footerEnd = '';
272 }
273 foreach ( $validFooterIcons as $blockName => $footerIcons ) {
274 $html .= Html::openElement( 'div', [
275 'id' => Sanitizer::escapeIdForAttribute( "f-{$blockName}ico" ),
276 'class' => 'footer-icons'
277 ] );
278 foreach ( $footerIcons as $icon ) {
279 $html .= $this->getSkin()->makeFooterIcon( $icon );
280 }
281 $html .= Html::closeElement( 'div' );
282 }
283 if ( count( $validFooterLinks ) > 0 ) {
284 $html .= Html::openElement( 'ul', [ 'id' => 'f-list', 'class' => 'footer-places' ] );
285 foreach ( $validFooterLinks as $aLink ) {
286 $html .= Html::rawElement(
287 'li',
288 [ 'id' => Sanitizer::escapeIdForAttribute( $aLink ) ],
289 $this->get( $aLink )
290 );
291 }
292 $html .= Html::closeElement( 'ul' );
293 }
294
295 $html .= $this->getClear() . $footerEnd;
296
297 return $html;
298 }
299
306 protected function getClear() {
307 return Html::element( 'div', [ 'class' => 'visualClear' ] );
308 }
309
325 public function getIndicators() {
326 $out = "<div class=\"mw-indicators\">\n";
327 foreach ( $this->data['indicators'] as $id => $content ) {
328 $out .= Html::rawElement(
329 'div',
330 [
331 'id' => Sanitizer::escapeIdForAttribute( "mw-indicator-$id" ),
332 'class' => 'mw-indicator',
333 ],
334 $content
335 ) .
336 // Add whitespace between the <div>s because
337 // they get displayed with display: inline-block
338 "\n";
339 }
340 $out .= "</div>\n";
341 return $out;
342 }
343}
344
346class_alias( BaseTemplate::class, 'BaseTemplate' );
This class is a collection of static functions that serve two purposes:
Definition Html.php:43
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition Message.php:144
HTML sanitizer for MediaWiki.
Definition Sanitizer.php:32
Extended QuickTemplate with additional MediaWiki-specific helper methods.
makeSearchInput( $attrs=[])
Wrapper for Skin method.
getIndicators()
Get the suggested HTML for page status indicators: icons (or short text snippets) usually displayed i...
getClear()
Get a div with the core visualClear class, for clearing floats.
makeLink( $key, $item, $options=[])
Wrapper for Skin method.
makeListItem( $key, $item, $options=[])
Wrapper for Skin method.
getFooterLinks( $option=null)
Returns an array of footerlinks trimmed down to only those footer links that are valid.
makeSearchButton( $mode, $attrs=[])
Wrapper for Skin method.
getFooter( $iconStyle='icononly', $linkStyle='flat')
Renderer for getFooterLinks.
getMsg( $name,... $params)
Get a Message object with its context set.
PHP-based skin template that holds data.
getSkin()
Get the Skin object related to this object.
Value object representing a message parameter that consists of a list of values.
element(SerializerNode $parent, SerializerNode $node, $contents)