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; }
/** * Execute the job * * @return bool */ public function run() { //sleep() could be added here to reduce unnecessary use $ill = $this->params['ill']; foreach ($ill as $lang => $pages) { $iw = Interwiki::fetch($lang); if (!$iw) { continue; } $apiUrl = $iw->getAPI(); if (!$apiUrl) { continue; } $apiUrl .= '?' . wfArrayToCGI(array('action' => 'purge', 'format' => 'json', 'titles' => implode('|', array_keys($pages)))); Http::post($apiUrl); //TODO: error handling } return true; }
/** * Load the interwiki, trying first memcached then the DB * * @param string $prefix The interwiki prefix * @return Interwiki|bool Interwiki if $prefix is valid, otherwise false */ protected static function load($prefix) { global $wgInterwikiExpiry; $iwData = array(); if (!Hooks::run('InterwikiLoadPrefix', array($prefix, &$iwData))) { return Interwiki::loadFromArray($iwData); } $cache = ObjectCache::getMainWANInstance(); if (!$iwData) { $key = wfMemcKey('interwiki', $prefix); $iwData = $cache->get($key); if ($iwData === '!NONEXISTENT') { // negative cache hit return false; } } // is_array is hack for old keys if ($iwData && is_array($iwData)) { $iw = Interwiki::loadFromArray($iwData); if ($iw) { return $iw; } } $db = wfGetDB(DB_SLAVE); $row = $db->fetchRow($db->select('interwiki', self::selectFields(), array('iw_prefix' => $prefix), __METHOD__)); $iw = Interwiki::loadFromArray($row); if ($iw) { $mc = array('iw_url' => $iw->mURL, 'iw_api' => $iw->mAPI, 'iw_local' => $iw->mLocal, 'iw_trans' => $iw->mTrans); $cache->set($key, $mc, $wgInterwikiExpiry); return $iw; } // negative cache hit $cache->set($key, '!NONEXISTENT', $wgInterwikiExpiry); return false; }
/** * Normalizes and splits a title string. * * This function removes illegal characters, splits off the interwiki and * namespace prefixes, sets the other forms, and canonicalizes * everything. * * @todo this method is only exposed as a temporary measure to ease refactoring. * It was copied with minimal changes from Title::secureAndSplit(). * * @todo This method should be split up and an appropriate interface * defined for use by the Title class. * * @param string $text * @param int $defaultNamespace * * @throws MalformedTitleException If $text is not a valid title string. * @return array A mapp with the fields 'interwiki', 'fragment', 'namespace', * 'user_case_dbkey', and 'dbkey'. */ public function splitTitleString($text, $defaultNamespace = NS_MAIN) { $dbkey = str_replace(' ', '_', $text); # Initialisation $parts = array('interwiki' => '', 'local_interwiki' => false, 'fragment' => '', 'namespace' => $defaultNamespace, 'dbkey' => $dbkey, 'user_case_dbkey' => $dbkey); # Strip Unicode bidi override characters. # Sometimes they slip into cut-n-pasted page titles, where the # override chars get included in list displays. $dbkey = preg_replace('/\\xE2\\x80[\\x8E\\x8F\\xAA-\\xAE]/S', '', $dbkey); # Clean up whitespace # Note: use of the /u option on preg_replace here will cause # input with invalid UTF-8 sequences to be nullified out in PHP 5.2.x, # conveniently disabling them. $dbkey = preg_replace('/[ _\\xA0\\x{1680}\\x{180E}\\x{2000}-\\x{200A}\\x{2028}\\x{2029}\\x{202F}\\x{205F}\\x{3000}]+/u', '_', $dbkey); $dbkey = trim($dbkey, '_'); if (strpos($dbkey, UtfNormal\Constants::UTF8_REPLACEMENT) !== false) { # Contained illegal UTF-8 sequences or forbidden Unicode chars. throw new MalformedTitleException('title-invalid-utf8', $text); } $parts['dbkey'] = $dbkey; # Initial colon indicates main namespace rather than specified default # but should not create invalid {ns,title} pairs such as {0,Project:Foo} if ($dbkey !== '' && ':' == $dbkey[0]) { $parts['namespace'] = NS_MAIN; $dbkey = substr($dbkey, 1); # remove the colon but continue processing $dbkey = trim($dbkey, '_'); # remove any subsequent whitespace } if ($dbkey == '') { throw new MalformedTitleException('title-invalid-empty', $text); } # Namespace or interwiki prefix $prefixRegexp = "/^(.+?)_*:_*(.*)\$/S"; do { $m = array(); if (preg_match($prefixRegexp, $dbkey, $m)) { $p = $m[1]; if (($ns = $this->language->getNsIndex($p)) !== false) { # Ordinary namespace $dbkey = $m[2]; $parts['namespace'] = $ns; # For Talk:X pages, check if X has a "namespace" prefix if ($ns == NS_TALK && preg_match($prefixRegexp, $dbkey, $x)) { if ($this->language->getNsIndex($x[1])) { # Disallow Talk:File:x type titles... throw new MalformedTitleException('title-invalid-talk-namespace', $text); } elseif (Interwiki::isValidInterwiki($x[1])) { // TODO: get rid of global state! # Disallow Talk:Interwiki:x type titles... throw new MalformedTitleException('title-invalid-talk-namespace', $text); } } } elseif (Interwiki::isValidInterwiki($p)) { # Interwiki link $dbkey = $m[2]; $parts['interwiki'] = $this->language->lc($p); # Redundant interwiki prefix to the local wiki foreach ($this->localInterwikis as $localIW) { if (0 == strcasecmp($parts['interwiki'], $localIW)) { if ($dbkey == '') { # Empty self-links should point to the Main Page, to ensure # compatibility with cross-wiki transclusions and the like. $mainPage = Title::newMainPage(); return array('interwiki' => $mainPage->getInterwiki(), 'local_interwiki' => true, 'fragment' => $mainPage->getFragment(), 'namespace' => $mainPage->getNamespace(), 'dbkey' => $mainPage->getDBkey(), 'user_case_dbkey' => $mainPage->getUserCaseDBKey()); } $parts['interwiki'] = ''; # local interwikis should behave like initial-colon links $parts['local_interwiki'] = true; # Do another namespace split... continue 2; } } # If there's an initial colon after the interwiki, that also # resets the default namespace if ($dbkey !== '' && $dbkey[0] == ':') { $parts['namespace'] = NS_MAIN; $dbkey = substr($dbkey, 1); } } # If there's no recognized interwiki or namespace, # then let the colon expression be part of the title. } break; } while (true); $fragment = strstr($dbkey, '#'); if (false !== $fragment) { $parts['fragment'] = str_replace('_', ' ', substr($fragment, 1)); $dbkey = substr($dbkey, 0, strlen($dbkey) - strlen($fragment)); # remove whitespace again: prevents "Foo_bar_#" # becoming "Foo_bar_" $dbkey = preg_replace('/_*$/', '', $dbkey); } # Reject illegal characters. $rxTc = self::getTitleInvalidRegex(); $matches = array(); if (preg_match($rxTc, $dbkey, $matches)) { throw new MalformedTitleException('title-invalid-characters', $text, array($matches[0])); } # Pages with "/./" or "/../" appearing in the URLs will often be un- # reachable due to the way web browsers deal with 'relative' URLs. # Also, they conflict with subpage syntax. Forbid them explicitly. if (strpos($dbkey, '.') !== false && ($dbkey === '.' || $dbkey === '..' || strpos($dbkey, './') === 0 || strpos($dbkey, '../') === 0 || strpos($dbkey, '/./') !== false || strpos($dbkey, '/../') !== false || substr($dbkey, -2) == '/.' || substr($dbkey, -3) == '/..')) { throw new MalformedTitleException('title-invalid-relative', $text); } # Magic tilde sequences? Nu-uh! if (strpos($dbkey, '~~~') !== false) { throw new MalformedTitleException('title-invalid-magic-tilde', $text); } # Limit the size of titles to 255 bytes. This is typically the size of the # underlying database field. We make an exception for special pages, which # don't need to be stored in the database, and may edge over 255 bytes due # to subpage syntax for long titles, e.g. [[Special:Block/Long name]] $maxLength = $parts['namespace'] != NS_SPECIAL ? 255 : 512; if (strlen($dbkey) > $maxLength) { throw new MalformedTitleException('title-invalid-too-long', $text, array(Message::numParam($maxLength))); } # Normally, all wiki links are forced to have an initial capital letter so [[foo]] # and [[Foo]] point to the same place. Don't force it for interwikis, since the # other site might be case-sensitive. $parts['user_case_dbkey'] = $dbkey; if ($parts['interwiki'] === '') { $dbkey = Title::capitalize($dbkey, $parts['namespace']); } # Can't make a link to a namespace alone... "empty" local links can only be # self-links with a fragment identifier. if ($dbkey == '' && $parts['interwiki'] === '') { if ($parts['namespace'] != NS_MAIN) { throw new MalformedTitleException('title-invalid-empty', $text); } } // Allow IPv6 usernames to start with '::' by canonicalizing IPv6 titles. // IP names are not allowed for accounts, and can only be referring to // edits from the IP. Given '::' abbreviations and caps/lowercaps, // there are numerous ways to present the same IP. Having sp:contribs scan // them all is silly and having some show the edits and others not is // inconsistent. Same for talk/userpages. Keep them normalized instead. if ($parts['namespace'] == NS_USER || $parts['namespace'] == NS_USER_TALK) { $dbkey = IP::sanitizeIP($dbkey); } // Any remaining initial :s are illegal. if ($dbkey !== '' && ':' == $dbkey[0]) { throw new MalformedTitleException('title-invalid-leading-colon', $text); } # Fill fields $parts['dbkey'] = $dbkey; return $parts; }
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); } }
protected function appendInterwikiMap($property, $filter) { $local = null; if ($filter === 'local') { $local = 1; } elseif ($filter === '!local') { $local = 0; } elseif ($filter) { ApiBase::dieDebug(__METHOD__, "Unknown filter={$filter}"); } $params = $this->extractRequestParams(); $langCode = isset($params['inlanguagecode']) ? $params['inlanguagecode'] : ''; $langNames = Language::fetchLanguageNames($langCode); $getPrefixes = Interwiki::getAllPrefixes($local); $extraLangPrefixes = $this->getConfig()->get('ExtraInterlanguageLinkPrefixes'); $localInterwikis = $this->getConfig()->get('LocalInterwikis'); $data = array(); foreach ($getPrefixes as $row) { $prefix = $row['iw_prefix']; $val = array(); $val['prefix'] = $prefix; if (isset($row['iw_local']) && $row['iw_local'] == '1') { $val['local'] = ''; } if ($row['iw_trans'] == '1') { $val['trans'] = ''; } if (isset($langNames[$prefix])) { $val['language'] = $langNames[$prefix]; } if (in_array($prefix, $localInterwikis)) { $val['localinterwiki'] = ''; } if (in_array($prefix, $extraLangPrefixes)) { $val['extralanglink'] = ''; $linktext = wfMessage("interlanguage-link-{$prefix}"); if (!$linktext->isDisabled()) { $val['linktext'] = $linktext->text(); } $sitename = wfMessage("interlanguage-link-sitename-{$prefix}"); if (!$sitename->isDisabled()) { $val['sitename'] = $sitename->text(); } } $val['url'] = wfExpandUrl($row['iw_url'], PROTO_CURRENT); if (substr($row['iw_url'], 0, 2) == '//') { $val['protorel'] = ''; } if (isset($row['iw_wikiid'])) { $val['wikiid'] = $row['iw_wikiid']; } if (isset($row['iw_api'])) { $val['api'] = $row['iw_api']; } $data[] = $val; } $this->getResult()->setIndexedTagName($data, 'iw'); return $this->getResult()->addValue('query', $property, $data); }
/** * Secure and split - main initialisation function for this object * * Assumes that mDbkeyform has been set, and is urldecoded * and uses underscores, but not otherwise munged. This function * removes illegal characters, splits off the interwiki and * namespace prefixes, sets the other forms, and canonicalizes * everything. * @return \type{\bool} true on success */ private function secureAndSplit() { global $wgContLang, $wgLocalInterwiki, $wgCapitalLinks; # Initialisation static $rxTc = false; if (!$rxTc) { # Matching titles will be held as illegal. $rxTc = '/' . '[^' . Title::legalChars() . ']' . '|%[0-9A-Fa-f]{2}' . '|&[A-Za-z0-9\\x80-\\xff]+;' . '|&#[0-9]+;' . '|&#x[0-9A-Fa-f]+;' . '/S'; } $this->mInterwiki = $this->mFragment = ''; $this->mNamespace = $this->mDefaultNamespace; # Usually NS_MAIN $dbkey = $this->mDbkeyform; # Strip Unicode bidi override characters. # Sometimes they slip into cut-n-pasted page titles, where the # override chars get included in list displays. $dbkey = preg_replace('/\\xE2\\x80[\\x8E\\x8F\\xAA-\\xAE]/S', '', $dbkey); # Clean up whitespace # $dbkey = preg_replace('/[ _]+/', '_', $dbkey); $dbkey = trim($dbkey, '_'); if ('' == $dbkey) { return false; } if (false !== strpos($dbkey, UTF8_REPLACEMENT)) { # Contained illegal UTF-8 sequences or forbidden Unicode chars. return false; } $this->mDbkeyform = $dbkey; # Initial colon indicates main namespace rather than specified default # but should not create invalid {ns,title} pairs such as {0,Project:Foo} if (':' == $dbkey[0]) { $this->mNamespace = NS_MAIN; $dbkey = substr($dbkey, 1); # remove the colon but continue processing $dbkey = trim($dbkey, '_'); # remove any subsequent whitespace } # Namespace or interwiki prefix $firstPass = true; do { $m = array(); if (preg_match("/^(.+?)_*:_*(.*)\$/S", $dbkey, $m)) { $p = $m[1]; if ($ns = $wgContLang->getNsIndex($p)) { # Ordinary namespace $dbkey = $m[2]; $this->mNamespace = $ns; } elseif (Interwiki::isValidInterwiki($p)) { if (!$firstPass) { # Can't make a local interwiki link to an interwiki link. # That's just crazy! return false; } # Interwiki link $dbkey = $m[2]; $this->mInterwiki = $wgContLang->lc($p); # Redundant interwiki prefix to the local wiki if (0 == strcasecmp($this->mInterwiki, $wgLocalInterwiki)) { if ($dbkey == '') { # Can't have an empty self-link return false; } $this->mInterwiki = ''; $firstPass = false; # Do another namespace split... continue; } # If there's an initial colon after the interwiki, that also # resets the default namespace if ($dbkey !== '' && $dbkey[0] == ':') { $this->mNamespace = NS_MAIN; $dbkey = substr($dbkey, 1); } } # If there's no recognized interwiki or namespace, # then let the colon expression be part of the title. } break; } while (true); # We already know that some pages won't be in the database! # if ('' != $this->mInterwiki || NS_SPECIAL == $this->mNamespace) { $this->mArticleID = 0; } $fragment = strstr($dbkey, '#'); if (false !== $fragment) { $this->setFragment($fragment); $dbkey = substr($dbkey, 0, strlen($dbkey) - strlen($fragment)); # remove whitespace again: prevents "Foo_bar_#" # becoming "Foo_bar_" $dbkey = preg_replace('/_*$/', '', $dbkey); } # Reject illegal characters. # if (preg_match($rxTc, $dbkey)) { return false; } /** * Pages with "/./" or "/../" appearing in the URLs will often be un- * reachable due to the way web browsers deal with 'relative' URLs. * Also, they conflict with subpage syntax. Forbid them explicitly. */ if (strpos($dbkey, '.') !== false && ($dbkey === '.' || $dbkey === '..' || strpos($dbkey, './') === 0 || strpos($dbkey, '../') === 0 || strpos($dbkey, '/./') !== false || strpos($dbkey, '/../') !== false || substr($dbkey, -2) == '/.' || substr($dbkey, -3) == '/..')) { return false; } /** * Magic tilde sequences? Nu-uh! */ if (strpos($dbkey, '~~~') !== false) { return false; } /** * Limit the size of titles to 255 bytes. * This is typically the size of the underlying database field. * We make an exception for special pages, which don't need to be stored * in the database, and may edge over 255 bytes due to subpage syntax * for long titles, e.g. [[Special:Block/Long name]] */ if ($this->mNamespace != NS_SPECIAL && strlen($dbkey) > 255 || strlen($dbkey) > 512) { return false; } /** * Normally, all wiki links are forced to have * an initial capital letter so [[foo]] and [[Foo]] * point to the same place. * * Don't force it for interwikis, since the other * site might be case-sensitive. */ $this->mUserCaseDBKey = $dbkey; if ($wgCapitalLinks && $this->mInterwiki == '') { $dbkey = $wgContLang->ucfirst($dbkey); } /** * Can't make a link to a namespace alone... * "empty" local links can only be self-links * with a fragment identifier. */ if ($dbkey == '' && $this->mInterwiki == '' && $this->mNamespace != NS_MAIN) { return false; } // Allow IPv6 usernames to start with '::' by canonicalizing IPv6 titles. // IP names are not allowed for accounts, and can only be referring to // edits from the IP. Given '::' abbreviations and caps/lowercaps, // there are numerous ways to present the same IP. Having sp:contribs scan // them all is silly and having some show the edits and others not is // inconsistent. Same for talk/userpages. Keep them normalized instead. $dbkey = $this->mNamespace == NS_USER || $this->mNamespace == NS_USER_TALK ? IP::sanitizeIP($dbkey) : $dbkey; // Any remaining initial :s are illegal. if ($dbkey !== '' && ':' == $dbkey[0]) { return false; } # Fill fields $this->mDbkeyform = $dbkey; $this->mUrlform = wfUrlencode($dbkey); $this->mTextform = str_replace('_', ' ', $dbkey); return true; }
/** * Get a URL with no fragment or server name (relative URL) from a Title object. * If this page is generated with action=render, however, * $wgServer is prepended to make an absolute URL. * * @see self::getFullURL to always get an absolute URL. * @see self::getLinkURL to always get a URL that's the simplest URL that will be * valid to link, locally, to the current Title. * @see self::newFromText to produce a Title object. * * @param string|array $query An optional query string, * not used for interwiki links. Can be specified as an associative array as well, * e.g., array( 'action' => 'edit' ) (keys and values will be URL-escaped). * Some query patterns will trigger various shorturl path replacements. * @param array $query2 An optional secondary query array. This one MUST * be an array. If a string is passed it will be interpreted as a deprecated * variant argument and urlencoded into a variant= argument. * This second query argument will be added to the $query * The second parameter is deprecated since 1.19. Pass it as a key,value * pair in the first parameter array instead. * * @return string String of the URL. */ public function getLocalURL($query = '', $query2 = false) { global $wgArticlePath, $wgScript, $wgServer, $wgRequest; $query = self::fixUrlQueryArgs($query, $query2); $interwiki = Interwiki::fetch($this->mInterwiki); if ($interwiki) { $namespace = $this->getNsText(); if ($namespace != '') { # Can this actually happen? Interwikis shouldn't be parsed. # Yes! It can in interwiki transclusion. But... it probably shouldn't. $namespace .= ':'; } $url = $interwiki->getURL($namespace . $this->getDBkey()); $url = wfAppendQuery($url, $query); } else { $dbkey = wfUrlencode($this->getPrefixedDBkey()); if ($query == '') { $url = str_replace('$1', $dbkey, $wgArticlePath); Hooks::run('GetLocalURL::Article', array(&$this, &$url)); } else { global $wgVariantArticlePath, $wgActionPaths, $wgContLang; $url = false; $matches = array(); if (!empty($wgActionPaths) && preg_match('/^(.*&|)action=([^&]*)(&(.*)|)$/', $query, $matches)) { $action = urldecode($matches[2]); if (isset($wgActionPaths[$action])) { $query = $matches[1]; if (isset($matches[4])) { $query .= $matches[4]; } $url = str_replace('$1', $dbkey, $wgActionPaths[$action]); if ($query != '') { $url = wfAppendQuery($url, $query); } } } if ($url === false && $wgVariantArticlePath && $wgContLang->getCode() === $this->getPageLanguage()->getCode() && $this->getPageLanguage()->hasVariants() && preg_match('/^variant=([^&]*)$/', $query, $matches)) { $variant = urldecode($matches[1]); if ($this->getPageLanguage()->hasVariant($variant)) { // Only do the variant replacement if the given variant is a valid // variant for the page's language. $url = str_replace('$2', urlencode($variant), $wgVariantArticlePath); $url = str_replace('$1', $dbkey, $url); } } if ($url === false) { if ($query == '-') { $query = ''; } $url = "{$wgScript}?title={$dbkey}&{$query}"; } } Hooks::run('GetLocalURL::Internal', array(&$this, &$url, $query)); // @todo FIXME: This causes breakage in various places when we // actually expected a local URL and end up with dupe prefixes. if ($wgRequest->getVal('action') == 'render') { $url = $wgServer . $url; } } Hooks::run('GetLocalURL', array(&$this, &$url, $query)); return $url; }
protected function appendInterwikiMap($property, $filter) { $local = null; if ($filter === 'local') { $local = 1; } elseif ($filter === '!local') { $local = 0; } elseif ($filter) { ApiBase::dieDebug(__METHOD__, "Unknown filter={$filter}"); } $params = $this->extractRequestParams(); $langCode = isset($params['inlanguagecode']) ? $params['inlanguagecode'] : ''; if ($langCode) { $langNames = Language::getTranslatedLanguageNames($langCode); } else { $langNames = Language::getLanguageNames(); } $getPrefixes = Interwiki::getAllPrefixes($local); $data = array(); foreach ($getPrefixes as $row) { $prefix = $row['iw_prefix']; $val = array(); $val['prefix'] = $prefix; if ($row['iw_local'] == '1') { $val['local'] = ''; } // $val['trans'] = intval( $row['iw_trans'] ); // should this be exposed? if (isset($langNames[$prefix])) { $val['language'] = $langNames[$prefix]; } $val['url'] = wfExpandUrl($row['iw_url'], PROTO_CURRENT); if (isset($row['iw_wikiid'])) { $val['wikiid'] = $row['iw_wikiid']; } if (isset($row['iw_api'])) { $val['api'] = $row['iw_api']; } $data[] = $val; } $this->getResult()->setIndexedTagName($data, 'iw'); return $this->getResult()->addValue('query', $property, $data); }
/** * Load the interwiki, trying first memcached then the DB * * @param string $prefix The interwiki prefix * @return Interwiki|bool Interwiki if $prefix is valid, otherwise false */ protected static function load($prefix) { global $wgInterwikiExpiry; $iwData = array(); if (!Hooks::run('InterwikiLoadPrefix', array($prefix, &$iwData))) { return Interwiki::loadFromArray($iwData); } if (is_array($iwData)) { $iw = Interwiki::loadFromArray($iwData); if ($iw) { return $iw; // handled by hook } } $iwData = ObjectCache::getMainWANInstance()->getWithSetCallback(wfMemcKey('interwiki', $prefix), $wgInterwikiExpiry, function ($oldValue, &$ttl, array &$setOpts) use($prefix) { $dbr = wfGetDB(DB_SLAVE); $setOpts += Database::getCacheSetOptions($dbr); $row = $dbr->selectRow('interwiki', Interwiki::selectFields(), array('iw_prefix' => $prefix), __METHOD__); return $row ? (array) $row : '!NONEXISTENT'; }); if (is_array($iwData)) { return Interwiki::loadFromArray($iwData) ?: false; } return false; }
public function testArrayStorage() { $dewiki = ['iw_prefix' => 'de', 'iw_url' => 'http://de.wikipedia.org/wiki/', 'iw_local' => 1]; $zzwiki = ['iw_prefix' => 'zz', 'iw_url' => 'http://zzwiki.org/wiki/', 'iw_local' => 0]; $cdbData = $this->populateHash('en', [$dewiki], [$zzwiki]); $this->setWgInterwikiCache($cdbData); $this->assertEquals([$dewiki, $zzwiki], Interwiki::getAllPrefixes(), 'getAllPrefixes()'); $this->assertTrue(Interwiki::isValidInterwiki('de'), 'known prefix is valid'); $this->assertTrue(Interwiki::isValidInterwiki('zz'), 'known prefix is valid'); $interwiki = Interwiki::fetch('de'); $this->assertInstanceOf('Interwiki', $interwiki); $this->assertSame('http://de.wikipedia.org/wiki/', $interwiki->getURL(), 'getURL'); $this->assertSame(true, $interwiki->isLocal(), 'isLocal'); $interwiki = Interwiki::fetch('zz'); $this->assertInstanceOf('Interwiki', $interwiki); $this->assertSame('http://zzwiki.org/wiki/', $interwiki->getURL(), 'getURL'); $this->assertSame(false, $interwiki->isLocal(), 'isLocal'); }
/** * Generate the URL out of the object reference * * @param string $objRef * @return bool|string */ private function getButtonHrefByObjectReference($objRef) { $arrObjRef = explode('|', $objRef); if (count($arrObjRef) > 1) { list($wiki, $title) = $arrObjRef; if (Interwiki::isValidInterwiki($wiki)) { return str_replace('$1', $title, Interwiki::fetch($wiki)->getURL()); } } return false; }
public function interwikiMap($filter = null) { global $wgLocalInterwikis, $wgExtraInterlanguageLinkPrefixes; $this->checkTypeOptional('interwikiMap', 1, $filter, 'string', null); $local = null; if ($filter === 'local') { $local = 1; } elseif ($filter === '!local') { $local = 0; } elseif ($filter !== null) { throw new Scribunto_LuaError("bad argument #1 to 'interwikiMap' (unknown filter '{$filter}')"); } $cacheKey = $filter === null ? 'null' : $filter; if (!isset(self::$interwikiMapCache[$cacheKey])) { // Not expensive because we can have a max of three cache misses in the // entire page parse. $interwikiMap = array(); $prefixes = Interwiki::getAllPrefixes($local); foreach ($prefixes as $row) { $prefix = $row['iw_prefix']; $val = array('prefix' => $prefix, 'url' => wfExpandUrl($row['iw_url'], PROTO_RELATIVE), 'isProtocolRelative' => substr($row['iw_url'], 0, 2) === '//', 'isLocal' => isset($row['iw_local']) && $row['iw_local'] == '1', 'isTranscludable' => isset($row['iw_trans']) && $row['iw_trans'] == '1', 'isCurrentWiki' => in_array($prefix, $wgLocalInterwikis), 'isExtraLanguageLink' => in_array($prefix, $wgExtraInterlanguageLinkPrefixes)); if ($val['isExtraLanguageLink']) { $displayText = wfMessage("interlanguage-link-{$prefix}"); if (!$displayText->isDisabled()) { $val['displayText'] = $displayText->text(); } $tooltip = wfMessage("interlanguage-link-sitename-{$prefix}"); if (!$tooltip->isDisabled()) { $val['tooltip'] = $tooltip->text(); } } $interwikiMap[$prefix] = $val; } self::$interwikiMapCache[$cacheKey] = $interwikiMap; } return array(self::$interwikiMapCache[$cacheKey]); }
/** * Load the interwiki, trying first memcached then the DB * * @param $prefix The interwiki prefix * @return bool The prefix is valid * @static * */ protected static function load($prefix) { global $wgMemc, $wgInterwikiExpiry; global $wgLanguageNames; $key = wfMemcKey('interwiki', $prefix); $mc = $wgMemc->get($key); $iw = false; if ($mc && is_array($mc)) { // is_array is hack for old keys $iw = Interwiki::loadFromArray($mc); if ($iw) { return $iw; } } # $$$ Sean: This is a hack to get the interwiki links working # but only accept a prefix that is a valid language if (isset($prefix, $wgLanguageNames[$prefix]) && '' != $wgLanguageNames[$prefix]) { $iw = new Interwiki(); $iw->mURL = $prefix . '.wiki'; $iw->mLocal = 0; $iw->mTrans = 0; } else { $iw = false; } /* $db = wfGetDB( DB_SLAVE ); $row = $db->fetchRow( $db->select( 'interwiki', '*', array( 'iw_prefix' => $prefix ), __METHOD__ ) ); $iw = Interwiki::loadFromArray( $row ); */ # $$$ end of hack if ($iw) { $mc = array('iw_url' => $iw->mURL, 'iw_local' => $iw->mLocal, 'iw_trans' => $iw->mTrans); $wgMemc->add($key, $mc, $wgInterwikiExpiry); return $iw; } return false; }
/** * Load the interwiki, trying first memcached then the DB * * @param $prefix string The interwiki prefix * @return Boolean: the prefix is valid */ protected static function load($prefix) { global $wgMemc, $wgInterwikiExpiry; $iwData = false; if (!wfRunHooks('InterwikiLoadPrefix', array($prefix, &$iwData))) { return Interwiki::loadFromArray($iwData); } if (!$iwData) { $key = wfMemcKey('interwiki', md5($prefix)); $iwData = $wgMemc->get($key); if ($iwData === '!NONEXISTENT') { return false; // negative cache hit } } if ($iwData && is_array($iwData)) { // is_array is hack for old keys $iw = Interwiki::loadFromArray($iwData); if ($iw) { return $iw; } } $db = wfGetDB(DB_SLAVE); $row = $db->fetchRow($db->select('interwiki', '*', array('iw_prefix' => $prefix), __METHOD__)); $iw = Interwiki::loadFromArray($row); if ($iw) { $mc = array('iw_url' => $iw->mURL, 'iw_api' => $iw->mAPI, 'iw_local' => $iw->mLocal, 'iw_trans' => $iw->mTrans); $wgMemc->add($key, $mc, $wgInterwikiExpiry); return $iw; } else { $wgMemc->add($key, '!NONEXISTENT', $wgInterwikiExpiry); // negative cache hit } return false; }
/** * Secure and split - main initialisation function for this object * * Assumes that mDbkeyform has been set, and is urldecoded * and uses underscores, but not otherwise munged. This function * removes illegal characters, splits off the interwiki and * namespace prefixes, sets the other forms, and canonicalizes * everything. * * @return Bool true on success */ private function secureAndSplit() { global $wgContLang, $wgLocalInterwiki; # Initialisation $this->mInterwiki = $this->mFragment = ''; $this->mNamespace = $this->mDefaultNamespace; # Usually NS_MAIN $dbkey = $this->mDbkeyform; # Strip Unicode bidi override characters. # Sometimes they slip into cut-n-pasted page titles, where the # override chars get included in list displays. $dbkey = preg_replace('/\\xE2\\x80[\\x8E\\x8F\\xAA-\\xAE]/S', '', $dbkey); # Clean up whitespace # Note: use of the /u option on preg_replace here will cause # input with invalid UTF-8 sequences to be nullified out in PHP 5.2.x, # conveniently disabling them. $dbkey = preg_replace('/[ _\\xA0\\x{1680}\\x{180E}\\x{2000}-\\x{200A}\\x{2028}\\x{2029}\\x{202F}\\x{205F}\\x{3000}]+/u', '_', $dbkey); $dbkey = trim($dbkey, '_'); if ($dbkey == '') { return false; } if (false !== strpos($dbkey, UTF8_REPLACEMENT)) { # Contained illegal UTF-8 sequences or forbidden Unicode chars. return false; } $this->mDbkeyform = $dbkey; # Initial colon indicates main namespace rather than specified default # but should not create invalid {ns,title} pairs such as {0,Project:Foo} if (':' == $dbkey[0]) { $this->mNamespace = NS_MAIN; $dbkey = substr($dbkey, 1); # remove the colon but continue processing $dbkey = trim($dbkey, '_'); # remove any subsequent whitespace } # Namespace or interwiki prefix $firstPass = true; $prefixRegexp = "/^(.+?)_*:_*(.*)\$/S"; do { $m = array(); if (preg_match($prefixRegexp, $dbkey, $m)) { $p = $m[1]; if (($ns = $wgContLang->getNsIndex($p)) !== false) { # Ordinary namespace $dbkey = $m[2]; $this->mNamespace = $ns; # For Talk:X pages, check if X has a "namespace" prefix if ($ns == NS_TALK && preg_match($prefixRegexp, $dbkey, $x)) { if ($wgContLang->getNsIndex($x[1])) { # Disallow Talk:File:x type titles... return false; } elseif (Interwiki::isValidInterwiki($x[1])) { # Disallow Talk:Interwiki:x type titles... return false; } } } elseif (Interwiki::isValidInterwiki($p)) { if (!$firstPass) { # Can't make a local interwiki link to an interwiki link. # That's just crazy! return false; } # Interwiki link $dbkey = $m[2]; $this->mInterwiki = $wgContLang->lc($p); # Redundant interwiki prefix to the local wiki if ($wgLocalInterwiki !== false && 0 == strcasecmp($this->mInterwiki, $wgLocalInterwiki)) { if ($dbkey == '') { # Can't have an empty self-link return false; } $this->mInterwiki = ''; $firstPass = false; # Do another namespace split... continue; } # If there's an initial colon after the interwiki, that also # resets the default namespace if ($dbkey !== '' && $dbkey[0] == ':') { $this->mNamespace = NS_MAIN; $dbkey = substr($dbkey, 1); } } # If there's no recognized interwiki or namespace, # then let the colon expression be part of the title. } break; } while (true); # We already know that some pages won't be in the database! if ($this->mInterwiki != '' || NS_SPECIAL == $this->mNamespace) { $this->mArticleID = 0; } $fragment = strstr($dbkey, '#'); if (false !== $fragment) { $this->setFragment($fragment); $dbkey = substr($dbkey, 0, strlen($dbkey) - strlen($fragment)); # remove whitespace again: prevents "Foo_bar_#" # becoming "Foo_bar_" $dbkey = preg_replace('/_*$/', '', $dbkey); } # Reject illegal characters. $rxTc = self::getTitleInvalidRegex(); if (preg_match($rxTc, $dbkey)) { return false; } # Pages with "/./" or "/../" appearing in the URLs will often be un- # reachable due to the way web browsers deal with 'relative' URLs. # Also, they conflict with subpage syntax. Forbid them explicitly. if (strpos($dbkey, '.') !== false && ($dbkey === '.' || $dbkey === '..' || strpos($dbkey, './') === 0 || strpos($dbkey, '../') === 0 || strpos($dbkey, '/./') !== false || strpos($dbkey, '/../') !== false || substr($dbkey, -2) == '/.' || substr($dbkey, -3) == '/..')) { return false; } # Magic tilde sequences? Nu-uh! if (strpos($dbkey, '~~~') !== false) { return false; } # Limit the size of titles to 255 bytes. This is typically the size of the # underlying database field. We make an exception for special pages, which # don't need to be stored in the database, and may edge over 255 bytes due # to subpage syntax for long titles, e.g. [[Special:Block/Long name]] if ($this->mNamespace != NS_SPECIAL && strlen($dbkey) > 255 || strlen($dbkey) > 512) { return false; } # Normally, all wiki links are forced to have an initial capital letter so [[foo]] # and [[Foo]] point to the same place. Don't force it for interwikis, since the # other site might be case-sensitive. $this->mUserCaseDBKey = $dbkey; if ($this->mInterwiki == '') { $dbkey = self::capitalize($dbkey, $this->mNamespace); } # Can't make a link to a namespace alone... "empty" local links can only be # self-links with a fragment identifier. if ($dbkey == '' && $this->mInterwiki == '' && $this->mNamespace != NS_MAIN) { return false; } // Allow IPv6 usernames to start with '::' by canonicalizing IPv6 titles. // IP names are not allowed for accounts, and can only be referring to // edits from the IP. Given '::' abbreviations and caps/lowercaps, // there are numerous ways to present the same IP. Having sp:contribs scan // them all is silly and having some show the edits and others not is // inconsistent. Same for talk/userpages. Keep them normalized instead. $dbkey = $this->mNamespace == NS_USER || $this->mNamespace == NS_USER_TALK ? IP::sanitizeIP($dbkey) : $dbkey; // Any remaining initial :s are illegal. if ($dbkey !== '' && ':' == $dbkey[0]) { return false; } # Fill fields $this->mDbkeyform = $dbkey; $this->mUrlform = wfUrlencode($dbkey); $this->mTextform = str_replace('_', ' ', $dbkey); return true; }
function showList() { $canModify = $this->canModify(); $this->getOutput()->addWikiMsg('interwiki_intro'); $this->getOutput()->addHTML(Html::rawElement('table', array('class' => 'mw-interwikitable wikitable intro'), self::addInfoRow('start', 'interwiki_prefix', 'interwiki_prefix_intro') . self::addInfoRow('start', 'interwiki_url', 'interwiki_url_intro') . self::addInfoRow('start', 'interwiki_local', 'interwiki_local_intro') . self::addInfoRow('end', 'interwiki_0', 'interwiki_local_0_intro') . self::addInfoRow('end', 'interwiki_1', 'interwiki_local_1_intro') . self::addInfoRow('start', 'interwiki_trans', 'interwiki_trans_intro') . self::addInfoRow('end', 'interwiki_0', 'interwiki_trans_0_intro') . self::addInfoRow('end', 'interwiki_1', 'interwiki_trans_1_intro')) . "\n"); $this->getOutput()->addWikiMsg('interwiki_intro_footer'); if ($canModify) { $addtext = wfMessage('interwiki_addtext')->escaped(); $addlink = Linker::linkKnown($this->getTitle('add'), $addtext); $this->getOutput()->addHTML('<p class="mw-interwiki-addlink">' . $addlink . '</p>'); } if (!method_exists('Interwiki', 'getAllPrefixes')) { # version 2.0 is not backwards compatible (but still display nice error) $this->error('interwiki_error'); return; } $iwPrefixes = Interwiki::getAllPrefixes(null); if (!is_array($iwPrefixes) || count($iwPrefixes) == 0) { # If the interwiki table is empty, display an error message $this->error('interwiki_error'); return; } $out = ''; # Output the table header $out .= Html::openElement('table', array('class' => 'mw-interwikitable wikitable sortable body')) . "\n"; $out .= Html::openElement('tr', array('id' => 'interwikitable-header')) . Html::element('th', null, wfMessage('interwiki_prefix')) . Html::element('th', null, wfMessage('interwiki_url')) . Html::element('th', null, wfMessage('interwiki_local')) . Html::element('th', null, wfMessage('interwiki_trans')) . ($canModify ? Html::element('th', array('class' => 'unsortable'), wfMessage('interwiki_edit')) : ''); $out .= Html::closeElement('tr') . "\n"; $selfTitle = $this->getTitle(); foreach ($iwPrefixes as $i => $iwPrefix) { $out .= Html::openElement('tr', array('class' => 'mw-interwikitable-row')); $out .= Html::element('td', array('class' => 'mw-interwikitable-prefix'), htmlspecialchars($iwPrefix['iw_prefix'])); $out .= Html::element('td', array('class' => 'mw-interwikitable-url'), $iwPrefix['iw_url']); $out .= Html::element('td', array('class' => 'mw-interwikitable-local'), isset($iwPrefix['iw_local']) ? wfMessage('interwiki_' . $iwPrefix['iw_local']) : '-'); $out .= Html::element('td', array('class' => 'mw-interwikitable-trans'), isset($iwPrefix['iw_trans']) ? wfMessage('interwiki_' . $iwPrefix['iw_trans']) : '-'); if ($canModify) { $out .= Html::rawElement('td', array('class' => 'mw-interwikitable-modify'), Linker::linkKnown($selfTitle, wfMessage('edit')->escaped(), array(), array('action' => 'edit', 'prefix' => $iwPrefix['iw_prefix'])) . wfMessage('comma-separator') . Linker::linkKnown($selfTitle, wfMessage('delete')->escaped(), array(), array('action' => 'delete', 'prefix' => $iwPrefix['iw_prefix']))); } $out .= Html::closeElement('tr') . "\n"; } $out .= Html::closeElement('table'); $this->getOutput()->addHTML($out); }
function showList() { $canModify = $this->canModify(); $this->getOutput()->addWikiMsg('interwiki_intro'); // Make collapsible. $this->getOutput()->addHTML(Html::openElement('div', array('class' => 'mw-collapsible mw-collapsed', 'data-collapsetext' => $this->msg('interwiki-legend-hide')->escaped(), 'data-expandtext' => $this->msg('interwiki-legend-show')->escaped()))); $this->getOutput()->addHTML(Html::rawElement('table', array('class' => 'mw-interwikitable wikitable intro'), $this->addInfoRow('start', 'interwiki_prefix', 'interwiki_prefix_intro') . "\n" . $this->addInfoRow('start', 'interwiki_url', 'interwiki_url_intro') . "\n" . $this->addInfoRow('start', 'interwiki_local', 'interwiki_local_intro') . "\n" . $this->addInfoRow('end', 'interwiki_0', 'interwiki_local_0_intro') . "\n" . $this->addInfoRow('end', 'interwiki_1', 'interwiki_local_1_intro') . "\n" . $this->addInfoRow('start', 'interwiki_trans', 'interwiki_trans_intro') . "\n" . $this->addInfoRow('end', 'interwiki_0', 'interwiki_trans_0_intro') . "\n" . $this->addInfoRow('end', 'interwiki_1', 'interwiki_trans_1_intro') . "\n")); $this->getOutput()->addHTML(Html::closeElement('div')); // end collapsible. if ($canModify) { $this->getOutput()->addHTML("<br />" . $this->msg('interwiki_intro_footer')->parse()); $addtext = $this->msg('interwiki_addtext')->escaped(); $addlink = Linker::linkKnown($this->getTitle('add'), $addtext); $this->getOutput()->addHTML('<p class="mw-interwiki-addlink">' . $addlink . '</p>'); } if (!method_exists('Interwiki', 'getAllPrefixes')) { # version 2.0 is not backwards compatible (but still display nice error) $this->error('interwiki_error'); return; } $iwPrefixes = Interwiki::getAllPrefixes(null); if (!is_array($iwPrefixes) || count($iwPrefixes) === 0) { # If the interwiki table is empty, display an error message $this->error('interwiki_error'); return; } # Output the existing Interwiki prefixes table header $out = ''; $out .= Html::openElement('table', array('class' => 'mw-interwikitable wikitable sortable body')) . "\n"; $out .= Html::openElement('tr', array('id' => 'interwikitable-header')) . Html::element('th', null, $this->msg('interwiki_prefix')->text()) . Html::element('th', null, $this->msg('interwiki_url')->text()) . Html::element('th', null, $this->msg('interwiki_local')->text()) . Html::element('th', null, $this->msg('interwiki_trans')->text()) . ($canModify ? Html::element('th', array('class' => 'unsortable'), $this->msg('interwiki_edit')->text()) : ''); $out .= Html::closeElement('tr') . "\n"; $selfTitle = $this->getTitle(); # Output the existing Interwiki prefixes table rows foreach ($iwPrefixes as $iwPrefix) { $out .= Html::openElement('tr', array('class' => 'mw-interwikitable-row')); $out .= Html::element('td', array('class' => 'mw-interwikitable-prefix'), $iwPrefix['iw_prefix']); $out .= Html::element('td', array('class' => 'mw-interwikitable-url'), $iwPrefix['iw_url']); $attribs = array('class' => 'mw-interwikitable-local'); // Green background for cells with "yes". if ($iwPrefix['iw_local']) { $attribs['style'] = 'background: lime;'; } // The messages interwiki_0 and interwiki_1 are used here. $contents = isset($iwPrefix['iw_local']) ? $this->msg('interwiki_' . $iwPrefix['iw_local'])->text() : '-'; $out .= Html::element('td', $attribs, $contents); $attribs = array('class' => 'mw-interwikitable-trans'); // Green background for cells with "yes". if ($iwPrefix['iw_trans']) { $attribs['style'] = 'background: lime;'; } // The messages interwiki_0 and interwiki_1 are used here. $contents = isset($iwPrefix['iw_trans']) ? $this->msg('interwiki_' . $iwPrefix['iw_trans'])->text() : '-'; $out .= Html::element('td', $attribs, $contents); // Additional column when the interwiki table can be modified. if ($canModify) { $out .= Html::rawElement('td', array('class' => 'mw-interwikitable-modify'), Linker::linkKnown($selfTitle, $this->msg('edit')->escaped(), array(), array('action' => 'edit', 'prefix' => $iwPrefix['iw_prefix'])) . $this->msg('comma-separator') . Linker::linkKnown($selfTitle, $this->msg('delete')->escaped(), array(), array('action' => 'delete', 'prefix' => $iwPrefix['iw_prefix']))); } $out .= Html::closeElement('tr') . "\n"; } $out .= Html::closeElement('table'); $this->getOutput()->addHTML($out); }
/** * Get a list of languages available for this project * @return string parsed Html */ private function getSiteSelector() { $selector = ''; $count = 0; $language = $this->getLanguage(); foreach (Interwiki::getAllPrefixes(true) as $interwiki) { $code = $interwiki['iw_prefix']; $name = $language->fetchLanguageName($code); if (!$name) { continue; } $title = Title::newFromText("{$code}:"); if ($title) { $url = $title->getFullURL(); } else { $url = ''; } $attrs = array('href' => $url); $count++; if ($code == $this->getConfig()->get('LanguageCode')) { $attrs['class'] = 'selected'; } $selector .= Html::openElement('li'); $selector .= Html::element('a', $attrs, $name); $selector .= Html::closeElement('li'); } if ($selector && $count > 1) { $selector = <<<HTML \t\t\t<p>{$this->msg('mobile-frontend-settings-site-description', $count)->parse()}</p> \t\t\t<ul id='mw-mf-language-list'> \t\t\t\t{$selector} \t\t\t</ul> HTML; } return $selector; }
/** * @param string $interwiki * @param string $page * @param bool $history * @param bool $templates * @param int $pageLinkDepth * @return Status */ public static function newFromInterwiki($interwiki, $page, $history = false, $templates = false, $pageLinkDepth = 0) { if ($page == '') { return Status::newFatal('import-noarticle'); } # Look up the first interwiki prefix, and let the foreign site handle # subsequent interwiki prefixes $firstIwPrefix = strtok($interwiki, ':'); $firstIw = Interwiki::fetch($firstIwPrefix); if (!$firstIw) { return Status::newFatal('importbadinterwiki'); } $additionalIwPrefixes = strtok(''); if ($additionalIwPrefixes) { $additionalIwPrefixes .= ':'; } # Have to do a DB-key replacement ourselves; otherwise spaces get # URL-encoded to +, which is wrong in this case. Similar to logic in # Title::getLocalURL $link = $firstIw->getURL(strtr("{$additionalIwPrefixes}Special:Export/{$page}", ' ', '_')); $params = array(); if ($history) { $params['history'] = 1; } if ($templates) { $params['templates'] = 1; } if ($pageLinkDepth) { $params['pagelink-depth'] = $pageLinkDepth; } $url = wfAppendQuery($link, $params); # For interwikis, use POST to avoid redirects. return ImportStreamSource::newFromURL($url, "POST"); }
/** * Get the interwiki list * * @return array */ private function getInterwikiList() { $result = Interwiki::getAllPrefixes(); $prefixes = array(); foreach ($result as $row) { $prefixes[] = $row['iw_prefix']; } return $prefixes; }
/** * Load the interwiki, trying first memcached then the DB * * @param $prefix The interwiki prefix * @return Boolean: the prefix is valid */ protected static function load($prefix) { global $wgMemc, $wgInterwikiExpiry; $key = wfMemcKey('interwiki', $prefix); $mc = $wgMemc->get($key); if ($mc && is_array($mc)) { // is_array is hack for old keys $iw = Interwiki::loadFromArray($mc); if ($iw) { return $iw; } } $db = wfGetDB(DB_SLAVE); $row = $db->fetchRow($db->select('interwiki', '*', array('iw_prefix' => $prefix), __METHOD__)); $iw = Interwiki::loadFromArray($row); if ($iw) { $mc = array('iw_url' => $iw->mURL, 'iw_api' => $iw->mAPI, 'iw_local' => $iw->mLocal, 'iw_trans' => $iw->mTrans); $wgMemc->add($key, $mc, $wgInterwikiExpiry); return $iw; } return false; }