}
/**
- * Create a new Title from text, such as what one would
- * find in a link. Decodes any HTML entities in the text.
+ * Create a new Title from text, such as what one would find in a link. De-
+ * codes any HTML entities in the text.
*
- * @param $text \type{\string} the link text; spaces, prefixes,
- * and an initial ':' indicating the main namespace
- * are accepted
- * @param $defaultNamespace \type{\int} the namespace to use if
- * none is specified by a prefix
- * @return \type{Title} the new object, or NULL on an error
+ * @param $text string The link text; spaces, prefixes, and an
+ * initial ':' indicating the main namespace are accepted.
+ * @param $defaultNamespace int The namespace to use if none is speci-
+ * fied by a prefix. If you want to force a specific namespace even if
+ * $text might begin with a namespace prefix, use makeTitle() or
+ * makeTitleSafe().
+ * @return Title The new object, or null on an error.
*/
public static function newFromText( $text, $defaultNamespace = NS_MAIN ) {
if( is_object( $text ) ) {
* @return \type{\string} the associated URL, containing "$1",
* which should be replaced by an article title
* @static (arguably)
+ * @deprecated See Interwiki class
*/
public function getInterwikiLink( $key ) {
- global $wgMemc, $wgInterwikiExpiry;
- global $wgInterwikiCache, $wgContLang;
- $fname = 'Title::getInterwikiLink';
-
- if ( count( Title::$interwikiCache ) >= self::CACHE_MAX ) {
- // Don't use infinite memory
- reset( Title::$interwikiCache );
- unset( Title::$interwikiCache[ key( Title::$interwikiCache ) ] );
- }
-
- $key = $wgContLang->lc( $key );
-
- $k = wfMemcKey( 'interwiki', $key );
- if( array_key_exists( $k, Title::$interwikiCache ) ) {
- return Title::$interwikiCache[$k]->iw_url;
- }
-
- if ($wgInterwikiCache) {
- return Title::getInterwikiCached( $key );
- }
-
- $s = $wgMemc->get( $k );
- # Ignore old keys with no iw_local
- if( $s && isset( $s->iw_local ) && isset($s->iw_trans)) {
- Title::$interwikiCache[$k] = $s;
- return $s->iw_url;
- }
-
- $dbr = wfGetDB( DB_SLAVE );
- $res = $dbr->select( 'interwiki',
- array( 'iw_url', 'iw_local', 'iw_trans' ),
- array( 'iw_prefix' => $key ), $fname );
- if( !$res ) {
- return '';
- }
-
- $s = $dbr->fetchObject( $res );
- if( !$s ) {
- # Cache non-existence: create a blank object and save it to memcached
- $s = (object)false;
- $s->iw_url = '';
- $s->iw_local = 0;
- $s->iw_trans = 0;
- }
- $wgMemc->set( $k, $s, $wgInterwikiExpiry );
- Title::$interwikiCache[$k] = $s;
-
- return $s->iw_url;
- }
-
- /**
- * Fetch interwiki prefix data from local cache in constant database.
- *
- * @note More logic is explained in DefaultSettings.
- *
- * @param $key \type{\string} Database key
- * @return \type{\string} URL of interwiki site
- */
- public static function getInterwikiCached( $key ) {
- global $wgInterwikiCache, $wgInterwikiScopes, $wgInterwikiFallbackSite;
- static $db, $site;
-
- if (!$db)
- $db=dba_open($wgInterwikiCache,'r','cdb');
- /* Resolve site name */
- if ($wgInterwikiScopes>=3 and !$site) {
- $site = dba_fetch('__sites:' . wfWikiID(), $db);
- if ($site=="")
- $site = $wgInterwikiFallbackSite;
- }
- $value = dba_fetch( wfMemcKey( $key ), $db);
- if ($value=='' and $wgInterwikiScopes>=3) {
- /* try site-level */
- $value = dba_fetch("_{$site}:{$key}", $db);
- }
- if ($value=='' and $wgInterwikiScopes>=2) {
- /* try globals */
- $value = dba_fetch("__global:{$key}", $db);
- }
- if ($value=='undef')
- $value='';
- $s = (object)false;
- $s->iw_url = '';
- $s->iw_local = 0;
- $s->iw_trans = 0;
- if ($value!='') {
- list($local,$url)=explode(' ',$value,2);
- $s->iw_url=$url;
- $s->iw_local=(int)$local;
- }
- Title::$interwikiCache[wfMemcKey( 'interwiki', $key )] = $s;
- return $s->iw_url;
+ return Interwiki::fetch( $key )->getURL( );
}
/**
*/
public function isLocal() {
if ( $this->mInterwiki != '' ) {
- # Make sure key is loaded into cache
- $this->getInterwikiLink( $this->mInterwiki );
- $k = wfMemcKey( 'interwiki', $this->mInterwiki );
- return (bool)(Title::$interwikiCache[$k]->iw_local);
+ return Interwiki::fetch( $this->mInterwiki )->isLocal();
} else {
return true;
}
public function isTrans() {
if ($this->mInterwiki == '')
return false;
- # Make sure key is loaded into cache
- $this->getInterwikiLink( $this->mInterwiki );
- $k = wfMemcKey( 'interwiki', $this->mInterwiki );
- return (bool)(Title::$interwikiCache[$k]->iw_trans);
+
+ return Interwiki::fetch( $this->mInterwiki )->isTranscludable();
}
/**
$query = wfArrayToCGI( $query );
}
- if ( '' == $this->mInterwiki ) {
+ $interwiki = Interwiki::fetch( $this->mInterwiki );
+ if ( !$interwiki ) {
$url = $this->getLocalUrl( $query, $variant );
// Ugly quick hack to avoid duplicate prefixes (bug 4571 etc)
$url = $wgServer . $url;
}
} else {
- $baseUrl = $this->getInterwikiLink( $this->mInterwiki );
+ $baseUrl = $interwiki->getURL( );
$namespace = wfUrlencode( $this->getNsText() );
if ( '' != $namespace ) {
$errors[] = array( 'confirmedittext' );
}
- if ( $user->isBlockedFrom( $this ) && $action != 'createaccount' ) {
+ // Edit blocks should not affect reading. Account creation blocks handled at userlogin.
+ if ( $user->isBlockedFrom( $this ) && $action != 'read' && $action != 'createaccount' ) {
$block = $user->mBlock;
// This is from OutputPage::blockedPage
( !$this->isTalkPage() && !$user->isAllowed( 'createpage' ) ) ) {
$errors[] = $user->isAnon() ? array ('nocreatetext') : array ('nocreate-loggedin');
}
- } elseif( $action == 'move' && !( $this->isMovable() && $user->isAllowed( 'move' ) ) ) {
- $errors[] = $user->isAnon() ? array ( 'movenologintext' ) : array ('movenotallowed');
+
+ } elseif ( $action == 'move' ) {
+ if ( !$user->isAllowed( 'move' ) ) {
+ // User can't move anything
+ $errors[] = $user->isAnon() ? array ( 'movenologintext' ) : array ('movenotallowed');
+ } elseif ( !$user->isAllowed( 'move-rootuserpages' )
+ && $this->getNamespace() == NS_USER && !$this->isSubpage() )
+ {
+ // Show user page-specific message only if the user can move other pages
+ $errors[] = array( 'cant-move-user-page' );
+ }
+
+ // Check for immobile pages
+ if ( !MWNamespace::isMovable( $this->getNamespace() ) ) {
+ // Specific message for this case
+ $errors[] = array( 'immobile-source-namespace', $this->getNsText() );
+ } elseif ( !$this->isMovable() ) {
+ // Less specific message for rarer cases
+ $errors[] = array( 'immobile-page' );
+ }
+
+ } elseif ( $action == 'move-target' ) {
+ if ( !$user->isAllowed( 'move' ) ) {
+ // User can't move anything
+ $errors[] = $user->isAnon() ? array ( 'movenologintext' ) : array ('movenotallowed');
+ } elseif ( !$user->isAllowed( 'move-rootuserpages' )
+ && $this->getNamespace() == NS_USER && !$this->isSubpage() )
+ {
+ // Show user page-specific message only if the user can move other pages
+ $errors[] = array( 'cant-move-to-user-page' );
+ }
+ if ( !MWNamespace::isMovable( $this->getNamespace() ) ) {
+ $errors[] = array( 'immobile-target-namespace', $this->getNsText() );
+ } elseif ( !$this->isMovable() ) {
+ $errors[] = array( 'immobile-target-page' );
+ }
+
} elseif ( !$user->isAllowed( $action ) ) {
$return = null;
$groups = array_map( array( 'User', 'makeGroupLinkWiki' ),
$log = new LogPage( 'protect' );
if( $create_perm ) {
- $log->addEntry( $this->mRestrictions['create'] ? 'modify' : 'protect', $this, trim( $reason . " [create=$create_perm] $expiry_description" ) );
+ $params = array("[create=$create_perm] $expiry_description",'');
+ $log->addEntry( $this->mRestrictions['create'] ? 'modify' : 'protect', $this, trim( $reason ), $params );
} else {
$log->addEntry( 'unprotect', $this, $reason );
}
: array();
}
+ /**
+ * Get the expiry time for the restriction against a given action
+ * @return 14-char timestamp, or 'infinity' if the page is protected forever
+ * or not protected at all, or false if the action is not recognised.
+ */
+ public function getRestrictionExpiry( $action ) {
+ if( !$this->mRestrictionsLoaded ) {
+ $this->loadRestrictions();
+ }
+ return isset( $this->mRestrictionsExpiry[$action] ) ? $this->mRestrictionsExpiry[$action] : false;
+ }
+
/**
* Is there a version of this page in the deletion archive?
* @return \type{\int} the number of archived revisions
# Ordinary namespace
$dbkey = $m[2];
$this->mNamespace = $ns;
- } elseif( $this->getInterwikiLink( $p ) ) {
+ } elseif( Interwiki::isValidInterwiki( $p ) ) {
if( !$firstPass ) {
# Can't make a local interwiki link to an interwiki link.
# That's just crazy!
* @return \type{\mixed} True on success, getUserPermissionsErrors()-like array on failure
*/
public function isValidMoveOperation( &$nt, $auth = true, $reason = '' ) {
+ global $wgUser;
+
$errors = array();
if( !$nt ) {
// Normally we'd add this to $errors, but we'll get
if( $this->equals( $nt ) ) {
$errors[] = array('selfmove');
}
- if( !$this->isMovable() || !$nt->isMovable() ) {
- $errors[] = array('immobile_namespace');
+ if( !$this->isMovable() ) {
+ $errors[] = array( 'immobile-source-namespace', $this->getNsText() );
+ }
+ if ( !$nt->isMovable() ) {
+ $errors[] = array('immobile-target-namespace', $nt->getNsText() );
}
$oldid = $this->getArticleID();
}
if ( $auth ) {
- global $wgUser;
$errors = wfArrayMerge($errors,
$this->getUserPermissionsErrors('move', $wgUser),
$this->getUserPermissionsErrors('edit', $wgUser),
- $nt->getUserPermissionsErrors('move', $wgUser),
+ $nt->getUserPermissionsErrors('move-target', $wgUser),
$nt->getUserPermissionsErrors('edit', $wgUser));
}
$errors[] = array('spamprotectiontext');
}
- global $wgUser;
$err = null;
if( !wfRunHooks( 'AbortMove', array( $this, $nt, $wgUser, &$err, $reason ) ) ) {
$errors[] = array('hookaborted', $err);
}
$pageid = $this->getArticleID();
+ $protected = $this->isProtected();
if( $nt->exists() ) {
$err = $this->moveOverExistingRedirect( $nt, $reason, $createRedirect );
$pageCountChange = ($createRedirect ? 0 : -1);
'cl_sortkey' => $this->getPrefixedText() ),
__METHOD__ );
- # Update watchlists
+ if( $protected ) {
+ # Protect the redirect title as the title used to be...
+ $dbw->insertSelect( 'page_restrictions', 'page_restrictions',
+ array(
+ 'pr_page' => $redirid,
+ 'pr_type' => 'pr_type',
+ 'pr_level' => 'pr_level',
+ 'pr_cascade' => 'pr_cascade',
+ 'pr_user' => 'pr_user',
+ 'pr_expiry' => 'pr_expiry'
+ ),
+ array( 'pr_page' => $pageid ),
+ __METHOD__,
+ array( 'IGNORE' )
+ );
+ # Update the protection log
+ $log = new LogPage( 'protect' );
+ $comment = wfMsgForContent('prot_1movedto2',$this->getPrefixedText(), $nt->getPrefixedText() );
+ if( $reason ) $comment .= ': ' . $reason;
+ $log->addEntry( 'move_prot', $nt, $comment, array($this->getPrefixedText()) ); // FIXME: $params?
+ }
+ # Update watchlists
$oldnamespace = $this->getNamespace() & ~1;
$newnamespace = $nt->getNamespace() & ~1;
$oldtitle = $this->getDBkey();
$latest = $this->getLatestRevID();
$dbw = wfGetDB( DB_MASTER );
- $dbw->begin();
# Delete the old redirect. We don't save it to history since
# by definition if we've got here it's rather uninteresting.
}
}
}
- $dbw->commit();
# Log the move
$log = new LogPage( 'move' );
$latest = $this->getLatestRevId();
$dbw = wfGetDB( DB_MASTER );
- $dbw->begin();
$now = $dbw->timestamp();
# Save a null revision in the page's history notifying of the move
}
}
}
- $dbw->commit();
# Log the move
$log = new LogPage( 'move' );