wiki.techinc.nl/includes/LinkCache.php

327 lines
8.3 KiB
PHP
Raw Normal View History

2003-04-14 23:10:40 +00:00
<?
# Cache for article titles and ids linked from one source
2003-07-06 11:42:42 +00:00
# These are used in incrementalSetup()
define ('LINKCACHE_GOOD', 0);
define ('LINKCACHE_BAD', 1);
define ('LINKCACHE_IMAGE', 2);
class LinkCache {
// Increment $mClassVer whenever old serialized versions of this class
// becomes incompatible with the new version.
/* private */ var $mClassVer = 1;
2003-04-14 23:10:40 +00:00
/* private */ var $mGoodLinks, $mBadLinks, $mActive;
2003-07-06 11:42:42 +00:00
/* private */ var $mImageLinks;
/* private */ var $mPreFilled, $mOldGoodLinks, $mOldBadLinks;
/* private */ function getKey( $title ) {
global $wgDBname;
return "$wgDBname:lc:title:$title";
}
2003-04-14 23:10:40 +00:00
function LinkCache()
{
$this->mActive = true;
2003-07-06 11:42:42 +00:00
$this->mPreFilled = false;
2003-04-14 23:10:40 +00:00
$this->mGoodLinks = array();
$this->mBadLinks = array();
$this->mImageLinks = array();
2003-07-06 11:42:42 +00:00
$this->mOldGoodLinks = array();
$this->mOldBadLinks = array();
2003-04-14 23:10:40 +00:00
}
function getGoodLinkID( $title )
{
if ( array_key_exists( $title, $this->mGoodLinks ) ) {
return $this->mGoodLinks[$title];
} else {
return 0;
}
}
function isBadLink( $title )
{
return array_key_exists( $title, $this->mBadLinks );
2003-04-14 23:10:40 +00:00
}
function addGoodLink( $id, $title )
{
if ( $this->mActive ) {
$this->mGoodLinks[$title] = $id;
}
}
function addBadLink( $title )
{
if ( $this->mActive && ( ! $this->isBadLink( $title ) ) ) {
$this->mBadLinks[$title] = 1;
2003-04-14 23:10:40 +00:00
}
}
function addImageLink( $title )
{
if ( $this->mActive ) { $this->mImageLinks[$title] = 1; }
}
function addImageLinkObj( $nt )
{
if ( $this->mActive ) { $this->mImageLinks[$nt->getDBkey()] = 1; }
}
2003-04-14 23:10:40 +00:00
function clearBadLink( $title )
{
unset( $this->mBadLinks[$title] );
$this->clearLink( $title );
}
function clearLink( $title )
{
global $wgMemc, $wgLinkCacheMemcached;
if( $wgLinkCacheMemcached )
$wgMemc->delete( $this->getKey( $title ) );
2003-04-14 23:10:40 +00:00
}
function suspend() { $this->mActive = false; }
function resume() { $this->mActive = true; }
function getGoodLinks() { return $this->mGoodLinks; }
function getBadLinks() { return array_keys( $this->mBadLinks ); }
2003-04-14 23:10:40 +00:00
function getImageLinks() { return $this->mImageLinks; }
function addLink( $title )
{
$nt = Title::newFromDBkey( $title );
if( $nt ) {
return $this->addLinkObj( $nt );
} else {
return 0;
}
2003-10-22 23:56:49 +00:00
}
function addLinkObj( &$nt )
{
global $wgMemc, $wgLinkCacheMemcached;
$title = $nt->getPrefixedDBkey();
if ( $this->isBadLink( $title ) ) { return 0; }
2003-04-14 23:10:40 +00:00
$id = $this->getGoodLinkID( $title );
if ( 0 != $id ) { return $id; }
$fname = "LinkCache::addLinkObj";
wfProfileIn( $fname );
2003-04-14 23:10:40 +00:00
$ns = $nt->getNamespace();
$t = $nt->getDBkey();
2003-04-14 23:10:40 +00:00
2003-10-22 23:56:49 +00:00
if ( "" == $title ) {
wfProfileOut( $fname );
return 0;
}
$id = FALSE;
if( $wgLinkCacheMemcached )
$id = $wgMemc->get( $key = $this->getKey( $title ) );
if( ! $id ) {
$sql = "SELECT cur_id FROM cur WHERE cur_namespace=" .
"{$ns} AND cur_title='" . wfStrencode( $t ) . "'";
$res = wfQuery( $sql, DB_READ, "LinkCache::addLink" );
if ( 0 == wfNumRows( $res ) ) {
$id = 0;
} else {
$s = wfFetchObject( $res );
$id = $s->cur_id;
}
if( $wgLinkCacheMemcached )
$wgMemc->add( $key, $id, time()+3600 );
2003-04-14 23:10:40 +00:00
}
2003-04-14 23:10:40 +00:00
if ( 0 == $id ) { $this->addBadLink( $title ); }
else { $this->addGoodLink( $id, $title ); }
wfProfileOut( $fname );
2003-04-14 23:10:40 +00:00
return $id;
}
2003-10-22 23:56:49 +00:00
function preFill( &$fromtitle )
2003-04-14 23:10:40 +00:00
{
global $wgEnablePersistentLC;
$fname = "LinkCache::preFill";
wfProfileIn( $fname );
2003-04-14 23:10:40 +00:00
# Note -- $fromtitle is a Title *object*
$dbkeyfrom = wfStrencode( $fromtitle->getPrefixedDBKey() );
if ( $wgEnablePersistentLC ) {
if( $this->fillFromLinkscc( $dbkeyfrom ) ){
return;
}
}
$sql = "SELECT cur_id,cur_namespace,cur_title
2003-04-14 23:10:40 +00:00
FROM cur,links
WHERE cur_id=l_to AND l_from='{$dbkeyfrom}'";
$res = wfQuery( $sql, DB_READ, $fname );
2003-04-14 23:10:40 +00:00
while( $s = wfFetchObject( $res ) ) {
$this->addGoodLink( $s->cur_id,
Title::makeName( $s->cur_namespace, $s->cur_title )
);
}
2003-07-06 11:42:42 +00:00
$this->suspend();
$id = $fromtitle->getArticleID();
$this->resume();
if( $id == 0 ) {
wfDebug( "$fname - got id 0 for title '" . $fromtitle->getPrefixedDBkey() . "'\n" );
wfProfileOut( $fname );
return;
}
$sql = "SELECT bl_to
FROM brokenlinks
2003-07-06 11:42:42 +00:00
WHERE bl_from='{$id}'";
$res = wfQuery( $sql, DB_READ, "LinkCache::preFill" );
while( $s = wfFetchObject( $res ) ) {
$this->addBadLink( $s->bl_to );
}
2003-07-06 11:42:42 +00:00
$this->mOldBadLinks = $this->mBadLinks;
$this->mOldGoodLinks = $this->mGoodLinks;
$this->mPreFilled = true;
if ( $wgEnablePersistentLC ) {
$this->saveToLinkscc( $id, $dbkeyfrom );
}
wfProfileOut( $fname );
2003-04-14 23:10:40 +00:00
}
2003-07-06 11:42:42 +00:00
function getGoodAdditions()
{
return array_diff( $this->mGoodLinks, $this->mOldGoodLinks );
}
function getBadAdditions()
{
#wfDebug( "mOldBadLinks: " . implode( ', ', array_keys( $this->mOldBadLinks ) ) . "\n" );
#wfDebug( "mBadLinks: " . implode( ', ', array_keys( $this->mBadLinks ) ) . "\n" );
return array_values( array_diff( array_keys( $this->mBadLinks ), array_keys( $this->mOldBadLinks ) ) );
2003-07-06 11:42:42 +00:00
}
function getImageAdditions()
{
return array_diff_assoc( $this->mImageLinks, $this->mOldImageLinks );
}
function getGoodDeletions()
{
return array_diff( $this->mOldGoodLinks, $this->mGoodLinks );
}
function getBadDeletions()
{
return array_values( array_diff( array_keys( $this->mOldBadLinks ), array_keys( $this->mBadLinks ) ));
2003-07-06 11:42:42 +00:00
}
function getImageDeletions()
{
return array_diff_assoc( $this->mOldImageLinks, $this->mImageLinks );
}
2003-04-14 23:10:40 +00:00
2003-07-06 11:42:42 +00:00
# Parameters: $which is one of the LINKCACHE_xxx constants, $del and $add are
# the incremental update arrays which will be filled. Returns whether or not it's
# worth doing the incremental version. For example, if [[List of mathematical topics]]
# was blanked, it would take a long, long time to do incrementally.
function incrementalSetup( $which, &$del, &$add )
{
if ( ! $this->mPreFilled ) {
return false;
}
switch ( $which ) {
case LINKCACHE_GOOD:
$old =& $this->mOldGoodLinks;
$cur =& $this->mGoodLinks;
$del = $this->getGoodDeletions();
$add = $this->getGoodAdditions();
break;
case LINKCACHE_BAD:
$old =& $this->mOldBadLinks;
$cur =& $this->mBadLinks;
$del = $this->getBadDeletions();
$add = $this->getBadAdditions();
break;
default: # LINKCACHE_IMAGE
return false;
}
2003-07-07 13:43:03 +00:00
return true;
2003-07-06 11:42:42 +00:00
}
# Clears cache but leaves old preFill copies alone
function clear()
{
$this->mGoodLinks = array();
$this->mBadLinks = array();
$this->mImageLinks = array();
}
/* private */ function fillFromLinkscc( $dbkeyfrom ){
$res = wfQuery("SELECT lcc_cacheobj FROM linkscc WHERE lcc_title = '{$dbkeyfrom}'",
DB_READ);
$row = wfFetchObject( $res );
if( $row == FALSE)
return false;
$cacheobj = false;
if( function_exists( "gzuncompress" ) )
$cacheobj = @gzuncompress( $row->lcc_cacheobj );
if($cacheobj == FALSE){
$cacheobj = $row->lcc_cacheobj;
}
$cc = @unserialize( $cacheobj );
if( isset( $cc->mClassVer ) and ($cc->mClassVer == $this->mClassVer ) ){
$this->mOldGoodLinks = $this->mGoodLinks = $cc->mGoodLinks;
$this->mOldBadLinks = $this->mBadLinks = $cc->mBadLinks;
$this->mPreFilled = true;
return TRUE;
} else {
return FALSE;
}
}
/* private */ function saveToLinkscc( $pid, $dbkeyfrom ){
global $wgCompressedPersistentLC;
if( $wgCompressedPersistentLC and function_exists( "gzcompress" ) ) {
$ser = wfStrencode( gzcompress( serialize( $this ), 3 ));
} else {
$ser = wfStrencode( serialize( $this ) );
}
wfQuery("REPLACE INTO linkscc(lcc_pageid,lcc_title,lcc_cacheobj) " .
"VALUES({$pid}, '{$dbkeyfrom}', '{$ser}')", DB_WRITE);
}
# $pid is a page id
/* static */ function linksccClearLinksTo( $pid ){
$pid = intval( $pid );
wfQuery("DELETE linkscc FROM linkscc,links ".
"WHERE lcc_title=links.l_from AND l_to={$pid}", DB_WRITE);
wfQuery("DELETE FROM linkscc WHERE lcc_pageid='{$pid}'", DB_WRITE);
}
# $title is a prefixed db title, for example like Title->getPrefixedDBkey() returns.
/* static */ function linksccClearBrokenLinksTo( $title ){
$title = wfStrencode( $title );
wfQuery("DELETE linkscc FROM linkscc,brokenlinks ".
"WHERE lcc_pageid=bl_from AND bl_to='{$title}'", DB_WRITE);
}
# $pid is a page id
/* static */ function linksccClearPage( $pid ){
2004-01-05 23:15:11 +00:00
$pid = intval( $pid );
wfQuery("DELETE FROM linkscc WHERE lcc_pageid='{$pid}'", DB_WRITE);
}
2003-07-06 11:42:42 +00:00
}
2003-04-14 23:10:40 +00:00
?>