var $mPrefixedText; # Text form including namespace/interwiki, initialised on demand
var $mDefaultNamespace; # Namespace index when there is no namespace
# Zero except in {{transclusion}} tags
+ var $mWatched; # Is $wgUser watching this page? NULL if unfilled, accessed through userIsWatching()
/**#@-*/
# Dont change the following, NS_MAIN is hardcoded in several place
# See bug #696
$this->mDefaultNamespace = NS_MAIN;
+ $this->mWatched = NULL;
}
/**
}
/**
- * Convert things like é into real text...
+ * Convert things like é ā or 〗 into real text...
*/
- global $wgInputEncoding;
- $filteredText = do_html_entity_decode( $text, ENT_COMPAT, $wgInputEncoding );
-
- /**
- * Convert things like ā or 〗 into real text...
- * WARNING: Not friendly to internal links on a latin-1 wiki.
- */
- $filteredText = wfMungeToUtf8( $filteredText );
-
- # What was this for? TS 2004-03-03
- # $text = urldecode( $text );
+ $filteredText = Sanitizer::decodeCharReferences( $text );
$t =& new Title();
$t->mDbkeyform = str_replace( ' ', '_', $filteredText );
* @access public
*/
function getFullURL( $query = '' ) {
- global $wgContLang, $wgServer, $wgScript;
+ global $wgContLang, $wgServer, $wgScript, $wgMakeDumpLinks, $wgArticlePath;
if ( '' == $this->mInterwiki ) {
return $wgServer . $this->getLocalUrl( $query );
- } else {
+ } elseif ( $wgMakeDumpLinks && $wgContLang->getLanguageName( $this->mInterwiki ) ) {
+ $baseUrl = str_replace( '$1', "../../{$this->mInterwiki}/$1", $wgArticlePath );
+ $baseUrl = str_replace( '$1', $this->getHashedDirectory() . '/$1', $baseUrl );
+ } else {
$baseUrl = $this->getInterwikiLink( $this->mInterwiki );
- $namespace = $wgContLang->getNsText( $this->mNamespace );
- if ( '' != $namespace ) {
- # Can this actually happen? Interwikis shouldn't be parsed.
- $namepace .= ':';
- }
- $url = str_replace( '$1', $namespace . $this->mUrlform, $baseUrl );
- if( $query != '' ) {
- if( false === strpos( $url, '?' ) ) {
- $url .= '?';
- } else {
- $url .= '&';
- }
- $url .= $query;
- }
- if ( '' != $this->mFragment ) {
- $url .= '#' . $this->mFragment;
+ }
+
+ $namespace = $wgContLang->getNsText( $this->mNamespace );
+ if ( '' != $namespace ) {
+ # Can this actually happen? Interwikis shouldn't be parsed.
+ $namepace .= ':';
+ }
+ $url = str_replace( '$1', $namespace . $this->mUrlform, $baseUrl );
+ if( $query != '' ) {
+ if( false === strpos( $url, '?' ) ) {
+ $url .= '?';
+ } else {
+ $url .= '&';
}
- return $url;
+ $url .= $query;
}
+ if ( '' != $this->mFragment ) {
+ $url .= '#' . $this->mFragment;
+ }
+ return $url;
}
/**
* Get a relative directory for putting an HTML version of this article into
*/
function getHashedDirectory() {
- $dbkey = $this->getPrefixedDBkey();
- if ( strlen( $dbkey ) < 2 ) {
- $dbkey = sprintf( "%2s", $dbkey );
+ global $wgMakeDumpLinks, $wgInputEncoding;
+ $dbkey = $this->getDBkey();
+
+ # Split into characters
+ if ( $wgInputEncoding == 'UTF-8' ) {
+ preg_match_all( '/./us', $dbkey, $m );
+ } else {
+ preg_match_all( '/./s', $dbkey, $m );
}
+ $chars = $m[0];
+ $length = count( $chars );
$dir = '';
- for ( $i=0; $i<=1; $i++ ) {
+
+ for ( $i = 0; $i < $wgMakeDumpLinks; $i++ ) {
if ( $i ) {
$dir .= '/';
}
- if ( ord( $dbkey{$i} ) < 128 && ord( $dbkey{$i} ) > 32 ) {
- $dir .= strtolower( $dbkey{$i} );
+ if ( $i >= $length ) {
+ $dir .= '_';
+ } elseif ( ord( $chars[$i] ) > 32 ) {
+ $dir .= strtolower( $chars[$i] );
} else {
- $dir .= sprintf( "%02X", ord( $dbkey{$i} ) );
+ $dir .= sprintf( "%02X", ord( $chars[$i] ) );
}
}
return $dir;
function getHashedFilename() {
$dbkey = $this->getPrefixedDBkey();
+ $mainPage = Title::newMainPage();
+ if ( $mainPage->getPrefixedDBkey() == $dbkey ) {
+ return 'index.html';
+ }
+
$dir = $this->getHashedDirectory();
- $friendlyName = strtr( $dbkey, '/\\:*?"<>|', '_________' );
+
+ # Replace illegal charcters for Windows paths with underscores
+ $friendlyName = strtr( $dbkey, '/\\*?"<>|~', '_________' );
+
+ # Work out lower case form. We assume we're on a system with case-insensitive
+ # filenames, so unless the case is of a special form, we have to disambiguate
+ $lowerCase = $this->prefix( ucfirst( strtolower( $this->getDBkey() ) ) );
+
+ # Make it mostly unique
+ if ( $lowerCase != $friendlyName ) {
+ $friendlyName .= '_' . substr(md5( $dbkey ), 0, 4);
+ }
+ # Handle colon specially by replacing it with tilde
+ # Thus we reduce the number of paths with hashes appended
+ $friendlyName = str_replace( ':', '~', $friendlyName );
return "$dir/$friendlyName.html";
}
function userIsWatching() {
global $wgUser;
- if ( -1 == $this->mNamespace ) { return false; }
- if ( 0 == $wgUser->getID() ) { return false; }
-
- return $wgUser->isWatched( $this );
+ if ( is_null( $this->mWatched ) ) {
+ if ( -1 == $this->mNamespace || 0 == $wgUser->getID()) {
+ $this->mWatched = false;
+ } else {
+ $this->mWatched = $wgUser->isWatched( $this );
+ }
+ }
+ return $this->mWatched;
}
/**
}
foreach( $this->getRestrictions($action) as $right ) {
+ // Backwards compatibility, rewrite sysop -> protect
+ if ( $right == 'sysop' ) {
+ $right = 'protect';
+ }
if( '' != $right && !$wgUser->isAllowed( $right ) ) {
wfProfileOut( $fname );
return false;
/** some pages are explicitly allowed */
$name = $this->getPrefixedText();
- if( in_array( $name, $wgWhitelistRead ) ) {
+ if( $wgWhitelistRead && in_array( $name, $wgWhitelistRead ) ) {
return true;
}
# Compatibility with old settings
- if( $this->getNamespace() == NS_MAIN ) {
+ if( $wgWhitelistRead && $this->getNamespace() == NS_MAIN ) {
if( in_array( ':' . $name, $wgWhitelistRead ) ) {
return true;
}
} else {
$db =& wfGetDB( DB_SLAVE );
}
- $page = $db->tableName( 'page' );
- $links = $db->tableName( 'links' );
-
- $sql = "SELECT page_namespace,page_title,page_id FROM $page,$links WHERE l_from=page_id AND l_to={$id} $options";
- $res = $db->query( $sql, 'Title::getLinksTo' );
+
+ $res = $db->select( array( 'page', 'pagelinks' ),
+ array( 'page_namespace', 'page_title', 'page_id' ),
+ array(
+ 'pl_from=page_id',
+ 'pl_namespace' => $this->getNamespace(),
+ 'pl_title' => $this->getDbKey() ),
+ 'Title::getLinksTo',
+ $options );
+
$retVal = array();
if ( $db->numRows( $res ) ) {
while ( $row = $db->fetchObject( $res ) ) {
if ( $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title ) ) {
- $wgLinkCache->addGoodLink( $row->page_id, $titleObj->getPrefixedDBkey() );
+ $wgLinkCache->addGoodLinkObj( $row->page_id, $titleObj );
$retVal[] = $titleObj;
}
}
return $retVal;
}
- /**
- * Get an array of Title objects linking to this non-existent title.
- * - Also stores the IDs in the link cache.
- *
- * @param string $options may be FOR UPDATE
- * @return array the Title objects linking here
- * @access public
- */
- function getBrokenLinksTo( $options = '' ) {
- global $wgLinkCache;
-
- if ( $options ) {
- $db =& wfGetDB( DB_MASTER );
- } else {
- $db =& wfGetDB( DB_SLAVE );
- }
- $page = $db->tableName( 'page' );
- $brokenlinks = $db->tableName( 'brokenlinks' );
- $encTitle = $db->strencode( $this->getPrefixedDBkey() );
-
- $sql = "SELECT page_namespace,page_title,page_id FROM $brokenlinks,$page " .
- "WHERE bl_from=page_id AND bl_to='$encTitle' $options";
- $res = $db->query( $sql, "Title::getBrokenLinksTo" );
- $retVal = array();
- if ( $db->numRows( $res ) ) {
- while ( $row = $db->fetchObject( $res ) ) {
- $titleObj = Title::makeTitle( $row->page_namespace, $row->page_title );
- $wgLinkCache->addGoodLink( $row->page_id, $titleObj->getPrefixedDBkey() );
- $retVal[] = $titleObj;
- }
- }
- $db->freeResult( $res );
- return $retVal;
- }
-
-
/**
* Get an array of Title objects referring to non-existent articles linked from this page
*
} else {
$db =& wfGetDB( DB_SLAVE );
}
- $page = $db->tableName( 'page' );
- $brokenlinks = $db->tableName( 'brokenlinks' );
- $id = $this->getArticleID();
-
- $sql = "SELECT bl_to FROM $brokenlinks WHERE bl_from=$id $options";
- $res = $db->query( $sql, "Title::getBrokenLinksFrom" );
+
+ $res = $db->safeQuery(
+ "SELECT pl_namespace, pl_title
+ FROM !
+ LEFT JOIN !
+ ON pl_namespace=page_namespace
+ AND pl_title=page_title
+ WHERE pl_from=?
+ AND page_namespace IS NULL
+ !",
+ $db->tableName( 'pagelinks' ),
+ $db->tableName( 'page' ),
+ $this->getArticleId(),
+ $options );
+
$retVal = array();
if ( $db->numRows( $res ) ) {
while ( $row = $db->fetchObject( $res ) ) {
- $retVal[] = Title::newFromText( $row->bl_to );
+ $retVal[] = Title::makeTitle( $row->pl_namespace, $row->pl_title );
}
}
$db->freeResult( $res );
$log = new LogPage( 'move' );
$log->addEntry( 'move_redir', $this, $reason, array( 1 => $nt->getPrefixedText() ) );
- # Swap links
-
- # Load titles and IDs
- $linksToOld = $this->getLinksTo( 'FOR UPDATE' );
- $linksToNew = $nt->getLinksTo( 'FOR UPDATE' );
-
- # Delete them all
- $sql = "DELETE FROM $links WHERE l_to=$oldid OR l_to=$newid";
- $dbw->query( $sql, $fname );
-
- # Reinsert
- if ( count( $linksToOld ) || count( $linksToNew )) {
- $sql = "INSERT INTO $links (l_from,l_to) VALUES ";
- $first = true;
-
- # Insert links to old title
- foreach ( $linksToOld as $linkTitle ) {
- if ( $first ) {
- $first = false;
- } else {
- $sql .= ',';
- }
- $id = $linkTitle->getArticleID();
- $sql .= "($id,$newid)";
- }
-
- # Insert links to new title
- foreach ( $linksToNew as $linkTitle ) {
- if ( $first ) {
- $first = false;
- } else {
- $sql .= ',';
- }
- $id = $linkTitle->getArticleID();
- $sql .= "($id, $oldid)";
- }
-
- $dbw->query( $sql, $fname );
- }
-
# Now, we record the link from the redirect to the new title.
# It should have no other outgoing links...
- $dbw->delete( 'links', array( 'l_from' => $newid ) );
- $dbw->insert( 'links', array( 'l_from' => $newid, 'l_to' => $oldid ) );
-
- # Clear linkscc
- LinkCache::linksccClearLinksTo( $oldid );
- LinkCache::linksccClearLinksTo( $newid );
+ $dbw->delete( 'pagelinks', array( 'pl_from' => $newid ), $fname );
+ $dbw->insert( 'pagelinks',
+ array(
+ 'pl_from' => $newid,
+ 'pl_namespace' => $this->getNamespace(),
+ 'pl_title' => $this->getDbKey() ),
+ $fname );
# Purge squid
if ( $wgUseSquid ) {
$log = new LogPage( 'move' );
$log->addEntry( 'move', $this, $reason, array( 1 => $nt->getPrefixedText()) );
- # Purge squid and linkscc as per article creation
+ # Purge caches as per article creation
Article::onArticleCreate( $nt );
- # Any text links to the old title must be reassigned to the redirect
- $dbw->update( 'links', array( 'l_to' => $newid ), array( 'l_to' => $oldid ), $fname );
- LinkCache::linksccClearLinksTo( $oldid );
-
# Record the just-created redirect's linking to the page
- $dbw->insert( 'links', array( 'l_from' => $newid, 'l_to' => $oldid ), $fname );
+ $dbw->insert( 'pagelinks',
+ array(
+ 'pl_from' => $newid,
+ 'pl_namespace' => $this->getNamespace(),
+ 'pl_title' => $this->getDBkey() ),
+ $fname );
# Non-existent target may have had broken links to it; these must
- # now be removed and made into good links.
- $update = new LinksUpdate( $oldid, $nt->getPrefixedDBkey() );
- $update->fixBrokenLinks();
+ # now be touched to update link coloring.
+ $nt->touchLinks();
# Purge old title from squid
# The new title, and links to the new title, are purged in Article::onArticleCreate()
$article->updateRevisionOn( $dbw, $revision, 0 );
# Link table
- if ( $dest->getArticleID() ) {
- $dbw->insert( 'links',
- array(
- 'l_to' => $dest->getArticleID(),
- 'l_from' => $newid
- ), $fname
- );
- } else {
- $dbw->insert( 'brokenlinks',
- array(
- 'bl_to' => $dest->getPrefixedDBkey(),
- 'bl_from' => $newid
- ), $fname
- );
- }
+ $dbw->insert( 'pagelinks',
+ array(
+ 'pl_from' => $newid,
+ 'pl_namespace' => $dest->getNamespace(),
+ 'pl_title' => $dest->getDbKey()
+ ), $fname
+ );
Article::onArticleCreate( $this );
return true;
return ( 0 == $this->mNamespace && "" == $this->mDbkeyform )
|| NS_SPECIAL == $this->mNamespace || NS_IMAGE == $this->mNamespace;
}
+
+ /**
+ * Update page_touched timestamps on pages linking to this title.
+ * In principal, this could be backgrounded and could also do squid
+ * purging.
+ */
+ function touchLinks() {
+ $fname = 'Title::touchLinks';
+
+ $dbw =& wfGetDB( DB_MASTER );
+
+ $res = $dbw->select( 'pagelinks',
+ array( 'pl_from' ),
+ array(
+ 'pl_namespace' => $this->getNamespace(),
+ 'pl_title' => $this->getDbKey() ),
+ $fname );
+ if ( 0 == $dbw->numRows( $res ) ) {
+ return;
+ }
+
+ $arr = array();
+ $toucharr = array();
+ while( $row = $dbw->fetchObject( $res ) ) {
+ $toucharr[] = $row->pl_from;
+ }
+
+ $dbw->update( 'page', /* SET */ array( 'page_touched' => $dbw->timestamp() ),
+ /* WHERE */ array( 'page_id' => $toucharr ),$fname);
+ }
}
?>