wiki.techinc.nl/includes/LinkCache.php

350 lines
9 KiB
PHP
Raw Normal View History

<?php
2004-03-20 14:33:18 +00:00
# Cache for article titles (prefixed DB keys) and ids linked from one source
2003-04-14 23:10:40 +00:00
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 = 2;
2003-04-14 23:10:40 +00:00
/* private */ var $mGoodLinks, $mBadLinks, $mActive;
/* private */ var $mImageLinks, $mCategoryLinks;
2003-07-06 11:42:42 +00:00
/* 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();
$this->mCategoryLinks = 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; }
}
function addCategoryLink( $title, $sortkey ) {
if ( $this->mActive ) { $this->mCategoryLinks[$title] = $sortkey; }
}
function addCategoryLinkObj( &$nt, $sortkey ) {
$this->addCategoryLink( $nt->getDBkey(), $sortkey );
}
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 getCategoryLinks() { return $this->mCategoryLinks; }
2003-04-14 23:10:40 +00:00
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 = NULL;
if( $wgLinkCacheMemcached )
$id = $wgMemc->get( $key = $this->getKey( $title ) );
if( ! is_integer( $id ) ) {
$dbr =& wfGetDB( DB_READ );
$id = $dbr->getField( 'cur', 'cur_id', array( 'cur_namespace' => $ns, 'cur_title' => $t ), $fname );
if ( !$id ) {
$id = 0;
}
if( $wgLinkCacheMemcached )
$wgMemc->add( $key, $id, 3600*24 );
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*
$this->suspend();
$id = $fromtitle->getArticleID();
$this->resume();
if( $id == 0 ) {
wfDebug( "$fname - got id 0 for title '" . $fromtitle->getPrefixedDBkey() . "'\n" );
wfProfileOut( $fname );
return;
}
if ( $wgEnablePersistentLC ) {
if( $this->fillFromLinkscc( $id ) ){
wfProfileOut( $fname );
return;
}
}
$dbr =& wfGetDB( DB_READ );
$cur = $dbr->tableName( 'cur' );
$links = $dbr->tableName( 'links' );
$sql = "SELECT cur_id,cur_namespace,cur_title
FROM $cur,$links
WHERE cur_id=l_to AND l_from=$id";
$res = $dbr->query( $sql, $fname );
while( $s = $dbr->fetchObject( $res ) ) {
2003-04-14 23:10:40 +00:00
$this->addGoodLink( $s->cur_id,
Title::makeName( $s->cur_namespace, $s->cur_title )
);
}
2003-07-06 11:42:42 +00:00
$res = $dbr->select( 'brokenlinks', array( 'bl_to' ), array( 'bl_from' => $id ), $fname );
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 );
}
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( $id ){
$id = IntVal( $id );
$dbr =& wfGetDB( DB_READ );
$raw = $dbr->getField( 'linkscc', 'lcc_cacheobj', array( 'lcc_pageid' => $id ) );
if ( $raw === false ) {
return false;
}
$cacheobj = false;
if( function_exists( "gzuncompress" ) )
$cacheobj = @gzuncompress( $raw );
if($cacheobj == FALSE){
$cacheobj = $raw;
}
$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 ){
global $wgCompressedPersistentLC;
if( $wgCompressedPersistentLC and function_exists( "gzcompress" ) ) {
$ser = gzcompress( serialize( $this ), 3 );
} else {
$ser = serialize( $this );
}
$db =& wfGetDB( DB_WRITE );
$db->replace( 'linkscc', array( 'lcc_pageid' ), array( 'lcc_pageid' => $pid, 'lcc_cacheobj' => $ser ) );
}
# Delete linkscc rows which link to here
# $pid is a page id
/* static */ function linksccClearLinksTo( $pid ){
global $wgEnablePersistentLC;
if ( $wgEnablePersistentLC ) {
$fname = "LinkCache::linksccClearLinksTo";
$pid = intval( $pid );
$dbw =& wfGetDB( DB_WRITE );
# Delete linkscc rows which link to here
$dbw->deleteJoin( 'linkscc', 'links', 'lcc_pageid', 'l_from', array( 'l_to' => $pid ), $fname );
# Delete linkscc row representing this page
$dbw->delete( 'linkscc', array( 'lcc_pageid' => $pid ), $fname);
}
}
# Delete linkscc rows with broken links to here
# $title is a prefixed db title, for example like Title->getPrefixedDBkey() returns.
/* static */ function linksccClearBrokenLinksTo( $title ){
global $wgEnablePersistentLC;
$fname = 'LinkCache::linksccClearBrokenLinksTo';
if ( $wgEnablePersistentLC ) {
$dbw =& wfGetDB( DB_WRITE );
$dbw->deleteJoin( 'linkscc', 'brokenlinks', 'lcc_pageid', 'bl_from', array( 'bl_to' => $title ), $fname );
}
}
# $pid is a page id
/* static */ function linksccClearPage( $pid ){
global $wgEnablePersistentLC;
if ( $wgEnablePersistentLC ) {
$pid = intval( $pid );
$dbw =& wfGetDB( DB_WRITE );
$dbw->delete( 'linkscc', array( 'lcc_pageid' => $pid ) );
}
}
2003-07-06 11:42:42 +00:00
}
2003-04-14 23:10:40 +00:00
?>