MediaWiki REL1_31
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 ?>
122 <div id="jump-to-nav" class="mw-jump">
123 <?php $this->msg( 'jumpto' ) ?>
124 <a href="#mw-head"><?php
125 $this->msg( 'jumptonavigation' )
126 ?></a><?php $this->msg( 'comma-separator' ) ?>
127 <a href="#p-search"><?php $this->msg( 'jumptosearch' ) ?></a>
128 </div>
129 <?php
130 $this->html( 'bodycontent' );
131
132 if ( $this->data['printfooter'] ) {
133 ?>
134 <div class="printfooter">
135 <?php $this->html( 'printfooter' ); ?>
136 </div>
137 <?php
138 }
139
140 if ( $this->data['catlinks'] ) {
141 $this->html( 'catlinks' );
142 }
143
144 if ( $this->data['dataAfterContent'] ) {
145 $this->html( 'dataAfterContent' );
146 }
147 ?>
148 <div class="visualClear"></div>
149 <?php $this->html( 'debughtml' ); ?>
150 </div>
151 </div>
152 <div id="mw-navigation">
153 <h2><?php $this->msg( 'navigation-heading' ) ?></h2>
154 <div id="mw-head">
155 <?php $this->renderNavigation( [ 'PERSONAL' ] ); ?>
156 <div id="left-navigation">
157 <?php $this->renderNavigation( [ 'NAMESPACES', 'VARIANTS' ] ); ?>
158 </div>
159 <div id="right-navigation">
160 <?php $this->renderNavigation( [ 'VIEWS', 'ACTIONS', 'SEARCH' ] ); ?>
161 </div>
162 </div>
163 <div id="mw-panel">
164 <div id="p-logo" role="banner"><a class="mw-wiki-logo" href="<?php
165 echo htmlspecialchars( $this->data['nav_urls']['mainpage']['href'] )
166 ?>" <?php
167 echo Xml::expandAttributes( Linker::tooltipAndAccesskeyAttribs( 'p-logo' ) )
168 ?>></a></div>
169 <?php $this->renderPortals( $this->data['sidebar'] ); ?>
170 </div>
171 </div>
172 <?php Hooks::run( 'VectorBeforeFooter' ); ?>
173 <div id="footer" role="contentinfo"<?php $this->html( 'userlangattributes' ) ?>>
174 <?php
175 foreach ( $this->getFooterLinks() as $category => $links ) {
176 ?>
177 <ul id="footer-<?php echo $category ?>">
178 <?php
179 foreach ( $links as $link ) {
180 ?>
181 <li id="footer-<?php echo $category ?>-<?php echo $link ?>"><?php $this->html( $link ) ?></li>
182 <?php
183 }
184 ?>
185 </ul>
186 <?php
187 }
188 ?>
189 <?php $footericons = $this->getFooterIcons( 'icononly' );
190 if ( count( $footericons ) > 0 ) {
191 ?>
192 <ul id="footer-icons" class="noprint">
193 <?php
194 foreach ( $footericons as $blockName => $footerIcons ) {
195 ?>
196 <li id="footer-<?php echo htmlspecialchars( $blockName ); ?>ico">
197 <?php
198 foreach ( $footerIcons as $icon ) {
199 echo $this->getSkin()->makeFooterIcon( $icon );
200 }
201 ?>
202 </li>
203 <?php
204 }
205 ?>
206 </ul>
207 <?php
208 }
209 ?>
210 <div style="clear: both;"></div>
211 </div>
212 <?php $this->printTrail(); ?>
213
214 </body>
215</html>
216<?php
217 }
218
224 protected function renderPortals( array $portals ) {
225 // Force the rendering of the following portals
226 if ( !isset( $portals['TOOLBOX'] ) ) {
227 $portals['TOOLBOX'] = true;
228 }
229 if ( !isset( $portals['LANGUAGES'] ) ) {
230 $portals['LANGUAGES'] = true;
231 }
232 // Render portals
233 foreach ( $portals as $name => $content ) {
234 if ( $content === false ) {
235 continue;
236 }
237
238 // Numeric strings gets an integer when set as key, cast back - T73639
239 $name = (string)$name;
240
241 switch ( $name ) {
242 case 'SEARCH':
243 break;
244 case 'TOOLBOX':
245 $this->renderPortal( 'tb', $this->getToolbox(), 'toolbox', 'SkinTemplateToolboxEnd' );
246 Hooks::run( 'VectorAfterToolbox' );
247 break;
248 case 'LANGUAGES':
249 if ( $this->data['language_urls'] !== false ) {
250 $this->renderPortal( 'lang', $this->data['language_urls'], 'otherlanguages' );
251 }
252 break;
253 default:
254 $this->renderPortal( $name, $content );
255 break;
256 }
257 }
258 }
259
266 protected function renderPortal( $name, $content, $msg = null, $hook = null ) {
267 if ( $msg === null ) {
268 $msg = $name;
269 }
270 $msgObj = wfMessage( $msg );
271 $labelId = Sanitizer::escapeIdForAttribute( "p-$name-label" );
272 ?>
273 <div class="portal" role="navigation" id="<?php
274 echo htmlspecialchars( Sanitizer::escapeIdForAttribute( "p-$name" ) )
275 ?>"<?php
276 echo Linker::tooltip( 'p-' . $name )
277 ?> aria-labelledby="<?php echo htmlspecialchars( $labelId ) ?>">
278 <h3<?php $this->html( 'userlangattributes' ) ?> id="<?php echo htmlspecialchars( $labelId )
279 ?>"><?php
280 echo htmlspecialchars( $msgObj->exists() ? $msgObj->text() : $msg );
281 ?></h3>
282 <div class="body">
283 <?php
284 if ( is_array( $content ) ) {
285 ?>
286 <ul>
287 <?php
288 foreach ( $content as $key => $val ) {
289 echo $this->makeListItem( $key, $val );
290 }
291 if ( $hook !== null ) {
292 // Avoid PHP 7.1 warning
293 $skin = $this;
294 Hooks::run( $hook, [ &$skin, true ] );
295 }
296 ?>
297 </ul>
298 <?php
299 } else {
300 // Allow raw HTML block to be defined by extensions
301 echo $content;
302 }
303
304 $this->renderAfterPortlet( $name );
305 ?>
306 </div>
307 </div>
308 <?php
309 }
310
317 protected function renderNavigation( array $elements ) {
318 // Render elements
319 foreach ( $elements as $name => $element ) {
320 switch ( $element ) {
321 case 'NAMESPACES':
322 ?>
323 <div id="p-namespaces" role="navigation" class="vectorTabs<?php
324 if ( count( $this->data['namespace_urls'] ) == 0 ) {
325 echo ' emptyPortlet';
326 }
327 ?>" aria-labelledby="p-namespaces-label">
328 <h3 id="p-namespaces-label"><?php $this->msg( 'namespaces' ) ?></h3>
329 <ul<?php $this->html( 'userlangattributes' ) ?>>
330 <?php
331 foreach ( $this->data['namespace_urls'] as $key => $item ) {
332 echo $this->makeListItem( $key, $item, [
333 'vector-wrap' => true,
334 ] );
335 }
336 ?>
337 </ul>
338 </div>
339 <?php
340 break;
341 case 'VARIANTS':
342 ?>
343 <div id="p-variants" role="navigation" class="vectorMenu<?php
344 if ( count( $this->data['variant_urls'] ) == 0 ) {
345 echo ' emptyPortlet';
346 }
347 ?>" aria-labelledby="p-variants-label">
348 <?php
349 // Replace the label with the name of currently chosen variant, if any
350 $variantLabel = $this->getMsg( 'variants' )->text();
351 foreach ( $this->data['variant_urls'] as $item ) {
352 if ( isset( $item['class'] ) && stripos( $item['class'], 'selected' ) !== false ) {
353 $variantLabel = $item['text'];
354 break;
355 }
356 }
357 ?>
358 <input type="checkbox" class="vectorMenuCheckbox" aria-labelledby="p-variants-label" />
359 <h3 id="p-variants-label">
360 <span><?php echo htmlspecialchars( $variantLabel ) ?></span>
361 </h3>
362 <div class="menu">
363 <ul>
364 <?php
365 foreach ( $this->data['variant_urls'] as $key => $item ) {
366 echo $this->makeListItem( $key, $item );
367 }
368 ?>
369 </ul>
370 </div>
371 </div>
372 <?php
373 break;
374 case 'VIEWS':
375 ?>
376 <div id="p-views" role="navigation" class="vectorTabs<?php
377 if ( count( $this->data['view_urls'] ) == 0 ) {
378 echo ' emptyPortlet';
379 }
380 ?>" aria-labelledby="p-views-label">
381 <h3 id="p-views-label"><?php $this->msg( 'views' ) ?></h3>
382 <ul<?php $this->html( 'userlangattributes' ) ?>>
383 <?php
384 foreach ( $this->data['view_urls'] as $key => $item ) {
385 echo $this->makeListItem( $key, $item, [
386 'vector-wrap' => true,
387 'vector-collapsible' => true,
388 ] );
389 }
390 ?>
391 </ul>
392 </div>
393 <?php
394 break;
395 case 'ACTIONS':
396 ?>
397 <div id="p-cactions" role="navigation" class="vectorMenu<?php
398 if ( count( $this->data['action_urls'] ) == 0 ) {
399 echo ' emptyPortlet';
400 }
401 ?>" aria-labelledby="p-cactions-label">
402 <input type="checkbox" class="vectorMenuCheckbox" aria-labelledby="p-cactions-label" />
403 <h3 id="p-cactions-label"><span><?php
404 $this->msg( 'vector-more-actions' )
405 ?></span></h3>
406 <div class="menu">
407 <ul<?php $this->html( 'userlangattributes' ) ?>>
408 <?php
409 foreach ( $this->data['action_urls'] as $key => $item ) {
410 echo $this->makeListItem( $key, $item );
411 }
412 ?>
413 </ul>
414 </div>
415 </div>
416 <?php
417 break;
418 case 'PERSONAL':
419 ?>
420 <div id="p-personal" role="navigation" class="<?php
421 if ( count( $this->data['personal_urls'] ) == 0 ) {
422 echo ' emptyPortlet';
423 }
424 ?>" aria-labelledby="p-personal-label">
425 <h3 id="p-personal-label"><?php $this->msg( 'personaltools' ) ?></h3>
426 <ul<?php $this->html( 'userlangattributes' ) ?>>
427 <?php
428 $notLoggedIn = '';
429
430 if ( !$this->getSkin()->getUser()->isLoggedIn() &&
431 User::groupHasPermission( '*', 'edit' )
432 ) {
433 $notLoggedIn =
434 Html::rawElement( 'li',
435 [ 'id' => 'pt-anonuserpage' ],
436 $this->getMsg( 'notloggedin' )->escaped()
437 );
438 }
439
440 $personalTools = $this->getPersonalTools();
441
442 $langSelector = '';
443 if ( array_key_exists( 'uls', $personalTools ) ) {
444 $langSelector = $this->makeListItem( 'uls', $personalTools[ 'uls' ] );
445 unset( $personalTools[ 'uls' ] );
446 }
447
448 echo $langSelector;
449 echo $notLoggedIn;
450 foreach ( $personalTools as $key => $item ) {
451 echo $this->makeListItem( $key, $item );
452 }
453 ?>
454 </ul>
455 </div>
456 <?php
457 break;
458 case 'SEARCH':
459 ?>
460 <div id="p-search" role="search">
461 <h3<?php $this->html( 'userlangattributes' ) ?>>
462 <label for="searchInput"><?php $this->msg( 'search' ) ?></label>
463 </h3>
464 <form action="<?php $this->text( 'wgScript' ) ?>" id="searchform">
465 <div<?php echo $this->config->get( 'VectorUseSimpleSearch' ) ? ' id="simpleSearch"' : '' ?>>
466 <?php
467 echo $this->makeSearchInput( [ 'id' => 'searchInput' ] );
468 echo Html::hidden( 'title', $this->get( 'searchtitle' ) );
469 /* We construct two buttons (for 'go' and 'fulltext' search modes),
470 * but only one will be visible and actionable at a time (they are
471 * overlaid on top of each other in CSS).
472 * * Browsers will use the 'fulltext' one by default (as it's the
473 * first in tree-order), which is desirable when they are unable
474 * to show search suggestions (either due to being broken or
475 * having JavaScript turned off).
476 * * The mediawiki.searchSuggest module, after doing tests for the
477 * broken browsers, removes the 'fulltext' button and handles
478 * 'fulltext' search itself; this will reveal the 'go' button and
479 * cause it to be used.
480 */
481 echo $this->makeSearchButton(
482 'fulltext',
483 [ 'id' => 'mw-searchButton', 'class' => 'searchButton mw-fallbackSearchButton' ]
484 );
485 echo $this->makeSearchButton(
486 'go',
487 [ 'id' => 'searchButton', 'class' => 'searchButton' ]
488 );
489 ?>
490 </div>
491 </form>
492 </div>
493 <?php
494
495 break;
496 }
497 }
498 }
499
503 public function makeLink( $key, $item, $options = [] ) {
504 $html = parent::makeLink( $key, $item, $options );
505 // Add an extra wrapper because our CSS is weird
506 if ( isset( $options['vector-wrap'] ) && $options['vector-wrap'] ) {
507 $html = Html::rawElement( 'span', [], $html );
508 }
509 return $html;
510 }
511
515 public function makeListItem( $key, $item, $options = [] ) {
516 // For fancy styling of watch/unwatch star
517 if (
518 $this->config->get( 'VectorUseIconWatch' )
519 && ( $key === 'watch' || $key === 'unwatch' )
520 ) {
521 $item['class'] = rtrim( 'icon ' . $item['class'], ' ' );
522 $item['primary'] = true;
523 }
524
525 // Add CSS class 'collapsible' to links which are not marked as "primary"
526 if (
527 isset( $options['vector-collapsible'] ) && $options['vector-collapsible'] ) {
528 $item['class'] = rtrim( 'collapsible ' . $item['class'], ' ' );
529 }
530
531 // We don't use this, prevent it from popping up in HTML output
532 unset( $item['redundant'] );
533
534 return parent::makeListItem( $key, $item, $options );
535 }
536}
shown</td >< td > a href
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:2163
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[], $options=null)
Returns the attributes for the tooltip and access key.
Definition Linker.php:2135
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:5005
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)
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add text
Definition design.txt:18
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:2001
null means default in associative array form
Definition hooks.txt:1996
either a unescaped string or a HtmlArmor object after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock() - offset Set to overwrite offset parameter in $wgRequest set to '' to unset offset - wrap String Wrap the message in html(usually something like "&lt;div ...>$1&lt;/div>"). - flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException':Called before an exception(or PHP error) is logged. This is meant for integration with external error aggregation services
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:2013
usually copyright or history_copyright This message must be in HTML not wikitext & $link
Definition hooks.txt:3021
Allows to change the fields on the form that will be generated $name
Definition hooks.txt:302
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 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:30
Bar style