/** * Show a global usage section on the image page * * @param object $imagePage The ImagePage * @param string $html HTML to add to the image page as global usage section * @return bool */ public static function onImagePageAfterImageLinks($imagePage, &$html) { if (!self::hasResults($imagePage)) { return true; } $title = $imagePage->getFile()->getTitle(); $targetName = $title->getText(); $query = self::getImagePageQuery($title); $guHtml = ''; foreach ($query->getSingleImageResult() as $wiki => $result) { $wikiName = WikiMap::getWikiName($wiki); $escWikiName = Sanitizer::escapeClass($wikiName); /* Wikia change begin */ wfRunHooks('GlobalUsageImagePageWikiLink', array(&$wikiName)); /* Wikia change end */ $guHtml .= "<li class='mw-gu-onwiki-{$escWikiName}'>" . wfMsgExt('globalusage-on-wiki', 'parseinline', $targetName, $wikiName) . "\n<ul>"; foreach ($result as $item) { $guHtml .= "\t<li>" . SpecialGlobalUsage::formatItem($item) . "</li>\n"; } $guHtml .= "</ul></li>\n"; } if ($guHtml) { $html .= '<h2 id="globalusage">' . wfMsgHtml('globalusage') . "</h2>\n" . '<div id="mw-imagepage-section-globalusage">' . wfMsgExt('globalusage-of-file', 'parse') . "<ul>\n" . $guHtml . "</ul>\n"; if ($query->hasMore()) { $html .= wfMsgExt('globalusage-more', 'parse', $targetName); } $html .= '</div>'; } return true; }
/** * Format a line using the old system (aka without any javascript). * * @param RecentChange $rc Passed by reference * @param bool $watched (default false) * @param int $linenumber (default null) * * @return string|bool */ public function recentChangesLine(&$rc, $watched = false, $linenumber = null) { $classes = array(); // use mw-line-even/mw-line-odd class only if linenumber is given (feature from bug 14468) if ($linenumber) { if ($linenumber & 1) { $classes[] = 'mw-line-odd'; } else { $classes[] = 'mw-line-even'; } } // Indicate watched status on the line to allow for more // comprehensive styling. $classes[] = $watched && $rc->mAttribs['rc_timestamp'] >= $watched ? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched'; $html = $this->formatChangeLine($rc, $classes, $watched); if ($this->watchlist) { $classes[] = Sanitizer::escapeClass('watchlist-' . $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title']); } if (!Hooks::run('OldChangesListRecentChangesLine', array(&$this, &$html, $rc, &$classes))) { return false; } $dateheader = ''; // $html now contains only <li>...</li>, for hooks' convenience. $this->insertDateHeader($dateheader, $rc->mAttribs['rc_timestamp']); return "{$dateheader}<li class=\"" . implode(' ', $classes) . "\">" . $html . "</li>\n"; }
/** * Creates HTML for the given tags * * @param string $tags Comma-separated list of tags * @param string $page A label for the type of action which is being displayed, * for example: 'history', 'contributions' or 'newpages' * @return array Array with two items: (html, classes) * - html: String: HTML for displaying the tags (empty string when param $tags is empty) * - classes: Array of strings: CSS classes used in the generated html, one class for each tag */ public static function formatSummaryRow($tags, $page) { global $wgLang; if (!$tags) { return array('', array()); } $classes = array(); $tags = explode(',', $tags); $displayTags = array(); foreach ($tags as $tag) { if (!$tag) { continue; } $description = self::tagDescription($tag); if ($description === false) { continue; } $displayTags[] = Xml::tags('span', array('class' => 'mw-tag-marker ' . Sanitizer::escapeClass("mw-tag-marker-{$tag}")), $description); $classes[] = Sanitizer::escapeClass("mw-tag-{$tag}"); } if (!$displayTags) { return array('', array()); } $markers = wfMessage('tag-list-wrapper')->numParams(count($displayTags))->rawParams($wgLang->commaList($displayTags))->parse(); $markers = Xml::tags('span', array('class' => 'mw-tag-markers'), $markers); return array($markers, $classes); }
/** * Creates HTML for the given tags * * @param string $tags Comma-separated list of tags * @param string $page A label for the type of action which is being displayed, * for example: 'history', 'contributions' or 'newpages' * @param IContextSource|null $context * @note Even though it takes null as a valid argument, an IContextSource is preferred * in a new code, as the null value is subject to change in the future * @return array Array with two items: (html, classes) * - html: String: HTML for displaying the tags (empty string when param $tags is empty) * - classes: Array of strings: CSS classes used in the generated html, one class for each tag */ public static function formatSummaryRow($tags, $page, IContextSource $context = null) { if (!$tags) { return array('', array()); } if (!$context) { $context = RequestContext::getMain(); } $classes = array(); $tags = explode(',', $tags); $displayTags = array(); foreach ($tags as $tag) { if (!$tag) { continue; } $description = self::tagDescription($tag); if ($description === false) { continue; } $displayTags[] = Xml::tags('span', array('class' => 'mw-tag-marker ' . Sanitizer::escapeClass("mw-tag-marker-{$tag}")), $description); $classes[] = Sanitizer::escapeClass("mw-tag-{$tag}"); } if (!$displayTags) { return array('', array()); } $markers = $context->msg('tag-list-wrapper')->numParams(count($displayTags))->rawParams($context->getLanguage()->commaList($displayTags))->parse(); $markers = Xml::tags('span', array('class' => 'mw-tag-markers'), $markers); return array($markers, $classes); }
static function formatSummaryRow($tags, $page) { if (!$tags) { return array('', array()); } $classes = array(); $tags = explode(',', $tags); $displayTags = array(); foreach ($tags as $tag) { $displayTags[] = Xml::tags('span', array('class' => 'mw-tag-marker ' . Sanitizer::escapeClass("mw-tag-marker-{$tag}")), self::tagDescription($tag)); $classes[] = Sanitizer::escapeClass("mw-tag-{$tag}"); } $markers = '(' . implode(', ', $displayTags) . ')'; $markers = Xml::tags('span', array('class' => 'mw-tag-markers'), $markers); return array($markers, $classes); }
/** * Generate an in icon using a canned CK icon * @param $icon string icon id or random seed * @param $size int intended height/width for rendered icon in px * @param $fallback string what to do for no icon; allowed values are 'random', 'none', or a valid icon id * @return string html */ public static function makeIcon($icon, $size = 50, $colour, $background = 'transparent') { $iconsPreset = CollaborationKitIcon::getCannedIcons(); if (in_array($icon, $iconsPreset)) { $iconClass = Sanitizer::escapeClass($icon); } else { // Random time // Choose class name using $icon value as seed $iconClass = $iconsPreset[hexdec(sha1($icon)[0]) % 27]; } if (!isset($colour) || $colour == 'black') { $colorSuffix = ''; } else { $colorSuffix = '-' . $colour; } return Html::element('div', ['class' => ['mw-ck-icon', 'mw-ck-icon-' . $iconClass . $colorSuffix], 'css' => "height: {$size}px; width: {$size}px; background-color: {$background};"]); }
/** * Creates HTML for the given tags * * @param string $tags Comma-separated list of tags * @param string $page A label for the type of action which is being displayed, * for example: 'history', 'contributions' or 'newpages' * * @return Array with two items: (html, classes) * - html: String: HTML for displaying the tags (empty string when param $tags is empty) * - classes: Array of strings: CSS classes used in the generated html, one class for each tag * */ static function formatSummaryRow($tags, $page) { global $wgLang; if (!$tags) { return array('', array()); } $classes = array(); $tags = explode(',', $tags); $displayTags = array(); foreach ($tags as $tag) { $displayTags[] = Xml::tags('span', array('class' => 'mw-tag-marker ' . Sanitizer::escapeClass("mw-tag-marker-{$tag}")), self::tagDescription($tag)); $classes[] = Sanitizer::escapeClass("mw-tag-{$tag}"); } $markers = wfMessage('parentheses')->rawParams($wgLang->commaList($displayTags))->text(); $markers = Xml::tags('span', array('class' => 'mw-tag-markers'), $markers); return array($markers, $classes); }
/** * Format a line using the old system (aka without any javascript). * * @param RecentChange $rc Passed by reference * @param bool $watched (default false) * @param int $linenumber (default null) * * @return string|bool */ public function recentChangesLine(&$rc, $watched = false, $linenumber = null) { $classes = $this->getHTMLClasses($rc, $watched); // use mw-line-even/mw-line-odd class only if linenumber is given (feature from bug 14468) if ($linenumber) { if ($linenumber & 1) { $classes[] = 'mw-line-odd'; } else { $classes[] = 'mw-line-even'; } } $html = $this->formatChangeLine($rc, $classes, $watched); if ($this->watchlist) { $classes[] = Sanitizer::escapeClass('watchlist-' . $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title']); } if (!Hooks::run('OldChangesListRecentChangesLine', [&$this, &$html, $rc, &$classes])) { return false; } $dateheader = ''; // $html now contains only <li>...</li>, for hooks' convenience. $this->insertDateHeader($dateheader, $rc->mAttribs['rc_timestamp']); return "{$dateheader}<li class=\"" . implode(' ', $classes) . "\">" . $html . "</li>\n"; }
/** * initialize various variables and generate the template * * @param $out OutputPage */ function outputPage(OutputPage $out) { global $wgUser, $wgLang, $wgContLang; global $wgScript, $wgStylePath; global $wgMimeType, $wgJsMimeType, $wgRequest; global $wgXhtmlDefaultNamespace, $wgXhtmlNamespaces, $wgHtml5Version; global $wgDisableCounters, $wgLogo, $wgHideInterlanguageLinks; global $wgMaxCredits, $wgShowCreditsIfMax; global $wgPageShowWatchingUsers; global $wgUseTrackbacks, $wgUseSiteJs, $wgDebugComments; global $wgArticlePath, $wgScriptPath, $wgServer; wfProfileIn(__METHOD__); Profiler::instance()->setTemplated(true); $oldid = $wgRequest->getVal('oldid'); $diff = $wgRequest->getVal('diff'); $action = $wgRequest->getVal('action', 'view'); wfProfileIn(__METHOD__ . '-init'); $this->initPage($out); $tpl = $this->setupTemplate($this->template, 'skins'); wfProfileOut(__METHOD__ . '-init'); wfProfileIn(__METHOD__ . '-stuff'); $this->thispage = $this->getTitle()->getPrefixedDBkey(); $this->userpage = $wgUser->getUserPage()->getPrefixedText(); $query = array(); if (!$wgRequest->wasPosted()) { $query = $wgRequest->getValues(); unset($query['title']); unset($query['returnto']); unset($query['returntoquery']); } $this->thisquery = wfArrayToCGI($query); $this->loggedin = $wgUser->isLoggedIn(); $this->iscontent = $this->getTitle()->getNamespace() != NS_SPECIAL; $this->iseditable = ($this->iscontent and !($action == 'edit' or $action == 'submit')); $this->username = $wgUser->getName(); if ($wgUser->isLoggedIn() || $this->showIPinHeader()) { $this->userpageUrlDetails = self::makeUrlDetails($this->userpage); } else { # This won't be used in the standard skins, but we define it to preserve the interface # To save time, we check for existence $this->userpageUrlDetails = self::makeKnownUrlDetails($this->userpage); } $this->titletxt = $this->getTitle()->getPrefixedText(); wfProfileOut(__METHOD__ . '-stuff'); wfProfileIn(__METHOD__ . '-stuff-head'); if ($this->useHeadElement) { $pagecss = $this->setupPageCss(); if ($pagecss) { $out->addInlineStyle($pagecss); } } else { $this->setupUserCss($out); $tpl->set('pagecss', $this->setupPageCss()); $tpl->set('usercss', false); $this->userjs = $this->userjsprev = false; # @todo FIXME: This is the only use of OutputPage::isUserJsAllowed() anywhere; can we # get rid of it? For that matter, why is any of this here at all? $this->setupUserJs($out->isUserJsAllowed()); $tpl->setRef('userjs', $this->userjs); $tpl->setRef('userjsprev', $this->userjsprev); if ($wgUseSiteJs) { $jsCache = $this->loggedin ? '&smaxage=0' : ''; $tpl->set('jsvarurl', self::makeUrl('-', "action=raw{$jsCache}&gen=js&useskin=" . urlencode($this->getSkinName()))); } else { $tpl->set('jsvarurl', false); } $tpl->setRef('xhtmldefaultnamespace', $wgXhtmlDefaultNamespace); $tpl->set('xhtmlnamespaces', $wgXhtmlNamespaces); $tpl->set('html5version', $wgHtml5Version); $tpl->set('headlinks', $out->getHeadLinks($this)); $tpl->set('csslinks', $out->buildCssLinks($this)); if ($wgUseTrackbacks && $out->isArticleRelated()) { $tpl->set('trackbackhtml', $out->getTitle()->trackbackRDF()); } else { $tpl->set('trackbackhtml', null); } } wfProfileOut(__METHOD__ . '-stuff-head'); wfProfileIn(__METHOD__ . '-stuff2'); $tpl->set('title', $out->getPageTitle()); $tpl->set('pagetitle', $out->getHTMLTitle()); $tpl->set('displaytitle', $out->mPageLinkTitle); $tpl->set('pageclass', $this->getPageClasses($this->getTitle())); $tpl->set('skinnameclass', 'skin-' . Sanitizer::escapeClass($this->getSkinName())); $nsname = MWNamespace::exists($this->getTitle()->getNamespace()) ? MWNamespace::getCanonicalName($this->getTitle()->getNamespace()) : $this->getTitle()->getNsText(); $tpl->set('nscanonical', $nsname); $tpl->set('nsnumber', $this->getTitle()->getNamespace()); $tpl->set('titleprefixeddbkey', $this->getTitle()->getPrefixedDBKey()); $tpl->set('titletext', $this->getTitle()->getText()); $tpl->set('articleid', $this->getTitle()->getArticleId()); $tpl->set('currevisionid', $this->getTitle()->getLatestRevID()); $tpl->set('isarticle', $out->isArticle()); $tpl->setRef('thispage', $this->thispage); $subpagestr = $this->subPageSubtitle(); $tpl->set('subtitle', !empty($subpagestr) ? '<span class="subpages">' . $subpagestr . '</span>' . $out->getSubtitle() : $out->getSubtitle()); $undelete = $this->getUndeleteLink(); $tpl->set('undelete', !empty($undelete) ? '<span class="subpages">' . $undelete . '</span>' : ''); $tpl->set('catlinks', $this->getCategories()); if ($out->isSyndicated()) { $feeds = array(); foreach ($out->getSyndicationLinks() as $format => $link) { $feeds[$format] = array('text' => wfMsg("feed-{$format}"), 'href' => $link); } $tpl->setRef('feeds', $feeds); } else { $tpl->set('feeds', false); } $tpl->setRef('mimetype', $wgMimeType); $tpl->setRef('jsmimetype', $wgJsMimeType); $tpl->set('charset', 'UTF-8'); $tpl->setRef('wgScript', $wgScript); $tpl->setRef('skinname', $this->skinname); $tpl->set('skinclass', get_class($this)); $tpl->setRef('stylename', $this->stylename); $tpl->set('printable', $out->isPrintable()); $tpl->set('handheld', $wgRequest->getBool('handheld')); $tpl->setRef('loggedin', $this->loggedin); $tpl->set('notspecialpage', $this->getTitle()->getNamespace() != NS_SPECIAL); /* XXX currently unused, might get useful later $tpl->set( 'editable', ( $this->getTitle()->getNamespace() != NS_SPECIAL ) ); $tpl->set( 'exists', $this->getTitle()->getArticleID() != 0 ); $tpl->set( 'watch', $this->getTitle()->userIsWatching() ? 'unwatch' : 'watch' ); $tpl->set( 'protect', count( $this->getTitle()->isProtected() ) ? 'unprotect' : 'protect' ); $tpl->set( 'helppage', wfMsg( 'helppage' ) ); */ $tpl->set('searchaction', $this->escapeSearchLink()); $tpl->set('searchtitle', SpecialPage::getTitleFor('Search')->getPrefixedDBKey()); $tpl->set('search', trim($wgRequest->getVal('search'))); $tpl->setRef('stylepath', $wgStylePath); $tpl->setRef('articlepath', $wgArticlePath); $tpl->setRef('scriptpath', $wgScriptPath); $tpl->setRef('serverurl', $wgServer); $tpl->setRef('logopath', $wgLogo); $contentlang = $wgContLang->getCode(); $contentdir = $wgContLang->getDir(); $userlang = $wgLang->getCode(); $userdir = $wgLang->getDir(); $tpl->set('lang', $userlang); $tpl->set('dir', $userdir); $tpl->set('rtl', $wgLang->isRTL()); $tpl->set('capitalizeallnouns', $wgLang->capitalizeAllNouns() ? ' capitalize-all-nouns' : ''); $tpl->set('showjumplinks', $wgUser->getOption('showjumplinks')); $tpl->set('username', $wgUser->isAnon() ? null : $this->username); $tpl->setRef('userpage', $this->userpage); $tpl->setRef('userpageurl', $this->userpageUrlDetails['href']); $tpl->set('userlang', $userlang); // Users can have their language set differently than the // content of the wiki. For these users, tell the web browser // that interface elements are in a different language. $tpl->set('userlangattributes', ''); $tpl->set('specialpageattributes', ''); # obsolete if ($userlang !== $contentlang || $userdir !== $contentdir) { $attrs = " lang='{$userlang}' dir='{$userdir}'"; $tpl->set('userlangattributes', $attrs); } $newtalks = $this->getNewtalks($out); wfProfileOut(__METHOD__ . '-stuff2'); wfProfileIn(__METHOD__ . '-stuff3'); $tpl->setRef('newtalk', $newtalks); $tpl->setRef('skin', $this); $tpl->set('logo', $this->logoText()); if ($out->isArticle() && (!isset($oldid) || isset($diff)) && $this->getTitle()->exists()) { $article = new Article($this->getTitle(), 0); if (!$wgDisableCounters) { $viewcount = $wgLang->formatNum($article->getCount()); if ($viewcount) { $tpl->set('viewcount', wfMsgExt('viewcount', array('parseinline'), $viewcount)); } else { $tpl->set('viewcount', false); } } else { $tpl->set('viewcount', false); } if ($wgPageShowWatchingUsers) { $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select('watchlist', array('COUNT(*) AS n'), array('wl_title' => $dbr->strencode($this->getTitle()->getDBkey()), 'wl_namespace' => $this->getTitle()->getNamespace()), __METHOD__); $x = $dbr->fetchObject($res); $numberofwatchingusers = $x->n; if ($numberofwatchingusers > 0) { $tpl->set('numberofwatchingusers', wfMsgExt('number_of_watching_users_pageview', array('parseinline'), $wgLang->formatNum($numberofwatchingusers))); } else { $tpl->set('numberofwatchingusers', false); } } else { $tpl->set('numberofwatchingusers', false); } $tpl->set('copyright', $this->getCopyright()); $this->credits = false; if ($wgMaxCredits != 0) { $this->credits = Action::factory('credits', $article)->getCredits($wgMaxCredits, $wgShowCreditsIfMax); } else { $tpl->set('lastmod', $this->lastModified($article)); } $tpl->setRef('credits', $this->credits); } elseif (isset($oldid) && !isset($diff)) { $tpl->set('copyright', $this->getCopyright()); $tpl->set('viewcount', false); $tpl->set('lastmod', false); $tpl->set('credits', false); $tpl->set('numberofwatchingusers', false); } else { $tpl->set('copyright', false); $tpl->set('viewcount', false); $tpl->set('lastmod', false); $tpl->set('credits', false); $tpl->set('numberofwatchingusers', false); } wfProfileOut(__METHOD__ . '-stuff3'); wfProfileIn(__METHOD__ . '-stuff4'); $tpl->set('copyrightico', $this->getCopyrightIcon()); $tpl->set('poweredbyico', $this->getPoweredBy()); $tpl->set('disclaimer', $this->disclaimerLink()); $tpl->set('privacy', $this->privacyLink()); $tpl->set('about', $this->aboutLink()); $tpl->set('footerlinks', array('info' => array('lastmod', 'viewcount', 'numberofwatchingusers', 'credits', 'copyright'), 'places' => array('privacy', 'about', 'disclaimer'))); global $wgFooterIcons; $tpl->set('footericons', $wgFooterIcons); foreach ($tpl->data['footericons'] as $footerIconsKey => &$footerIconsBlock) { if (count($footerIconsBlock) > 0) { foreach ($footerIconsBlock as &$footerIcon) { if (isset($footerIcon['src'])) { if (!isset($footerIcon['width'])) { $footerIcon['width'] = 88; } if (!isset($footerIcon['height'])) { $footerIcon['height'] = 31; } } } } else { unset($tpl->data['footericons'][$footerIconsKey]); } } if ($wgDebugComments) { $tpl->setRef('debug', $out->mDebugtext); } else { $tpl->set('debug', ''); } $tpl->set('reporttime', wfReportTime()); $tpl->set('sitenotice', $this->getSiteNotice()); $tpl->set('bottomscripts', $this->bottomScripts($out)); $tpl->set('printfooter', $this->printSource()); # Add a <div class="mw-content-ltr/rtl"> around the body text # not for special pages or file pages AND only when viewing AND if the page exists # (or is in MW namespace, because that has default content) if (!in_array($this->getTitle()->getNamespace(), array(NS_SPECIAL, NS_FILE)) && in_array($action, array('view', 'historysubmit')) && ($this->getTitle()->exists() || $this->getTitle()->getNamespace() == NS_MEDIAWIKI)) { $pageLang = $this->getTitle()->getPageLanguage(); $realBodyAttribs = array('lang' => $pageLang->getCode(), 'dir' => $pageLang->getDir(), 'class' => 'mw-content-' . $pageLang->getDir()); $out->mBodytext = Html::rawElement('div', $realBodyAttribs, $out->mBodytext); } $tpl->setRef('bodytext', $out->mBodytext); # Language links $language_urls = array(); if (!$wgHideInterlanguageLinks) { foreach ($out->getLanguageLinks() as $l) { $tmp = explode(':', $l, 2); $class = 'interwiki-' . $tmp[0]; unset($tmp); $nt = Title::newFromText($l); if ($nt) { $language_urls[] = array('href' => $nt->getFullURL(), 'text' => $wgContLang->getLanguageName($nt->getInterwiki()) != '' ? $wgContLang->getLanguageName($nt->getInterwiki()) : $l, 'title' => $nt->getText(), 'class' => $class, 'lang' => $nt->getInterwiki(), 'hreflang' => $nt->getInterwiki()); } } } if (count($language_urls)) { $tpl->setRef('language_urls', $language_urls); } else { $tpl->set('language_urls', false); } wfProfileOut(__METHOD__ . '-stuff4'); wfProfileIn(__METHOD__ . '-stuff5'); # Personal toolbar $tpl->set('personal_urls', $this->buildPersonalUrls($out)); $content_navigation = $this->buildContentNavigationUrls($out); $content_actions = $this->buildContentActionUrls($content_navigation); $tpl->setRef('content_navigation', $content_navigation); $tpl->setRef('content_actions', $content_actions); $tpl->set('sidebar', $this->buildSidebar()); $tpl->set('nav_urls', $this->buildNavUrls($out)); // Set the head scripts near the end, in case the above actions resulted in added scripts if ($this->useHeadElement) { $tpl->set('headelement', $out->headElement($this)); } else { $tpl->set('headscripts', $out->getScript()); } $tpl->set('debughtml', $this->generateDebugHTML()); // original version by hansm if (!wfRunHooks('SkinTemplateOutputPageBeforeExec', array(&$this, &$tpl))) { wfDebug(__METHOD__ . ": Hook SkinTemplateOutputPageBeforeExec broke outputPage execution!\n"); } // Set the bodytext to another key so that skins can just output it on it's own // and output printfooter and debughtml separately $tpl->set('bodycontent', $tpl->data['bodytext']); // Append printfooter and debughtml onto bodytext so that skins that were already // using bodytext before they were split out don't suddenly start not outputting information $tpl->data['bodytext'] .= Html::rawElement('div', array('class' => 'printfooter'), "\n{$tpl->data['printfooter']}") . "\n"; $tpl->data['bodytext'] .= $tpl->data['debughtml']; // allow extensions adding stuff after the page content. // See Skin::afterContentHook() for further documentation. $tpl->set('dataAfterContent', $this->afterContentHook()); wfProfileOut(__METHOD__ . '-stuff5'); // execute template wfProfileIn(__METHOD__ . '-execute'); $res = $tpl->execute(); wfProfileOut(__METHOD__ . '-execute'); // result may be an error $this->printOrError($res); wfProfileOut(__METHOD__); }
<table class="mw-collapsible mw-collapsed mw-enhanced-rc <?php echo Sanitizer::escapeClass('mw-changeslist-ns' . $title->getNamespace() . '-' . $title->getText()); ?> "> <tr> <td> <span class="mw-collapsible-toggle"> <span class="mw-rc-openarrow"> <a title="<?php echo htmlspecialchars(wfMsg('rc-enhanced-expand')); ?> " href="#"> <img width="12" height="12" title="<?php echo htmlspecialchars(wfMsg('rc-enhanced-expand')); ?> " alt="+" src="<?php echo $wgStylePath; ?> /common/images/Arr_r.png"> </a> </span> <span class="mw-rc-closearrow"> <a title="<?php echo htmlspecialchars(wfMsg('rc-enhanced-hide')); ?> " href="#"> <img width="12" height="12" title="<?php echo htmlspecialchars(wfMsg('rc-enhanced-hide')); ?> " alt="-" src="<?php echo $wgStylePath;
/** * Insert the tags of the given change */ private function formatReviewSummaryRow($rc, $page) { global $wgRequest; $s = ''; if (!$rc) { return $s; } $attr = $rc->mAttribs; $tagRows = $attr['collabwatchlist_tags']; $classes = array(); $displayTags = array(); foreach ($tagRows as $tagRow) { $tag = $tagRow['ct_tag']; $collabwatchlistTag = Xml::tags('span', array('class' => 'mw-collabwatchlist-tag-marker ' . Sanitizer::escapeClass("mw-collabwatchlist-tag-marker-{$tag}"), 'title' => $tagRow['rrt_comment']), ChangeTags::tagDescription($tag)); $classes[] = Sanitizer::escapeClass("mw-collabwatchlist-tag-{$tag}"); /** Insert links to user page, user talk page and eventually a blocking link */ $userLink = $this->skin->userLink($tagRow['user_id'], $tagRow['user_name']); $delTagTarget = CollabWatchlistEditor::getUnsetTagUrl($wgRequest->getFullRequestURL(), $attr['rc_title'], $tagRow['cw_id'], $tag, $attr['rc_id']); $delTagLink = Xml::element('a', array('href' => $delTagTarget, 'class' => 'mw-collabwatchlist-unsettag-' . $tag), wfMsg('collabwatchlist-unset-tag')); $displayTags[] = $collabwatchlistTag . ' ' . $delTagLink . ' ' . $userLink; } $markers = '(' . implode(', ', $displayTags) . ')'; $markers = Xml::tags('span', array('class' => 'mw-collabwatchlist-tag-markers'), $markers); return array($markers, $classes); }
/** * Enhanced RC ungrouped line. * @return String: a HTML formated line (generated using $r) */ protected function recentChangesBlockLine($rcObj) { global $wgRCShowChangedSize; wfProfileIn(__METHOD__); # Extract fields from DB into the function scope (rc_xxxx variables) // FIXME: Would be good to replace this extract() call with something // that explicitly initializes variables. // TODO implement extract($rcObj->mAttribs); $query['curid'] = $rc_cur_id; if ($rc_log_type) { # Log entry $classes = 'mw-enhanced-rc ' . Sanitizer::escapeClass('mw-changeslist-log-' . $rc_log_type . '-' . $rcObj->mAttribs['rc_title']); } else { $classes = 'mw-enhanced-rc ' . Sanitizer::escapeClass('mw-changeslist-ns' . $rcObj->mAttribs['rc_namespace'] . '-' . $rcObj->mAttribs['rc_title']); } $r = Html::openElement('table', array('class' => $classes)) . Html::openElement('tr'); $r .= '<td class="mw-enhanced-rc">' . $this->spacerArrow() . ' '; # Flag and Timestamp if ($rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT) { $r .= '    '; // 4 flags -> 4 spaces } else { $r .= $this->recentChangesFlags($rc_type == RC_NEW, $rc_minor, $rcObj->unpatrolled, ' ', $rc_bot); } $r .= ' ' . $rcObj->timestamp . ' </td><td style="padding:0px;">'; # Article or log link if ($rc_log_type) { $logtitle = Title::newFromText("Log/{$rc_log_type}", NS_SPECIAL); $logname = LogPage::logName($rc_log_type); $r .= '(' . $this->skin->link($logtitle, $logname, array(), array(), array('known', 'noclasses')) . ')'; } else { $this->insertArticleLink($r, $rcObj, $rcObj->unpatrolled, $rcObj->watched); } # Diff and hist links if ($rc_type != RC_LOG) { $r .= ' (' . $rcObj->difflink . $this->message['pipe-separator']; $query['action'] = 'history'; $r .= $this->skin->link($rcObj->getTitle(), $this->message['hist'], array(), $query, array('known', 'noclasses')) . ')'; } $r .= ' . . '; # Character diff if ($wgRCShowChangedSize && ($cd = $rcObj->getCharacterDifference())) { $r .= "{$cd} . . "; } # User/talk $r .= ' ' . $rcObj->userlink . $rcObj->usertalklink; # Log action (if any) if ($rc_log_type) { if ($this->isDeleted($rcObj, LogPage::DELETED_ACTION)) { $r .= ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>'; } else { $r .= ' ' . LogPage::actionText($rc_log_type, $rc_log_action, $rcObj->getTitle(), $this->skin, LogPage::extractParams($rc_params), true, true); } } $this->insertComment($r, $rcObj); $this->insertRollback($r, $rcObj); # Tags $classes = explode(' ', $classes); $this->insertTags($r, $rcObj, $classes); # Show how many people are watching this if enabled $r .= $this->numberofWatchingusers($rcObj->numberofWatchingusers); $r .= "</td></tr></table>\n"; wfProfileOut(__METHOD__); return $r; }
/** * TODO: document * @param $title Title * @return String */ function getPageClasses($title) { $numeric = 'ns-' . $title->getNamespace(); if ($title->isSpecialPage()) { $type = 'ns-special'; // bug 23315: provide a class based on the canonical special page name without subpages list($canonicalName) = SpecialPageFactory::resolveAlias($title->getDBkey()); if ($canonicalName) { $type .= ' ' . Sanitizer::escapeClass("mw-special-{$canonicalName}"); } else { $type .= ' mw-invalidspecialpage'; } } elseif ($title->isTalkPage()) { $type = 'ns-talk'; } else { $type = 'ns-subject'; } $name = Sanitizer::escapeClass('page-' . $title->getPrefixedText()); return "{$numeric} {$type} {$name}"; }
/** * Enhanced RC ungrouped line. * * @param $rcObj RecentChange * @return String: a HTML formatted line (generated using $r) */ protected function recentChangesBlockLine($rcObj) { global $wgRCShowChangedSize; wfProfileIn(__METHOD__); $query['curid'] = $rcObj->mAttribs['rc_cur_id']; $type = $rcObj->mAttribs['rc_type']; $logType = $rcObj->mAttribs['rc_log_type']; if ($logType) { # Log entry $classes = Sanitizer::escapeClass('mw-changeslist-log-' . $logType); } else { $classes = 'mw-enhanced-rc ' . Sanitizer::escapeClass('mw-changeslist-ns' . $rcObj->mAttribs['rc_namespace'] . '-' . $rcObj->mAttribs['rc_title']); } $r = Html::openElement('table', array('class' => $classes)) . Html::openElement('tr'); $r .= '<td class="mw-enhanced-rc">' . $this->spacerArrow(); # Flag and Timestamp if ($type == RC_MOVE || $type == RC_MOVE_OVER_REDIRECT) { $r .= '    '; // 4 flags -> 4 spaces } else { $r .= $this->recentChangesFlags(array('newpage' => $type == RC_NEW, 'minor' => $rcObj->mAttribs['rc_minor'], 'unpatrolled' => $rcObj->unpatrolled, 'bot' => $rcObj->mAttribs['rc_bot'])); } $r .= ' ' . $rcObj->timestamp . ' </td><td>'; # Article or log link if ($logType) { $logtitle = SpecialPage::getTitleFor('Log', $logType); $logname = LogPage::logName($logType); $r .= '(' . Linker::linkKnown($logtitle, htmlspecialchars($logname)) . ')'; } else { $this->insertArticleLink($r, $rcObj, $rcObj->unpatrolled, $rcObj->watched); } # Diff and hist links if ($type != RC_LOG) { $r .= ' (' . $rcObj->difflink . $this->message['pipe-separator']; $query['action'] = 'history'; $r .= Linker::linkKnown($rcObj->getTitle(), $this->message['hist'], array(), $query) . ')'; } $r .= ' . . '; # Character diff if ($wgRCShowChangedSize && ($cd = $rcObj->getCharacterDifference())) { $r .= "{$cd} . . "; } if ($type == RC_LOG) { $r .= $this->insertLogEntry($rcObj); } else { $r .= ' ' . $rcObj->userlink . $rcObj->usertalklink; $r .= $this->insertComment($rcObj); $r .= $this->insertRollback($r, $rcObj); } # Tags $classes = explode(' ', $classes); $this->insertTags($r, $rcObj, $classes); # Show how many people are watching this if enabled $r .= $this->numberofWatchingusers($rcObj->numberofWatchingusers); $r .= "</td></tr></table>\n"; wfProfileOut(__METHOD__); return $r; }
/** * Enhanced RC ungrouped line. * * @param RecentChange|RCCacheEntry $rcObj * @return string A HTML formatted line (generated using $r) */ protected function recentChangesBlockLine($rcObj) { $data = array(); $query['curid'] = $rcObj->mAttribs['rc_cur_id']; $type = $rcObj->mAttribs['rc_type']; $logType = $rcObj->mAttribs['rc_log_type']; $classes = array('mw-enhanced-rc'); if ($logType) { # Log entry $classes[] = Sanitizer::escapeClass('mw-changeslist-log-' . $logType); } else { $classes[] = Sanitizer::escapeClass('mw-changeslist-ns' . $rcObj->mAttribs['rc_namespace'] . '-' . $rcObj->mAttribs['rc_title']); } $classes[] = $rcObj->watched && $rcObj->mAttribs['rc_timestamp'] >= $rcObj->watched ? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched'; # Flag and Timestamp $data['recentChangesFlags'] = array('newpage' => $type == RC_NEW, 'minor' => $rcObj->mAttribs['rc_minor'], 'unpatrolled' => $rcObj->unpatrolled, 'bot' => $rcObj->mAttribs['rc_bot']); // timestamp is not really a link here, but is called timestampLink // for consistency with EnhancedChangesListModifyLineData $data['timestampLink'] = $rcObj->timestamp; # Article or log link if ($logType) { $logPage = new LogPage($logType); $logTitle = SpecialPage::getTitleFor('Log', $logType); $logName = $logPage->getName()->escaped(); $data['logLink'] = $this->msg('parentheses')->rawParams(Linker::linkKnown($logTitle, $logName))->escaped(); } else { $data['articleLink'] = $this->getArticleLink($rcObj, $rcObj->unpatrolled, $rcObj->watched); } # Diff and hist links if ($type != RC_LOG) { $query['action'] = 'history'; $data['historyLink'] = ' ' . $this->msg('parentheses')->rawParams($rcObj->difflink . $this->message['pipe-separator'] . Linker::linkKnown($rcObj->getTitle(), $this->message['hist'], array(), $query))->escaped(); } $data['separatorAfterLinks'] = ' <span class="mw-changeslist-separator">. .</span> '; # Character diff if ($this->getConfig()->get('RCShowChangedSize')) { $cd = $this->formatCharacterDifference($rcObj); if ($cd !== '') { $data['characterDiff'] = $cd; $data['separatorAftercharacterDiff'] = ' <span class="mw-changeslist-separator">. .</span> '; } } if ($type == RC_LOG) { $data['logEntry'] = $this->insertLogEntry($rcObj); } else { $data['userLink'] = $rcObj->userlink; $data['userTalkLink'] = $rcObj->usertalklink; $data['comment'] = $this->insertComment($rcObj); $data['rollback'] = $this->getRollback($rcObj); } # Tags $data['tags'] = $this->getTags($rcObj, $classes); # Show how many people are watching this if enabled $data['watchingUsers'] = $this->numberofWatchingusers($rcObj->numberofWatchingusers); // give the hook a chance to modify the data $success = Hooks::run('EnhancedChangesListModifyBlockLineData', array($this, &$data, $rcObj)); if (!$success) { // skip entry if hook aborted it return ''; } $line = Html::openElement('table', array('class' => $classes)) . Html::openElement('tr'); $line .= '<td class="mw-enhanced-rc"><span class="mw-enhancedchanges-arrow-space"></span>'; if (isset($data['recentChangesFlags'])) { $line .= $this->recentChangesFlags($data['recentChangesFlags']); unset($data['recentChangesFlags']); } if (isset($data['timestampLink'])) { $line .= ' ' . $data['timestampLink']; unset($data['timestampLink']); } $line .= ' </td><td>'; // everything else: makes it easier for extensions to add or remove data $line .= implode('', $data); $line .= "</td></tr></table>\n"; return $line; }
/** * Format a line using the old system (aka without any javascript). */ public function recentChangesLine(&$rc, $watched = false, $linenumber = null) { global $wgLang, $wgRCShowChangedSize, $wgUser; wfProfileIn(__METHOD__); # Should patrol-related stuff be shown? $unpatrolled = $wgUser->useRCPatrol() && !$rc->mAttribs['rc_patrolled']; $dateheader = ''; // $s now contains only <li>...</li>, for hooks' convenience. $this->insertDateHeader($dateheader, $rc->mAttribs['rc_timestamp']); $s = ''; $classes = array(); // use mw-line-even/mw-line-odd class only if linenumber is given (feature from bug 14468) if ($linenumber) { if ($linenumber & 1) { $classes[] = 'mw-line-odd'; } else { $classes[] = 'mw-line-even'; } } // Moved pages if ($rc->mAttribs['rc_type'] == RC_MOVE || $rc->mAttribs['rc_type'] == RC_MOVE_OVER_REDIRECT) { $this->insertMove($s, $rc); // Log entries } elseif ($rc->mAttribs['rc_log_type']) { $logtitle = Title::newFromText('Log/' . $rc->mAttribs['rc_log_type'], NS_SPECIAL); $this->insertLog($s, $logtitle, $rc->mAttribs['rc_log_type']); // Log entries (old format) or log targets, and special pages } elseif ($rc->mAttribs['rc_namespace'] == NS_SPECIAL) { list($name, $subpage) = SpecialPage::resolveAliasWithSubpage($rc->mAttribs['rc_title']); if ($name == 'Log') { $this->insertLog($s, $rc->getTitle(), $subpage); } // Regular entries } else { $this->insertDiffHist($s, $rc, $unpatrolled); # M, N, b and ! (minor, new, bot and unpatrolled) $s .= $this->recentChangesFlags($rc->mAttribs['rc_new'], $rc->mAttribs['rc_minor'], $unpatrolled, '', $rc->mAttribs['rc_bot']); $this->insertArticleLink($s, $rc, $unpatrolled, $watched); } # Edit/log timestamp $this->insertTimestamp($s, $rc); # Bytes added or removed if ($wgRCShowChangedSize) { $cd = $rc->getCharacterDifference(); if ($cd != '') { $s .= "{$cd} . . "; } } # User tool links $this->insertUserRelatedLinks($s, $rc); # Log action text (if any) $this->insertAction($s, $rc); # Edit or log comment $this->insertComment($s, $rc); # Tags $this->insertTags($s, $rc, $classes); # Rollback $this->insertRollback($s, $rc); # For subclasses $this->insertExtra($s, $rc, $classes); # How many users watch this page if ($rc->numberofWatchingusers > 0) { $s .= ' ' . wfMsgExt('number_of_watching_users_RCview', array('parsemag', 'escape'), $wgLang->formatNum($rc->numberofWatchingusers)); } if ($this->watchlist) { $classes[] = Sanitizer::escapeClass('watchlist-' . $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title']); } wfRunHooks('OldChangesListRecentChangesLine', array(&$this, &$s, $rc)); wfProfileOut(__METHOD__); return "{$dateheader}<li class=\"" . implode(' ', $classes) . "\">" . $s . "</li>\n"; }
/** * initialize various variables and generate the template * * @param $out OutputPage */ function outputPage(OutputPage $out = null) { global $wgContLang; global $wgScript, $wgStylePath; global $wgMimeType, $wgJsMimeType; global $wgXhtmlDefaultNamespace, $wgXhtmlNamespaces, $wgHtml5Version; global $wgDisableCounters, $wgSitename, $wgLogo, $wgHideInterlanguageLinks; global $wgMaxCredits, $wgShowCreditsIfMax; global $wgPageShowWatchingUsers; global $wgDebugComments; global $wgArticlePath, $wgScriptPath, $wgServer; wfProfileIn(__METHOD__); Profiler::instance()->setTemplated(true); $oldContext = null; if ($out !== null) { // @todo Add wfDeprecated in 1.20 $oldContext = $this->getContext(); $this->setContext($out->getContext()); } $out = $this->getOutput(); $request = $this->getRequest(); $user = $this->getUser(); $title = $this->getTitle(); wfProfileIn(__METHOD__ . '-init'); $this->initPage($out); $tpl = $this->setupTemplate($this->template, 'skins'); wfProfileOut(__METHOD__ . '-init'); wfProfileIn(__METHOD__ . '-stuff'); $this->thispage = $title->getPrefixedDBkey(); $this->titletxt = $title->getPrefixedText(); $this->userpage = $user->getUserPage()->getPrefixedText(); $query = array(); if (!$request->wasPosted()) { $query = $request->getValues(); unset($query['title']); unset($query['returnto']); unset($query['returntoquery']); } $this->thisquery = wfArrayToCGI($query); $this->loggedin = $user->isLoggedIn(); $this->username = $user->getName(); if ($this->loggedin || $this->showIPinHeader()) { $this->userpageUrlDetails = self::makeUrlDetails($this->userpage); } else { # This won't be used in the standard skins, but we define it to preserve the interface # To save time, we check for existence $this->userpageUrlDetails = self::makeKnownUrlDetails($this->userpage); } wfProfileOut(__METHOD__ . '-stuff'); wfProfileIn(__METHOD__ . '-stuff-head'); if (!$this->useHeadElement) { $tpl->set('pagecss', false); $tpl->set('usercss', false); $tpl->set('userjs', false); $tpl->set('userjsprev', false); $tpl->set('jsvarurl', false); $tpl->setRef('xhtmldefaultnamespace', $wgXhtmlDefaultNamespace); $tpl->set('xhtmlnamespaces', $wgXhtmlNamespaces); $tpl->set('html5version', $wgHtml5Version); $tpl->set('headlinks', $out->getHeadLinks()); $tpl->set('csslinks', $out->buildCssLinks()); $tpl->set('pageclass', $this->getPageClasses($title)); $tpl->set('skinnameclass', 'skin-' . Sanitizer::escapeClass($this->getSkinName())); } wfProfileOut(__METHOD__ . '-stuff-head'); wfProfileIn(__METHOD__ . '-stuff2'); $tpl->set('title', $out->getPageTitle()); $tpl->set('pagetitle', $out->getHTMLTitle()); $tpl->set('displaytitle', $out->mPageLinkTitle); $tpl->setRef('thispage', $this->thispage); $tpl->setRef('titleprefixeddbkey', $this->thispage); $tpl->set('titletext', $title->getText()); $tpl->set('articleid', $title->getArticleId()); $tpl->set('isarticle', $out->isArticle()); $subpagestr = $this->subPageSubtitle(); if ($subpagestr !== '') { $subpagestr = '<span class="subpages">' . $subpagestr . '</span>'; } $tpl->set('subtitle', $subpagestr . $out->getSubtitle()); $undelete = $this->getUndeleteLink(); if ($undelete === '') { $tpl->set('undelete', ''); } else { $tpl->set('undelete', '<span class="subpages">' . $undelete . '</span>'); } $tpl->set('catlinks', $this->getCategories()); if ($out->isSyndicated()) { $feeds = array(); foreach ($out->getSyndicationLinks() as $format => $link) { $feeds[$format] = array('text' => $this->msg("feed-{$format}")->text(), 'href' => $link); } $tpl->setRef('feeds', $feeds); } else { $tpl->set('feeds', false); } $tpl->setRef('mimetype', $wgMimeType); $tpl->setRef('jsmimetype', $wgJsMimeType); $tpl->set('charset', 'UTF-8'); $tpl->setRef('wgScript', $wgScript); $tpl->setRef('skinname', $this->skinname); $tpl->set('skinclass', get_class($this)); $tpl->setRef('skin', $this); $tpl->setRef('stylename', $this->stylename); $tpl->set('printable', $out->isPrintable()); $tpl->set('handheld', $request->getBool('handheld')); $tpl->setRef('loggedin', $this->loggedin); $tpl->set('notspecialpage', !$title->isSpecialPage()); /* XXX currently unused, might get useful later $tpl->set( 'editable', ( !$title->isSpecialPage() ) ); $tpl->set( 'exists', $title->getArticleID() != 0 ); $tpl->set( 'watch', $title->userIsWatching() ? 'unwatch' : 'watch' ); $tpl->set( 'protect', count( $title->isProtected() ) ? 'unprotect' : 'protect' ); $tpl->set( 'helppage', $this->msg( 'helppage' )->text() ); */ $tpl->set('searchaction', $this->escapeSearchLink()); $tpl->set('searchtitle', SpecialPage::getTitleFor('Search')->getPrefixedDBKey()); $tpl->set('search', trim($request->getVal('search'))); $tpl->setRef('stylepath', $wgStylePath); $tpl->setRef('articlepath', $wgArticlePath); $tpl->setRef('scriptpath', $wgScriptPath); $tpl->setRef('serverurl', $wgServer); $tpl->setRef('logopath', $wgLogo); $tpl->setRef('sitename', $wgSitename); $lang = $this->getLanguage(); $userlang = $lang->getHtmlCode(); $userdir = $lang->getDir(); $tpl->set('lang', $userlang); $tpl->set('dir', $userdir); $tpl->set('rtl', $lang->isRTL()); $tpl->set('capitalizeallnouns', $lang->capitalizeAllNouns() ? ' capitalize-all-nouns' : ''); $tpl->set('showjumplinks', $user->getOption('showjumplinks')); $tpl->set('username', $this->loggedin ? $this->username : null); $tpl->setRef('userpage', $this->userpage); $tpl->setRef('userpageurl', $this->userpageUrlDetails['href']); $tpl->set('userlang', $userlang); // Users can have their language set differently than the // content of the wiki. For these users, tell the web browser // that interface elements are in a different language. $tpl->set('userlangattributes', ''); $tpl->set('specialpageattributes', ''); # obsolete if ($userlang !== $wgContLang->getHtmlCode() || $userdir !== $wgContLang->getDir()) { $escUserlang = htmlspecialchars($userlang); $escUserdir = htmlspecialchars($userdir); // Attributes must be in double quotes because htmlspecialchars() doesn't // escape single quotes $attrs = " lang=\"{$escUserlang}\" dir=\"{$escUserdir}\""; $tpl->set('userlangattributes', $attrs); } wfProfileOut(__METHOD__ . '-stuff2'); wfProfileIn(__METHOD__ . '-stuff3'); $tpl->set('newtalk', $this->getNewtalks()); $tpl->set('logo', $this->logoText()); $tpl->set('copyright', false); $tpl->set('viewcount', false); $tpl->set('lastmod', false); $tpl->set('credits', false); $tpl->set('numberofwatchingusers', false); if ($out->isArticle() && $title->exists()) { if ($this->isRevisionCurrent()) { if (!$wgDisableCounters) { $viewcount = $this->getWikiPage()->getCount(); if ($viewcount) { $tpl->set('viewcount', $this->msg('viewcount')->numParams($viewcount)->parse()); } } if ($wgPageShowWatchingUsers) { $dbr = wfGetDB(DB_SLAVE); $num = $dbr->selectField('watchlist', 'COUNT(*)', array('wl_title' => $title->getDBkey(), 'wl_namespace' => $title->getNamespace()), __METHOD__); if ($num > 0) { $tpl->set('numberofwatchingusers', $this->msg('number_of_watching_users_pageview')->numParams($num)->parse()); } } if ($wgMaxCredits != 0) { $tpl->set('credits', Action::factory('credits', $this->getWikiPage(), $this->getContext())->getCredits($wgMaxCredits, $wgShowCreditsIfMax)); } else { $tpl->set('lastmod', $this->lastModified()); } } $tpl->set('copyright', $this->getCopyright()); } wfProfileOut(__METHOD__ . '-stuff3'); wfProfileIn(__METHOD__ . '-stuff4'); $tpl->set('copyrightico', $this->getCopyrightIcon()); $tpl->set('poweredbyico', $this->getPoweredBy()); $tpl->set('disclaimer', $this->disclaimerLink()); $tpl->set('privacy', $this->privacyLink()); $tpl->set('about', $this->aboutLink()); $tpl->set('footerlinks', array('info' => array('lastmod', 'viewcount', 'numberofwatchingusers', 'credits', 'copyright'), 'places' => array('privacy', 'about', 'disclaimer'))); global $wgFooterIcons; $tpl->set('footericons', $wgFooterIcons); foreach ($tpl->data['footericons'] as $footerIconsKey => &$footerIconsBlock) { if (count($footerIconsBlock) > 0) { foreach ($footerIconsBlock as &$footerIcon) { if (isset($footerIcon['src'])) { if (!isset($footerIcon['width'])) { $footerIcon['width'] = 88; } if (!isset($footerIcon['height'])) { $footerIcon['height'] = 31; } } } } else { unset($tpl->data['footericons'][$footerIconsKey]); } } if ($wgDebugComments) { $tpl->setRef('debug', $out->mDebugtext); } else { $tpl->set('debug', ''); } $tpl->set('sitenotice', $this->getSiteNotice()); $tpl->set('bottomscripts', $this->bottomScripts()); $tpl->set('printfooter', $this->printSource()); # An ID that includes the actual body text; without categories, contentSub, ... $realBodyAttribs = array('id' => 'mw-content-text'); # Add a mw-content-ltr/rtl class to be able to style based on text direction # when the content is different from the UI language, i.e.: # not for special pages or file pages AND only when viewing AND if the page exists # (or is in MW namespace, because that has default content) if (!in_array($title->getNamespace(), array(NS_SPECIAL, NS_FILE)) && in_array($request->getVal('action', 'view'), array('view', 'historysubmit')) && ($title->exists() || $title->getNamespace() == NS_MEDIAWIKI)) { $pageLang = $title->getPageLanguage(); $realBodyAttribs['lang'] = $pageLang->getHtmlCode(); $realBodyAttribs['dir'] = $pageLang->getDir(); $realBodyAttribs['class'] = 'mw-content-' . $pageLang->getDir(); } $out->mBodytext = Html::rawElement('div', $realBodyAttribs, $out->mBodytext); $tpl->setRef('bodytext', $out->mBodytext); # Language links $language_urls = array(); if (!$wgHideInterlanguageLinks) { foreach ($out->getLanguageLinks() as $l) { $tmp = explode(':', $l, 2); $class = 'interwiki-' . $tmp[0]; unset($tmp); $nt = Title::newFromText($l); if ($nt) { $language_urls[] = array('href' => $nt->getFullURL(), 'text' => $wgContLang->getLanguageName($nt->getInterwiki()) != '' ? $wgContLang->getLanguageName($nt->getInterwiki()) : $l, 'title' => $nt->getText(), 'class' => $class, 'lang' => $nt->getInterwiki(), 'hreflang' => $nt->getInterwiki()); } } } if (count($language_urls)) { $tpl->setRef('language_urls', $language_urls); } else { $tpl->set('language_urls', false); } wfProfileOut(__METHOD__ . '-stuff4'); wfProfileIn(__METHOD__ . '-stuff5'); # Personal toolbar $tpl->set('personal_urls', $this->buildPersonalUrls()); $content_navigation = $this->buildContentNavigationUrls(); $content_actions = $this->buildContentActionUrls($content_navigation); $tpl->setRef('content_navigation', $content_navigation); $tpl->setRef('content_actions', $content_actions); $tpl->set('sidebar', $this->buildSidebar()); $tpl->set('nav_urls', $this->buildNavUrls()); // Set the head scripts near the end, in case the above actions resulted in added scripts if ($this->useHeadElement) { $tpl->set('headelement', $out->headElement($this)); } else { $tpl->set('headscripts', $out->getHeadScripts() . $out->getHeadItems()); } $tpl->set('debughtml', $this->generateDebugHTML()); $tpl->set('reporttime', wfReportTime()); // original version by hansm if (!wfRunHooks('SkinTemplateOutputPageBeforeExec', array(&$this, &$tpl))) { wfDebug(__METHOD__ . ": Hook SkinTemplateOutputPageBeforeExec broke outputPage execution!\n"); } // Set the bodytext to another key so that skins can just output it on it's own // and output printfooter and debughtml separately $tpl->set('bodycontent', $tpl->data['bodytext']); // Append printfooter and debughtml onto bodytext so that skins that were already // using bodytext before they were split out don't suddenly start not outputting information $tpl->data['bodytext'] .= Html::rawElement('div', array('class' => 'printfooter'), "\n{$tpl->data['printfooter']}") . "\n"; $tpl->data['bodytext'] .= $tpl->data['debughtml']; // allow extensions adding stuff after the page content. // See Skin::afterContentHook() for further documentation. $tpl->set('dataAfterContent', $this->afterContentHook()); wfProfileOut(__METHOD__ . '-stuff5'); // execute template wfProfileIn(__METHOD__ . '-execute'); $res = $tpl->execute(); wfProfileOut(__METHOD__ . '-execute'); // result may be an error $this->printOrError($res); if ($oldContext) { $this->setContext($oldContext); } wfProfileOut(__METHOD__); }
private function getGroupStats() { global $wgGroupPermissions, $wgImplicitGroups; $text = ''; foreach ($wgGroupPermissions as $group => $permissions) { # Skip generic * and implicit groups if (in_array($group, $wgImplicitGroups) || $group == '*') { continue; } $groupname = htmlspecialchars($group); $msg = $this->msg('group-' . $groupname); if ($msg->isBlank()) { $groupnameLocalized = $groupname; } else { $groupnameLocalized = $msg->text(); } $msg = $this->msg('grouppage-' . $groupname)->inContentLanguage(); if ($msg->isBlank()) { $grouppageLocalized = MWNamespace::getCanonicalName(NS_PROJECT) . ':' . $groupname; } else { $grouppageLocalized = $msg->text(); } $linkTarget = Title::newFromText($grouppageLocalized); $grouppage = Linker::link($linkTarget, htmlspecialchars($groupnameLocalized)); $grouplink = Linker::linkKnown(SpecialPage::getTitleFor('Listusers'), $this->msg('listgrouprights-members')->escaped(), array(), array('group' => $group)); # Add a class when a usergroup contains no members to allow hiding these rows $classZero = ''; $countUsers = SiteStats::numberingroup($groupname); if ($countUsers == 0) { $classZero = ' statistics-group-zero'; } $text .= $this->formatRow($grouppage . ' ' . $grouplink, $this->getLanguage()->formatNum($countUsers), array('class' => 'statistics-group-' . Sanitizer::escapeClass($group) . $classZero)); } return $text; }
/** * @param $sk Skin The given Skin * @param $includeStyle Boolean: unused * @return String: The doctype, opening <html>, and head element. */ public function headElement(Skin $sk, $includeStyle = true) { global $wgContLang; # start wikia change global $wgDevelEnvironment; if ($wgDevelEnvironment) { $this->addMeta('robots', 'noindex, nofollow'); } # end wikia change $userdir = $this->getLanguage()->getDir(); $sitedir = $wgContLang->getDir(); if ($sk->commonPrintStylesheet()) { $this->addModuleStyles('mediawiki.legacy.wikiprintable'); } $ret = Html::htmlHeader(array('lang' => $this->getLanguage()->getHtmlCode(), 'dir' => $userdir, 'class' => 'client-nojs')); if ($this->getHTMLTitle() == '') { # start wikia change wfProfileIn("parsePageTitle"); $this->setHTMLTitle($this->getWikiaPageTitle($this->getPageTitle())); wfProfileOut("parsePageTitle"); # end wikia change # $this->setHTMLTitle( $this->msg( 'pagetitle', $this->getPageTitle() ) ); } $openHead = Html::openElement('head'); if ($openHead) { # Don't bother with the newline if $head == '' $ret .= "{$openHead}\n"; } $ret .= Html::element('title', null, $this->getHTMLTitle()) . "\n"; $ret .= implode("\n", array($this->getHeadLinks(null, true), $this->buildCssLinks(), $this->getHeadScripts(), $this->getHeadItems())); $closeHead = Html::closeElement('head'); if ($closeHead) { $ret .= "{$closeHead}\n"; } $bodyAttrs = array(); # Classes for LTR/RTL directionality support $bodyAttrs['class'] = "mediawiki {$userdir} sitedir-{$sitedir}"; if ($this->getLanguage()->capitalizeAllNouns()) { # A <body> class is probably not the best way to do this . . . $bodyAttrs['class'] .= ' capitalize-all-nouns'; } $bodyAttrs['class'] .= ' ' . $sk->getPageClasses($this->getTitle()); $bodyAttrs['class'] .= ' skin-' . Sanitizer::escapeClass($sk->getSkinName()); $bodyAttrs['class'] .= ' action-' . Sanitizer::escapeClass(Action::getActionName($this->getContext())); $sk->addToBodyAttributes($this, $bodyAttrs); // Allow skins to add body attributes they need wfRunHooks('OutputPageBodyAttributes', array($this, $sk, &$bodyAttrs)); $ret .= Html::openElement('body', $bodyAttrs) . "\n"; return $ret; }
/** * initialize various variables and generate the template * * @param $out OutputPage */ function outputPage(OutputPage $out) { global $wgTitle, $wgArticle, $wgUser, $wgLang, $wgContLang; global $wgScript, $wgStylePath, $wgContLanguageCode; global $wgMimeType, $wgJsMimeType, $wgOutputEncoding, $wgRequest; global $wgXhtmlDefaultNamespace, $wgXhtmlNamespaces; global $wgDisableCounters, $wgLogo, $action, $wgFeedClasses, $wgHideInterlanguageLinks; global $wgMaxCredits, $wgShowCreditsIfMax; global $wgPageShowWatchingUsers; global $wgUseTrackbacks, $wgUseSiteJs; global $wgArticlePath, $wgScriptPath, $wgServer, $wgLang, $wgCanonicalNamespaceNames; wfProfileIn(__METHOD__); $oldid = $wgRequest->getVal('oldid'); $diff = $wgRequest->getVal('diff'); wfProfileIn(__METHOD__ . "-init"); $this->initPage($out); $this->setMembers(); $tpl = $this->setupTemplate($this->template, 'skins'); #if ( $wgUseDatabaseMessages ) { // uncomment this to fall back to GetText $tpl->setTranslator(new MediaWiki_I18N()); #} wfProfileOut(__METHOD__ . "-init"); wfProfileIn(__METHOD__ . "-stuff"); $this->thispage = $this->mTitle->getPrefixedDbKey(); $this->thisurl = $this->mTitle->getPrefixedURL(); $this->loggedin = $wgUser->isLoggedIn(); $this->iscontent = $this->mTitle->getNamespace() != NS_SPECIAL; $this->iseditable = ($this->iscontent and !($action == 'edit' or $action == 'submit')); $this->username = $wgUser->getName(); if ($wgUser->isLoggedIn() || $this->showIPinHeader()) { $this->userpageUrlDetails = self::makeUrlDetails($this->userpage); } else { # This won't be used in the standard skins, but we define it to preserve the interface # To save time, we check for existence $this->userpageUrlDetails = self::makeKnownUrlDetails($this->userpage); } $this->userjs = $this->userjsprev = false; $this->setupUserCss($out); $this->setupUserJs($out->isUserJsAllowed()); $this->titletxt = $this->mTitle->getPrefixedText(); wfProfileOut(__METHOD__ . "-stuff"); wfProfileIn(__METHOD__ . "-stuff2"); $tpl->set('title', $out->getPageTitle()); $tpl->set('pagetitle', $out->getHTMLTitle()); $tpl->set('displaytitle', $out->mPageLinkTitle); $tpl->set('pageclass', $this->getPageClasses($this->mTitle)); $tpl->set('skinnameclass', "skin-" . Sanitizer::escapeClass($this->getSkinName())); $nsname = isset($wgCanonicalNamespaceNames[$this->mTitle->getNamespace()]) ? $wgCanonicalNamespaceNames[$this->mTitle->getNamespace()] : $this->mTitle->getNsText(); $tpl->set('nscanonical', $nsname); $tpl->set('nsnumber', $this->mTitle->getNamespace()); $tpl->set('titleprefixeddbkey', $this->mTitle->getPrefixedDBKey()); $tpl->set('titletext', $this->mTitle->getText()); $tpl->set('articleid', $this->mTitle->getArticleId()); $tpl->set('currevisionid', isset($wgArticle) ? $wgArticle->getLatest() : 0); $tpl->set('isarticle', $out->isArticle()); $tpl->setRef("thispage", $this->thispage); $subpagestr = $this->subPageSubtitle(); $tpl->set('subtitle', !empty($subpagestr) ? '<span class="subpages">' . $subpagestr . '</span>' . $out->getSubtitle() : $out->getSubtitle()); $undelete = $this->getUndeleteLink(); $tpl->set("undelete", !empty($undelete) ? '<span class="subpages">' . $undelete . '</span>' : ''); $tpl->set('catlinks', $this->getCategories()); if ($out->isSyndicated()) { $feeds = array(); foreach ($out->getSyndicationLinks() as $format => $link) { $feeds[$format] = array('text' => wfMsg("feed-{$format}"), 'href' => $link); } $tpl->setRef('feeds', $feeds); } else { $tpl->set('feeds', false); } if ($wgUseTrackbacks && $out->isArticleRelated()) { $tpl->set('trackbackhtml', $wgTitle->trackbackRDF()); } else { $tpl->set('trackbackhtml', null); } $tpl->setRef('xhtmldefaultnamespace', $wgXhtmlDefaultNamespace); $tpl->set('xhtmlnamespaces', $wgXhtmlNamespaces); $tpl->setRef('mimetype', $wgMimeType); $tpl->setRef('jsmimetype', $wgJsMimeType); $tpl->setRef('charset', $wgOutputEncoding); $tpl->set('headlinks', $out->getHeadLinks()); $tpl->set('headscripts', $out->getScript()); $tpl->set('csslinks', $out->buildCssLinks()); $tpl->setRef('wgScript', $wgScript); $tpl->setRef('skinname', $this->skinname); $tpl->set('skinclass', get_class($this)); $tpl->setRef('stylename', $this->stylename); $tpl->set('printable', $wgRequest->getBool('printable')); $tpl->set('handheld', $wgRequest->getBool('handheld')); $tpl->setRef('loggedin', $this->loggedin); $tpl->set('notspecialpage', $this->mTitle->getNamespace() != NS_SPECIAL); /* XXX currently unused, might get useful later $tpl->set( "editable", ($this->mTitle->getNamespace() != NS_SPECIAL ) ); $tpl->set( "exists", $this->mTitle->getArticleID() != 0 ); $tpl->set( "watch", $this->mTitle->userIsWatching() ? "unwatch" : "watch" ); $tpl->set( "protect", count($this->mTitle->isProtected()) ? "unprotect" : "protect" ); $tpl->set( "helppage", wfMsg('helppage')); */ $tpl->set('searchaction', $this->escapeSearchLink()); $tpl->set('search', trim($wgRequest->getVal('search'))); $tpl->setRef('stylepath', $wgStylePath); $tpl->setRef('articlepath', $wgArticlePath); $tpl->setRef('scriptpath', $wgScriptPath); $tpl->setRef('serverurl', $wgServer); $tpl->setRef('logopath', $wgLogo); $tpl->setRef("lang", $wgContLanguageCode); $tpl->set('dir', $wgContLang->isRTL() ? "rtl" : "ltr"); $tpl->set('rtl', $wgContLang->isRTL()); $tpl->set('langname', $wgContLang->getLanguageName($wgContLanguageCode)); $tpl->set('showjumplinks', $wgUser->getOption('showjumplinks')); $tpl->set('username', $wgUser->isAnon() ? NULL : $this->username); $tpl->setRef('userpage', $this->userpage); $tpl->setRef('userpageurl', $this->userpageUrlDetails['href']); $tpl->set('userlang', $wgLang->getCode()); $tpl->set('pagecss', $this->setupPageCss()); $tpl->setRef('usercss', $this->usercss); $tpl->setRef('userjs', $this->userjs); $tpl->setRef('userjsprev', $this->userjsprev); if ($wgUseSiteJs) { $jsCache = $this->loggedin ? '&smaxage=0' : ''; $tpl->set('jsvarurl', self::makeUrl('-', "action=raw{$jsCache}&gen=js&useskin=" . urlencode($this->getSkinName()))); } else { $tpl->set('jsvarurl', false); } $newtalks = $wgUser->getNewMessageLinks(); if (count($newtalks) == 1 && $newtalks[0]["wiki"] === wfWikiID()) { $usertitle = $this->mUser->getUserPage(); $usertalktitle = $usertitle->getTalkPage(); if (!$usertalktitle->equals($this->mTitle)) { $ntl = wfMsg('youhavenewmessages', $this->makeKnownLinkObj($usertalktitle, wfMsgHtml('newmessageslink'), 'redirect=no'), $this->makeKnownLinkObj($usertalktitle, wfMsgHtml('newmessagesdifflink'), 'diff=cur')); # Disable Cache $out->setSquidMaxage(0); } } else { if (count($newtalks)) { $sep = str_replace("_", " ", wfMsgHtml("newtalkseparator")); $msgs = array(); foreach ($newtalks as $newtalk) { $msgs[] = Xml::element("a", array('href' => $newtalk["link"]), $newtalk["wiki"]); } $parts = implode($sep, $msgs); $ntl = wfMsgHtml('youhavenewmessagesmulti', $parts); $out->setSquidMaxage(0); } else { $ntl = ''; } } wfProfileOut(__METHOD__ . "-stuff2"); wfProfileIn(__METHOD__ . "-stuff3"); $tpl->setRef('newtalk', $ntl); $tpl->setRef('skin', $this); $tpl->set('logo', $this->logoText()); if ($out->isArticle() and (!isset($oldid) or isset($diff)) and $wgArticle and 0 != $wgArticle->getID()) { if (!$wgDisableCounters) { $viewcount = $wgLang->formatNum($wgArticle->getCount()); if ($viewcount) { $tpl->set('viewcount', wfMsgExt('viewcount', array('parseinline'), $viewcount)); } else { $tpl->set('viewcount', false); } } else { $tpl->set('viewcount', false); } if ($wgPageShowWatchingUsers) { $dbr = wfGetDB(DB_SLAVE); $watchlist = $dbr->tableName('watchlist'); $sql = "SELECT COUNT(*) AS n FROM {$watchlist}\n\t\t\t\t\tWHERE wl_title='" . $dbr->strencode($this->mTitle->getDBkey()) . "' AND wl_namespace=" . $this->mTitle->getNamespace(); $res = $dbr->query($sql, 'SkinTemplate::outputPage'); $x = $dbr->fetchObject($res); $numberofwatchingusers = $x->n; if ($numberofwatchingusers > 0) { $tpl->set('numberofwatchingusers', wfMsgExt('number_of_watching_users_pageview', array('parseinline'), $wgLang->formatNum($numberofwatchingusers))); } else { $tpl->set('numberofwatchingusers', false); } } else { $tpl->set('numberofwatchingusers', false); } $tpl->set('copyright', $this->getCopyright()); $this->credits = false; if ($wgMaxCredits != 0) { $this->credits = Credits::getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax); } else { $tpl->set('lastmod', $this->lastModified()); } $tpl->setRef('credits', $this->credits); } elseif (isset($oldid) && !isset($diff)) { $tpl->set('copyright', $this->getCopyright()); $tpl->set('viewcount', false); $tpl->set('lastmod', false); $tpl->set('credits', false); $tpl->set('numberofwatchingusers', false); } else { $tpl->set('copyright', false); $tpl->set('viewcount', false); $tpl->set('lastmod', false); $tpl->set('credits', false); $tpl->set('numberofwatchingusers', false); } wfProfileOut(__METHOD__ . "-stuff3"); wfProfileIn(__METHOD__ . "-stuff4"); $tpl->set('copyrightico', $this->getCopyrightIcon()); $tpl->set('poweredbyico', $this->getPoweredBy()); $tpl->set('disclaimer', $this->disclaimerLink()); $tpl->set('privacy', $this->privacyLink()); $tpl->set('about', $this->aboutLink()); $tpl->setRef('debug', $out->mDebugtext); $tpl->set('reporttime', wfReportTime()); $tpl->set('sitenotice', wfGetSiteNotice()); $tpl->set('bottomscripts', $this->bottomScripts()); $printfooter = "<div class=\"printfooter\">\n" . $this->printSource() . "</div>\n"; $out->mBodytext .= $printfooter; $tpl->setRef('bodytext', $out->mBodytext); # Language links $language_urls = array(); if (!$wgHideInterlanguageLinks) { foreach ($out->getLanguageLinks() as $l) { $tmp = explode(':', $l, 2); $class = 'interwiki-' . $tmp[0]; unset($tmp); $nt = Title::newFromText($l); if ($nt) { $language_urls[] = array('href' => $nt->getFullURL(), 'text' => $wgContLang->getLanguageName($nt->getInterwiki()) != '' ? $wgContLang->getLanguageName($nt->getInterwiki()) : $l, 'class' => $class); } } } if (count($language_urls)) { $tpl->setRef('language_urls', $language_urls); } else { $tpl->set('language_urls', false); } wfProfileOut(__METHOD__ . "-stuff4"); wfProfileIn(__METHOD__ . "-stuff5"); # Personal toolbar $tpl->set('personal_urls', $this->buildPersonalUrls()); $content_actions = $this->buildContentActionUrls(); $tpl->setRef('content_actions', $content_actions); // XXX: attach this from javascript, same with section editing if ($this->iseditable && $wgUser->getOption("editondblclick")) { $encEditUrl = Xml::escapeJsString($this->mTitle->getLocalUrl($this->editUrlOptions())); $tpl->set('body_ondblclick', 'document.location = "' . $encEditUrl . '";'); } else { $tpl->set('body_ondblclick', false); } $tpl->set('body_onload', false); $tpl->set('sidebar', $this->buildSidebar()); $tpl->set('nav_urls', $this->buildNavUrls()); // original version by hansm if (!wfRunHooks('SkinTemplateOutputPageBeforeExec', array(&$this, &$tpl))) { wfDebug(__METHOD__ . ': Hook SkinTemplateOutputPageBeforeExec broke outputPage execution!'); } // allow extensions adding stuff after the page content. // See Skin::afterContentHook() for further documentation. $tpl->set('dataAfterContent', $this->afterContentHook()); wfProfileOut(__METHOD__ . "-stuff5"); // execute template wfProfileIn(__METHOD__ . "-execute"); $res = $tpl->execute(); wfProfileOut(__METHOD__ . "-execute"); // result may be an error $this->printOrError($res); wfProfileOut(__METHOD__); }
/** * @param $sk Skin The given Skin * @param $includeStyle Unused (?) * @return String: The doctype, opening <html>, and head element. */ public function headElement(Skin $sk, $includeStyle = true) { global $wgDocType, $wgDTD, $wgContLanguageCode, $wgOutputEncoding, $wgMimeType; global $wgXhtmlDefaultNamespace, $wgXhtmlNamespaces, $wgHtml5Version; global $wgContLang, $wgUseTrackbacks, $wgStyleVersion, $wgHtml5, $wgWellFormedXml; global $wgUser, $wgRequest, $wgLang; $this->addMeta("http:Content-Type", "{$wgMimeType}; charset={$wgOutputEncoding}"); if ($sk->commonPrintStylesheet()) { $this->addStyle('common/wikiprintable.css', 'print'); } $sk->setupUserCss($this); $ret = ''; if ($wgMimeType == 'text/xml' || $wgMimeType == 'application/xhtml+xml' || $wgMimeType == 'application/xml') { $ret .= "<?xml version=\"1.0\" encoding=\"{$wgOutputEncoding}\" ?" . ">\n"; } if ($this->getHTMLTitle() == '') { $this->setHTMLTitle(wfMsg('pagetitle', $this->getPageTitle())); } $dir = $wgContLang->getDir(); if ($wgHtml5) { if ($wgWellFormedXml) { # Unknown elements and attributes are okay in XML, but unknown # named entities are well-formedness errors and will break XML # parsers. Thus we need a doctype that gives us appropriate # entity definitions. The HTML5 spec permits four legacy # doctypes as obsolete but conforming, so let's pick one of # those, although it makes our pages look like XHTML1 Strict. # Isn't compatibility great? $ret .= "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"; } else { # Much saner. $ret .= "<!doctype html>\n"; } $ret .= "<html lang=\"{$wgContLanguageCode}\" dir=\"{$dir}\""; if ($wgHtml5Version) { $ret .= " version=\"{$wgHtml5Version}\""; } $ret .= ">\n"; } else { $ret .= "<!DOCTYPE html PUBLIC \"{$wgDocType}\" \"{$wgDTD}\">\n"; $ret .= "<html xmlns=\"{$wgXhtmlDefaultNamespace}\" "; foreach ($wgXhtmlNamespaces as $tag => $ns) { $ret .= "xmlns:{$tag}=\"{$ns}\" "; } $ret .= "lang=\"{$wgContLanguageCode}\" dir=\"{$dir}\">\n"; } $ret .= "<head>\n"; $ret .= "<title>" . htmlspecialchars($this->getHTMLTitle()) . "</title>\n"; $ret .= implode("\n", array($this->getHeadLinks(), $this->buildCssLinks(), $this->getHeadScripts($sk), $this->getHeadItems())); if ($sk->usercss) { $ret .= Html::inlineStyle($sk->usercss); } if ($wgUseTrackbacks && $this->isArticleRelated()) { $ret .= $this->getTitle()->trackbackRDF(); } $ret .= "</head>\n"; $bodyAttrs = array(); # Crazy edit-on-double-click stuff $action = $wgRequest->getVal('action', 'view'); if ($this->getTitle()->getNamespace() != NS_SPECIAL && !in_array($action, array('edit', 'submit')) && $wgUser->getOption('editondblclick')) { $bodyAttrs['ondblclick'] = "document.location = '" . Xml::escapeJsString($this->getTitle()->getEditURL()) . "'"; } # Class bloat $bodyAttrs['class'] = "mediawiki {$dir}"; if ($wgLang->capitalizeAllNouns()) { # A <body> class is probably not the best way to do this . . . $bodyAttrs['class'] .= ' capitalize-all-nouns'; } $bodyAttrs['class'] .= ' ns-' . $this->getTitle()->getNamespace(); if ($this->getTitle()->getNamespace() == NS_SPECIAL) { $bodyAttrs['class'] .= ' ns-special'; } elseif ($this->getTitle()->isTalkPage()) { $bodyAttrs['class'] .= ' ns-talk'; } else { $bodyAttrs['class'] .= ' ns-subject'; } $bodyAttrs['class'] .= ' ' . Sanitizer::escapeClass('page-' . $this->getTitle()->getPrefixedText()); $bodyAttrs['class'] .= ' skin-' . Sanitizer::escapeClass($wgUser->getSkin()->getSkinName()); $ret .= Html::openElement('body', $bodyAttrs) . "\n"; return $ret; }
function getBodyOptions() { global $wgUser, $wgTitle, $wgOut, $wgRequest, $wgContLang; extract($wgRequest->getValues('oldid', 'redirect', 'diff')); if (0 != $wgTitle->getNamespace()) { $a = array('bgcolor' => '#ffffec'); } else { $a = array('bgcolor' => '#FFFFFF'); } if ($wgOut->isArticle() && $wgUser->getOption('editondblclick') && $wgTitle->userCan('edit')) { $s = $wgTitle->getFullURL($this->editUrlOptions()); $s = 'document.location = "' . wfEscapeJSString($s) . '";'; $a += array('ondblclick' => $s); } $a['onload'] = $wgOut->getOnloadHandler(); if ($wgUser->getOption('editsectiononrightclick')) { if ($a['onload'] != '') { $a['onload'] .= ';'; } $a['onload'] .= 'setupRightClickEdit()'; } $a['class'] = 'ns-' . $wgTitle->getNamespace() . ' ' . ($wgContLang->isRTL() ? "rtl" : "ltr") . ' ' . Sanitizer::escapeClass('page-' . $wgTitle->getPrefixedText()); return $a; }
function getPageClasses($title) { $numeric = 'ns-' . $title->getNamespace(); if ($title->getNamespace() == NS_SPECIAL) { $type = "ns-special"; } elseif ($title->isTalkPage()) { $type = "ns-talk"; } else { $type = "ns-subject"; } $name = Sanitizer::escapeClass('page-' . $title->getPrefixedText()); return "{$numeric} {$type} {$name}"; }
/** * Provide the "<abbr>" element appropriate to a given abbreviated flag, * namely the flag indicating a new page, a minor edit, a bot edit, or an * unpatrolled edit. By default in English it will contain "N", "m", "b", * "!" respectively, plus it will have an appropriate title and class. * * @param string $flag One key of $wgRecentChangesFlags * @return string Raw HTML */ public static function flag($flag) { static $flagInfos = null; if (is_null($flagInfos)) { global $wgRecentChangesFlags; $flagInfos = array(); foreach ($wgRecentChangesFlags as $key => $value) { $flagInfos[$key]['letter'] = wfMessage($value['letter'])->escaped(); $flagInfos[$key]['title'] = wfMessage($value['title'])->escaped(); // Allow customized class name, fall back to flag name $flagInfos[$key]['class'] = Sanitizer::escapeClass(isset($value['class']) ? $value['class'] : $key); } } // Inconsistent naming, bleh, kepted for b/c $map = array('minoredit' => 'minor', 'botedit' => 'bot'); if (isset($map[$flag])) { $flag = $map[$flag]; } return "<abbr class='" . $flagInfos[$flag]['class'] . "' title='" . $flagInfos[$flag]['title'] . "'>" . $flagInfos[$flag]['letter'] . '</abbr>'; }
/** * Return the legend displayed within the fieldset * * @return string */ public function makeLegend() { $context = $this->getContext(); $user = $context->getUser(); # The legend showing what the letters and stuff mean $legend = Html::openElement('dl') . "\n"; # Iterates through them and gets the messages for both letter and tooltip $legendItems = $context->getConfig()->get('RecentChangesFlags'); if (!($user->useRCPatrol() || $user->useNPPatrol())) { unset($legendItems['unpatrolled']); } foreach ($legendItems as $key => $item) { # generate items of the legend $label = isset($item['legend']) ? $item['legend'] : $item['title']; $letter = $item['letter']; $cssClass = isset($item['class']) ? $item['class'] : $key; $legend .= Html::element('dt', ['class' => $cssClass], $context->msg($letter)->text()) . "\n" . Html::rawElement('dd', ['class' => Sanitizer::escapeClass('mw-changeslist-legend-' . $key)], $context->msg($label)->parse()) . "\n"; } # (+-123) $legend .= Html::rawElement('dt', ['class' => 'mw-plusminus-pos'], $context->msg('recentchanges-legend-plusminus')->parse()) . "\n"; $legend .= Html::element('dd', ['class' => 'mw-changeslist-legend-plusminus'], $context->msg('recentchanges-label-plusminus')->text()) . "\n"; $legend .= Html::closeElement('dl') . "\n"; # Collapsibility $legend = '<div class="mw-changeslist-legend">' . $context->msg('recentchanges-legend-heading')->parse() . '<div class="mw-collapsible-content">' . $legend . '</div>' . '</div>'; return $legend; }
/** * @param $sk Skin The given Skin * @param $includeStyle Boolean: unused * @return String: The doctype, opening <html>, and head element. */ public function headElement(Skin $sk, $includeStyle = true) { global $wgContLang, $wgUseTrackbacks; $userdir = $this->getLang()->getDir(); $sitedir = $wgContLang->getDir(); if ($sk->commonPrintStylesheet()) { $this->addModuleStyles('mediawiki.legacy.wikiprintable'); } $sk->setupUserCss($this); $ret = Html::htmlHeader(array('lang' => $this->getLang()->getCode(), 'dir' => $userdir, 'class' => 'client-nojs')); if ($this->getHTMLTitle() == '') { $this->setHTMLTitle(wfMsg('pagetitle', $this->getPageTitle())); } $openHead = Html::openElement('head'); if ($openHead) { # Don't bother with the newline if $head == '' $ret .= "{$openHead}\n"; } $ret .= Html::element('title', null, $this->getHTMLTitle()) . "\n"; $ret .= implode("\n", array($this->getHeadLinks($sk, true), $this->buildCssLinks($sk), $this->getHeadScripts($sk), $this->getHeadItems())); if ($wgUseTrackbacks && $this->isArticleRelated()) { $ret .= $this->getTitle()->trackbackRDF(); } $closeHead = Html::closeElement('head'); if ($closeHead) { $ret .= "{$closeHead}\n"; } $bodyAttrs = array(); # Crazy edit-on-double-click stuff $action = $this->getRequest()->getVal('action', 'view'); if ($this->getTitle()->getNamespace() != NS_SPECIAL && in_array($action, array('view', 'purge')) && $this->getUser()->getOption('editondblclick')) { $editUrl = $this->getTitle()->getLocalUrl($sk->editUrlOptions()); $bodyAttrs['ondblclick'] = "document.location = '" . Xml::escapeJsString($editUrl) . "'"; } # Classes for LTR/RTL directionality support $bodyAttrs['class'] = "mediawiki {$userdir} sitedir-{$sitedir}"; if ($this->getContext()->getLang()->capitalizeAllNouns()) { # A <body> class is probably not the best way to do this . . . $bodyAttrs['class'] .= ' capitalize-all-nouns'; } $bodyAttrs['class'] .= ' ' . $sk->getPageClasses($this->getTitle()); $bodyAttrs['class'] .= ' skin-' . Sanitizer::escapeClass($sk->getSkinName()); $sk->addToBodyAttributes($this, $bodyAttrs); // Allow skins to add body attributes they need wfRunHooks('OutputPageBodyAttributes', array($this, $sk, &$bodyAttrs)); $ret .= Html::openElement('body', $bodyAttrs) . "\n"; return $ret; }
/** * Get a list of rendered edit notices for this page. * * Array is keyed by the original message key, and values are rendered using parseAsBlock, so * they will already be wrapped in paragraphs. * * @since 1.21 * @param int $oldid Revision ID that's being edited * @return array */ public function getEditNotices($oldid = 0) { $notices = array(); // Optional notice for the entire namespace $editnotice_ns = 'editnotice-' . $this->getNamespace(); $msg = wfMessage($editnotice_ns); if ($msg->exists()) { $html = $msg->parseAsBlock(); // Edit notices may have complex logic, but output nothing (T91715) if (trim($html) !== '') { $notices[$editnotice_ns] = Html::rawElement('div', array('class' => array('mw-editnotice', 'mw-editnotice-namespace', Sanitizer::escapeClass("mw-{$editnotice_ns}"))), $html); } } if (MWNamespace::hasSubpages($this->getNamespace())) { // Optional notice for page itself and any parent page $parts = explode('/', $this->getDBkey()); $editnotice_base = $editnotice_ns; while (count($parts) > 0) { $editnotice_base .= '-' . array_shift($parts); $msg = wfMessage($editnotice_base); if ($msg->exists()) { $html = $msg->parseAsBlock(); if (trim($html) !== '') { $notices[$editnotice_base] = Html::rawElement('div', array('class' => array('mw-editnotice', 'mw-editnotice-base', Sanitizer::escapeClass("mw-{$editnotice_base}"))), $html); } } } } else { // Even if there are no subpages in namespace, we still don't want "/" in MediaWiki message keys $editnoticeText = $editnotice_ns . '-' . strtr($this->getDBkey(), '/', '-'); $msg = wfMessage($editnoticeText); if ($msg->exists()) { $html = $msg->parseAsBlock(); if (trim($html) !== '') { $notices[$editnoticeText] = Html::rawElement('div', array('class' => array('mw-editnotice', 'mw-editnotice-page', Sanitizer::escapeClass("mw-{$editnoticeText}"))), $html); } } } Hooks::run('TitleGetEditNotices', array($this, $oldid, &$notices)); return $notices; }
/** * Enhanced RC ungrouped line. * * @param $rcObj RecentChange * @return String: a HTML formatted line (generated using $r) */ protected function recentChangesBlockLine( $rcObj ) { global $wgRCShowChangedSize; wfProfileIn( __METHOD__ ); $query['curid'] = $rcObj->mAttribs['rc_cur_id']; $type = $rcObj->mAttribs['rc_type']; $logType = $rcObj->mAttribs['rc_log_type']; $classes = array( 'mw-enhanced-rc' ); if ( $logType ) { # Log entry + $classes[] = Sanitizer::escapeClass( 'mw-changeslist-log-' . $logType ); } else { $classes[] = Sanitizer::escapeClass( 'mw-changeslist-ns' . $rcObj->mAttribs['rc_namespace'] . '-' . $rcObj->mAttribs['rc_title'] ); } $classes[] = $rcObj->watched && $rcObj->mAttribs['rc_timestamp'] >= $rcObj->watched ? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched'; $r = Html::openElement( 'table', array( 'class' => $classes ) ) . Html::openElement( 'tr' ); $r .= '<td class="mw-enhanced-rc"><span class="mw-enhancedchanges-arrow-space"></span>'; # Flag and Timestamp if ( $type == RC_MOVE || $type == RC_MOVE_OVER_REDIRECT ) { $r .= $this->recentChangesFlags( array() ); // no flags, but need the placeholders } else { $r .= $this->recentChangesFlags( array( 'newpage' => $type == RC_NEW, 'minor' => $rcObj->mAttribs['rc_minor'], 'unpatrolled' => $rcObj->unpatrolled, 'bot' => $rcObj->mAttribs['rc_bot'], ) ); } $r .= ' ' . $rcObj->timestamp . ' </td><td>'; # Article or log link if ( $logType ) { $logPage = new LogPage( $logType ); $logTitle = SpecialPage::getTitleFor( 'Log', $logType ); $logName = $logPage->getName()->escaped(); $r .= $this->msg( 'parentheses' )->rawParams( Linker::linkKnown( $logTitle, $logName ) )->escaped(); } else { $this->insertArticleLink( $r, $rcObj, $rcObj->unpatrolled, $rcObj->watched ); } # Diff and hist links if ( $type != RC_LOG ) { $query['action'] = 'history'; $r .= ' ' . $this->msg( 'parentheses' )->rawParams( $rcObj->difflink . $this->message['pipe-separator'] . Linker::linkKnown( $rcObj->getTitle(), $this->message['hist'], array(), $query ) )->escaped(); } $r .= ' <span class="mw-changeslist-separator">. .</span> '; # Character diff if ( $wgRCShowChangedSize ) { $cd = $this->formatCharacterDifference( $rcObj ); if ( $cd !== '' ) { $r .= $cd . ' <span class="mw-changeslist-separator">. .</span> '; } } if ( $type == RC_LOG ) { $r .= $this->insertLogEntry( $rcObj ); } else { $r .= ' ' . $rcObj->userlink . $rcObj->usertalklink; $r .= $this->insertComment( $rcObj ); $this->insertRollback( $r, $rcObj ); } # Tags $this->insertTags( $r, $rcObj, $classes ); # Show how many people are watching this if enabled $r .= $this->numberofWatchingusers( $rcObj->numberofWatchingusers ); $r .= "</td></tr></table>\n"; wfProfileOut( __METHOD__ ); return $r; }
/** * @param Skin $sk The given Skin * @param bool $includeStyle Unused * @return string The doctype, opening "<html>", and head element. */ public function headElement(Skin $sk, $includeStyle = true) { global $wgContLang; $userdir = $this->getLanguage()->getDir(); $sitedir = $wgContLang->getDir(); $ret = Html::htmlHeader($sk->getHtmlElementAttributes()); if ($this->getHTMLTitle() == '') { $this->setHTMLTitle($this->msg('pagetitle', $this->getPageTitle())->inContentLanguage()); } $openHead = Html::openElement('head'); if ($openHead) { # Don't bother with the newline if $head == '' $ret .= "{$openHead}\n"; } if (!Html::isXmlMimeType($this->getConfig()->get('MimeType'))) { // Add <meta charset="UTF-8"> // This should be before <title> since it defines the charset used by // text including the text inside <title>. // The spec recommends defining XHTML5's charset using the XML declaration // instead of meta. // Our XML declaration is output by Html::htmlHeader. // http://www.whatwg.org/html/semantics.html#attr-meta-http-equiv-content-type // http://www.whatwg.org/html/semantics.html#charset $ret .= Html::element('meta', array('charset' => 'UTF-8')) . "\n"; } $ret .= Html::element('title', null, $this->getHTMLTitle()) . "\n"; foreach ($this->getHeadLinksArray() as $item) { $ret .= $item . "\n"; } // No newline after buildCssLinks since makeResourceLoaderLink did that already $ret .= $this->buildCssLinks(); $ret .= $this->getHeadScripts() . "\n"; foreach ($this->mHeadItems as $item) { $ret .= $item . "\n"; } $closeHead = Html::closeElement('head'); if ($closeHead) { $ret .= "{$closeHead}\n"; } $bodyClasses = array(); $bodyClasses[] = 'mediawiki'; # Classes for LTR/RTL directionality support $bodyClasses[] = $userdir; $bodyClasses[] = "sitedir-{$sitedir}"; if ($this->getLanguage()->capitalizeAllNouns()) { # A <body> class is probably not the best way to do this . . . $bodyClasses[] = 'capitalize-all-nouns'; } $bodyClasses[] = $sk->getPageClasses($this->getTitle()); $bodyClasses[] = 'skin-' . Sanitizer::escapeClass($sk->getSkinName()); $bodyClasses[] = 'action-' . Sanitizer::escapeClass(Action::getActionName($this->getContext())); $bodyAttrs = array(); // While the implode() is not strictly needed, it's used for backwards compatibility // (this used to be built as a string and hooks likely still expect that). $bodyAttrs['class'] = implode(' ', $bodyClasses); // Allow skins and extensions to add body attributes they need $sk->addToBodyAttributes($this, $bodyAttrs); Hooks::run('OutputPageBodyAttributes', array($this, $sk, &$bodyAttrs)); $ret .= Html::openElement('body', $bodyAttrs) . "\n"; return $ret; }
/** * @param Skin $sk The given Skin * @param bool $includeStyle Unused * @return string The doctype, opening "<html>", and head element. */ public function headElement(Skin $sk, $includeStyle = true) { global $wgContLang; $userdir = $this->getLanguage()->getDir(); $sitedir = $wgContLang->getDir(); $pieces = []; $pieces[] = Html::htmlHeader(Sanitizer::mergeAttributes($this->getRlClient()->getDocumentAttributes(), $sk->getHtmlElementAttributes())); $pieces[] = Html::openElement('head'); if ($this->getHTMLTitle() == '') { $this->setHTMLTitle($this->msg('pagetitle', $this->getPageTitle())->inContentLanguage()); } if (!Html::isXmlMimeType($this->getConfig()->get('MimeType'))) { // Add <meta charset="UTF-8"> // This should be before <title> since it defines the charset used by // text including the text inside <title>. // The spec recommends defining XHTML5's charset using the XML declaration // instead of meta. // Our XML declaration is output by Html::htmlHeader. // http://www.whatwg.org/html/semantics.html#attr-meta-http-equiv-content-type // http://www.whatwg.org/html/semantics.html#charset $pieces[] = Html::element('meta', ['charset' => 'UTF-8']); } $pieces[] = Html::element('title', null, $this->getHTMLTitle()); $pieces[] = $this->getRlClient()->getHeadHtml(); $pieces[] = $this->buildExemptModules(); $pieces = array_merge($pieces, array_values($this->getHeadLinksArray())); $pieces = array_merge($pieces, array_values($this->mHeadItems)); $pieces[] = Html::closeElement('head'); $bodyClasses = []; $bodyClasses[] = 'mediawiki'; # Classes for LTR/RTL directionality support $bodyClasses[] = $userdir; $bodyClasses[] = "sitedir-{$sitedir}"; if ($this->getLanguage()->capitalizeAllNouns()) { # A <body> class is probably not the best way to do this . . . $bodyClasses[] = 'capitalize-all-nouns'; } // Parser feature migration class // The idea is that this will eventually be removed, after the wikitext // which requires it is cleaned up. $bodyClasses[] = 'mw-hide-empty-elt'; $bodyClasses[] = $sk->getPageClasses($this->getTitle()); $bodyClasses[] = 'skin-' . Sanitizer::escapeClass($sk->getSkinName()); $bodyClasses[] = 'action-' . Sanitizer::escapeClass(Action::getActionName($this->getContext())); $bodyAttrs = []; // While the implode() is not strictly needed, it's used for backwards compatibility // (this used to be built as a string and hooks likely still expect that). $bodyAttrs['class'] = implode(' ', $bodyClasses); // Allow skins and extensions to add body attributes they need $sk->addToBodyAttributes($this, $bodyAttrs); Hooks::run('OutputPageBodyAttributes', [$this, $sk, &$bodyAttrs]); $pieces[] = Html::openElement('body', $bodyAttrs); return self::combineWrappedStrings($pieces); }