MediaWiki REL1_32
VectorTemplate.php
Go to the documentation of this file.
1<?php
30 /* Functions */
31
35 public function execute() {
36 $this->data['namespace_urls'] = $this->data['content_navigation']['namespaces'];
37 $this->data['view_urls'] = $this->data['content_navigation']['views'];
38 $this->data['action_urls'] = $this->data['content_navigation']['actions'];
39 $this->data['variant_urls'] = $this->data['content_navigation']['variants'];
40
41 // Move the watch/unwatch star outside of the collapsed "actions" menu to the main "views" menu
42 if ( $this->config->get( 'VectorUseIconWatch' ) ) {
43 $mode = $this->getSkin()->getUser()->isWatched( $this->getSkin()->getRelevantTitle() )
44 ? 'unwatch'
45 : 'watch';
46
47 if ( isset( $this->data['action_urls'][$mode] ) ) {
48 $this->data['view_urls'][$mode] = $this->data['action_urls'][$mode];
49 unset( $this->data['action_urls'][$mode] );
50 }
51 }
52 $this->data['pageLanguage'] =
53 $this->getSkin()->getTitle()->getPageViewLanguage()->getHtmlCode();
54
55 // Output HTML Page
56 $this->html( 'headelement' );
57 ?>
58 <div id="mw-page-base" class="noprint"></div>
59 <div id="mw-head-base" class="noprint"></div>
60 <div id="content" class="mw-body" role="main">
61 <a id="top"></a>
62 <?php
63 if ( $this->data['sitenotice'] ) {
64 echo Html::rawElement( 'div',
65 [
66 'id' => 'siteNotice',
67 'class' => 'mw-body-content',
68 ],
69 // Raw HTML
70 $this->get( 'sitenotice' )
71 );
72 }
73 if ( is_callable( [ $this, 'getIndicators' ] ) ) {
74 echo $this->getIndicators();
75 }
76 // Loose comparison with '!=' is intentional, to catch null and false too, but not '0'
77 if ( $this->data['title'] != '' ) {
78 echo Html::rawElement( 'h1',
79 [
80 'id' => 'firstHeading',
81 'class' => 'firstHeading',
82 'lang' => $this->get( 'pageLanguage' ),
83 ],
84 // Raw HTML
85 $this->get( 'title' )
86 );
87 }
88
89 $this->html( 'prebodyhtml' );
90 ?>
91 <div id="bodyContent" class="mw-body-content">
92 <?php
93 if ( $this->data['isarticle'] ) {
94 echo Html::element( 'div',
95 [
96 'id' => 'siteSub',
97 'class' => 'noprint',
98 ],
99 $this->getMsg( 'tagline' )->text()
100 );
101 }
102 ?>
103 <div id="contentSub"<?php $this->html( 'userlangattributes' ) ?>><?php
104 $this->html( 'subtitle' )
105 ?></div>
106 <?php
107 if ( $this->data['undelete'] ) {
108 echo Html::rawElement( 'div',
109 [ 'id' => 'contentSub2' ],
110 // Raw HTML
111 $this->get( 'undelete' )
112 );
113 }
114 if ( $this->data['newtalk'] ) {
115 echo Html::rawElement( 'div',
116 [ 'class' => 'usermessage' ],
117 // Raw HTML
118 $this->get( 'newtalk' )
119 );
120 }
121 // Keep this empty `div` for compatibility with gadgets and user scripts
122 // using this place to insert extra elements before.
123 echo Html::element( 'div', [ 'id' => 'jump-to-nav' ] );
124 ?>
125 <a class="mw-jump-link" href="#mw-head"><?php $this->msg( 'vector-jumptonavigation' ) ?></a>
126 <a class="mw-jump-link" href="#p-search"><?php $this->msg( 'vector-jumptosearch' ) ?></a>
127 <?php
128 $this->html( 'bodycontent' );
129
130 if ( $this->data['printfooter'] ) {
131 ?>
132 <div class="printfooter">
133 <?php $this->html( 'printfooter' ); ?>
134 </div>
135 <?php
136 }
137
138 if ( $this->data['catlinks'] ) {
139 $this->html( 'catlinks' );
140 }
141
142 if ( $this->data['dataAfterContent'] ) {
143 $this->html( 'dataAfterContent' );
144 }
145 ?>
146 <div class="visualClear"></div>
147 <?php $this->html( 'debughtml' ); ?>
148 </div>
149 </div>
150 <div id="mw-navigation">
151 <h2><?php $this->msg( 'navigation-heading' ) ?></h2>
152 <div id="mw-head">
153 <?php $this->renderNavigation( [ 'PERSONAL' ] ); ?>
154 <div id="left-navigation">
155 <?php $this->renderNavigation( [ 'NAMESPACES', 'VARIANTS' ] ); ?>
156 </div>
157 <div id="right-navigation">
158 <?php $this->renderNavigation( [ 'VIEWS', 'ACTIONS', 'SEARCH' ] ); ?>
159 </div>
160 </div>
161 <div id="mw-panel">
162 <div id="p-logo" role="banner"><a class="mw-wiki-logo" href="<?php
163 echo htmlspecialchars( $this->data['nav_urls']['mainpage']['href'] )
164 ?>" <?php
165 echo Xml::expandAttributes( Linker::tooltipAndAccesskeyAttribs( 'p-logo' ) )
166 ?>></a></div>
167 <?php $this->renderPortals( $this->data['sidebar'] ); ?>
168 </div>
169 </div>
170 <?php Hooks::run( 'VectorBeforeFooter' ); ?>
171 <div id="footer" role="contentinfo"<?php $this->html( 'userlangattributes' ) ?>>
172 <?php
173 foreach ( $this->getFooterLinks() as $category => $links ) {
174 ?>
175 <ul id="footer-<?php echo $category ?>">
176 <?php
177 foreach ( $links as $link ) {
178 ?>
179 <li id="footer-<?php echo $category ?>-<?php echo $link ?>"><?php $this->html( $link ) ?></li>
180 <?php
181 }
182 ?>
183 </ul>
184 <?php
185 }
186 ?>
187 <?php $footericons = $this->getFooterIcons( 'icononly' );
188 if ( count( $footericons ) > 0 ) {
189 ?>
190 <ul id="footer-icons" class="noprint">
191 <?php
192 foreach ( $footericons as $blockName => $footerIcons ) {
193 ?>
194 <li id="footer-<?php echo htmlspecialchars( $blockName ); ?>ico">
195 <?php
196 foreach ( $footerIcons as $icon ) {
197 echo $this->getSkin()->makeFooterIcon( $icon );
198 }
199 ?>
200 </li>
201 <?php
202 }
203 ?>
204 </ul>
205 <?php
206 }
207 ?>
208 <div style="clear: both;"></div>
209 </div>
210 <?php $this->printTrail(); ?>
211
212 </body>
213</html>
214<?php
215 }
216
222 protected function renderPortals( array $portals ) {
223 // Force the rendering of the following portals
224 if ( !isset( $portals['TOOLBOX'] ) ) {
225 $portals['TOOLBOX'] = true;
226 }
227 if ( !isset( $portals['LANGUAGES'] ) ) {
228 $portals['LANGUAGES'] = true;
229 }
230 // Render portals
231 foreach ( $portals as $name => $content ) {
232 if ( $content === false ) {
233 continue;
234 }
235
236 // Numeric strings gets an integer when set as key, cast back - T73639
237 $name = (string)$name;
238
239 switch ( $name ) {
240 case 'SEARCH':
241 break;
242 case 'TOOLBOX':
243 $this->renderPortal( 'tb', $this->getToolbox(), 'toolbox', 'SkinTemplateToolboxEnd' );
244 Hooks::run( 'VectorAfterToolbox' );
245 break;
246 case 'LANGUAGES':
247 if ( $this->data['language_urls'] !== false ) {
248 $this->renderPortal( 'lang', $this->data['language_urls'], 'otherlanguages' );
249 }
250 break;
251 default:
252 $this->renderPortal( $name, $content );
253 break;
254 }
255 }
256 }
257
264 protected function renderPortal( $name, $content, $msg = null, $hook = null ) {
265 if ( $msg === null ) {
266 $msg = $name;
267 }
268 $msgObj = $this->getMsg( $msg );
269 $labelId = Sanitizer::escapeIdForAttribute( "p-$name-label" );
270 ?>
271 <div class="portal" role="navigation" id="<?php
272 echo htmlspecialchars( Sanitizer::escapeIdForAttribute( "p-$name" ) )
273 ?>"<?php
274 echo Linker::tooltip( 'p-' . $name )
275 ?> aria-labelledby="<?php echo htmlspecialchars( $labelId ) ?>">
276 <h3<?php $this->html( 'userlangattributes' ) ?> id="<?php echo htmlspecialchars( $labelId )
277 ?>"><?php
278 echo htmlspecialchars( $msgObj->exists() ? $msgObj->text() : $msg );
279 ?></h3>
280 <div class="body">
281 <?php
282 if ( is_array( $content ) ) {
283 ?>
284 <ul>
285 <?php
286 foreach ( $content as $key => $val ) {
287 echo $this->makeListItem( $key, $val );
288 }
289 if ( $hook !== null ) {
290 // Avoid PHP 7.1 warning
291 $skin = $this;
292 Hooks::run( $hook, [ &$skin, true ] );
293 }
294 ?>
295 </ul>
296 <?php
297 } else {
298 // Allow raw HTML block to be defined by extensions
299 echo $content;
300 }
301
302 $this->renderAfterPortlet( $name );
303 ?>
304 </div>
305 </div>
306 <?php
307 }
308
315 protected function renderNavigation( array $elements ) {
316 // Render elements
317 foreach ( $elements as $name => $element ) {
318 switch ( $element ) {
319 case 'NAMESPACES':
320 ?>
321 <div id="p-namespaces" role="navigation" class="vectorTabs<?php
322 if ( count( $this->data['namespace_urls'] ) == 0 ) {
323 echo ' emptyPortlet';
324 }
325 ?>" aria-labelledby="p-namespaces-label">
326 <h3 id="p-namespaces-label"><?php $this->msg( 'namespaces' ) ?></h3>
327 <ul<?php $this->html( 'userlangattributes' ) ?>>
328 <?php
329 foreach ( $this->data['namespace_urls'] as $key => $item ) {
330 echo $this->makeListItem( $key, $item, [
331 'vector-wrap' => true,
332 ] );
333 }
334 ?>
335 </ul>
336 </div>
337 <?php
338 break;
339 case 'VARIANTS':
340 ?>
341 <div id="p-variants" role="navigation" class="vectorMenu<?php
342 if ( count( $this->data['variant_urls'] ) == 0 ) {
343 echo ' emptyPortlet';
344 }
345 ?>" aria-labelledby="p-variants-label">
346 <?php
347 // Replace the label with the name of currently chosen variant, if any
348 $variantLabel = $this->getMsg( 'variants' )->text();
349 foreach ( $this->data['variant_urls'] as $item ) {
350 if ( isset( $item['class'] ) && stripos( $item['class'], 'selected' ) !== false ) {
351 $variantLabel = $item['text'];
352 break;
353 }
354 }
355 ?>
356 <input type="checkbox" class="vectorMenuCheckbox" aria-labelledby="p-variants-label" />
357 <h3 id="p-variants-label">
358 <span><?php echo htmlspecialchars( $variantLabel ) ?></span>
359 </h3>
360 <div class="menu">
361 <ul>
362 <?php
363 foreach ( $this->data['variant_urls'] as $key => $item ) {
364 echo $this->makeListItem( $key, $item );
365 }
366 ?>
367 </ul>
368 </div>
369 </div>
370 <?php
371 break;
372 case 'VIEWS':
373 ?>
374 <div id="p-views" role="navigation" class="vectorTabs<?php
375 if ( count( $this->data['view_urls'] ) == 0 ) {
376 echo ' emptyPortlet';
377 }
378 ?>" aria-labelledby="p-views-label">
379 <h3 id="p-views-label"><?php $this->msg( 'views' ) ?></h3>
380 <ul<?php $this->html( 'userlangattributes' ) ?>>
381 <?php
382 foreach ( $this->data['view_urls'] as $key => $item ) {
383 echo $this->makeListItem( $key, $item, [
384 'vector-wrap' => true,
385 'vector-collapsible' => true,
386 ] );
387 }
388 ?>
389 </ul>
390 </div>
391 <?php
392 break;
393 case 'ACTIONS':
394 ?>
395 <div id="p-cactions" role="navigation" class="vectorMenu<?php
396 if ( count( $this->data['action_urls'] ) == 0 ) {
397 echo ' emptyPortlet';
398 }
399 ?>" aria-labelledby="p-cactions-label">
400 <input type="checkbox" class="vectorMenuCheckbox" aria-labelledby="p-cactions-label" />
401 <h3 id="p-cactions-label"><span><?php
402 $this->msg( 'vector-more-actions' )
403 ?></span></h3>
404 <div class="menu">
405 <ul<?php $this->html( 'userlangattributes' ) ?>>
406 <?php
407 foreach ( $this->data['action_urls'] as $key => $item ) {
408 echo $this->makeListItem( $key, $item );
409 }
410 ?>
411 </ul>
412 </div>
413 </div>
414 <?php
415 break;
416 case 'PERSONAL':
417 ?>
418 <div id="p-personal" role="navigation" class="<?php
419 if ( count( $this->data['personal_urls'] ) == 0 ) {
420 echo ' emptyPortlet';
421 }
422 ?>" aria-labelledby="p-personal-label">
423 <h3 id="p-personal-label"><?php $this->msg( 'personaltools' ) ?></h3>
424 <ul<?php $this->html( 'userlangattributes' ) ?>>
425 <?php
426 $notLoggedIn = '';
427
428 if ( !$this->getSkin()->getUser()->isLoggedIn() &&
429 User::groupHasPermission( '*', 'edit' )
430 ) {
431 $notLoggedIn =
432 Html::element( 'li',
433 [ 'id' => 'pt-anonuserpage' ],
434 $this->getMsg( 'notloggedin' )->text()
435 );
436 }
437
438 $personalTools = $this->getPersonalTools();
439
440 $langSelector = '';
441 if ( array_key_exists( 'uls', $personalTools ) ) {
442 $langSelector = $this->makeListItem( 'uls', $personalTools[ 'uls' ] );
443 unset( $personalTools[ 'uls' ] );
444 }
445
446 echo $langSelector;
447 echo $notLoggedIn;
448 foreach ( $personalTools as $key => $item ) {
449 echo $this->makeListItem( $key, $item );
450 }
451 ?>
452 </ul>
453 </div>
454 <?php
455 break;
456 case 'SEARCH':
457 ?>
458 <div id="p-search" role="search">
459 <h3<?php $this->html( 'userlangattributes' ) ?>>
460 <label for="searchInput"><?php $this->msg( 'search' ) ?></label>
461 </h3>
462 <form action="<?php $this->text( 'wgScript' ) ?>" id="searchform">
463 <div<?php echo $this->config->get( 'VectorUseSimpleSearch' ) ? ' id="simpleSearch"' : '' ?>>
464 <?php
465 echo $this->makeSearchInput( [ 'id' => 'searchInput' ] );
466 echo Html::hidden( 'title', $this->get( 'searchtitle' ) );
467 /* We construct two buttons (for 'go' and 'fulltext' search modes),
468 * but only one will be visible and actionable at a time (they are
469 * overlaid on top of each other in CSS).
470 * * Browsers will use the 'fulltext' one by default (as it's the
471 * first in tree-order), which is desirable when they are unable
472 * to show search suggestions (either due to being broken or
473 * having JavaScript turned off).
474 * * The mediawiki.searchSuggest module, after doing tests for the
475 * broken browsers, removes the 'fulltext' button and handles
476 * 'fulltext' search itself; this will reveal the 'go' button and
477 * cause it to be used.
478 */
479 echo $this->makeSearchButton(
480 'fulltext',
481 [ 'id' => 'mw-searchButton', 'class' => 'searchButton mw-fallbackSearchButton' ]
482 );
483 echo $this->makeSearchButton(
484 'go',
485 [ 'id' => 'searchButton', 'class' => 'searchButton' ]
486 );
487 ?>
488 </div>
489 </form>
490 </div>
491 <?php
492
493 break;
494 }
495 }
496 }
497
501 public function makeLink( $key, $item, $options = [] ) {
502 $html = parent::makeLink( $key, $item, $options );
503 // Add an extra wrapper because our CSS is weird
504 if ( isset( $options['vector-wrap'] ) && $options['vector-wrap'] ) {
505 $html = Html::rawElement( 'span', [], $html );
506 }
507 return $html;
508 }
509
513 public function makeListItem( $key, $item, $options = [] ) {
514 // For fancy styling of watch/unwatch star
515 if (
516 $this->config->get( 'VectorUseIconWatch' )
517 && ( $key === 'watch' || $key === 'unwatch' )
518 ) {
519 $item['class'] = rtrim( 'icon ' . $item['class'], ' ' );
520 $item['primary'] = true;
521 }
522
523 // Add CSS class 'collapsible' to links which are not marked as "primary"
524 if (
525 isset( $options['vector-collapsible'] ) && $options['vector-collapsible'] ) {
526 $item['class'] = rtrim( 'collapsible ' . $item['class'], ' ' );
527 }
528
529 // We don't use this, prevent it from popping up in HTML output
530 unset( $item['redundant'] );
531
532 return parent::makeListItem( $key, $item, $options );
533 }
534}
shown</td >< td > a href
This list may contain false positives That usually means there is additional text with links below the first Each row contains links to the first and second as well as the first line of the second redirect text
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=[])
renderAfterPortlet( $name)
getToolbox()
Create an array of common toolbox items from the data in the quicktemplate stored by SkinTemplate.
printTrail()
Output getTrail.
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 ...
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=[])
static tooltip( $name, $options=null)
Returns raw bits of HTML, use titleAttrib()
Definition Linker.php:2161
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[], $options=null)
Returns the attributes for the tooltip and access key.
Definition Linker.php:2133
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:5013
QuickTemplate subclass for Vector.
makeLink( $key, $item, $options=[])
@inheritDoc
makeListItem( $key, $item, $options=[])
@inheritDoc
renderNavigation(array $elements)
Render one or more navigations elements by name, automatically reversed by css when UI is in RTL mode...
renderPortals(array $portals)
Render a series of portals.
execute()
Outputs the entire contents of the (X)HTML page.
renderPortal( $name, $content, $msg=null, $hook=null)
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:2050
null means default in associative array form
Definition hooks.txt:2045
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:2062
usually copyright or history_copyright This message must be in HTML not wikitext & $link
Definition hooks.txt:3106
Allows to change the fields on the form that will be generated $name
Definition hooks.txt:302
The wiki should then use memcached to cache various data To use multiple just add more items to the array To increase the weight of a make its entry a array("192.168.0.1:11211", 2))
$content
This document describes the state of Postgres support in and is fairly well maintained The main code is very well while extensions are very hit and miss it is probably the most supported database after MySQL Much of the work in making MediaWiki database agnostic came about through the work of creating Postgres as and are nearing end of but without copying over all the usage comments General notes on the but these can almost always be programmed around *Although Postgres has a true BOOLEAN type
Definition postgres.txt:36
Bar style