5define(
'NS_MAIN',
"nsmain");
6define(
'NS_SPECIAL',
"nsspecial");
8define(
'GAID_FOR_UPDATE', 1);
10# Title::newFromTitle maintains a cache to avoid
11# expensive re-normalization of commonly used titles.
12# On a batch operation this can become a memory leak
13# if not bounded. After hitting this many titles,
15define(
'MW_TITLECACHE_MAX', 1000);
17# Constants for pr_cascade bitfield
47 public $mNamespace; # Namespace index, i.e. one of the NS_xxxx constants
49 public
$mFragment;
# Title fragment (i.e. the bit after the #)
50 public $mArticleID; # Article ID, fetched from the link cache on demand
60 # Zero except in {{transclusion}} tags
71 $this->mInterwiki = $this->mUrlform =
72 $this->mTextform = $this->mDbkeyform =
'';
73 $this->mArticleID = -1;
75 $this->mRestrictionsLoaded =
false;
76 $this->mRestrictions = array();
77 # Dont change the following, NS_MAIN is hardcoded in several place
79 $this->mDefaultNamespace =
NS_MAIN;
80 $this->mWatched =
null;
81 $this->mLatestID =
false;
82 $this->mOldRestrictions =
false;
95 $t->mDbkeyform =
$key;
96 if ($t->secureAndSplit()) {
116 if (is_object($text)) {
117 throw new MWException(
'Title::newFromText given an object');
138 $t->mDbkeyform = str_replace(
' ',
'_', $filteredText);
139 $t->mDefaultNamespace = $defaultNamespace;
141 static $cachedcount = 0 ;
142 if ($t->secureAndSplit()) {
143 if ($defaultNamespace ==
NS_MAIN) {
145 # Avoid memory leaks on mass operations...
167 global $wgLegalTitleChars;
170 # For compatibility with old buggy URLs. "+" is usually not valid in titles,
171 # but some URLs used it as a space replacement and they still come
172 # from some external search tools.
173 if (strpos($wgLegalTitleChars,
'+') ===
false) {
177 $t->mDbkeyform = str_replace(
' ',
'_',
$url);
178 if ($t->secureAndSplit()) {
196 $fname =
'Title::newFromID';
197 $dbr = wfGetDB(DB_SLAVE);
198 $row = $dbr->selectRow(
200 array(
'page_namespace',
'page_title' ),
201 array(
'page_id' =>
$id ),
204 if ($row !==
false) {
217 $dbr = wfGetDB(DB_SLAVE);
220 array(
'page_namespace',
'page_title' ),
221 'page_id IN (' . $dbr->makeList($ids) .
')',
226 while ($row = $dbr->fetchObject(
$res)) {
248 $t->mNamespace = intval($ns);
249 $t->mDbkeyform = str_replace(
' ',
'_', $title);
250 $t->mArticleID = ($ns >= 0) ? -1 : 0;
251 $t->mUrlform = wfUrlencode($t->mDbkeyform);
252 $t->mTextform = str_replace(
'_',
' ', $title);
269 if ($t->secureAndSplit()) {
286 #----------------------------------------------------------------------------
288 #----------------------------------------------------------------------------
300 $fname =
'Title::nameOf';
301 $dbr = wfGetDB(DB_SLAVE);
303 $s = $dbr->selectRow(
'page', array(
'page_namespace',
'page_title' ), array(
'page_id' =>
$id ), $fname);
318 global $wgLegalTitleChars;
320 $wgLegalTitleChars =
" %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF+";
322 return $wgLegalTitleChars;
336 $n = $wgContLang->getNsText($ns);
337 return $n ==
'' ? $title :
"$n:$title";
349 global $wgMemc, $wgInterwikiExpiry;
350 global $wgInterwikiCache, $wgContLang;
354 $fname =
'Title::getInterwikiLink';
358 $k = wfMemcKey(
'interwiki',
$key);
363 if ($wgInterwikiCache) {
367 $s = $wgMemc->get($k);
368 # Ignore old keys with no iw_local
369 if ($s && isset($s->iw_local) && isset($s->iw_trans)) {
374 $dbr = wfGetDB(DB_SLAVE);
377 array(
'iw_url',
'iw_local',
'iw_trans' ),
378 array(
'iw_prefix' =>
$key ),
385 $s = $dbr->fetchObject(
$res);
387 # Cache non-existence: create a blank object and save it to memcached
393 $wgMemc->set($k, $s, $wgInterwikiExpiry);
408 global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite;
412 $db = dba_open($wgInterwikiCache,
'r',
'cdb');
415 if ($wgInterwikiScopes >= 3 and !$site) {
416 $site = dba_fetch(
'__sites:' . wfWikiID(), $db);
418 $site = $wgInterwikiFallbackSite;
421 $value = dba_fetch(wfMemcKey(
$key), $db);
422 if ($value ==
'' and $wgInterwikiScopes >= 3) {
424 $value = dba_fetch(
"_{$site}:{$key}", $db);
426 if ($value ==
'' and $wgInterwikiScopes >= 2) {
428 $value = dba_fetch(
"__global:{$key}", $db);
430 if ($value ==
'undef') {
438 list($local,
$url) = explode(
' ', $value, 2);
440 $s->iw_local = (
int) $local;
454 if ($this->mInterwiki !=
'') {
455 # Make sure key is loaded into cache
457 $k = wfMemcKey(
'interwiki', $this->mInterwiki);
472 if ($this->mInterwiki ==
'') {
475 # Make sure key is loaded into cache
477 $k = wfMemcKey(
'interwiki', $this->mInterwiki);
486 $fragment = str_replace(
' ',
'_', $fragment);
488 $replaceArray = array(
492 return strtr($fragment, $replaceArray);
495 #----------------------------------------------------------------------------
497 #----------------------------------------------------------------------------
538 global $wgContLang, $wgCanonicalNamespaceNames;
540 if (
'' != $this->mInterwiki) {
547 if (isset($wgCanonicalNamespaceNames[$this->mNamespace])) {
551 return $wgContLang->getNsText($this->mNamespace);
601 if ($this->mFragment ==
'') {
623 return Title::indexTitle($this->mNamespace, $this->mTextform);
633 $s = $this->
prefix($this->mDbkeyform);
634 $s = str_replace(
' ',
'_', $s);
645 if (empty($this->mPrefixedText)) {
646 $s = $this->
prefix($this->mTextform);
647 $s = str_replace(
'_',
' ', $s);
648 $this->mPrefixedText = $s;
662 if (
'' != $this->mFragment) {
674 global $wgNamespacesWithSubpages;
675 if (isset($wgNamespacesWithSubpages[ $this->mNamespace ]) && $wgNamespacesWithSubpages[ $this->mNamespace ]) {
677 # Don't discard the real title if there's no subpage involved
681 return implode(
'/',
$parts);
693 global $wgNamespacesWithSubpages;
694 if (isset($wgNamespacesWithSubpages[ $this->mNamespace ]) && $wgNamespacesWithSubpages[ $this->mNamespace ]) {
695 $parts = explode(
'/', $this->mTextform);
698 return($this->mTextform);
709 $text = wfUrlencode(str_replace(
' ',
'_', $text));
710 $text = str_replace(
'%28',
'(', str_replace(
'%29',
')', $text)); # Clean
up the URL; per below,
this might not be safe
720 $s = $this->
prefix($this->mDbkeyform);
721 $s = str_replace(
' ',
'_', $s);
723 $s = wfUrlencode($s) ;
725 # Cleaning up URL to make it look nice -- is this safe?
726 $s = str_replace(
'%28',
'(', $s);
727 $s = str_replace(
'%29',
')', $s);
743 global $wgContLang, $wgServer, $wgRequest;
745 if (
'' == $this->mInterwiki) {
750 if ($wgRequest->getVal(
'action') !=
'render') {
758 # Can this actually happen? Interwikis shouldn't be parsed.
759 # Yes! It can in interwiki transclusion. But... it probably shouldn't.
766 # Finally, add the fragment.
769 wfRunHooks(
'GetFullURL', array( &$this, &
$url,
$query ));
783 global $wgArticlePath, $wgScript, $wgServer, $wgRequest;
784 global $wgVariantArticlePath, $wgContLang, $wgUser;
787 if ($variant ==
false && $wgContLang->hasVariants() && !$wgUser->isLoggedIn()) {
788 $pref = $wgContLang->getPreferredVariant(
false);
789 if ($pref != $wgContLang->getCode()) {
806 if ($variant !=
false && $wgContLang->hasVariants()) {
807 if ($wgVariantArticlePath ==
false) {
808 $variantArticlePath =
"$wgScript?title=$1&variant=$2";
810 $variantArticlePath = $wgVariantArticlePath;
812 $url = str_replace(
'$2', urlencode($variant), $variantArticlePath);
813 $url = str_replace(
'$1', $dbkey,
$url);
815 $url = str_replace(
'$1', $dbkey, $wgArticlePath);
818 global $wgActionPaths;
821 if (!empty($wgActionPaths) &&
822 preg_match(
'/^(.*&|)action=([^&]*)(&(.*)|)$/',
$query, $matches)) {
823 $action = urldecode($matches[2]);
824 if (isset($wgActionPaths[$action])) {
826 if (isset($matches[4])) {
829 $url = str_replace(
'$1', $dbkey, $wgActionPaths[$action]);
835 if (
$url ===
false) {
839 $url =
"{$wgScript}?title={$dbkey}&{$query}";
845 if ($wgRequest->getVal(
'action') ==
'render') {
849 wfRunHooks(
'GetLocalURL', array( &$this, &
$url,
$query ));
887 global $wgInternalServer;
889 wfRunHooks(
'GetInternalURL', array( &$this, &
$url,
$query ));
900 if (
'' != $this->mInterwiki) {
924 return (
'' != $this->mInterwiki);
937 if (count($restrictions) > 0) {
938 foreach ($restrictions as $restriction) {
939 if (strtolower($restriction) !=
'autoconfirmed') {
949 # If it doesn't exist, it can't be protected
962 global $wgRestrictionLevels;
964 # Special pages have inherent protection
969 # Check regular protection levels
970 if ($action ==
'edit' || $action ==
'') {
972 foreach ($wgRestrictionLevels as $level) {
973 if (in_array($level, $r) && $level !=
'') {
979 if ($action ==
'move' || $action ==
'') {
981 foreach ($wgRestrictionLevels as $level) {
982 if (in_array($level, $r) && $level !=
'') {
999 if (is_null($this->mWatched)) {
1000 if (
NS_SPECIAL == $this->mNamespace || !$wgUser->isLoggedIn()) {
1001 $this->mWatched =
false;
1003 $this->mWatched = $wgUser->isWatched($this);
1020 return $this->
userCan($action,
false);
1029 public function userCan($action, $doExpensiveQueries =
true)
1031 $fname =
'Title::userCan';
1032 wfProfileIn($fname);
1034 global $wgUser, $wgNamespaceProtection;
1037 wfRunHooks(
'userCan', array( &$this, &$wgUser, $action, &$result ));
1038 if ($result !==
null) {
1039 wfProfileOut($fname);
1044 wfProfileOut($fname);
1048 if (array_key_exists($this->mNamespace, $wgNamespaceProtection)) {
1050 if (!is_array($nsProt)) {
1051 $nsProt = array($nsProt);
1053 foreach ($nsProt as $right) {
1054 if (
'' != $right && !$wgUser->isAllowed($right)) {
1055 wfProfileOut($fname);
1061 if ($this->mDbkeyform ==
'_') {
1062 # FIXME: Is this necessary? Shouldn't be allowed anyway...
1063 wfProfileOut($fname);
1067 # protect css/js subpages of user pages
1068 # XXX: this might be better using restrictions
1069 # XXX: Find a way to work around the php bug that prevents using $this->userCanEditCssJsSubpage() from working
1070 if ($this->isCssJsSubpage()
1071 && !$wgUser->isAllowed(
'editinterface')
1072 && !preg_match(
'/^' . preg_quote($wgUser->getName(),
'/') .
'\//', $this->mTextform)) {
1073 wfProfileOut($fname);
1077 if ($doExpensiveQueries && !$this->isCssJsSubpage()) {
1078 # We /could/ use the protection level on the source page, but it's fairly ugly
1079 # as we have to establish a precedence hierarchy for pages included by multiple
1080 # cascade-protected pages. So just restrict it to people with 'protect' permission,
1081 # as they could remove the protection anyway.
1082 list($cascadingSources, $restrictions) = $this->getCascadeProtectionSources();
1083 # Cascading protection depends on more than this page...
1084 # Several cascading protected pages may include this page...
1085 # Check each cascading level
1086 # This is only for protection restrictions, not for all actions
1087 if ($cascadingSources > 0 && isset($restrictions[$action])) {
1088 foreach ($restrictions[$action] as $right) {
1089 $right = ($right ==
'sysop') ?
'protect' : $right;
1090 if (
'' != $right && !$wgUser->isAllowed($right)) {
1091 wfProfileOut($fname);
1100 if ($right ==
'sysop') {
1103 if (
'' != $right && !$wgUser->isAllowed($right)) {
1104 wfProfileOut($fname);
1109 if ($action ==
'move' &&
1110 !($this->isMovable() && $wgUser->isAllowed(
'move'))) {
1111 wfProfileOut($fname);
1115 if ($action ==
'create') {
1116 if (($this->isTalkPage() && !$wgUser->isAllowed(
'createtalk')) ||
1117 (!$this->isTalkPage() && !$wgUser->isAllowed(
'createpage'))) {
1118 wfProfileOut($fname);
1123 wfProfileOut($fname);
1134 return $this->
userCan(
'edit', $doExpensiveQueries);
1144 return $this->
userCan(
'create', $doExpensiveQueries);
1154 return $this->
userCan(
'move', $doExpensiveQueries);
1178 wfRunHooks(
'userCan', array( &$this, &$wgUser,
'read', &$result ));
1179 if ($result !==
null) {
1183 if ($wgUser->isAllowed(
'read')) {
1186 global $wgWhitelistRead;
1198 if ($wgWhitelistRead && in_array(
$name, $wgWhitelistRead)) {
1202 # Compatibility with old settings
1204 if (in_array(
':' .
$name, $wgWhitelistRead)) {
1226 global $wgNamespacesWithSubpages;
1228 if (isset($wgNamespacesWithSubpages[ $this->mNamespace ])) {
1229 return (strpos($this->
getText(),
'/') !==
false && $wgNamespacesWithSubpages[ $this->mNamespace ] ==
true);
1240 $subpage = explode(
'/', $this->mTextform);
1241 $subpage = $subpage[ count($subpage) - 1 ];
1242 return(str_replace(array(
'.css',
'.js' ), array(
'',
'' ), $subpage));
1250 return (NS_USER == $this->mNamespace and preg_match(
"/\\/.*\\.css$/", $this->mTextform));
1258 return (NS_USER == $this->mNamespace and preg_match(
"/\\/.*\\.js$/", $this->mTextform));
1269 return ($wgUser->isAllowed(
'editinterface') or preg_match(
'/^' . preg_quote($wgUser->getName(),
'/') .
'\//', $this->mTextform));
1274 if (!$this->mRestrictionsLoaded) {
1287 $dbr = wfGetDb(DB_SLAVE);
1289 $this->mRestrictions[
'edit'] = array();
1290 $this->mRestrictions[
'move'] = array();
1292 # Backwards-compatibility: also load the restrictions from the page record (old format).
1294 if ($oldFashionedRestrictions ==
null) {
1295 $oldFashionedRestrictions = $dbr->selectField(
'page',
'page_restrictions', array(
'page_id' => $this->
getArticleID() ), __METHOD__);
1298 if ($oldFashionedRestrictions !=
'') {
1299 foreach (explode(
':', trim($oldFashionedRestrictions)) as $restrict) {
1300 $temp = explode(
'=', trim($restrict));
1301 if (count($temp) == 1) {
1303 $this->mRestrictions[
"edit"] = explode(
',', trim($temp[0]));
1304 $this->mRestrictions[
"move"] = explode(
',', trim($temp[0]));
1306 $this->mRestrictions[$temp[0]] = explode(
',', trim($temp[1]));
1310 $this->mOldRestrictions =
true;
1311 $this->mCascadeRestriction =
false;
1312 $this->mRestrictionsExpiry = Block::decodeExpiry(
'');
1315 if ($dbr->numRows(
$res)) {
1316 # Current system - load second to make them override.
1317 $now = wfTimestampNow();
1318 $purgeExpired =
false;
1320 while ($row = $dbr->fetchObject(
$res)) {
1321 # Cycle through all the restrictions.
1325 $expiry = Block::decodeExpiry($row->pr_expiry);
1328 if (!$expiry || $expiry > $now) {
1329 $this->mRestrictionsExpiry = $expiry;
1330 $this->mRestrictions[$row->pr_type] = explode(
',', trim($row->pr_level));
1332 $this->mCascadeRestriction |= $row->pr_cascade;
1335 $purgeExpired =
true;
1339 if ($purgeExpired) {
1344 $this->mRestrictionsLoaded =
true;
1349 if (!$this->mRestrictionsLoaded) {
1350 $dbr = wfGetDB(DB_SLAVE);
1352 $res = $dbr->select(
1353 'page_restrictions',
1368 $dbw = wfGetDB(DB_MASTER);
1370 'page_restrictions',
1371 array(
'pr_expiry < ' . $dbw->addQuotes($dbw->timestamp()) ),
1385 if (!$this->mRestrictionsLoaded) {
1388 return $this->mRestrictions[$action] ?? array();
1400 $fname =
'Title::isDeleted';
1404 $dbr = wfGetDB(DB_SLAVE);
1405 $n = $dbr->selectField(
'archive',
'COUNT(*)', array(
'ar_namespace' => $this->
getNamespace(),
1406 'ar_title' => $this->
getDBkey() ), $fname);
1408 $n += $dbr->selectField(
1411 array(
'fa_name' => $this->
getDBkey() ),
1428 $linkCache = &LinkCache::singleton();
1430 $oldUpdate = $linkCache->forUpdate(
true);
1431 $this->mArticleID = $linkCache->addLinkObj($this);
1432 $linkCache->forUpdate($oldUpdate);
1434 if (-1 == $this->mArticleID) {
1435 $this->mArticleID = $linkCache->addLinkObj($this);
1443 if ($this->mLatestID !==
false) {
1447 $db = wfGetDB(DB_SLAVE);
1448 return $this->mLatestID = $db->selectField(
1452 'Title::getLatestRevID'
1468 $linkCache = &LinkCache::singleton();
1472 $this->mArticleID = -1;
1474 $this->mArticleID = $newid;
1476 $this->mRestrictionsLoaded =
false;
1477 $this->mRestrictions = array();
1486 global $wgUseFileCache;
1492 $dbw = wfGetDB(DB_MASTER);
1493 $success = $dbw->update(
1496 'page_touched' => $dbw->timestamp()
1502 'Title::invalidateCache'
1505 if ($wgUseFileCache) {
1506 $cache =
new HTMLFileCache($this);
1507 @unlink($cache->fileCacheName());
1524 if (
'' != $this->mInterwiki) {
1525 $p = $this->mInterwiki .
':';
1527 if (0 != $this->mNamespace) {
1545 global $wgContLang, $wgLocalInterwiki, $wgCapitalLinks;
1548 static $rxTc =
false;
1550 # % is needed as well
1554 $this->mInterwiki = $this->mFragment =
'';
1559 # Strip Unicode bidi override characters.
1560 # Sometimes they slip into cut-n-pasted page titles, where the
1561 # override chars get included in list displays.
1562 $dbkey = str_replace(
"\xE2\x80\x8E",
'', $dbkey);
1563 $dbkey = str_replace(
"\xE2\x80\x8F",
'', $dbkey);
1565 # Clean up whitespace
1567 $dbkey = preg_replace(
'/[ _]+/',
'_', $dbkey);
1568 $dbkey = trim($dbkey,
'_');
1574 if (
false !== strpos($dbkey, UTF8_REPLACEMENT)) {
1575 # Contained illegal UTF-8 sequences or forbidden Unicode chars.
1579 $this->mDbkeyform = $dbkey;
1581 # Initial colon indicates main namespace rather than specified default
1582 # but should not create invalid {ns,title} pairs such as {0,Project:Foo}
1583 if (
':' == $dbkey[0]) {
1585 $dbkey = substr($dbkey, 1); #
remove the colon but
continue processing
1586 $dbkey = trim($dbkey,
'_'); #
remove any subsequent whitespace
1589 # Namespace or interwiki prefix
1593 if (preg_match(
"/^(.+?)_*:_*(.*)$/S", $dbkey, $m)) {
1595 if ($ns = $wgContLang->getNsIndex($p)) {
1596 # Ordinary namespace
1598 $this->mNamespace = $ns;
1601 # Can't make a local interwiki link to an interwiki link.
1602 # That's just crazy!
1608 $this->mInterwiki = $wgContLang->lc($p);
1610 # Redundant interwiki prefix to the local wiki
1611 if (0 == strcasecmp($this->mInterwiki, $wgLocalInterwiki)) {
1613 # Can't have an empty self-link
1616 $this->mInterwiki =
'';
1618 # Do another namespace split...
1622 # If there's an initial colon after the interwiki, that also
1623 # resets the default namespace
1624 if ($dbkey !==
'' && $dbkey[0] ==
':') {
1626 $dbkey = substr($dbkey, 1);
1629 # If there's no recognized interwiki or namespace,
1630 # then let the colon expression be part of the title.
1635 # We already know that some pages won't be in the database!
1637 if (
'' != $this->mInterwiki ||
NS_SPECIAL == $this->mNamespace) {
1638 $this->mArticleID = 0;
1640 $fragment = strstr($dbkey,
'#');
1641 if (
false !== $fragment) {
1643 $dbkey = substr($dbkey, 0, strlen($dbkey) - strlen($fragment));
1644 # remove whitespace again: prevents "Foo_bar_#"
1645 # becoming "Foo_bar_"
1646 $dbkey = preg_replace(
'/_*$/',
'', $dbkey);
1649 # Reject illegal characters.
1651 if (preg_match($rxTc, $dbkey)) {
1660 if (strpos($dbkey,
'.') !==
false &&
1661 ($dbkey ===
'.' || $dbkey ===
'..' ||
1662 strpos($dbkey,
'./') === 0 ||
1663 strpos($dbkey,
'../') === 0 ||
1664 strpos($dbkey,
'/./') !==
false ||
1665 strpos($dbkey,
'/../') !==
false)) {
1672 if (strpos($dbkey,
'~~~') !==
false) {
1683 if (($this->mNamespace !=
NS_SPECIAL && strlen($dbkey) > 255) ||
1684 strlen($dbkey) > 512) {
1696 if ($wgCapitalLinks && $this->mInterwiki ==
'') {
1697 $dbkey = $wgContLang->ucfirst($dbkey);
1706 $this->mInterwiki ==
'' &&
1707 $this->mNamespace !=
NS_MAIN) {
1712 if ($dbkey !==
'' &&
':' == $dbkey[0]) {
1717 $this->mDbkeyform = $dbkey;
1720 $this->mTextform = str_replace(
'_',
' ', $dbkey);
1736 $this->mFragment = str_replace(
'_',
' ', substr($fragment, 1));
1767 public function getLinksTo($options =
'', $table =
'pagelinks', $prefix =
'pl')
1769 $linkCache = &LinkCache::singleton();
1772 $db = wfGetDB(DB_MASTER);
1774 $db = wfGetDB(DB_SLAVE);
1778 array(
'page', $table ),
1779 array(
'page_namespace',
'page_title',
'page_id' ),
1781 "{$prefix}_from=page_id",
1783 "{$prefix}_title" => $this->
getDBkey() ),
1784 'Title::getLinksTo',
1789 if ($db->numRows(
$res)) {
1790 while ($row = $db->fetchObject(
$res)) {
1791 if ($titleObj =
Title::makeTitle($row->page_namespace, $row->page_title)) {
1792 $linkCache->addGoodLinkObj($row->page_id, $titleObj);
1793 $retVal[] = $titleObj;
1797 $db->freeResult(
$res);
1813 return $this->
getLinksTo($options,
'templatelinks',
'tl');
1825 $db = wfGetDB(DB_MASTER);
1827 $db = wfGetDB(DB_SLAVE);
1830 $res = $db->safeQuery(
1831 "SELECT pl_namespace, pl_title
1834 ON pl_namespace=page_namespace
1835 AND pl_title=page_title
1837 AND page_namespace IS NULL
1839 $db->tableName(
'pagelinks'),
1840 $db->tableName(
'page'),
1841 $this->getArticleID(),
1846 if ($db->numRows(
$res)) {
1847 while ($row = $db->fetchObject(
$res)) {
1851 $db->freeResult(
$res);
1872 if ($wgContLang->hasVariants()) {
1873 $variants = $wgContLang->getVariants();
1874 foreach ($variants as $vCode) {
1875 if ($vCode == $wgContLang->getCode()) {
1890 $u =
new SquidUpdate($urls);
1901 return $this->
moveTo($nt,
false);
1915 if (!$this or !$nt) {
1916 return 'badtitletext';
1918 if ($this->
equals($nt)) {
1921 if (!$this->isMovable() || !$nt->isMovable()) {
1922 return 'immobile_namespace';
1926 $newid = $nt->getArticleID();
1928 if (strlen($nt->getDBkey()) < 1) {
1929 return 'articleexists';
1933 (
'' == $nt->getDBkey())) {
1934 return 'badarticleerror';
1938 !$this->
userCan(
'edit') || !$nt->userCan(
'edit') ||
1939 !$this->userCan(
'move') || !$nt->userCan(
'move')
1941 return 'protectedpage';
1944 # The move is allowed only if (1) the target doesn't exist, or
1945 # (2) the target is a redirect to the source, and has no history
1946 # (so we can undo bad moves right after they're done).
1948 if (0 != $newid) { # Target
exists; check
for validity
1950 return 'articleexists';
1966 if (is_string($err)) {
1971 if ($nt->exists()) {
1973 $pageCountChange = 0;
1974 }
else { # Target didn
't exist, do normal move.
1975 $this->moveToNewTitle($nt, $reason);
1976 $pageCountChange = 1;
1978 $redirid = $this->getArticleID();
1980 # Fixing category links (those without piped 'alternate
' names) to be sorted under the new title
1981 $dbw = wfGetDB(DB_MASTER);
1982 $categorylinks = $dbw->tableName('categorylinks
');
1983 $sql = "UPDATE $categorylinks SET cl_sortkey=" . $dbw->addQuotes($nt->getPrefixedText()) .
1984 " WHERE cl_from=" . $dbw->addQuotes($pageid) .
1985 " AND cl_sortkey=" . $dbw->addQuotes($this->getPrefixedText());
1986 $dbw->query($sql, 'SpecialMovepage::doSubmit
');
1990 $oldnamespace = $this->getNamespace() & ~1;
1991 $newnamespace = $nt->getNamespace() & ~1;
1992 $oldtitle = $this->getDBkey();
1993 $newtitle = $nt->getDBkey();
1995 if ($oldnamespace != $newnamespace || $oldtitle != $newtitle) {
1996 WatchedItem::duplicateEntries($this, $nt);
1999 # Update search engine
2000 $u = new SearchUpdate($pageid, $nt->getPrefixedDBkey());
2002 $u = new SearchUpdate($redirid, $this->getPrefixedDBkey(), '');
2006 if ($this->isContentPage() && !$nt->isContentPage()) {
2007 # No longer a content page
2008 # Not viewed, edited, removing
2009 $u = new SiteStatsUpdate(0, 1, -1, $pageCountChange);
2010 } elseif (!$this->isContentPage() && $nt->isContentPage()) {
2011 # Now a content page
2012 # Not viewed, edited, adding
2013 $u = new SiteStatsUpdate(0, 1, +1, $pageCountChange);
2014 } elseif ($pageCountChange) {
2016 $u = new SiteStatsUpdate(0, 0, 0, 1);
2026 wfRunHooks('TitleMoveComplete
', array( &$this, &$nt, &$wgUser, $pageid, $redirid ));
2037 private function moveOverExistingRedirect($nt, $reason = '')
2041 $comment = wfMsgForContent('1movedto2_redir
', $this->getPrefixedText(), $nt->getPrefixedText());
2044 $comment .= ": $reason";
2047 $now = wfTimestampNow();
2048 $newid = $nt->getArticleID();
2049 $oldid = $this->getArticleID();
2050 $dbw = wfGetDB(DB_MASTER);
2051 $linkCache = &LinkCache::singleton();
2053 # Delete the old redirect. We don't save it to history since
2054 # by definition if we've got here it's rather uninteresting.
2055 # We have to remove it so that the next step doesn't trigger
2056 # a conflict on the unique namespace+title index...
2057 $dbw->delete(
'page', array(
'page_id' => $newid ), $fname);
2059 # Save a null revision in the page's history notifying of the move
2060 $nullRevision = Revision::newNullRevision($dbw, $oldid,
$comment,
true);
2061 $nullRevId = $nullRevision->insertOn($dbw);
2063 # Change the name of the target page:
2068 'page_touched' => $dbw->timestamp($now),
2069 'page_namespace' => $nt->getNamespace(),
2070 'page_title' => $nt->getDBkey(),
2071 'page_latest' => $nullRevId,
2074 array(
'page_id' => $oldid ),
2077 $linkCache->clearLink($nt->getPrefixedDBkey());
2079 # Recreate the redirect, this time in the other direction.
2081 $redirectText = $mwRedir->getSynonym(0) .
' [[' . $nt->getPrefixedText() .
"]]\n";
2082 $redirectArticle =
new Article($this);
2083 $newid = $redirectArticle->insertOn($dbw);
2084 $redirectRevision =
new Revision(array(
2087 'text' => $redirectText ));
2088 $redirectRevision->insertOn($dbw);
2089 $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0);
2093 $log =
new LogPage(
'move');
2094 $log->addEntry(
'move_redir', $this,
$reason, array( 1 => $nt->getPrefixedText() ));
2096 # Now, we record the link from the redirect to the new title.
2097 # It should have no other outgoing links...
2098 $dbw->delete(
'pagelinks', array(
'pl_from' => $newid ), $fname);
2102 'pl_from' => $newid,
2103 'pl_namespace' => $nt->getNamespace(),
2104 'pl_title' => $nt->getDBkey() ),
2110 $urls = array_merge($nt->getSquidURLs(), $this->getSquidURLs());
2111 $u =
new SquidUpdate($urls);
2123 $fname =
'MovePageForm::moveToNewTitle';
2129 $newid = $nt->getArticleID();
2131 $dbw = wfGetDB(DB_MASTER);
2132 $now = $dbw->timestamp();
2133 $linkCache = &LinkCache::singleton();
2135 # Save a null revision in the page's history notifying of the move
2136 $nullRevision = Revision::newNullRevision($dbw, $oldid,
$comment,
true);
2137 $nullRevId = $nullRevision->insertOn($dbw);
2144 'page_touched' => $now,
2145 'page_namespace' => $nt->getNamespace(),
2146 'page_title' => $nt->getDBkey(),
2147 'page_latest' => $nullRevId,
2150 array(
'page_id' => $oldid ),
2154 $linkCache->clearLink($nt->getPrefixedDBkey());
2158 $redirectText = $mwRedir->getSynonym(0) .
' [[' . $nt->getPrefixedText() .
"]]\n";
2159 $redirectArticle =
new Article($this);
2160 $newid = $redirectArticle->insertOn($dbw);
2161 $redirectRevision =
new Revision(array(
2164 'text' => $redirectText ));
2165 $redirectRevision->insertOn($dbw);
2166 $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0);
2170 $log =
new LogPage(
'move');
2171 $log->addEntry(
'move', $this,
$reason, array( 1 => $nt->getPrefixedText()));
2173 # Purge caches as per article creation
2174 Article::onArticleCreate($nt);
2176 # Record the just-created redirect's linking to the page
2180 'pl_from' => $newid,
2181 'pl_namespace' => $nt->getNamespace(),
2182 'pl_title' => $nt->getDBkey() ),
2186 # Purge old title from squid
2187 # The new title, and links to the new title, are purged in Article::onArticleCreate()
2199 $fname =
'Title::isValidMoveTarget';
2200 $dbw = wfGetDB(DB_MASTER);
2203 $id = $nt->getArticleID();
2204 $obj = $dbw->selectRow(
2205 array(
'page',
'revision',
'text'),
2206 array(
'page_is_redirect',
'old_text',
'old_flags' ),
2207 array(
'page_id' =>
$id,
'page_latest=rev_id',
'rev_text_id=old_id' ),
2212 if (!$obj || 0 == $obj->page_is_redirect) {
2214 wfDebug(__METHOD__ .
": not a redirect\n");
2217 $text = Revision::getRevisionText($obj);
2219 # Does the redirect point to the source?
2220 # Or is it a broken self-redirect, usually caused by namespace collisions?
2222 if (preg_match(
"/\\[\\[\\s*([^\\]\\|]*)]]/", $text, $m)) {
2224 if (!is_object($redirTitle) ||
2225 ($redirTitle->getPrefixedDBkey() != $this->getPrefixedDBkey() &&
2226 $redirTitle->getPrefixedDBkey() != $nt->getPrefixedDBkey())) {
2227 wfDebug(__METHOD__ .
": redirect points to other page\n");
2232 wfDebug(__METHOD__ .
": failsafe\n");
2236 # Does the article have a history?
2237 $row = $dbw->selectRow(
2238 array(
'page',
'revision'),
2240 array(
'page_namespace' => $nt->getNamespace(),
2241 'page_title' => $nt->getDBkey(),
2242 'page_id=rev_page AND page_latest != rev_id'
2248 # Return true if there was no history
2249 return $row ===
false;
2264 $dbr = wfGetDB(DB_SLAVE);
2265 $categorylinks = $dbr->tableName(
'categorylinks');
2268 $sql =
"SELECT * FROM $categorylinks"
2269 .
" WHERE cl_from='$titlekey'"
2270 .
" AND cl_from <> '0'"
2271 .
" ORDER BY cl_sortkey";
2273 $res = $dbr->query($sql) ;
2275 if ($dbr->numRows(
$res) > 0) {
2276 while ($x = $dbr->fetchObject(
$res)) {
2278 $data[$wgContLang->getNSText(NS_CATEGORY) .
':' . $x->cl_to] = $this->
getFullText();
2280 $dbr->freeResult(
$res) ;
2296 if ($parents !=
'') {
2297 foreach ($parents as $parent => $current) {
2298 if (array_key_exists($parent, $children)) {
2299 # Circular reference
2300 $stack[$parent] = array();
2304 $stack[$parent] = $nt->getParentCategoryTree($children + array($parent => 1));
2323 return array(
'page_namespace' => $this->mNamespace,
'page_title' => $this->mDbkeyform );
2333 $dbr = wfGetDB(DB_SLAVE);
2334 return $dbr->selectField(
2338 ' AND rev_id<' . intval($revision) .
' ORDER BY rev_id DESC'
2349 $dbr = wfGetDB(DB_SLAVE);
2350 return $dbr->selectField(
2354 ' AND rev_id>' . intval($revision) .
' ORDER BY rev_id'
2366 $dbr = wfGetDB(DB_SLAVE);
2367 return $dbr->selectField(
2371 ' AND rev_id > ' . intval($old) .
2372 ' AND rev_id < ' . intval($new)
2385 return $this->
getInterwiki() === $title->getInterwiki()
2387 && $this->
getDBkey() === $title->getDBkey();
2418 $u =
new HTMLCacheUpdate($this,
'pagelinks');
2422 $u =
new HTMLCacheUpdate($this,
'categorylinks');
2432 $dbr = wfGetDB(DB_SLAVE);
2433 $touched = $dbr->selectField(
2447 global $wgTitle, $wgScriptPath, $wgServer;
2449 return "$wgServer$wgScriptPath/trackback.php?article="
2450 . htmlspecialchars(urlencode($wgTitle->getPrefixedDBkey()));
2456 $title = htmlspecialchars($this->
getText());
2460<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"
2461 xmlns:dc=\"http://purl.org/dc/elements/1.1/\"
2462 xmlns:trackback=\"http://madskills.com/public/xml/rss/module/trackback/\">
2465 dc:identifier=\"$url\"
2467 trackback:ping=\"$tburl\" />
2481 return 'nstab-main';
2484 return 'nstab-user';
2486 return 'nstab-media';
2488 return 'nstab-special';
2490 case NS_PROJECT_TALK:
2491 return 'nstab-project';
2494 return 'nstab-image';
2496 case NS_MEDIAWIKI_TALK:
2497 return 'nstab-mediawiki';
2499 case NS_TEMPLATE_TALK:
2500 return 'nstab-template';
2503 return 'nstab-help';
2505 case NS_CATEGORY_TALK:
2506 return 'nstab-category';
2508 return 'nstab-' . $wgContLang->lc($this->getSubjectNsText());
2519 list($thisName, ) = SpecialPage::resolveAliasWithSubpage($this->
getDBkey());
2520 if (
$name == $thisName) {
2534 $canonicalName = SpecialPage::resolveAlias($this->mDbkeyform);
2535 if ($canonicalName) {
2536 $localName = SpecialPage::getLocalNameFor($canonicalName);
2537 if ($localName != $this->mDbkeyform) {
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
static return function(ContainerConfigurator $containerConfigurator)
static decodeCharReferences($text)
Decode any character references, numeric or named entities, in the text and return a UTF-8 string.
getInternalURL($query='', $variant=false)
Get the URL form for an internal link.
escapeFullURL($query='')
Get an HTML-escaped version of the URL form, suitable for using in a link, including the server name ...
getTouched()
Get the last touched timestamp.
getNamespace()
Get the namespace index, i.e.
static getInterwikiCached($key)
Fetch interwiki prefix data from local cache in constant database.
userCanRead()
Would anybody with sufficient privileges be able to move this page? Some pages just aren't movable.
static $titleCache
Static cache variables.
invalidateCache()
Updates page_touched for this page; called from LinksUpdate.php.
$mHasCascadingRestrictions
moveTo(&$nt, $auth=true, $reason='')
Move a title to a new location.
$mTextform
All member variables should be considered private Please use the accessor functions.
nameOf($id)
Get the prefixed DB key associated with an ID.
getNextRevisionID($revision)
Get the revision ID of the next revision.
secureAndSplit()
Secure and split - main initialisation function for this object.
getSkinFromCssJsSubpage()
Trim down a .css or .js subpage title to get the corresponding skin name.
getDefaultNamespace()
Get the default namespace index, for when there is no namespace.
resetArticleID($newid)
This clears some fields in this object, and clears any associated keys in the "bad links" section of ...
getFragment()
Get the Title fragment (i.e.
isProtected($action='')
Does the title correspond to a protected article?
getIndexTitle()
Get title for search index.
getPrefixedURL()
Get a URL-encoded title (not an actual URL) including interwiki.
getLinksTo($options='', $table='pagelinks', $prefix='pl')
Get a Title object associated with the talk page of this article.
prefix($name)
Prefix some arbitrary text with the namespace or interwiki prefix of this object.
static newFromText($text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
areRestrictionsCascading()
getEscapedText()
Get the HTML-escaped displayable text form.
getFullText()
Get the prefixed title with spaces, plus any fragment (part beginning with '#')
getFullURL($query='', $variant=false)
Get a real URL referring to this title, with interwiki link and fragment.
isLocal()
Determine whether the object refers to a page within this project.
moveNoAuth(&$nt)
Move this page without authentication.
$mCascadeRestrictionSources
static makeTitleSafe($ns, $title)
Create a new Title from a namespace index and a DB key.
quickUserCan($action)
Can $wgUser perform $action on this page? This skips potentially expensive cascading permission check...
fixSpecialName()
If the Title refers to a special page alias which is not the local default, returns a new Title which...
static legalChars()
Get a regex character class describing the legal characters in a link.
getPrefixedDBkey()
Get the prefixed database key form.
getNsText()
Get the namespace text.
static purgeExpiredRestrictions()
Purge expired restrictions from the page_restrictions table.
equals($title)
Compare with another title.
userCanCreate($doExpensiveQueries=true)
Can $wgUser create this page?
isTrans()
Determine whether the object refers to a page within this project and is transcludable.
static makeName($ns, $title)
touchLinks()
Update page_touched timestamps and send squid purge messages for pages linking to this title.
userIsWatching()
Is $wgUser is watching this page?
isExternal()
Is this Title interwiki?
getFragmentForURL()
Get the fragment in URL form, including the "#" character if there is one.
static newFromID($id)
Create a new Title from an article ID.
getArticleID($flags=0)
Get the article ID for this Title from the link cache, adding it if necessary.
static & makeTitle($ns, $title)
Create a new Title from a namespace index and a DB key.
getSubpageUrlForm()
Get a URL-encoded form of the subpage text.
getDBkey()
Get the main part with underscores.
countRevisionsBetween($old, $new)
Get the number of revisions between the given revision IDs.
userCanEditCssJsSubpage()
Protect css/js subpages of user pages: can $wgUser edit this page?
userCanEdit($doExpensiveQueries=true)
Can $wgUser edit this page?
getBrokenLinksFrom($options='')
Get an array of Title objects referring to non-existent articles linked from this page.
getPartialURL()
Get the URL-encoded form of the main part.
getBaseText()
Get the base name, i.e.
getText()
Simple accessors.
pageCond()
Get an associative array for selecting this title from the "page" table.
isSemiProtected($action='edit')
Is this page "semi-protected" - the only protection is autoconfirm?
isJsSubpage()
Is this a .js subpage of a user page?
userCanMove($doExpensiveQueries=true)
Can $wgUser move this page?
isSpecial($name)
Returns true if this title resolves to the named special page.
static newMainPage()
Create a new Title for the Main Page.
moveOverExistingRedirect($nt, $reason='')
Move page to a title which is at present a redirect to the source page.
isCssSubpage()
Is this a .css subpage of a user page?
exists()
Check if page exists.
getSquidURLs()
Get a list of URLs to purge from the Squid cache when this page changes.
getLocalURL($query='', $variant=false)
Get a URL with no fragment or server name.
static newFromURL($url)
Create a new Title from URL-encoded text.
isDeleted()
Is there a version of this page in the deletion archive?
static newFromDBkey($key)
Create a new Title from a prefixed DB key.
setFragment($fragment)
Set the fragment for this title This is kind of bad, since except for this rarely-used function,...
loadRestrictions($oldFashionedRestrictions=null)
getParentCategoryTree($children=array())
Get a tree of parent categories.
getEditURL()
Get the edit URL for this Title.
getParentCategories()
Get categories to which this Title belongs and return an array of categories' names.
getNamespaceKey()
Generate strings used for xml 'id' names in monobook tabs.
static newFromIDs($ids)
Make an array of titles from an array of IDs.
getInterwikiLink($key)
Returns the URL associated with an interwiki prefix.
isSubpage()
Is this a talk page of some sort?
moveToNewTitle(&$nt, $reason='')
Move page to non-existing title.
getInterwiki()
Get the namespace text of the subject (rather than talk) page.
isValidMoveOperation($nt, $auth=true)
Check whether a given move operation would be valid.
isValidMoveTarget($nt)
Checks if $this can be moved to a given Title.
userCan($action, $doExpensiveQueries=true)
Can $wgUser perform $action on this page?
getTemplateLinksTo($options='')
Get an array of Title objects using this Title as a template Also stores the IDs in the link cache.
getSubpageText()
Get the lowest-level subpage name, i.e.
getPreviousRevisionID($revision)
Get the revision ID of the previous revision.
getPrefixedText()
Get the prefixed title with spaces.
getRestrictions($action)
Accessor/initialisation for mRestrictions.
loadRestrictionsFromRow($res, $oldFashionedRestrictions=null)
Loads a string into mRestrictions array.
isAlwaysKnown()
Should a link should be displayed as a known link, just based on its title?
static escapeFragmentForURL($fragment)
Escape a text fragment, say from a link, for a URL.
escapeLocalURL($query='')
Get an HTML-escaped version of the URL form, suitable for using in a link, without a server name or f...
static wfUrlencode(string $s)
if($err=$client->getError()) $namespace
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
form( $class_path, string $cmd)
get(string $key, Refinery\Transformation $t)
Get passed parameter, if not data passed, get key from http request.