protected function showLanguage($code, $users) { $out = $this->getOutput(); $lang = $this->getLanguage(); $usernames = array_keys($users); $userStats = $this->getUserStats($usernames); // Information to be used inside the foreach loop. $linkInfo = array(); $linkInfo['rc']['title'] = SpecialPage::getTitleFor('Recentchanges'); $linkInfo['rc']['msg'] = $this->msg('supportedlanguages-recenttranslations')->escaped(); $linkInfo['stats']['title'] = SpecialPage::getTitleFor('LanguageStats'); $linkInfo['stats']['msg'] = $this->msg('languagestats')->escaped(); $local = Language::fetchLanguageName($code, $lang->getCode(), 'all'); $native = Language::fetchLanguageName($code, null, 'all'); if ($local !== $native) { $headerText = $this->msg('supportedlanguages-portallink')->params($code, $local, $native)->escaped(); } else { // No CLDR, so a less localised header and link title. $headerText = $this->msg('supportedlanguages-portallink-nocldr')->params($code, $native)->escaped(); } $out->addHtml(Html::rawElement('h2', array('id' => $code), $headerText)); // Add useful links for language stats and recent changes for the language. $links = array(); $links[] = Linker::link($linkInfo['stats']['title'], $linkInfo['stats']['msg'], array(), array('code' => $code, 'suppresscomplete' => '1'), array('known', 'noclasses')); $links[] = Linker::link($linkInfo['rc']['title'], $linkInfo['rc']['msg'], array(), array('translations' => 'only', 'trailer' => "/" . $code), array('known', 'noclasses')); $linkList = $lang->listToText($links); $out->addHTML("<p>" . $linkList . "</p>\n"); $this->makeUserList($users, $userStats); }
private function makeLanguageLinks() { global $wgWRLanguageLinksShowOnly, $wgWRLanguageLinksShowTitles; // Language links - ripped from SkinTemplate.php and then mangled badly $parserLanguageLinks = $this->mParser->getOutput()->getLanguageLinks(); $language_urls = array(); $showOnly = array(); if ($wgWRLanguageLinksShowOnly != null) { $showOnly = explode(',', $wgWRLanguageLinksShowOnly); } foreach ($parserLanguageLinks as $languageLinkText) { $languageLinkTitle = Title::newFromText($languageLinkText); if ($languageLinkTitle) { $ilInterwikiCode = $languageLinkTitle->getInterwiki(); if (is_null($wgWRLanguageLinksShowOnly) || in_array($ilInterwikiCode, $showOnly)) { $ilLangName = Language::fetchLanguageName($ilInterwikiCode); if (strval($ilLangName) === '') { $ilLangName = $languageLinkText; } $ilArticleName = $languageLinkTitle->getText(); $language_urls[] = array('href' => $languageLinkTitle->getFullURL(), 'text' => $wgWRLanguageLinksShowTitles ? $ilArticleName : $ilLangName, 'title' => $wgWRLanguageLinksShowTitles ? $ilLangName : $ilArticleName, 'class' => "wr-languagelinks-{$ilInterwikiCode}", 'lang' => $ilInterwikiCode); } } } return $language_urls; }
function wfGlobalInterwikis($prefix, &$iwData) { global $wgInterwikiCentralDB; // docs/hooks.txt says: Return true without providing an interwiki to continue interwiki search. if ($wgInterwikiCentralDB === null || $wgInterwikiCentralDB === wfWikiId()) { // No global set or this is global, nothing to add return true; } if (!Language::fetchLanguageName($prefix)) { // Check if prefix exists locally and skip foreach (Interwiki::getAllPrefixes(null) as $id => $localPrefixInfo) { if ($prefix === $localPrefixInfo['iw_prefix']) { return true; } } $dbr = wfGetDB(DB_SLAVE, array(), $wgInterwikiCentralDB); $res = $dbr->selectRow('interwiki', '*', array('iw_prefix' => $prefix), __METHOD__); if (!$res) { return true; } // Excplicitly make this an array since it's expected to be one $iwData = (array) $res; // At this point, we can safely return false because we know that we have something return false; } return true; }
public function __construct($name = null, array $data = array(), $dataName = '', $engineName = null) { parent::__construct($name, $data, $dataName, $engineName); // Skip certain tests if something isn't providing translated language names // (bug 67343) if (Language::fetchLanguageName('en', 'fr') === 'English') { $msg = 'Language name translations are unavailable; ' . 'install Extension:CLDR or something similar'; $this->skipTests += array('fetchLanguageName (en,ru)' => $msg, 'fetchLanguageName (ru,en)' => $msg, 'fetchLanguageNames (de)' => $msg, 'fetchLanguageNames ([[bogus]])' => $msg); } }
/** * Fetches appropriate HTML for the tutorial portion of the wizard. * Looks up an image on the current wiki. This will work as is on Commons, and will also work * on test wikis that enable instantCommons. * @param String|null $campaign Upload Wizard campaign for which the tutorial should be displayed. * @return String html that will display the tutorial. */ public static function getHtml($campaign = null) { global $wgLang; $error = null; $errorHtml = ''; $tutorialHtml = ''; $langCode = $wgLang->getCode(); $tutorial = UploadWizardConfig::getSetting('tutorial', $campaign); // getFile returns false if it can't find the right file $tutorialFile = self::getFile($langCode, $tutorial); if ($tutorialFile === false) { $error = 'localized-file-missing'; foreach ($wgLang->getFallbackLanguages() as $langCode) { $tutorialFile = self::getFile($langCode, $tutorial); if ($tutorialFile !== false) { // $langCode remains as the code where a file is found. break; } } } // at this point, we have one of the following situations: // $error is null, and tutorialFile is the right one for this language // $error notes we couldn't find the tutorialFile for your language, and $tutorialFile is the english one // $error notes we couldn't find the tutorialFile for your language, and $tutorialFile is still false (major file failure) if ($tutorialFile) { // XXX TODO if the client can handle SVG, we could also just send it the unscaled thumb, client-scaled into a DIV or something. // if ( client can handle SVG ) { // $tutorialThumbnailImage->getUnscaledThumb(); // } // put it into a div of appropriate dimensions. // n.b. File::transform() returns false if failed, MediaTransformOutput otherwise $thumbnailImage = $tutorialFile->transform(array('width' => $tutorial['width'])); if ($thumbnailImage) { $tutorialHtml = self::getImageHtml($thumbnailImage, $tutorial); } else { $error = 'cannot-transform'; } } else { $error = 'file-missing'; } if ($error !== null) { // Messages: // mwe-upwiz-tutorial-error-localized-file-missing, mwe-upwiz-tutorial-error-file-missing, // mwe-upwiz-tutorial-error-cannot-transform $errorMsg = wfMessage('mwe-upwiz-tutorial-error-' . $error); if ($error === 'localized-file-missing') { $errorMsg->params(Language::fetchLanguageName($langCode, $wgLang->getCode())); } $errorHtml = Html::element('p', array('class' => 'errorbox', 'style' => 'float: none;'), $errorMsg->text()); } return $errorHtml . $tutorialHtml; }
/** * Takes a language code, and attempt to obtain a better variant of it, * checks the MediaWiki language codes for a match, otherwise checks the * Babel language codes CDB (preferring ISO 639-1 over ISO 639-3). * * @param $code String: Code to try and get a "better" code for. * @return String (language code) or false (invalid language code). */ public static function getCode($code) { wfProfileIn(__METHOD__); global $wgBabelLanguageCodesCdb; $mediawiki = Language::fetchLanguageName($code); if ($mediawiki !== '') { wfProfileOut(__METHOD__); return $code; } $codesCdb = CdbReader::open($wgBabelLanguageCodesCdb); $codes = $codesCdb->get($code); wfProfileOut(__METHOD__); return $codes; }
/** * Returns a WikitextContent object representing a redirect to the given destination page. * * @param Title $destination The page to redirect to. * @param string $text Text to include in the redirect, if possible. * * @return Content * * @see ContentHandler::makeRedirectContent */ public function makeRedirectContent(Title $destination, $text = '') { $optionalColon = ''; if ($destination->getNamespace() == NS_CATEGORY) { $optionalColon = ':'; } else { $iw = $destination->getInterwiki(); if ($iw && Language::fetchLanguageName($iw, null, 'mw')) { $optionalColon = ':'; } } $mwRedir = MagicWord::get('redirect'); $redirectText = $mwRedir->getSynonym(0) . ' [[' . $optionalColon . $destination->getFullText() . ']]'; if ($text != '') { $redirectText .= "\n" . $text; } return new WikitextContent($redirectText); }
/** * Takes a language code, and attempt to obtain a better variant of it, * checks the MediaWiki language codes for a match, otherwise checks the * Babel language codes CDB (preferring ISO 639-1 over ISO 639-3). * * @param $code String: Code to try and get a "better" code for. * @return String (language code) or false (invalid language code). */ public static function getCode($code) { wfProfileIn(__METHOD__); global $wgBabelLanguageCodesCdb; $mediawiki = Language::fetchLanguageName($code); if ($mediawiki !== '') { wfProfileOut(__METHOD__); return $code; } $codes = false; try { $codesCdb = CdbReader::open($wgBabelLanguageCodesCdb); $codes = $codesCdb->get($code); } catch (CdbException $e) { wfDebug(__METHOD__ . ": CdbException caught, error message was " . $e->getMessage()); } wfProfileOut(__METHOD__); return $codes; }
function heading() { global $wgDummyLanguageCodes; $version = SpecialVersion::getVersion('nodb'); echo "'''Statistics are based on:''' <code>" . $version . "</code>\n\n"; echo "'''Note:''' These statistics can be generated by running " . "<code>php maintenance/language/transstat.php</code>.\n\n"; echo "For additional information on specific languages (the message names, the actual " . "problems, etc.), run <code>php maintenance/language/checkLanguage.php --lang=foo</code>.\n\n"; echo 'English (en) is excluded because it is the default localization'; if (is_array($wgDummyLanguageCodes)) { $dummyCodes = array(); foreach ($wgDummyLanguageCodes as $dummyCode => $correctCode) { $dummyCodes[] = Language::fetchLanguageName($dummyCode) . ' (' . $dummyCode . ')'; } echo ', as well as the following languages that are not intended for ' . 'system message translations, usually because they redirect to other ' . 'language codes: ' . implode(', ', $dummyCodes); } echo ".\n\n"; # dot to end sentence echo '{| class="sortable wikitable" border="2" style="background-color: #F9F9F9; ' . 'border: 1px #AAAAAA solid; border-collapse: collapse; clear:both; width:100%;"' . "\n"; }
public function execute() { $dbw = wfGetDB(DB_SLAVE); // Get all Athena logs $res = $dbw->select(array('athena_page_details'), array('al_id', 'apd_language', 'apd_content'), array(), __METHOD__, array(), array()); foreach ($res as $row) { echo "\n----------------------------------------------\n"; echo "al_id is {$row->al_id} \n"; echo "apd_language is {$row->apd_language} \n"; $content = $row->apd_content; if (strlen($content) == 0) { $code = null; } else { file_put_contents("temp", $content); $code = system("franc < temp"); } $code = AthenaHelper::convertISOCode($code); echo "Language code is {$code}\n"; $str = $dbw->strencode(Language::fetchLanguageName($code)); echo "Language name is {$str} \n"; $dbw->update('athena_page_details', array('apd_language' => $str), array('al_id' => $row->al_id), __METHOD__, null); echo "\n----------------------------------------------\n"; } }
protected function getMessageParameters() { // Get the user language for displaying language names $userLang = $this->context->getLanguage()->getCode(); $params = parent::getMessageParameters(); // Get the language codes from log $oldLang = $params[3]; $kOld = strrpos($oldLang, '['); if ($kOld) { $oldLang = substr($oldLang, 0, $kOld); } $newLang = $params[4]; $kNew = strrpos($newLang, '['); if ($kNew) { $newLang = substr($newLang, 0, $kNew); } // Convert language codes to names in user language $logOld = Language::fetchLanguageName($oldLang, $userLang) . ' (' . $oldLang . ')'; $logNew = Language::fetchLanguageName($newLang, $userLang) . ' (' . $newLang . ')'; // Add the default message to languages if required $params[3] = !$kOld ? $logOld : $logOld . ' [' . $this->msg('default') . ']'; $params[4] = !$kNew ? $logNew : $logNew . ' [' . $this->msg('default') . ']'; return $params; }
public function execute() { global $wgTranslateFuzzyBotName, $wgSitename; $days = (int) $this->getOption('days', 30); $hours = $days * 24; $top = (int) $this->getOption('top', -1); $bots = $this->hasOption('bots'); $namespaces = array(); if ($this->hasOption('ns')) { $input = explode(',', $this->getOption('ns')); foreach ($input as $namespace) { if (is_numeric($namespace)) { $namespaces[] = $namespace; } } } // Select set of edits to report on // Fetch some extrac fields that normally TranslateUtils::translationChanges wont $extraFields = array('rc_old_len', 'rc_new_len'); $rows = TranslateUtils::translationChanges($hours, $bots, $namespaces, $extraFields); // Get counts for edits per language code after filtering out edits by FuzzyBot $codes = array(); foreach ($rows as $_) { // Filter out edits by $wgTranslateFuzzyBotName if ($_->rc_user_text === $wgTranslateFuzzyBotName) { continue; } $handle = new MessageHandle(Title::newFromText($_->rc_title)); $code = $handle->getCode(); if (!isset($codes[$code])) { $codes[$code] = 0; } if ($this->hasOption('diff')) { $diff = abs($_->rc_new_len - $_->rc_old_len); } else { $diff = $_->rc_new_len; } $codes[$code] += $diff; } // Sort counts and report descending up to $top rows. arsort($codes); $i = 0; $total = 0; $this->output("Character edit stats for last {$days} days in {$wgSitename}\n"); $this->output("code\tname\tedit\n"); $this->output("-----------------------\n"); foreach ($codes as $code => $num) { if ($i++ === $top) { break; } $language = Language::fetchLanguageName($code); if (!$language) { // this will be very rare, but avoid division by zero in next line continue; } $charRatio = mb_strlen($language, 'UTF-8') / strlen($language); $num = intval($num * $charRatio); $total += $num; $this->output("{$code}\t{$language}\t{$num}\n"); } $this->output("-----------------------\n"); $this->output("Total\t\t{$total}\n"); }
public function execute() { if ($this->getPageSet()->getGoodTitleCount() == 0) { return; } $params = $this->extractRequestParams(); $prop = array_flip((array) $params['prop']); if (isset($params['title']) && !isset($params['lang'])) { $this->dieUsageMsg(array('missingparam', 'lang')); } // Handle deprecated param $this->requireMaxOneParameter($params, 'url', 'prop'); if ($params['url']) { $prop = array('url' => 1); } $this->addFields(array('ll_from', 'll_lang', 'll_title')); $this->addTables('langlinks'); $this->addWhereFld('ll_from', array_keys($this->getPageSet()->getGoodTitles())); if (!is_null($params['continue'])) { $cont = explode('|', $params['continue']); $this->dieContinueUsageIf(count($cont) != 2); $op = $params['dir'] == 'descending' ? '<' : '>'; $llfrom = intval($cont[0]); $lllang = $this->getDB()->addQuotes($cont[1]); $this->addWhere("ll_from {$op} {$llfrom} OR " . "(ll_from = {$llfrom} AND " . "ll_lang {$op}= {$lllang})"); } // FIXME: (follow-up) To allow extensions to add to the language links, we need // to load them all, add the extra links, then apply paging. // Should not be terrible, it's not going to be more than a few hundred links. // Note that, since (ll_from, ll_lang) is a unique key, we don't need // to sort by ll_title to ensure deterministic ordering. $sort = $params['dir'] == 'descending' ? ' DESC' : ''; if (isset($params['lang'])) { $this->addWhereFld('ll_lang', $params['lang']); if (isset($params['title'])) { $this->addWhereFld('ll_title', $params['title']); } $this->addOption('ORDER BY', 'll_from' . $sort); } else { // Don't order by ll_from if it's constant in the WHERE clause if (count($this->getPageSet()->getGoodTitles()) == 1) { $this->addOption('ORDER BY', 'll_lang' . $sort); } else { $this->addOption('ORDER BY', array('ll_from' . $sort, 'll_lang' . $sort)); } } $this->addOption('LIMIT', $params['limit'] + 1); $res = $this->select(__METHOD__); $count = 0; foreach ($res as $row) { if (++$count > $params['limit']) { // We've reached the one extra which shows that // there are additional pages to be had. Stop here... $this->setContinueEnumParameter('continue', "{$row->ll_from}|{$row->ll_lang}"); break; } $entry = array('lang' => $row->ll_lang); if (isset($prop['url'])) { $title = Title::newFromText("{$row->ll_lang}:{$row->ll_title}"); if ($title) { $entry['url'] = wfExpandUrl($title->getFullURL(), PROTO_CURRENT); } } if (isset($prop['langname'])) { $entry['langname'] = Language::fetchLanguageName($row->ll_lang, $params['inlanguagecode']); } if (isset($prop['autonym'])) { $entry['autonym'] = Language::fetchLanguageName($row->ll_lang); } ApiResult::setContentValue($entry, 'title', $row->ll_title); $fit = $this->addPageSubItem($row->ll_from, $entry); if (!$fit) { $this->setContinueEnumParameter('continue', "{$row->ll_from}|{$row->ll_lang}"); break; } } }
/** * Generates array of language links for the current page * * @return array */ public function getLanguages() { global $wgHideInterlanguageLinks; if ($wgHideInterlanguageLinks) { return array(); } $userLang = $this->getLanguage(); $languageLinks = array(); foreach ($this->getOutput()->getLanguageLinks() as $languageLinkText) { $languageLinkParts = explode(':', $languageLinkText, 2); $class = 'interlanguage-link interwiki-' . $languageLinkParts[0]; unset($languageLinkParts); $languageLinkTitle = Title::newFromText($languageLinkText); if ($languageLinkTitle) { $ilInterwikiCode = $languageLinkTitle->getInterwiki(); $ilLangName = Language::fetchLanguageName($ilInterwikiCode); if (strval($ilLangName) === '') { $ilDisplayTextMsg = wfMessage("interlanguage-link-{$ilInterwikiCode}"); if (!$ilDisplayTextMsg->isDisabled()) { // Use custom MW message for the display text $ilLangName = $ilDisplayTextMsg->text(); } else { // Last resort: fallback to the language link target $ilLangName = $languageLinkText; } } else { // Use the language autonym as display text $ilLangName = $this->formatLanguageName($ilLangName); } // CLDR extension or similar is required to localize the language name; // otherwise we'll end up with the autonym again. $ilLangLocalName = Language::fetchLanguageName($ilInterwikiCode, $userLang->getCode()); $languageLinkTitleText = $languageLinkTitle->getText(); if ($ilLangLocalName === '') { $ilFriendlySiteName = wfMessage("interlanguage-link-sitename-{$ilInterwikiCode}"); if (!$ilFriendlySiteName->isDisabled()) { if ($languageLinkTitleText === '') { $ilTitle = wfMessage('interlanguage-link-title-nonlangonly', $ilFriendlySiteName->text())->text(); } else { $ilTitle = wfMessage('interlanguage-link-title-nonlang', $languageLinkTitleText, $ilFriendlySiteName->text())->text(); } } else { // we have nothing friendly to put in the title, so fall back to // displaying the interlanguage link itself in the title text // (similar to what is done in page content) $ilTitle = $languageLinkTitle->getInterwiki() . ":{$languageLinkTitleText}"; } } elseif ($languageLinkTitleText === '') { $ilTitle = wfMessage('interlanguage-link-title-langonly', $ilLangLocalName)->text(); } else { $ilTitle = wfMessage('interlanguage-link-title', $languageLinkTitleText, $ilLangLocalName)->text(); } $ilInterwikiCodeBCP47 = wfBCP47($ilInterwikiCode); $languageLink = array('href' => $languageLinkTitle->getFullURL(), 'text' => $ilLangName, 'title' => $ilTitle, 'class' => $class, 'lang' => $ilInterwikiCodeBCP47, 'hreflang' => $ilInterwikiCodeBCP47); Hooks::run('SkinTemplateGetLanguageLink', array(&$languageLink, $languageLinkTitle, $this->getTitle(), $this->getOutput())); $languageLinks[] = $languageLink; } } return $languageLinks; }
/** * Returns page information in an easily-manipulated format. Array keys are used so extensions * may add additional information in arbitrary positions. Array values are arrays with one * element to be rendered as a header, arrays with two elements to be rendered as a table row. * * @return array */ protected function pageInfo() { global $wgContLang, $wgRCMaxAge; $user = $this->getUser(); $lang = $this->getLanguage(); $title = $this->getTitle(); $id = $title->getArticleID(); // Get page information that would be too "expensive" to retrieve by normal means $pageCounts = self::pageCounts($title, $user); // Get page properties $dbr = wfGetDB(DB_SLAVE); $result = $dbr->select('page_props', array('pp_propname', 'pp_value'), array('pp_page' => $id), __METHOD__); $pageProperties = array(); foreach ($result as $row) { $pageProperties[$row->pp_propname] = $row->pp_value; } // Basic information $pageInfo = array(); $pageInfo['header-basic'] = array(); // Display title $displayTitle = $title->getPrefixedText(); if (!empty($pageProperties['displaytitle'])) { $displayTitle = $pageProperties['displaytitle']; } $pageInfo['header-basic'][] = array($this->msg('pageinfo-display-title'), $displayTitle); // Is it a redirect? If so, where to? if ($title->isRedirect()) { $pageInfo['header-basic'][] = array($this->msg('pageinfo-redirectsto'), Linker::link($this->page->getRedirectTarget()) . $this->msg('word-separator')->text() . $this->msg('parentheses', Linker::link($this->page->getRedirectTarget(), $this->msg('pageinfo-redirectsto-info')->escaped(), array(), array('action' => 'info')))->text()); } // Default sort key $sortKey = $title->getCategorySortKey(); if (!empty($pageProperties['defaultsort'])) { $sortKey = $pageProperties['defaultsort']; } $pageInfo['header-basic'][] = array($this->msg('pageinfo-default-sort'), $sortKey); // Page length (in bytes) $pageInfo['header-basic'][] = array($this->msg('pageinfo-length'), $lang->formatNum($title->getLength())); // Page ID (number not localised, as it's a database ID) $pageInfo['header-basic'][] = array($this->msg('pageinfo-article-id'), $id); // Language in which the page content is (supposed to be) written $pageLang = $title->getPageLanguage()->getCode(); $pageInfo['header-basic'][] = array($this->msg('pageinfo-language'), Language::fetchLanguageName($pageLang, $lang->getCode()) . ' ' . $this->msg('parentheses', $pageLang)); // Search engine status $pOutput = new ParserOutput(); if (isset($pageProperties['noindex'])) { $pOutput->setIndexPolicy('noindex'); } // Use robot policy logic $policy = $this->page->getRobotPolicy('view', $pOutput); $pageInfo['header-basic'][] = array($this->msg('pageinfo-robot-policy'), $this->msg("pageinfo-robot-{$policy['index']}")); if (isset($pageCounts['views'])) { // Number of views $pageInfo['header-basic'][] = array($this->msg('pageinfo-views'), $lang->formatNum($pageCounts['views'])); } if (isset($pageCounts['watchers'])) { // Number of page watchers $pageInfo['header-basic'][] = array($this->msg('pageinfo-watchers'), $lang->formatNum($pageCounts['watchers'])); } // Redirects to this page $whatLinksHere = SpecialPage::getTitleFor('Whatlinkshere', $title->getPrefixedText()); $pageInfo['header-basic'][] = array(Linker::link($whatLinksHere, $this->msg('pageinfo-redirects-name')->escaped(), array(), array('hidelinks' => 1, 'hidetrans' => 1)), $this->msg('pageinfo-redirects-value')->numParams(count($title->getRedirectsHere()))); // Is it counted as a content page? if ($this->page->isCountable()) { $pageInfo['header-basic'][] = array($this->msg('pageinfo-contentpage'), $this->msg('pageinfo-contentpage-yes')); } // Subpages of this page, if subpages are enabled for the current NS if (MWNamespace::hasSubpages($title->getNamespace())) { $prefixIndex = SpecialPage::getTitleFor('Prefixindex', $title->getPrefixedText() . '/'); $pageInfo['header-basic'][] = array(Linker::link($prefixIndex, $this->msg('pageinfo-subpages-name')->escaped()), $this->msg('pageinfo-subpages-value')->numParams($pageCounts['subpages']['total'], $pageCounts['subpages']['redirects'], $pageCounts['subpages']['nonredirects'])); } // Page protection $pageInfo['header-restrictions'] = array(); // Is this page effected by the cascading protection of something which includes it? if ($title->isCascadeProtected()) { $cascadingFrom = ''; $sources = $title->getCascadeProtectionSources(); // Array deferencing is in PHP 5.4 :( foreach ($sources[0] as $sourceTitle) { $cascadingFrom .= Html::rawElement('li', array(), Linker::linkKnown($sourceTitle)); } $cascadingFrom = Html::rawElement('ul', array(), $cascadingFrom); $pageInfo['header-restrictions'][] = array($this->msg('pageinfo-protect-cascading-from'), $cascadingFrom); } // Is out protection set to cascade to other pages? if ($title->areRestrictionsCascading()) { $pageInfo['header-restrictions'][] = array($this->msg('pageinfo-protect-cascading'), $this->msg('pageinfo-protect-cascading-yes')); } // Page protection foreach ($title->getRestrictionTypes() as $restrictionType) { $protectionLevel = implode(', ', $title->getRestrictions($restrictionType)); if ($protectionLevel == '') { // Allow all users $message = $this->msg('protect-default')->escaped(); } else { // Administrators only $message = $this->msg("protect-level-{$protectionLevel}"); if ($message->isDisabled()) { // Require "$1" permission $message = $this->msg("protect-fallback", $protectionLevel)->parse(); } else { $message = $message->escaped(); } } $pageInfo['header-restrictions'][] = array($this->msg("restriction-{$restrictionType}"), $message); } if (!$this->page->exists()) { return $pageInfo; } // Edit history $pageInfo['header-edits'] = array(); $firstRev = $this->page->getOldestRevision(); // Page creator $pageInfo['header-edits'][] = array($this->msg('pageinfo-firstuser'), Linker::revUserTools($firstRev)); // Date of page creation $pageInfo['header-edits'][] = array($this->msg('pageinfo-firsttime'), Linker::linkKnown($title, $lang->userTimeAndDate($firstRev->getTimestamp(), $user), array(), array('oldid' => $firstRev->getId()))); // Latest editor $pageInfo['header-edits'][] = array($this->msg('pageinfo-lastuser'), Linker::revUserTools($this->page->getRevision())); // Date of latest edit $pageInfo['header-edits'][] = array($this->msg('pageinfo-lasttime'), Linker::linkKnown($title, $lang->userTimeAndDate($this->page->getTimestamp(), $user), array(), array('oldid' => $this->page->getLatest()))); // Total number of edits $pageInfo['header-edits'][] = array($this->msg('pageinfo-edits'), $lang->formatNum($pageCounts['edits'])); // Total number of distinct authors $pageInfo['header-edits'][] = array($this->msg('pageinfo-authors'), $lang->formatNum($pageCounts['authors'])); // Recent number of edits (within past 30 days) $pageInfo['header-edits'][] = array($this->msg('pageinfo-recent-edits', $lang->formatDuration($wgRCMaxAge)), $lang->formatNum($pageCounts['recent_edits'])); // Recent number of distinct authors $pageInfo['header-edits'][] = array($this->msg('pageinfo-recent-authors'), $lang->formatNum($pageCounts['recent_authors'])); // Array of MagicWord objects $magicWords = MagicWord::getDoubleUnderscoreArray(); // Array of magic word IDs $wordIDs = $magicWords->names; // Array of IDs => localized magic words $localizedWords = $wgContLang->getMagicWords(); $listItems = array(); foreach ($pageProperties as $property => $value) { if (in_array($property, $wordIDs)) { $listItems[] = Html::element('li', array(), $localizedWords[$property][1]); } } $localizedList = Html::rawElement('ul', array(), implode('', $listItems)); $hiddenCategories = $this->page->getHiddenCategories(); $transcludedTemplates = $title->getTemplateLinksFrom(); if (count($listItems) > 0 || count($hiddenCategories) > 0 || count($transcludedTemplates) > 0) { // Page properties $pageInfo['header-properties'] = array(); // Magic words if (count($listItems) > 0) { $pageInfo['header-properties'][] = array($this->msg('pageinfo-magic-words')->numParams(count($listItems)), $localizedList); } // Hidden categories if (count($hiddenCategories) > 0) { $pageInfo['header-properties'][] = array($this->msg('pageinfo-hidden-categories')->numParams(count($hiddenCategories)), Linker::formatHiddenCategories($hiddenCategories)); } // Transcluded templates if (count($transcludedTemplates) > 0) { $pageInfo['header-properties'][] = array($this->msg('pageinfo-templates')->numParams(count($transcludedTemplates)), Linker::formatTemplates($transcludedTemplates)); } } return $pageInfo; }
/** * Gives language names. * @param Parser $parser * @param string $code Language code (of which to get name) * @param string $inLanguage Language code (in which to get name) * @return string */ public static function language($parser, $code = '', $inLanguage = '') { $code = strtolower($code); $inLanguage = strtolower($inLanguage); $lang = Language::fetchLanguageName($code, $inLanguage); return $lang !== '' ? $lang : wfBCP47($code); }
private function formatLangLinks($links) { $result = array(); foreach ($links as $link) { $entry = array(); $bits = explode(':', $link, 2); $title = Title::newFromText($link); $entry['lang'] = $bits[0]; if ($title) { $entry['url'] = wfExpandUrl($title->getFullURL(), PROTO_CURRENT); // localised language name in 'uselang' language $entry['langname'] = Language::fetchLanguageName($title->getInterwiki(), $this->getLanguage()->getCode()); // native language name $entry['autonym'] = Language::fetchLanguageName($title->getInterwiki()); } ApiResult::setContentValue($entry, 'title', $bits[1]); $result[] = $entry; } return $result; }
/** * @param string $key * @return array */ public function figureMessage($key) { global $wgLanguageCode; $pieces = explode('/', $key); if (count($pieces) < 2) { return array($key, $wgLanguageCode); } $lang = array_pop($pieces); if (!Language::fetchLanguageName($lang, null, 'mw')) { return array($key, $wgLanguageCode); } $message = implode('/', $pieces); return array($message, $lang); }
$output->element('Translated', true); $output->element('%', true); $output->element('Obsolete', true); $output->element('%', true); $output->element('Problematic', true); $output->element('%', true); $output->blockend(); $wgGeneralMessages = $wgLanguages->getGeneralMessages(); $wgRequiredMessagesNumber = count($wgGeneralMessages['required']); foreach ($wgLanguages->getLanguages() as $code) { # Don't check English, RTL English or dummy language codes if ($code == 'en' || $code == 'enRTL' || is_array($wgDummyLanguageCodes) && isset($wgDummyLanguageCodes[$code])) { continue; } # Calculate the numbers $language = Language::fetchLanguageName($code); $fallback = $wgLanguages->getFallback($code); $messages = $wgLanguages->getMessages($code); $messagesNumber = count($messages['translated']); $requiredMessagesNumber = count($messages['required']); $requiredMessagesPercent = $output->formatPercent($requiredMessagesNumber, $wgRequiredMessagesNumber); $obsoleteMessagesNumber = count($messages['obsolete']); $obsoleteMessagesPercent = $output->formatPercent($obsoleteMessagesNumber, $messagesNumber, true); $messagesWithMismatchVariables = $wgLanguages->getMessagesWithMismatchVariables($code); $emptyMessages = $wgLanguages->getEmptyMessages($code); $messagesWithWhitespace = $wgLanguages->getMessagesWithWhitespace($code); $nonXHTMLMessages = $wgLanguages->getNonXHTMLMessages($code); $messagesWithWrongChars = $wgLanguages->getMessagesWithWrongChars($code); $problematicMessagesNumber = count(array_unique(array_merge($messagesWithMismatchVariables, $emptyMessages, $messagesWithWhitespace, $nonXHTMLMessages, $messagesWithWrongChars))); $problematicMessagesPercent = $output->formatPercent($problematicMessagesNumber, $messagesNumber, true); # Output them
/** * Prepare an array with the details we want to insert into the athena_page_details table * * @param $namespace int * @param $title string * @param $content string * @param $comment string * @param $user int * @return array */ static function preparePageDetailsArray($namespace, $title, $content, $comment, $user) { $dbw = wfGetDB(DB_MASTER); $title = $dbw->strencode($title); $content = $dbw->strencode($content); $insertArray = array('apd_namespace' => $namespace, 'apd_title' => $title, 'apd_content' => $content, 'apd_user' => $user, 'page_id' => 'NULL', 'rev_id' => 'NULL'); if ($comment != '') { $comment = $dbw->strencode($comment); $insertArray['apd_comment'] = $comment; } $language = AthenaHelper::getTextLanguage($content); $insertArray['apd_language'] = $dbw->strencode(Language::fetchLanguageName($language)); return $insertArray; }
function fetchLanguageName($code, $inLanguage) { $this->checkType('fetchLanguageName', 1, $code, 'string'); $this->checkTypeOptional('fetchLanguageName', 2, $inLanguage, 'string', null); return array(Language::fetchLanguageName($code, $inLanguage)); }
/** * Output a drop-down box for language options for the file * * @param Array $langChoices Array of string language codes * @param String $curLang Language code file is being viewed in. * @param String $defaultLang Language code that image is rendered in by default * @return String HTML to insert underneath image. */ protected function doRenderLangOpt(array $langChoices, $curLang, $defaultLang) { global $wgScript; sort($langChoices); $curLang = wfBCP47($curLang); $defaultLang = wfBCP47($defaultLang); $opts = ''; $haveCurrentLang = false; $haveDefaultLang = false; // We make a list of all the language choices in the file. // Additionally if the default language to render this file // is not included as being in this file (for example, in svgs // usually the fallback content is the english content) also // include a choice for that. Last of all, if we're viewing // the file in a language not on the list, add it as a choice. foreach ($langChoices as $lang) { $code = wfBCP47($lang); $name = Language::fetchLanguageName($code, $this->getContext()->getLanguage()->getCode()); if ($name !== '') { $display = wfMessage('img-lang-opt', $code, $name)->text(); } else { $display = $code; } $opts .= "\n" . Xml::option($display, $code, $curLang === $code); if ($curLang === $code) { $haveCurrentLang = true; } if ($defaultLang === $code) { $haveDefaultLang = true; } } if (!$haveDefaultLang) { // Its hard to know if the content is really in the default language, or // if its just unmarked content that could be in any language. $opts = Xml::option(wfMessage('img-lang-default')->text(), $defaultLang, $defaultLang === $curLang) . $opts; } if (!$haveCurrentLang && $defaultLang !== $curLang) { $name = Language::fetchLanguageName($curLang, $this->getContext()->getLanguage()->getCode()); if ($name !== '') { $display = wfMessage('img-lang-opt', $curLang, $name)->text(); } else { $display = $curLang; } $opts = Xml::option($display, $curLang, true) . $opts; } $select = Html::rawElement('select', array('id' => 'mw-imglangselector', 'name' => 'lang'), $opts); $submit = Xml::submitButton(wfMessage('img-lang-go')->text()); $formContents = wfMessage('img-lang-info')->rawParams($select, $submit)->parse() . Html::hidden('title', $this->getTitle()->getPrefixedDBkey()); $langSelectLine = Html::rawElement('div', array('id' => 'mw-imglangselector-line'), Html::rawElement('form', array('action' => $wgScript), $formContents)); return $langSelectLine; }
/** * @deprecated since 1.18 No modern skin generates language links this way, * please use language links data to generate your own HTML. * @param $languages array * @return string */ private function languagesHtml($languages) { wfDeprecated(__METHOD__, '1.18'); $this->setWarning('"action=parse&prop=languageshtml" is deprecated ' . 'and will be removed in MediaWiki 1.24. Use "prop=langlinks" ' . 'to generate your own HTML.'); global $wgContLang, $wgHideInterlanguageLinks; if ($wgHideInterlanguageLinks || count($languages) == 0) { return ''; } $s = htmlspecialchars(wfMessage('otherlanguages')->text() . wfMessage('colon-separator')->text()); $langs = array(); foreach ($languages as $l) { $nt = Title::newFromText($l); $text = Language::fetchLanguageName($nt->getInterwiki()); $langs[] = Html::element('a', array('href' => $nt->getFullURL(), 'title' => $nt->getText(), 'class' => 'external'), $text == '' ? $l : $text); } $s .= implode(wfMessage('pipe-separator')->escaped(), $langs); if ($wgContLang->isRTL()) { $s = Html::rawElement('span', array('dir' => 'LTR'), $s); } return $s; }
function showList() { global $wgInterwikiCentralDB, $wgInterwikiViewOnly; $canModify = $this->canModify(); // Build lists if (!method_exists('Interwiki', 'getAllPrefixes')) { // version 2.0 is not backwards compatible (but will still display a nice error) $this->error('interwiki_error'); return; } $iwPrefixes = Interwiki::getAllPrefixes(null); $iwGlobalPrefixes = array(); if ($wgInterwikiCentralDB !== null && $wgInterwikiCentralDB !== wfWikiId()) { // Fetch list from global table $dbrCentralDB = wfGetDB(DB_SLAVE, array(), $wgInterwikiCentralDB); $res = $dbrCentralDB->select('interwiki', '*', false, __METHOD__); $retval = array(); foreach ($res as $row) { $row = (array) $row; if (!Language::fetchLanguageName($row['iw_prefix'])) { $retval[] = $row; } } $iwGlobalPrefixes = $retval; } // Split out language links $iwLocalPrefixes = array(); $iwLanguagePrefixes = array(); foreach ($iwPrefixes as $iwPrefix) { if (Language::fetchLanguageName($iwPrefix['iw_prefix'])) { $iwLanguagePrefixes[] = $iwPrefix; } else { $iwLocalPrefixes[] = $iwPrefix; } } // Page intro content $this->getOutput()->addWikiMsg('interwiki_intro'); // Add 'view log' link when possible if ($wgInterwikiViewOnly === false) { $logLink = Linker::link(SpecialPage::getTitleFor('Log', 'interwiki'), $this->msg('interwiki-logtext')->escaped()); $this->getOutput()->addHTML('<p class="mw-interwiki-log">' . $logLink . '</p>'); } // Add 'add' link if ($canModify) { if (count($iwGlobalPrefixes) !== 0) { $addtext = $this->msg('interwiki-addtext-local')->escaped(); } else { $addtext = $this->msg('interwiki_addtext')->escaped(); } $addlink = Linker::linkKnown($this->getPageTitle('add'), $addtext); $this->getOutput()->addHTML('<p class="mw-interwiki-addlink">' . $addlink . '</p>'); } $this->getOutput()->addWikiMsg('interwiki-legend'); if (!is_array($iwPrefixes) || count($iwPrefixes) === 0) { if (!is_array($iwGlobalPrefixes) || count($iwGlobalPrefixes) === 0) { // If the interwiki table(s) are empty, display an error message $this->error('interwiki_error'); return; } } // Add the global table if (count($iwGlobalPrefixes) !== 0) { $this->getOutput()->addHTML('<h2 id="interwikitable-global">' . $this->msg('interwiki-global-links')->parse() . '</h2>'); $this->getOutput()->addWikiMsg('interwiki-global-description'); // $canModify is false here because this is just a display of remote data $this->makeTable(false, $iwGlobalPrefixes); } // Add the local table if (count($iwLocalPrefixes) !== 0) { if (count($iwGlobalPrefixes) !== 0) { $this->getOutput()->addHTML('<h2 id="interwikitable-local">' . $this->msg('interwiki-local-links')->parse() . '</h2>'); $this->getOutput()->addWikiMsg('interwiki-local-description'); } else { $this->getOutput()->addHTML('<h2 id="interwikitable-local">' . $this->msg('interwiki-links')->parse() . '</h2>'); $this->getOutput()->addWikiMsg('interwiki-description'); } $this->makeTable($canModify, $iwLocalPrefixes); } // Add the language table if (count($iwLanguagePrefixes) !== 0) { $this->getOutput()->addHTML('<h2 id="interwikitable-language">' . $this->msg('interwiki-language-links')->parse() . '</h2>'); $this->getOutput()->addWikiMsg('interwiki-language-description'); $this->makeTable($canModify, $iwLanguagePrefixes); } }
/** * Process [[ ]] wikilinks (RIL) * @param $s * @throws MWException * @return LinkHolderArray * * @private */ function replaceInternalLinks2(&$s) { wfProfileIn(__METHOD__); wfProfileIn(__METHOD__ . '-setup'); static $tc = false, $e1, $e1_img; # the % is needed to support urlencoded titles as well if (!$tc) { $tc = Title::legalChars() . '#%'; # Match a link having the form [[namespace:link|alternate]]trail $e1 = "/^([{$tc}]+)(?:\\|(.+?))?]](.*)\$/sD"; # Match cases where there is no "]]", which might still be images $e1_img = "/^([{$tc}]+)\\|(.*)\$/sD"; } $holders = new LinkHolderArray($this); # split the entire text string on occurrences of [[ $a = StringUtils::explode('[[', ' ' . $s); # get the first element (all text up to first [[), and remove the space we added $s = $a->current(); $a->next(); $line = $a->current(); # Workaround for broken ArrayIterator::next() that returns "void" $s = substr($s, 1); $useLinkPrefixExtension = $this->getTargetLanguage()->linkPrefixExtension(); $e2 = null; if ($useLinkPrefixExtension) { # Match the end of a line for a word that's not followed by whitespace, # e.g. in the case of 'The Arab al[[Razi]]', 'al' will be matched global $wgContLang; $charset = $wgContLang->linkPrefixCharset(); $e2 = "/^((?>.*[^{$charset}]|))(.+)\$/sDu"; } if (is_null($this->mTitle)) { wfProfileOut(__METHOD__ . '-setup'); wfProfileOut(__METHOD__); throw new MWException(__METHOD__ . ": \$this->mTitle is null\n"); } $nottalk = !$this->mTitle->isTalkPage(); if ($useLinkPrefixExtension) { $m = array(); if (preg_match($e2, $s, $m)) { $first_prefix = $m[2]; } else { $first_prefix = false; } } else { $prefix = ''; } $useSubpages = $this->areSubpagesAllowed(); wfProfileOut(__METHOD__ . '-setup'); # Loop for each link for (; $line !== false && $line !== null; $a->next(), $line = $a->current()) { # Check for excessive memory usage if ($holders->isBig()) { # Too big # Do the existence check, replace the link holders and clear the array $holders->replace($s); $holders->clear(); } if ($useLinkPrefixExtension) { wfProfileIn(__METHOD__ . '-prefixhandling'); if (preg_match($e2, $s, $m)) { $prefix = $m[2]; $s = $m[1]; } else { $prefix = ''; } # first link if ($first_prefix) { $prefix = $first_prefix; $first_prefix = false; } wfProfileOut(__METHOD__ . '-prefixhandling'); } $might_be_img = false; wfProfileIn(__METHOD__ . "-e1"); if (preg_match($e1, $line, $m)) { # page with normal text or alt $text = $m[2]; # If we get a ] at the beginning of $m[3] that means we have a link that's something like: # [[Image:Foo.jpg|[http://example.com desc]]] <- having three ] in a row f***s up, # the real problem is with the $e1 regex # See bug 1300. # # Still some problems for cases where the ] is meant to be outside punctuation, # and no image is in sight. See bug 2095. # if ($text !== '' && substr($m[3], 0, 1) === ']' && strpos($text, '[') !== false) { $text .= ']'; # so that replaceExternalLinks($text) works later $m[3] = substr($m[3], 1); } # fix up urlencoded title texts if (strpos($m[1], '%') !== false) { # Should anchors '#' also be rejected? $m[1] = str_replace(array('<', '>'), array('<', '>'), rawurldecode($m[1])); } $trail = $m[3]; } elseif (preg_match($e1_img, $line, $m)) { # Invalid, but might be an image with a link in its caption $might_be_img = true; $text = $m[2]; if (strpos($m[1], '%') !== false) { $m[1] = rawurldecode($m[1]); } $trail = ""; } else { # Invalid form; output directly $s .= $prefix . '[[' . $line; wfProfileOut(__METHOD__ . "-e1"); continue; } wfProfileOut(__METHOD__ . "-e1"); wfProfileIn(__METHOD__ . "-misc"); # Don't allow internal links to pages containing # PROTO: where PROTO is a valid URL protocol; these # should be external links. if (preg_match('/^(?i:' . $this->mUrlProtocols . ')/', $m[1])) { $s .= $prefix . '[[' . $line; wfProfileOut(__METHOD__ . "-misc"); continue; } # Make subpage if necessary if ($useSubpages) { $link = $this->maybeDoSubpageLink($m[1], $text); } else { $link = $m[1]; } $noforce = substr($m[1], 0, 1) !== ':'; if (!$noforce) { # Strip off leading ':' $link = substr($link, 1); } wfProfileOut(__METHOD__ . "-misc"); wfProfileIn(__METHOD__ . "-title"); $nt = Title::newFromText($this->mStripState->unstripNoWiki($link)); if ($nt === null) { $s .= $prefix . '[[' . $line; wfProfileOut(__METHOD__ . "-title"); continue; } $ns = $nt->getNamespace(); $iw = $nt->getInterwiki(); wfProfileOut(__METHOD__ . "-title"); if ($might_be_img) { # if this is actually an invalid link wfProfileIn(__METHOD__ . "-might_be_img"); if ($ns == NS_FILE && $noforce) { # but might be an image $found = false; while (true) { # look at the next 'line' to see if we can close it there $a->next(); $next_line = $a->current(); if ($next_line === false || $next_line === null) { break; } $m = explode(']]', $next_line, 3); if (count($m) == 3) { # the first ]] closes the inner link, the second the image $found = true; $text .= "[[{$m[0]}]]{$m[1]}"; $trail = $m[2]; break; } elseif (count($m) == 2) { # if there's exactly one ]] that's fine, we'll keep looking $text .= "[[{$m[0]}]]{$m[1]}"; } else { # if $next_line is invalid too, we need look no further $text .= '[[' . $next_line; break; } } if (!$found) { # we couldn't find the end of this imageLink, so output it raw # but don't ignore what might be perfectly normal links in the text we've examined $holders->merge($this->replaceInternalLinks2($text)); $s .= "{$prefix}[[{$link}|{$text}"; # note: no $trail, because without an end, there *is* no trail wfProfileOut(__METHOD__ . "-might_be_img"); continue; } } else { # it's not an image, so output it raw $s .= "{$prefix}[[{$link}|{$text}"; # note: no $trail, because without an end, there *is* no trail wfProfileOut(__METHOD__ . "-might_be_img"); continue; } wfProfileOut(__METHOD__ . "-might_be_img"); } $wasblank = $text == ''; if ($wasblank) { $text = $link; } else { # Bug 4598 madness. Handle the quotes only if they come from the alternate part # [[Lista d''e paise d''o munno]] -> <a href="...">Lista d''e paise d''o munno</a> # [[Criticism of Harry Potter|Criticism of ''Harry Potter'']] # -> <a href="Criticism of Harry Potter">Criticism of <i>Harry Potter</i></a> $text = $this->doQuotes($text); } # Link not escaped by : , create the various objects if ($noforce) { # Interwikis wfProfileIn(__METHOD__ . "-interwiki"); if ($iw && $this->mOptions->getInterwikiMagic() && $nottalk && Language::fetchLanguageName($iw, null, 'mw')) { // XXX: the above check prevents links to sites with identifiers that are not language codes # Bug 24502: filter duplicates if (!isset($this->mLangLinkLanguages[$iw])) { $this->mLangLinkLanguages[$iw] = true; $this->mOutput->addLanguageLink($nt->getFullText()); } $s = rtrim($s . $prefix); $s .= trim($trail, "\n") == '' ? '' : $prefix . $trail; wfProfileOut(__METHOD__ . "-interwiki"); continue; } wfProfileOut(__METHOD__ . "-interwiki"); if ($ns == NS_FILE) { wfProfileIn(__METHOD__ . "-image"); if (!wfIsBadImage($nt->getDBkey(), $this->mTitle)) { if ($wasblank) { # if no parameters were passed, $text # becomes something like "File:Foo.png", # which we don't want to pass on to the # image generator $text = ''; } else { # recursively parse links inside the image caption # actually, this will parse them in any other parameters, too, # but it might be hard to fix that, and it doesn't matter ATM $text = $this->replaceExternalLinks($text); $holders->merge($this->replaceInternalLinks2($text)); } # cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them $s .= $prefix . $this->armorLinks($this->makeImage($nt, $text, $holders)) . $trail; } else { $s .= $prefix . $trail; } wfProfileOut(__METHOD__ . "-image"); continue; } if ($ns == NS_CATEGORY) { wfProfileIn(__METHOD__ . "-category"); $s = rtrim($s . "\n"); # bug 87 if ($wasblank) { $sortkey = $this->getDefaultSort(); } else { $sortkey = $text; } $sortkey = Sanitizer::decodeCharReferences($sortkey); $sortkey = str_replace("\n", '', $sortkey); $sortkey = $this->getConverterLanguage()->convertCategoryKey($sortkey); $this->mOutput->addCategory($nt->getDBkey(), $sortkey); /** * Strip the whitespace Category links produce, see bug 87 */ $s .= trim($prefix . $trail, "\n") == '' ? '' : $prefix . $trail; wfProfileOut(__METHOD__ . "-category"); continue; } } # Self-link checking. For some languages, variants of the title are checked in # LinkHolderArray::doVariants() to allow batching the existence checks necessary # for linking to a different variant. if ($ns != NS_SPECIAL && $nt->equals($this->mTitle) && !$nt->hasFragment()) { $s .= $prefix . Linker::makeSelfLinkObj($nt, $text, '', $trail); continue; } # NS_MEDIA is a pseudo-namespace for linking directly to a file # @todo FIXME: Should do batch file existence checks, see comment below if ($ns == NS_MEDIA) { wfProfileIn(__METHOD__ . "-media"); # Give extensions a chance to select the file revision for us $options = array(); $descQuery = false; wfRunHooks('BeforeParserFetchFileAndTitle', array($this, $nt, &$options, &$descQuery)); # Fetch and register the file (file title may be different via hooks) list($file, $nt) = $this->fetchFileAndTitle($nt, $options); # Cloak with NOPARSE to avoid replacement in replaceExternalLinks $s .= $prefix . $this->armorLinks(Linker::makeMediaLinkFile($nt, $file, $text)) . $trail; wfProfileOut(__METHOD__ . "-media"); continue; } wfProfileIn(__METHOD__ . "-always_known"); # Some titles, such as valid special pages or files in foreign repos, should # be shown as bluelinks even though they're not included in the page table # # @todo FIXME: isAlwaysKnown() can be expensive for file links; we should really do # batch file existence checks for NS_FILE and NS_MEDIA if ($iw == '' && $nt->isAlwaysKnown()) { $this->mOutput->addLink($nt); $s .= $this->makeKnownLinkHolder($nt, $text, array(), $trail, $prefix); } else { # Links will be added to the output link list after checking $s .= $holders->makeHolder($nt, $text, array(), $trail, $prefix); } wfProfileOut(__METHOD__ . "-always_known"); } wfProfileOut(__METHOD__); return $holders; }
function otherLanguages() { global $wgOut, $wgLang, $wgHideInterlanguageLinks; if ($wgHideInterlanguageLinks) { return ''; } $a = $wgOut->getLanguageLinks(); if (0 == count($a)) { return ''; } $s = wfMessage('otherlanguages')->text() . wfMessage('colon-separator')->text(); $first = true; if ($wgLang->isRTL()) { $s .= '<span dir="ltr">'; } foreach ($a as $l) { if (!$first) { $s .= wfMessage('pipe-separator')->escaped(); } $first = false; $nt = Title::newFromText($l); $text = Language::fetchLanguageName($nt->getInterwiki()); $s .= Html::element('a', array('href' => $nt->getFullURL(), 'title' => $nt->getText(), 'class' => "external"), $text == '' ? $l : $text); } if ($wgLang->isRTL()) { $s .= '</span>'; } return $s; }
/** Helper function for creating lists of translations. * * @param string $value value (this is not escaped) * @param string $lang lang code of item or false * @param $default Boolean if it is default value. * @param $noHtml Boolean If to avoid html (for back-compat) * @throws MWException * @return string language item (Note: despite how this looks, * this is treated as wikitext not html). */ private static function langItem($value, $lang, $default = false, $noHtml = false) { if ($lang === false && $default === false) { throw new MWException('$lang and $default cannot both ' . 'be false.'); } if ($noHtml) { $wrappedValue = $value; } else { $wrappedValue = '<span class="mw-metadata-lang-value">' . $value . '</span>'; } if ($lang === false) { if ($noHtml) { return wfMessage('metadata-langitem-default', $wrappedValue)->text() . "\n\n"; } /* else */ return '<li class="mw-metadata-lang-default">' . wfMessage('metadata-langitem-default', $wrappedValue)->text() . "</li>\n"; } $lowLang = strtolower($lang); $langName = Language::fetchLanguageName($lowLang); if ($langName === '') { //try just the base language name. (aka en-US -> en ). list($langPrefix) = explode('-', $lowLang, 2); $langName = Language::fetchLanguageName($langPrefix); if ($langName === '') { // give up. $langName = $lang; } } // else we have a language specified if ($noHtml) { return '*' . wfMessage('metadata-langitem', $wrappedValue, $langName, $lang)->text(); } /* else: */ $item = '<li class="mw-metadata-lang-code-' . $lang; if ($default) { $item .= ' mw-metadata-lang-default'; } $item .= '" lang="' . $lang . '">'; $item .= wfMessage('metadata-langitem', $wrappedValue, $langName, $lang)->text(); $item .= "</li>\n"; return $item; }
protected function tuxLanguageSelector() { // Changes here must also be reflected when the language // changes on the client side global $wgTranslateDocumentationLanguageCode; if ($this->options['language'] === $wgTranslateDocumentationLanguageCode) { // The name will be displayed in the UI language, // so use for lang and dir $targetLangCode = $this->getLanguage()->getCode(); $targetLangDir = $this->getLanguage()->getDir(); $targetLangName = $this->msg('translate-documentation-language')->text(); } else { $targetLangCode = $this->options['language']; $targetLangDir = Language::factory($this->options['language'])->getDir(); $targetLangName = Language::fetchLanguageName($this->options['language']); } // No-break space is added for spacing after the label // and to ensure separation of words (in Arabic, for example) return Html::rawElement('div', array('class' => 'four columns ext-translate-language-selector'), Html::element('span', array('class' => 'ext-translate-language-selector-label'), $this->msg('tux-languageselector')->text()) . ' ' . Html::element('span', array('class' => 'uls', 'lang' => $targetLangCode, 'dir' => $targetLangDir), $targetLangName)); }
/** * @deprecated since 1.18 No modern skin generates language links this way, please use language links * data to generate your own HTML. * @param $languages array * @return string */ private function languagesHtml($languages) { wfDeprecated(__METHOD__, '1.18'); global $wgContLang, $wgHideInterlanguageLinks; if ($wgHideInterlanguageLinks || count($languages) == 0) { return ''; } $s = htmlspecialchars(wfMessage('otherlanguages')->text() . wfMessage('colon-separator')->text()); $langs = array(); foreach ($languages as $l) { $nt = Title::newFromText($l); $text = Language::fetchLanguageName($nt->getInterwiki()); $langs[] = Html::element('a', array('href' => $nt->getFullURL(), 'title' => $nt->getText(), 'class' => "external"), $text == '' ? $l : $text); } $s .= implode(wfMessage('pipe-separator')->escaped(), $langs); if ($wgContLang->isRTL()) { $s = Html::rawElement('span', array('dir' => "LTR"), $s); } return $s; }
/** * Returns page information in an easily-manipulated format. Array keys are used so extensions * may add additional information in arbitrary positions. Array values are arrays with one * element to be rendered as a header, arrays with two elements to be rendered as a table row. * * @return array */ protected function pageInfo() { global $wgContLang; $user = $this->getUser(); $lang = $this->getLanguage(); $title = $this->getTitle(); $id = $title->getArticleID(); $config = $this->context->getConfig(); $cache = ObjectCache::getMainWANInstance(); $memcKey = wfMemcKey('infoaction', sha1($title->getPrefixedText()), $this->page->getLatest()); $pageCounts = $cache->get($memcKey); $version = isset($pageCounts['cacheversion']) ? $pageCounts['cacheversion'] : false; if ($pageCounts === false || $version !== self::CACHE_VERSION) { // Get page information that would be too "expensive" to retrieve by normal means $pageCounts = $this->pageCounts($title); $pageCounts['cacheversion'] = self::CACHE_VERSION; $cache->set($memcKey, $pageCounts); } // Get page properties $dbr = wfGetDB(DB_SLAVE); $result = $dbr->select('page_props', array('pp_propname', 'pp_value'), array('pp_page' => $id), __METHOD__); $pageProperties = array(); foreach ($result as $row) { $pageProperties[$row->pp_propname] = $row->pp_value; } // Basic information $pageInfo = array(); $pageInfo['header-basic'] = array(); // Display title $displayTitle = $title->getPrefixedText(); if (isset($pageProperties['displaytitle'])) { $displayTitle = $pageProperties['displaytitle']; } $pageInfo['header-basic'][] = array($this->msg('pageinfo-display-title'), $displayTitle); // Is it a redirect? If so, where to? if ($title->isRedirect()) { $pageInfo['header-basic'][] = array($this->msg('pageinfo-redirectsto'), Linker::link($this->page->getRedirectTarget()) . $this->msg('word-separator')->escaped() . $this->msg('parentheses')->rawParams(Linker::link($this->page->getRedirectTarget(), $this->msg('pageinfo-redirectsto-info')->escaped(), array(), array('action' => 'info')))->escaped()); } // Default sort key $sortKey = $title->getCategorySortkey(); if (isset($pageProperties['defaultsort'])) { $sortKey = $pageProperties['defaultsort']; } $sortKey = htmlspecialchars($sortKey); $pageInfo['header-basic'][] = array($this->msg('pageinfo-default-sort'), $sortKey); // Page length (in bytes) $pageInfo['header-basic'][] = array($this->msg('pageinfo-length'), $lang->formatNum($title->getLength())); // Page ID (number not localised, as it's a database ID) $pageInfo['header-basic'][] = array($this->msg('pageinfo-article-id'), $id); // Language in which the page content is (supposed to be) written $pageLang = $title->getPageLanguage()->getCode(); if ($config->get('PageLanguageUseDB') && $this->getTitle()->userCan('pagelang', $this->getUser())) { // Link to Special:PageLanguage with pre-filled page title if user has permissions $titleObj = SpecialPage::getTitleFor('PageLanguage', $title->getPrefixedText()); $langDisp = Linker::link($titleObj, $this->msg('pageinfo-language')->escaped()); } else { // Display just the message $langDisp = $this->msg('pageinfo-language')->escaped(); } $pageInfo['header-basic'][] = array($langDisp, Language::fetchLanguageName($pageLang, $lang->getCode()) . ' ' . $this->msg('parentheses', $pageLang)->escaped()); // Content model of the page $pageInfo['header-basic'][] = array($this->msg('pageinfo-content-model'), htmlspecialchars(ContentHandler::getLocalizedName($title->getContentModel()))); // Search engine status $pOutput = new ParserOutput(); if (isset($pageProperties['noindex'])) { $pOutput->setIndexPolicy('noindex'); } if (isset($pageProperties['index'])) { $pOutput->setIndexPolicy('index'); } // Use robot policy logic $policy = $this->page->getRobotPolicy('view', $pOutput); $pageInfo['header-basic'][] = array($this->msg('pageinfo-robot-policy'), $this->msg("pageinfo-robot-{$policy['index']}")); $unwatchedPageThreshold = $config->get('UnwatchedPageThreshold'); if ($user->isAllowed('unwatchedpages') || $unwatchedPageThreshold !== false && $pageCounts['watchers'] >= $unwatchedPageThreshold) { // Number of page watchers $pageInfo['header-basic'][] = array($this->msg('pageinfo-watchers'), $lang->formatNum($pageCounts['watchers'])); if ($config->get('ShowUpdatedMarker') && isset($pageCounts['visitingWatchers'])) { $minToDisclose = $config->get('UnwatchedPageSecret'); if ($pageCounts['visitingWatchers'] > $minToDisclose || $user->isAllowed('unwatchedpages')) { $pageInfo['header-basic'][] = array($this->msg('pageinfo-visiting-watchers'), $lang->formatNum($pageCounts['visitingWatchers'])); } else { $pageInfo['header-basic'][] = array($this->msg('pageinfo-visiting-watchers'), $this->msg('pageinfo-few-visiting-watchers')); } } } elseif ($unwatchedPageThreshold !== false) { $pageInfo['header-basic'][] = array($this->msg('pageinfo-watchers'), $this->msg('pageinfo-few-watchers')->numParams($unwatchedPageThreshold)); } // Redirects to this page $whatLinksHere = SpecialPage::getTitleFor('Whatlinkshere', $title->getPrefixedText()); $pageInfo['header-basic'][] = array(Linker::link($whatLinksHere, $this->msg('pageinfo-redirects-name')->escaped(), array(), array('hidelinks' => 1, 'hidetrans' => 1, 'hideimages' => $title->getNamespace() == NS_FILE)), $this->msg('pageinfo-redirects-value')->numParams(count($title->getRedirectsHere()))); // Is it counted as a content page? if ($this->page->isCountable()) { $pageInfo['header-basic'][] = array($this->msg('pageinfo-contentpage'), $this->msg('pageinfo-contentpage-yes')); } // Subpages of this page, if subpages are enabled for the current NS if (MWNamespace::hasSubpages($title->getNamespace())) { $prefixIndex = SpecialPage::getTitleFor('Prefixindex', $title->getPrefixedText() . '/'); $pageInfo['header-basic'][] = array(Linker::link($prefixIndex, $this->msg('pageinfo-subpages-name')->escaped()), $this->msg('pageinfo-subpages-value')->numParams($pageCounts['subpages']['total'], $pageCounts['subpages']['redirects'], $pageCounts['subpages']['nonredirects'])); } if ($title->inNamespace(NS_CATEGORY)) { $category = Category::newFromTitle($title); // $allCount is the total number of cat members, // not the count of how many members are normal pages. $allCount = (int) $category->getPageCount(); $subcatCount = (int) $category->getSubcatCount(); $fileCount = (int) $category->getFileCount(); $pagesCount = $allCount - $subcatCount - $fileCount; $pageInfo['category-info'] = array(array($this->msg('pageinfo-category-total'), $lang->formatNum($allCount)), array($this->msg('pageinfo-category-pages'), $lang->formatNum($pagesCount)), array($this->msg('pageinfo-category-subcats'), $lang->formatNum($subcatCount)), array($this->msg('pageinfo-category-files'), $lang->formatNum($fileCount))); } // Page protection $pageInfo['header-restrictions'] = array(); // Is this page affected by the cascading protection of something which includes it? if ($title->isCascadeProtected()) { $cascadingFrom = ''; $sources = $title->getCascadeProtectionSources(); // Array deferencing is in PHP 5.4 :( foreach ($sources[0] as $sourceTitle) { $cascadingFrom .= Html::rawElement('li', array(), Linker::linkKnown($sourceTitle)); } $cascadingFrom = Html::rawElement('ul', array(), $cascadingFrom); $pageInfo['header-restrictions'][] = array($this->msg('pageinfo-protect-cascading-from'), $cascadingFrom); } // Is out protection set to cascade to other pages? if ($title->areRestrictionsCascading()) { $pageInfo['header-restrictions'][] = array($this->msg('pageinfo-protect-cascading'), $this->msg('pageinfo-protect-cascading-yes')); } // Page protection foreach ($title->getRestrictionTypes() as $restrictionType) { $protectionLevel = implode(', ', $title->getRestrictions($restrictionType)); if ($protectionLevel == '') { // Allow all users $message = $this->msg('protect-default')->escaped(); } else { // Administrators only // Messages: protect-level-autoconfirmed, protect-level-sysop $message = $this->msg("protect-level-{$protectionLevel}"); if ($message->isDisabled()) { // Require "$1" permission $message = $this->msg("protect-fallback", $protectionLevel)->parse(); } else { $message = $message->escaped(); } } $expiry = $title->getRestrictionExpiry($restrictionType); $formattedexpiry = $this->msg('parentheses', $this->getLanguage()->formatExpiry($expiry))->escaped(); $message .= $this->msg('word-separator')->escaped() . $formattedexpiry; // Messages: restriction-edit, restriction-move, restriction-create, // restriction-upload $pageInfo['header-restrictions'][] = array($this->msg("restriction-{$restrictionType}"), $message); } if (!$this->page->exists()) { return $pageInfo; } // Edit history $pageInfo['header-edits'] = array(); $firstRev = $this->page->getOldestRevision(); $lastRev = $this->page->getRevision(); $batch = new LinkBatch(); if ($firstRev) { $firstRevUser = $firstRev->getUserText(Revision::FOR_THIS_USER); if ($firstRevUser !== '') { $batch->add(NS_USER, $firstRevUser); $batch->add(NS_USER_TALK, $firstRevUser); } } if ($lastRev) { $lastRevUser = $lastRev->getUserText(Revision::FOR_THIS_USER); if ($lastRevUser !== '') { $batch->add(NS_USER, $lastRevUser); $batch->add(NS_USER_TALK, $lastRevUser); } } $batch->execute(); if ($firstRev) { // Page creator $pageInfo['header-edits'][] = array($this->msg('pageinfo-firstuser'), Linker::revUserTools($firstRev)); // Date of page creation $pageInfo['header-edits'][] = array($this->msg('pageinfo-firsttime'), Linker::linkKnown($title, htmlspecialchars($lang->userTimeAndDate($firstRev->getTimestamp(), $user)), array(), array('oldid' => $firstRev->getId()))); } if ($lastRev) { // Latest editor $pageInfo['header-edits'][] = array($this->msg('pageinfo-lastuser'), Linker::revUserTools($lastRev)); // Date of latest edit $pageInfo['header-edits'][] = array($this->msg('pageinfo-lasttime'), Linker::linkKnown($title, htmlspecialchars($lang->userTimeAndDate($this->page->getTimestamp(), $user)), array(), array('oldid' => $this->page->getLatest()))); } // Total number of edits $pageInfo['header-edits'][] = array($this->msg('pageinfo-edits'), $lang->formatNum($pageCounts['edits'])); // Total number of distinct authors if ($pageCounts['authors'] > 0) { $pageInfo['header-edits'][] = array($this->msg('pageinfo-authors'), $lang->formatNum($pageCounts['authors'])); } // Recent number of edits (within past 30 days) $pageInfo['header-edits'][] = array($this->msg('pageinfo-recent-edits', $lang->formatDuration($config->get('RCMaxAge'))), $lang->formatNum($pageCounts['recent_edits'])); // Recent number of distinct authors $pageInfo['header-edits'][] = array($this->msg('pageinfo-recent-authors'), $lang->formatNum($pageCounts['recent_authors'])); // Array of MagicWord objects $magicWords = MagicWord::getDoubleUnderscoreArray(); // Array of magic word IDs $wordIDs = $magicWords->names; // Array of IDs => localized magic words $localizedWords = $wgContLang->getMagicWords(); $listItems = array(); foreach ($pageProperties as $property => $value) { if (in_array($property, $wordIDs)) { $listItems[] = Html::element('li', array(), $localizedWords[$property][1]); } } $localizedList = Html::rawElement('ul', array(), implode('', $listItems)); $hiddenCategories = $this->page->getHiddenCategories(); if (count($listItems) > 0 || count($hiddenCategories) > 0 || $pageCounts['transclusion']['from'] > 0 || $pageCounts['transclusion']['to'] > 0) { $options = array('LIMIT' => $config->get('PageInfoTransclusionLimit')); $transcludedTemplates = $title->getTemplateLinksFrom($options); if ($config->get('MiserMode')) { $transcludedTargets = array(); } else { $transcludedTargets = $title->getTemplateLinksTo($options); } // Page properties $pageInfo['header-properties'] = array(); // Magic words if (count($listItems) > 0) { $pageInfo['header-properties'][] = array($this->msg('pageinfo-magic-words')->numParams(count($listItems)), $localizedList); } // Hidden categories if (count($hiddenCategories) > 0) { $pageInfo['header-properties'][] = array($this->msg('pageinfo-hidden-categories')->numParams(count($hiddenCategories)), Linker::formatHiddenCategories($hiddenCategories)); } // Transcluded templates if ($pageCounts['transclusion']['from'] > 0) { if ($pageCounts['transclusion']['from'] > count($transcludedTemplates)) { $more = $this->msg('morenotlisted')->escaped(); } else { $more = null; } $pageInfo['header-properties'][] = array($this->msg('pageinfo-templates')->numParams($pageCounts['transclusion']['from']), Linker::formatTemplates($transcludedTemplates, false, false, $more)); } if (!$config->get('MiserMode') && $pageCounts['transclusion']['to'] > 0) { if ($pageCounts['transclusion']['to'] > count($transcludedTargets)) { $more = Linker::link($whatLinksHere, $this->msg('moredotdotdot')->escaped(), array(), array('hidelinks' => 1, 'hideredirs' => 1)); } else { $more = null; } $pageInfo['header-properties'][] = array($this->msg('pageinfo-transclusions')->numParams($pageCounts['transclusion']['to']), Linker::formatTemplates($transcludedTargets, false, false, $more)); } } return $pageInfo; }