public function execute() { $params = $this->extractRequestParams(); $result = $this->getResult(); if (is_null($params['lang'])) { $langCode = false; } elseif (!Language::isValidCode($params['lang'])) { $this->dieUsage('Invalid language code for parameter lang', 'invalidlang'); } else { $langCode = $params['lang']; } $pageSet = $this->getPageSet(); $pageSet->execute(); $titles = $pageSet->getGoodTitles(); // page_id => Title object if (!count($titles)) { $result->addValue(null, 'pages', (object) array()); return; } $db = $this->getDB(); $res = $db->select('page_props', array('pp_page', 'pp_value'), array('pp_page' => array_keys($titles), 'pp_propname' => 'templatedata'), __METHOD__, array('ORDER BY', 'pp_page')); $resp = array(); foreach ($res as $row) { $rawData = $row->pp_value; $tdb = TemplateDataBlob::newFromDatabase($rawData); $status = $tdb->getStatus(); if (!$status->isOK()) { $this->dieUsage('Page #' . intval($row->pp_page) . ' templatedata contains invalid data: ' . $status->getMessage(), 'templatedata-corrupt'); } if ($langCode) { $data = $tdb->getDataInLanguage($langCode); } else { $data = $tdb->getData(); } $resp[$row->pp_page] = array('title' => strval($titles[$row->pp_page])) + (array) $data; } // Set top level element $result->addValue(null, 'pages', (object) $resp); $values = $pageSet->getNormalizedTitlesAsResult(); if ($values) { $result->addValue(null, 'normalized', $values); } $redirects = $pageSet->getRedirectTitlesAsResult(); if ($redirects) { $result->addValue(null, 'redirects', $redirects); } }
public static function getFromFilter($moduleId, $lang = null, $master = false) { global $wgExternalSharedDB, $wgMemc; wfProfileIn(__METHOD__); $timestampNow = wfTimestampNow(); $key = 'phalanx:' . $moduleId . ':' . ($lang ? $lang : 'all'); $sLang = $lang ? $lang : 'all'; if (isset(self::$moduleData[$moduleId][$sLang])) { $blocksData = self::$moduleData[$moduleId][$sLang]; } else { $blocksData = $wgMemc->get($key); } //cache miss (or we have expired blocks in cache), get from DB if (empty($blocksData) || !is_null($blocksData['closestExpire']) && $blocksData['closestExpire'] < $timestampNow && $blocksData['closestExpire']) { $blocks = $cond = array(); $closestTimestamp = 0; $dbr = wfGetDB($master ? DB_MASTER : DB_SLAVE, array(), $wgExternalSharedDB); if (!empty($moduleId) && is_numeric($moduleId)) { $cond[] = "p_type & {$moduleId} = {$moduleId}"; } if (!empty($lang) && Language::isValidCode($lang)) { $cond[] = "(p_lang = '{$lang}' OR p_lang IS NULL)"; } else { $cond[] = "p_lang IS NULL"; } $res = $dbr->select('phalanx', '*', $cond, __METHOD__); while ($row = $res->fetchObject()) { if ($timestampNow > $row->p_expire && !is_null($row->p_expire)) { continue; //skip expired } //use p_id as array key for easier deletion from cache $blocks[$row->p_id] = array('id' => $row->p_id, 'author_id' => $row->p_author_id, 'text' => $row->p_text, 'type' => $row->p_type, 'timestamp' => $row->p_timestamp, 'expire' => $row->p_expire, 'exact' => $row->p_exact, 'regex' => $row->p_regex, 'case' => $row->p_case, 'reason' => $row->p_reason, 'lang' => $row->p_lang); if (!is_null($row->p_expire) && $closestTimestamp > $row->p_expire || !$closestTimestamp) { $closestTimestamp = $row->p_expire; } } $blocksData['blocks'] = $blocks; $blocksData['closestExpire'] = $closestTimestamp; $wgMemc->set($key, $blocksData); } self::$moduleData[$moduleId][$sLang] = $blocksData; wfProfileOut(__METHOD__); return $blocksData['blocks']; }
public function execute() { wfProfileIn(__METHOD__); $params = $this->extractRequestParams(); global $wgFeedClasses; if (!isset($wgFeedClasses[$params['feedformat']])) { wfProfileOut(__METHOD__); $this->dieUsage('Invalid subscription feed type', 'feed-invalid'); } $language = isset($params['language']) ? $params['language'] : false; if ($language !== false && !Language::isValidCode($language)) { $language = false; } $feeds = FeaturedFeeds::getFeeds($language); $ourFeed = $feeds[$params['feed']]; $feedClass = new $wgFeedClasses[$params['feedformat']]($ourFeed->title, $ourFeed->description, wfExpandUrl(Title::newMainPage()->getFullURL())); ApiFormatFeedWrapper::setResult($this->getResult(), $feedClass, $ourFeed->getFeedItems()); // Cache stuff in squids $this->getMain()->setCacheMode('public'); $this->getMain()->setCacheMaxAge(FeaturedFeeds::getMaxAge()); wfProfileOut(__METHOD__); }
/** * Get the name of a file for a certain language code * @param $prefix string Prepend this to the filename * @param $code string Language code * @param $suffix string Append this to the filename * @return string $prefix . $mangledCode . $suffix */ static function getFileName($prefix = 'Language', $code, $suffix = '.php') { // Protect against path traversal if (!Language::isValidCode($code) || strcspn($code, ":/\\") !== strlen($code)) { throw new MWException("Invalid language code \"{$code}\""); } return $prefix . str_replace('-', '_', ucfirst($code)) . $suffix; }
/** * Uncached helper for fetchLanguageNames * @param null|string $inLanguage Code of language in which to return the names * Use null for autonyms (native names) * @param string $include One of: * 'all' all available languages * 'mw' only if the language is defined in MediaWiki or wgExtraLanguageNames (default) * 'mwfile' only if the language is in 'mw' *and* has a message file * @return array Language code => language name */ private static function fetchLanguageNamesUncached($inLanguage = null, $include = 'mw') { global $wgExtraLanguageNames; static $coreLanguageNames; if ($coreLanguageNames === null) { global $IP; include "{$IP}/languages/Names.php"; } // If passed an invalid language code to use, fallback to en if ($inLanguage !== null && !Language::isValidCode($inLanguage)) { $inLanguage = 'en'; } $names = array(); if ($inLanguage) { # TODO: also include when $inLanguage is null, when this code is more efficient Hooks::run('LanguageGetTranslatedLanguageNames', array(&$names, $inLanguage)); } $mwNames = $wgExtraLanguageNames + $coreLanguageNames; foreach ($mwNames as $mwCode => $mwName) { # - Prefer own MediaWiki native name when not using the hook # - For other names just add if not added through the hook if ($mwCode === $inLanguage || !isset($names[$mwCode])) { $names[$mwCode] = $mwName; } } if ($include === 'all') { ksort($names); return $names; } $returnMw = array(); $coreCodes = array_keys($mwNames); foreach ($coreCodes as $coreCode) { $returnMw[$coreCode] = $names[$coreCode]; } if ($include === 'mwfile') { $namesMwFile = array(); # We do this using a foreach over the codes instead of a directory # loop so that messages files in extensions will work correctly. foreach ($returnMw as $code => $value) { if (is_readable(self::getMessagesFileName($code)) || is_readable(self::getJsonMessagesFileName($code))) { $namesMwFile[$code] = $names[$code]; } } ksort($namesMwFile); return $namesMwFile; } ksort($returnMw); # 'mw' option; default if it's not one of the other two options (all/mwfile) return $returnMw; }
/** * Accepts a language code and ensures it's sane. Outputs a cleaned up language * code and replaces with $wgLanguageCode if not sane. * @param string $code Language code * @return string */ public static function sanitizeLangCode($code) { global $wgLanguageCode; // BCP 47 - letter case MUST NOT carry meaning $code = strtolower($code); # Validate $code if (!$code || !Language::isValidCode($code) || $code === 'qqq') { wfDebug("Invalid user language code\n"); $code = $wgLanguageCode; } return $code; }
public function execute() { $params = $this->extractRequestParams(); if (is_null($params['lang'])) { $langObj = $this->getLanguage(); } elseif (!Language::isValidCode($params['lang'])) { $this->dieUsage('Invalid language code for parameter lang', 'invalidlang'); } else { $langObj = Language::factory($params['lang']); } if ($params['enableparser']) { if (!is_null($params['title'])) { $title = Title::newFromText($params['title']); if (!$title || $title->isExternal()) { $this->dieUsageMsg(['invalidtitle', $params['title']]); } } else { $title = Title::newFromText('API'); } } $prop = array_flip((array) $params['prop']); // Determine which messages should we print if (in_array('*', $params['messages'])) { $message_names = Language::getMessageKeysFor($langObj->getCode()); if ($params['includelocal']) { $message_names = array_unique(array_merge($message_names, MessageCache::singleton()->getAllMessageKeys($this->getConfig()->get('LanguageCode')))); } sort($message_names); $messages_target = $message_names; } else { $messages_target = $params['messages']; } // Filter messages that have the specified prefix // Because we sorted the message array earlier, they will appear in a clump: if (isset($params['prefix'])) { $skip = false; $messages_filtered = []; foreach ($messages_target as $message) { // === 0: must be at beginning of string (position 0) if (strpos($message, $params['prefix']) === 0) { if (!$skip) { $skip = true; } $messages_filtered[] = $message; } elseif ($skip) { break; } } $messages_target = $messages_filtered; } // Filter messages that contain specified string if (isset($params['filter'])) { $messages_filtered = []; foreach ($messages_target as $message) { // !== is used because filter can be at the beginning of the string if (strpos($message, $params['filter']) !== false) { $messages_filtered[] = $message; } } $messages_target = $messages_filtered; } // Whether we have any sort of message customisation filtering $customiseFilterEnabled = $params['customised'] !== 'all'; if ($customiseFilterEnabled) { global $wgContLang; $customisedMessages = AllMessagesTablePager::getCustomisedStatuses(array_map([$langObj, 'ucfirst'], $messages_target), $langObj->getCode(), !$langObj->equals($wgContLang)); $customised = $params['customised'] === 'modified'; } // Get all requested messages and print the result $skip = !is_null($params['from']); $useto = !is_null($params['to']); $result = $this->getResult(); foreach ($messages_target as $message) { // Skip all messages up to $params['from'] if ($skip && $message === $params['from']) { $skip = false; } if ($useto && $message > $params['to']) { break; } if (!$skip) { $a = ['name' => $message, 'normalizedname' => MessageCache::normalizeKey($message)]; $args = []; if (isset($params['args']) && count($params['args']) != 0) { $args = $params['args']; } if ($customiseFilterEnabled) { $messageIsCustomised = isset($customisedMessages['pages'][$langObj->ucfirst($message)]); if ($customised === $messageIsCustomised) { if ($customised) { $a['customised'] = true; } } else { continue; } } $msg = wfMessage($message, $args)->inLanguage($langObj); if (!$msg->exists()) { $a['missing'] = true; } else { // Check if the parser is enabled: if ($params['enableparser']) { $msgString = $msg->title($title)->text(); } else { $msgString = $msg->plain(); } if (!$params['nocontent']) { ApiResult::setContentValue($a, 'content', $msgString); } if (isset($prop['default'])) { $default = wfMessage($message)->inLanguage($langObj)->useDatabase(false); if (!$default->exists()) { $a['defaultmissing'] = true; } elseif ($default->plain() != $msgString) { $a['default'] = $default->plain(); } } } $fit = $result->addValue(['query', $this->getModuleName()], null, $a); if (!$fit) { $this->setContinueEnumParameter('from', $message); break; } } } $result->addIndexedTagName(['query', $this->getModuleName()], 'message'); }
public function appendSkins($property) { $data = array(); $allowed = Skin::getAllowedSkins(); $default = Skin::normalizeKey('default'); foreach (Skin::getSkinNames() as $name => $displayName) { $msg = $this->msg("skinname-{$name}"); $code = $this->getParameter('inlanguagecode'); if ($code && Language::isValidCode($code)) { $msg->inLanguage($code); } else { $msg->inContentLanguage(); } if ($msg->exists()) { $displayName = $msg->text(); } $skin = array('code' => $name); ApiResult::setContentValue($skin, 'name', $displayName); if (!isset($allowed[$name])) { $skin['unusable'] = true; } if ($name === $default) { $skin['default'] = true; } $data[] = $skin; } ApiResult::setIndexedTagName($data, 'skin'); return $this->getResult()->addValue('query', $property, $data); }
function isValidCode($code) { $this->checkType('isValidCode', 1, $code, 'string'); return array(Language::isValidCode($code)); }
/** * Get the Language object * * @return Language */ public function getLang() { if ($this->lang === null) { global $wgLanguageCode, $wgContLang; $code = $this->getRequest()->getVal('uselang', $this->getUser()->getOption('language')); // BCP 47 - letter case MUST NOT carry meaning $code = strtolower($code); # Validate $code if (empty($code) || !Language::isValidCode($code) || $code === 'qqq') { wfDebug("Invalid user language code\n"); $code = $wgLanguageCode; } wfRunHooks('UserGetLanguageObject', array($this->getUser(), &$code)); if ($code === $wgLanguageCode) { $this->lang = $wgContLang; } else { $obj = Language::factory($code); $this->lang = $obj; } } return $this->lang; }
public static function getFromFilterShort($moduleId, $lang = null, $master = false, $skipCache = false) { global $wgExternalSharedDB, $wgMemc; wfProfileIn(__METHOD__); $timestampNow = wfTimestampNow(); $key = 'phalanx:' . $moduleId . ':' . ($lang ? $lang : 'all') . ':short'; $sLang = $lang ? $lang : 'all'; if ($skipCache) { $blocksData = null; } else { if (isset(self::$moduleDataShort[$moduleId][$sLang])) { $blocksData = self::$moduleDataShort[$moduleId][$sLang]; } else { $blocksData = $wgMemc->get($key); } } //cache miss (or we have expired blocks in cache), get from DB if (empty($blocksData) || !is_null($blocksData['closestExpire']) && $blocksData['closestExpire'] < $timestampNow && $blocksData['closestExpire']) { $blocks = $cond = array(); $closestTimestamp = 0; $dbr = wfGetDB($master ? DB_MASTER : DB_SLAVE, array(), $wgExternalSharedDB); if (!empty($moduleId) && is_numeric($moduleId)) { $cond[] = "p_type & {$moduleId} = {$moduleId}"; } if (!empty($lang) && Language::isValidCode($lang)) { $cond[] = "(p_lang = '{$lang}' OR p_lang IS NULL)"; } else { $cond[] = "p_lang IS NULL"; } $cond[] = "p_expire is null or p_expire > '{$timestampNow}'"; $res = $dbr->select('phalanx', '*', $cond, __METHOD__); foreach ($res as $row) { $blocks[$row->p_id] = array($row->p_id, $row->p_text, ($row->p_exact ? self::FLAG_EXACT : 0) + ($row->p_regex ? self::FLAG_REGEX : 0) + ($row->p_case ? self::FLAG_CASE : 0)); if (!is_null($row->p_expire) && $closestTimestamp > $row->p_expire || !$closestTimestamp) { $closestTimestamp = $row->p_expire; } } $blocksData['blocks'] = $blocks; $blocksData['closestExpire'] = $closestTimestamp; $wgMemc->set($key, $blocksData); } self::$moduleDataShort[$moduleId][$sLang] = $blocksData; PhalanxShadowing::setType($moduleId); wfProfileOut(__METHOD__); return $blocksData['blocks']; }
function _newObject() { global $wgLanguageCode, $wgRequest, $wgUser, $wgContLang; $code = $wgRequest->getVal('uselang', $wgUser->getOption('language')); // BCP 47 - letter case MUST NOT carry meaning $code = strtolower($code); # Validate $code if (empty($code) || !Language::isValidCode($code) || $code === 'qqq') { wfDebug("Invalid user language code\n"); $code = $wgLanguageCode; } if ($code === $wgLanguageCode) { return $wgContLang; } else { $obj = Language::factory($code); return $obj; } }