295
296
* Extract a redirect destination from a string and return the
296
297
* Title, or null if the text doesn't contain a valid redirect
298
* This will only return the very next target, useful for
299
* the redirect table and other checks that don't need full recursion
298
* @param $text \type{String} Text with possible redirect
301
* @param $text \type{\string} Text with possible redirect
299
302
* @return \type{Title} The corresponding Title
301
304
public static function newFromRedirect( $text ) {
305
return self::newFromRedirectInternal( $text );
309
* Extract a redirect destination from a string and return the
310
* Title, or null if the text doesn't contain a valid redirect
311
* This will recurse down $wgMaxRedirects times or until a non-redirect target is hit
312
* in order to provide (hopefully) the Title of the final destination instead of another redirect
314
* @param $text \type{\string} Text with possible redirect
315
* @return \type{Title} The corresponding Title
317
public static function newFromRedirectRecurse( $text ) {
318
$titles = self::newFromRedirectArray( $text );
319
return $titles ? array_pop( $titles ) : null;
323
* Extract a redirect destination from a string and return an
324
* array of Titles, or null if the text doesn't contain a valid redirect
325
* The last element in the array is the final destination after all redirects
326
* have been resolved (up to $wgMaxRedirects times)
328
* @param $text \type{\string} Text with possible redirect
329
* @return \type{\array} Array of Titles, with the destination last
331
public static function newFromRedirectArray( $text ) {
332
global $wgMaxRedirects;
333
// are redirects disabled?
334
if( $wgMaxRedirects < 1 )
336
$title = self::newFromRedirectInternal( $text );
337
if( is_null( $title ) )
339
// recursive check to follow double redirects
340
$recurse = $wgMaxRedirects;
341
$titles = array( $title );
342
while( --$recurse > 0 ) {
343
if( $title->isRedirect() ) {
344
$article = new Article( $title, 0 );
345
$newtitle = $article->getRedirectTarget();
349
// Redirects to some special pages are not permitted
350
if( $newtitle instanceOf Title && $newtitle->isValidRedirectTarget() ) {
351
// the new title passes the checks, so make that our current title so that further recursion can be checked
353
$titles[] = $newtitle;
362
* Really extract the redirect destination
363
* Do not call this function directly, use one of the newFromRedirect* functions above
365
* @param $text \type{\string} Text with possible redirect
366
* @return \type{Title} The corresponding Title
368
protected static function newFromRedirectInternal( $text ) {
302
369
$redir = MagicWord::get( 'redirect' );
303
370
$text = trim($text);
304
371
if( $redir->matchStartAndRemove( $text ) ) {
316
383
$m[1] = urldecode( ltrim( $m[1], ':' ) );
318
385
$title = Title::newFromText( $m[1] );
319
// Redirects to some special pages are not permitted
320
if( $title instanceof Title
321
&& !$title->isSpecial( 'Userlogout' )
322
&& !$title->isSpecial( 'Filepath' ) )
386
// If the title is a redirect to bad special pages or is invalid, return null
387
if( !$title instanceof Title || !$title->isValidRedirectTarget() ) {
802
867
* @return \type{\string} the URL
804
869
public function getLinkUrl( $query = array(), $variant = false ) {
870
wfProfileIn( __METHOD__ );
805
871
if( !is_array( $query ) ) {
872
wfProfileOut( __METHOD__ );
806
873
throw new MWException( 'Title::getLinkUrl passed a non-array for '.
809
876
if( $this->isExternal() ) {
810
return $this->getFullURL( $query );
811
} elseif( $this->getPrefixedText() === ''
812
and $this->getFragment() !== '' ) {
813
return $this->getFragmentForURL();
877
$ret = $this->getFullURL( $query );
878
} elseif( $this->getPrefixedText() === '' && $this->getFragment() !== '' ) {
879
$ret = $this->getFragmentForURL();
815
return $this->getLocalURL( $query, $variant )
816
. $this->getFragmentForURL();
881
$ret = $this->getLocalURL( $query, $variant ) . $this->getFragmentForURL();
883
wfProfileOut( __METHOD__ );
1094
1161
* @param $action \type{\string} action that permission needs to be checked for
1095
1162
* @param $user \type{User} user to check
1096
1163
* @param $doExpensiveQueries \type{\bool} Set this to false to avoid doing unnecessary queries.
1164
* @param $short \type{\bool} Set this to true to stop after the first permission error.
1097
1165
* @return \type{\array} Array of arrays of the arguments to wfMsg to explain permissions problems.
1099
private function getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries = true ) {
1167
private function getUserPermissionsErrorsInternal( $action, $user, $doExpensiveQueries=true, $short=false ) {
1100
1168
wfProfileIn( __METHOD__ );
1102
1170
$errors = array();
1172
// First stop is permissions checks, which fail most often, and which are easiest to test.
1173
if ( $action == 'move' ) {
1174
if( !$user->isAllowed( 'move-rootuserpages' )
1175
&& $this->getNamespace() == NS_USER && !$this->isSubpage() )
1177
// Show user page-specific message only if the user can move other pages
1178
$errors[] = array( 'cant-move-user-page' );
1181
// Check if user is allowed to move files if it's a file
1182
if( $this->getNamespace() == NS_FILE && !$user->isAllowed( 'movefile' ) ) {
1183
$errors[] = array( 'movenotallowedfile' );
1186
if( !$user->isAllowed( 'move' ) ) {
1187
// User can't move anything
1188
$errors[] = $user->isAnon() ? array ( 'movenologintext' ) : array ('movenotallowed');
1190
} elseif ( $action == 'create' ) {
1191
if( ( $this->isTalkPage() && !$user->isAllowed( 'createtalk' ) ) ||
1192
( !$this->isTalkPage() && !$user->isAllowed( 'createpage' ) ) )
1194
$errors[] = $user->isAnon() ? array ('nocreatetext') : array ('nocreate-loggedin');
1196
} elseif( $action == 'move-target' ) {
1197
if( !$user->isAllowed( 'move' ) ) {
1198
// User can't move anything
1199
$errors[] = $user->isAnon() ? array ( 'movenologintext' ) : array ('movenotallowed');
1200
} elseif( !$user->isAllowed( 'move-rootuserpages' )
1201
&& $this->getNamespace() == NS_USER && !$this->isSubpage() )
1203
// Show user page-specific message only if the user can move other pages
1204
$errors[] = array( 'cant-move-to-user-page' );
1206
} elseif( !$user->isAllowed( $action ) ) {
1208
$groups = array_map( array( 'User', 'makeGroupLinkWiki' ),
1209
User::getGroupsWithPermission( $action ) );
1211
$return = array( 'badaccess-groups',
1212
array( implode( ', ', $groups ), count( $groups ) ) );
1214
$return = array( "badaccess-group0" );
1216
$errors[] = $return;
1219
# Short-circuit point
1220
if( $short && count($errors) > 0 ) {
1221
wfProfileOut( __METHOD__ );
1104
1225
// Use getUserPermissionsErrors instead
1105
1226
if( !wfRunHooks( 'userCan', array( &$this, &$user, $action, &$result ) ) ) {
1106
1227
wfProfileOut( __METHOD__ );
1107
1228
return $result ? array() : array( array( 'badaccess-group0' ) );
1230
// Check getUserPermissionsErrors hook
1110
1231
if( !wfRunHooks( 'getUserPermissionsErrors', array(&$this,&$user,$action,&$result) ) ) {
1111
1232
if( is_array($result) && count($result) && !is_array($result[0]) )
1112
1233
$errors[] = $result; # A single array representing an error
1117
1238
else if( $result === false )
1118
1239
$errors[] = array('badaccess-group0'); # a generic "We don't want them to do that"
1241
# Short-circuit point
1242
if( $short && count($errors) > 0 ) {
1243
wfProfileOut( __METHOD__ );
1246
// Check getUserPermissionsErrorsExpensive hook
1120
1247
if( $doExpensiveQueries && !wfRunHooks( 'getUserPermissionsErrorsExpensive', array(&$this,&$user,$action,&$result) ) ) {
1121
1248
if( is_array($result) && count($result) && !is_array($result[0]) )
1122
1249
$errors[] = $result; # A single array representing an error
1127
1254
else if( $result === false )
1128
1255
$errors[] = array('badaccess-group0'); # a generic "We don't want them to do that"
1257
# Short-circuit point
1258
if( $short && count($errors) > 0 ) {
1259
wfProfileOut( __METHOD__ );
1263
# Only 'createaccount' and 'execute' can be performed on
1264
# special pages, which don't actually exist in the DB.
1132
1265
$specialOKActions = array( 'createaccount', 'execute' );
1133
1266
if( NS_SPECIAL == $this->mNamespace && !in_array( $action, $specialOKActions) ) {
1134
1267
$errors[] = array('ns-specialprotected');
1270
# Check $wgNamespaceProtection for restricted namespaces
1137
1271
if( $this->isNamespaceProtected() ) {
1138
1272
$ns = $this->getNamespace() == NS_MAIN ?
1139
1273
wfMsg( 'nstab-main' ) : $this->getNsText();
1150
1284
$errors[] = array('customcssjsprotected');
1287
# Check against page_restrictions table requirements on this
1288
# page. The user must possess all required rights for this action.
1289
foreach( $this->getRestrictions($action) as $right ) {
1290
// Backwards compatibility, rewrite sysop -> protect
1291
if( $right == 'sysop' ) {
1294
if( '' != $right && !$user->isAllowed( $right ) ) {
1295
// Users with 'editprotected' permission can edit protected pages
1296
if( $action=='edit' && $user->isAllowed( 'editprotected' ) ) {
1297
// Users with 'editprotected' permission cannot edit protected pages
1298
// with cascading option turned on.
1299
if( $this->mCascadeRestriction ) {
1300
$errors[] = array( 'protectedpagetext', $right );
1303
$errors[] = array( 'protectedpagetext', $right );
1307
# Short-circuit point
1308
if( $short && count($errors) > 0 ) {
1309
wfProfileOut( __METHOD__ );
1153
1313
if( $doExpensiveQueries && !$this->isCssJsSubpage() ) {
1154
1314
# We /could/ use the protection level on the source page, but it's fairly ugly
1155
1315
# as we have to establish a precedence hierarchy for pages included by multiple
1176
foreach( $this->getRestrictions($action) as $right ) {
1177
// Backwards compatibility, rewrite sysop -> protect
1178
if( $right == 'sysop' ) {
1181
if( '' != $right && !$user->isAllowed( $right ) ) {
1182
// Users with 'editprotected' permission can edit protected pages
1183
if( $action=='edit' && $user->isAllowed( 'editprotected' ) ) {
1184
// Users with 'editprotected' permission cannot edit protected pages
1185
// with cascading option turned on.
1186
if( $this->mCascadeRestriction ) {
1187
$errors[] = array( 'protectedpagetext', $right );
1189
// Nothing, user can edit!
1192
$errors[] = array( 'protectedpagetext', $right );
1335
# Short-circuit point
1336
if( $short && count($errors) > 0 ) {
1337
wfProfileOut( __METHOD__ );
1197
1341
if( $action == 'protect' ) {
1212
1356
$errors[] = array( 'titleprotected', User::whoIs($pt_user), $pt_reason );
1216
if( ( $this->isTalkPage() && !$user->isAllowed( 'createtalk' ) ) ||
1217
( !$this->isTalkPage() && !$user->isAllowed( 'createpage' ) ) )
1219
$errors[] = $user->isAnon() ? array ('nocreatetext') : array ('nocreate-loggedin');
1221
1359
} elseif( $action == 'move' ) {
1222
if( !$user->isAllowed( 'move' ) ) {
1223
// User can't move anything
1224
$errors[] = $user->isAnon() ? array ( 'movenologintext' ) : array ('movenotallowed');
1225
} elseif( !$user->isAllowed( 'move-rootuserpages' )
1226
&& $this->getNamespace() == NS_USER && !$this->isSubpage() )
1228
// Show user page-specific message only if the user can move other pages
1229
$errors[] = array( 'cant-move-user-page' );
1231
// Check if user is allowed to move files if it's a file
1232
if( $this->getNamespace() == NS_FILE && !$user->isAllowed( 'movefile' ) ) {
1233
$errors[] = array( 'movenotallowedfile' );
1235
1360
// Check for immobile pages
1236
1361
if( !MWNamespace::isMovable( $this->getNamespace() ) ) {
1237
1362
// Specific message for this case
1241
1366
$errors[] = array( 'immobile-page' );
1243
1368
} elseif( $action == 'move-target' ) {
1244
if( !$user->isAllowed( 'move' ) ) {
1245
// User can't move anything
1246
$errors[] = $user->isAnon() ? array ( 'movenologintext' ) : array ('movenotallowed');
1247
} elseif( !$user->isAllowed( 'move-rootuserpages' )
1248
&& $this->getNamespace() == NS_USER && !$this->isSubpage() )
1250
// Show user page-specific message only if the user can move other pages
1251
$errors[] = array( 'cant-move-to-user-page' );
1253
1369
if( !MWNamespace::isMovable( $this->getNamespace() ) ) {
1254
1370
$errors[] = array( 'immobile-target-namespace', $this->getNsText() );
1255
1371
} elseif( !$this->isMovable() ) {
1256
1372
$errors[] = array( 'immobile-target-page' );
1258
} elseif( !$user->isAllowed( $action ) ) {
1260
$groups = array_map( array( 'User', 'makeGroupLinkWiki' ),
1261
User::getGroupsWithPermission( $action ) );
1263
$return = array( 'badaccess-groups',
1264
array( implode( ', ', $groups ), count( $groups ) ) );
1266
$return = array( "badaccess-group0" );
1268
$errors[] = $return;
1271
1376
wfProfileOut( __METHOD__ );
1510
1615
return $this->mHasSubpages;
1513
$db = wfGetDB( DB_SLAVE );
1514
return $this->mHasSubpages = (bool)$db->selectField( 'page', '1',
1515
"page_namespace = {$this->mNamespace} AND page_title LIKE '"
1516
. $db->escapeLike( $this->mDbkeyform ) . "/%'",
1618
$subpages = $this->getSubpages( 1 );
1619
if( $subpages instanceof TitleArray )
1620
return $this->mHasSubpages = (bool)$subpages->count();
1621
return $this->mHasSubpages = false;
1625
* Get all subpages of this page.
1626
* @param $limit Maximum number of subpages to fetch; -1 for no limit
1627
* @return mixed TitleArray, or empty array if this page's namespace
1628
* doesn't allow subpages
1630
public function getSubpages( $limit = -1 ) {
1631
if( !MWNamespace::hasSubpages( $this->getNamespace() ) )
1634
$dbr = wfGetDB( DB_SLAVE );
1635
$conds['page_namespace'] = $this->getNamespace();
1636
$conds[] = 'page_title LIKE ' . $dbr->addQuotes(
1637
$dbr->escapeLike( $this->getDBkey() ) . '/%' );
1640
$options['LIMIT'] = $limit;
1641
return $this->mSubpages = TitleArray::newFromResult(
1642
$dbr->select( 'page',
1643
array( 'page_id', 'page_namespace', 'page_title', 'page_is_redirect' ),
1849
1979
* @return \type{\int} the number of archived revisions
1851
1981
public function isDeleted() {
1852
$fname = 'Title::isDeleted';
1853
if ( $this->getNamespace() < 0 ) {
1982
if( $this->getNamespace() < 0 ) {
1856
1985
$dbr = wfGetDB( DB_SLAVE );
1857
$n = $dbr->selectField( 'archive', 'COUNT(*)', array( 'ar_namespace' => $this->getNamespace(),
1858
'ar_title' => $this->getDBkey() ), $fname );
1986
$n = $dbr->selectField( 'archive', 'COUNT(*)',
1987
array( 'ar_namespace' => $this->getNamespace(), 'ar_title' => $this->getDBkey() ),
1859
1990
if( $this->getNamespace() == NS_FILE ) {
1860
1991
$n += $dbr->selectField( 'filearchive', 'COUNT(*)',
1861
array( 'fa_name' => $this->getDBkey() ), $fname );
1992
array( 'fa_name' => $this->getDBkey() ),
1864
1997
return (int)$n;
2001
* Is there a version of this page in the deletion archive?
2004
public function isDeletedQuick() {
2005
if( $this->getNamespace() < 0 ) {
2008
$dbr = wfGetDB( DB_SLAVE );
2009
$deleted = (bool)$dbr->selectField( 'archive', '1',
2010
array( 'ar_namespace' => $this->getNamespace(), 'ar_title' => $this->getDBkey() ),
2013
if( !$deleted && $this->getNamespace() == NS_FILE ) {
2014
$deleted = (bool)$dbr->selectField( 'filearchive', '1',
2015
array( 'fa_name' => $this->getDBkey() ),
1868
2023
* Get the article ID for this Title from the link cache,
2065
2220
# Namespace or interwiki prefix
2066
2221
$firstPass = true;
2222
$prefixRegexp = "/^(.+?)_*:_*(.*)$/S";
2069
if ( preg_match( "/^(.+?)_*:_*(.*)$/S", $dbkey, $m ) ) {
2225
if ( preg_match( $prefixRegexp, $dbkey, $m ) ) {
2071
if ( $ns = $wgContLang->getNsIndex( $p )) {
2227
if ( $ns = $wgContLang->getNsIndex( $p ) ) {
2072
2228
# Ordinary namespace
2073
2229
$dbkey = $m[2];
2074
2230
$this->mNamespace = $ns;
2231
# For Talk:X pages, check if X has a "namespace" prefix
2232
if( $ns == NS_TALK && preg_match( $prefixRegexp, $dbkey, $x ) ) {
2233
if( $wgContLang->getNsIndex( $x[1] ) )
2234
return false; # Disallow Talk:File:x type titles...
2235
else if( Interwiki::isValidInterwiki( $x[1] ) )
2236
return false; # Disallow Talk:Interwiki:x type titles...
2075
2238
} elseif( Interwiki::isValidInterwiki( $p ) ) {
2076
2239
if( !$firstPass ) {
2077
2240
# Can't make a local interwiki link to an interwiki link.
2254
2417
* WARNING: do not use this function on arbitrary user-supplied titles!
2255
2418
* On heavily-used templates it will max out the memory.
2257
* @param $options \type{\string} may be FOR UPDATE
2420
* @param array $options may be FOR UPDATE
2258
2421
* @return \type{\arrayof{Title}} the Title objects linking here
2260
public function getLinksTo( $options = '', $table = 'pagelinks', $prefix = 'pl' ) {
2423
public function getLinksTo( $options = array(), $table = 'pagelinks', $prefix = 'pl' ) {
2261
2424
$linkCache = LinkCache::singleton();
2426
if ( count( $options ) > 0 ) {
2264
2427
$db = wfGetDB( DB_MASTER );
2266
2429
$db = wfGetDB( DB_SLAVE );
2295
2458
* WARNING: do not use this function on arbitrary user-supplied titles!
2296
2459
* On heavily-used templates it will max out the memory.
2298
* @param $options \type{\string} may be FOR UPDATE
2461
* @param array $options may be FOR UPDATE
2299
2462
* @return \type{\arrayof{Title}} the Title objects linking here
2301
public function getTemplateLinksTo( $options = '' ) {
2464
public function getTemplateLinksTo( $options = array() ) {
2302
2465
return $this->getLinksTo( $options, 'templatelinks', 'tl' );
2306
2469
* Get an array of Title objects referring to non-existent articles linked from this page
2308
2471
* @todo check if needed (used only in SpecialBrokenRedirects.php, and should use redirect table in this case)
2309
* @param $options \type{\string} may be FOR UPDATE
2310
2472
* @return \type{\arrayof{Title}} the Title objects
2312
public function getBrokenLinksFrom( $options = '' ) {
2474
public function getBrokenLinksFrom() {
2313
2475
if ( $this->getArticleId() == 0 ) {
2314
2476
# All links from article ID 0 are false positives
2315
2477
return array();
2319
$db = wfGetDB( DB_MASTER );
2321
$db = wfGetDB( DB_SLAVE );
2324
$res = $db->safeQuery(
2325
"SELECT pl_namespace, pl_title
2328
ON pl_namespace=page_namespace
2329
AND pl_title=page_title
2331
AND page_namespace IS NULL
2333
$db->tableName( 'pagelinks' ),
2334
$db->tableName( 'page' ),
2335
$this->getArticleId(),
2480
$dbr = wfGetDB( DB_SLAVE );
2481
$res = $dbr->select(
2482
array( 'page', 'pagelinks' ),
2483
array( 'pl_namespace', 'pl_title' ),
2485
'pl_from' => $this->getArticleId(),
2486
'page_namespace IS NULL'
2488
__METHOD__, array(),
2492
array( 'pl_namespace=page_namespace', 'pl_title=page_title' )
2338
2497
$retVal = array();
2339
if ( $db->numRows( $res ) ) {
2340
foreach( $res as $row ) {
2341
$retVal[] = Title::makeTitle( $row->pl_namespace, $row->pl_title );
2498
foreach( $res as $row ) {
2499
$retVal[] = Title::makeTitle( $row->pl_namespace, $row->pl_title );
2344
$db->freeResult( $res );
2345
2501
return $retVal;
2560
2716
# Update the protection log
2561
2717
$log = new LogPage( 'protect' );
2562
$comment = wfMsgForContent('prot_1movedto2',$this->getPrefixedText(), $nt->getPrefixedText() );
2563
if( $reason ) $comment .= ': ' . $reason;
2718
$comment = wfMsgForContent( 'prot_1movedto2', $this->getPrefixedText(), $nt->getPrefixedText() );
2719
if( $reason ) $comment .= wfMsgForContent( 'colon-separator' ) . $reason;
2564
2720
$log->addEntry( 'move_prot', $nt, $comment, array($this->getPrefixedText()) ); // FIXME: $params?
2601
2757
# Update message cache for interface messages
2602
2758
if( $nt->getNamespace() == NS_MEDIAWIKI ) {
2603
2759
global $wgMessageCache;
2604
$oldarticle = new Article( $this );
2605
$wgMessageCache->replace( $this->getDBkey(), $oldarticle->getContent() );
2761
# @bug 17860: old article can be deleted, if this the case,
2762
# delete it from message cache
2763
if ( $this->getArticleID === 0 ) {
2764
$wgMessageCache->replace( $this->getDBkey(), false );
2766
$oldarticle = new Article( $this );
2767
$wgMessageCache->replace( $this->getDBkey(), $oldarticle->getContent() );
2606
2770
$newarticle = new Article( $nt );
2607
2771
$wgMessageCache->replace( $nt->getDBkey(), $newarticle->getContent() );
2997
* Move this page's subpages to be subpages of $nt
2998
* @param $nt Title Move target
2999
* @param $auth bool Whether $wgUser's permissions should be checked
3000
* @param $reason string The reason for the move
3001
* @param $createRedirect bool Whether to create redirects from the old subpages to the new ones
3002
* Ignored if the user doesn't have the 'suppressredirect' right
3003
* @return mixed array with old page titles as keys, and strings (new page titles) or
3004
* arrays (errors) as values, or an error array with numeric indices if no pages were moved
3006
public function moveSubpages( $nt, $auth = true, $reason = '', $createRedirect = true ) {
3007
global $wgUser, $wgMaximumMovedPages;
3008
// Check permissions
3009
if( !$this->userCan( 'move-subpages' ) )
3010
return array( 'cant-move-subpages' );
3011
// Do the source and target namespaces support subpages?
3012
if( !MWNamespace::hasSubpages( $this->getNamespace() ) )
3013
return array( 'namespace-nosubpages',
3014
MWNamespace::getCanonicalName( $this->getNamespace() ) );
3015
if( !MWNamespace::hasSubpages( $nt->getNamespace() ) )
3016
return array( 'namespace-nosubpages',
3017
MWNamespace::getCanonicalName( $nt->getNamespace() ) );
3019
$subpages = $this->getSubpages($wgMaximumMovedPages + 1);
3022
foreach( $subpages as $oldSubpage ) {
3024
if( $count > $wgMaximumMovedPages ) {
3025
$retval[$oldSubpage->getPrefixedTitle()] =
3026
array( 'movepage-max-pages',
3027
$wgMaximumMovedPages );
3031
if( $oldSubpage->getArticleId() == $this->getArticleId() )
3032
// When moving a page to a subpage of itself,
3033
// don't move it twice
3035
$newPageName = preg_replace(
3036
'#^'.preg_quote( $this->getDBKey(), '#' ).'#',
3037
$nt->getDBKey(), $oldSubpage->getDBKey() );
3038
if( $oldSubpage->isTalkPage() ) {
3039
$newNs = $nt->getTalkPage()->getNamespace();
3041
$newNs = $nt->getSubjectPage()->getNamespace();
3043
# Bug 14385: we need makeTitleSafe because the new page names may
3044
# be longer than 255 characters.
3045
$newSubpage = Title::makeTitleSafe( $newNs, $newPageName );
3047
$success = $oldSubpage->moveTo( $newSubpage, $auth, $reason, $createRedirect );
3048
if( $success === true ) {
3049
$retval[$oldSubpage->getPrefixedText()] = $newSubpage->getPrefixedText();
3051
$retval[$oldSubpage->getPrefixedText()] = $success;
2833
3058
* Checks if this page is just a one-rev redirect.
2834
3059
* Adds lock, so don't use just for light purposes.
3262
* Get the first revision of the page
3264
* @param $flags \type{\int} GAID_FOR_UPDATE
3265
* @return Revision (or NULL if page doesn't exist)
3267
public function getFirstRevision( $flags=0 ) {
3268
$db = ($flags & GAID_FOR_UPDATE) ? wfGetDB( DB_MASTER ) : wfGetDB( DB_SLAVE );
3269
$pageId = $this->getArticleId($flags);
3270
if( !$pageId ) return NULL;
3271
$row = $db->selectRow( 'revision', '*',
3272
array( 'rev_page' => $pageId ),
3274
array( 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 1 )
3279
return new Revision( $row );
3037
3284
* Check if this is a new page
3397
3644
return $redirs;
3648
* Check if this Title is a valid redirect target
3650
* @return \type{\bool} TRUE or FALSE
3652
public function isValidRedirectTarget() {
3653
global $wgInvalidRedirectTargets;
3655
// invalid redirect targets are stored in a global array, but explicity disallow Userlogout here
3656
if( $this->isSpecial( 'Userlogout' ) ) {
3660
foreach( $wgInvalidRedirectTargets as $target ) {
3661
if( $this->isSpecial( $target ) ) {
3670
* Get a backlink cache object
3672
function getBacklinkCache() {
3673
if ( is_null( $this->mBacklinkCache ) ) {
3674
$this->mBacklinkCache = new BacklinkCache( $this );
3676
return $this->mBacklinkCache;