00001 <?php
00002
00003
# Message cache
00004
# Performs various useful MediaWiki namespace-related functions
00005
00006 define(
"MSG_LOAD_TIMEOUT", 60);
00007 define(
"MSG_LOCK_TIMEOUT", 10);
00008 define(
"MSG_WAIT_TIMEOUT", 10);
00009
00010 class MessageCache
00011 {
00012 var
$mCache,
$mUseCache,
$mDisable,
$mExpiry;
00013 var
$mMemcKey,
$mKeys,
$mParserOptions,
$mParser;
00014 var
$mExtensionMessages;
00015
00016 var
$mInitialised =
false;
00017
00018 function
initialise( &$memCached, $useDB, $expiry, $memcPrefix ) {
00019 $this->mUseCache = !is_null( $memCached );
00020 $this->mMemc = &$memCached;
00021 $this->mDisable = !$useDB;
00022 $this->mExpiry = $expiry;
00023 $this->mDisableTransform =
false;
00024 $this->mMemcKey =
"$memcPrefix:messages";
00025 $this->mKeys =
false; # initialised on demand
00026 $this->mInitialised =
true;
00027 $this->mParserOptions = ParserOptions::newFromUser( $u=NULL );
00028 $this->mParser =
new Parser;
00029
00030 $this->
load();
00031 }
00032
00033
# Loads messages either from memcached or the database, if not disabled
00034
# On error, quietly switches to a fallback mode
00035
# Returns false for a reportable error, true otherwise
00036 function
load() {
00037 global
$wgAllMessagesEn;
00038
00039
if ( $this->mDisable ) {
00040
return true;
00041 }
00042
00043 $success =
true;
00044
00045
if ( $this->mUseCache ) {
00046 $this->mCache = $this->mMemc->get( $this->mMemcKey );
00047
00048
# If there's nothing in memcached, load all the messages from the database
00049
if ( !$this->mCache ) {
00050 $this->
lock();
00051
# Other threads don't need to load the messages if another thread is doing it.
00052
$this->mMemc->set( $this->mMemcKey,
"loading",
MSG_LOAD_TIMEOUT );
00053 $this->
loadFromDB();
00054
# Save in memcached
00055
if ( !$this->mMemc->set( $this->mMemcKey, $this->mCache, $this->mExpiry ) ) {
00056
# Hack for slabs reassignment problem
00057
$this->mMemc->set( $this->mMemcKey,
"error" );
00058
wfDebug(
"MemCached set error in MessageCache: restart memcached server!\n" );
00059 }
00060 $this->
unlock();
00061 }
00062
00063
if ( !is_array( $this->mCache ) ) {
00064
# If it is 'loading' or 'error', switch to individual message mode, otherwise disable
00065
if ( $this->mCache ==
"loading" ) {
00066 $this->mUseCache =
false;
00067 } elseif ( $this->mCache ==
"error" ) {
00068 $this->mUseCache =
false;
00069 $success =
false;
00070 }
else {
00071 $this->mDisable =
true;
00072 $success =
false;
00073 }
00074 $this->mCache =
false;
00075 }
00076 }
00077
return $success;
00078 }
00079
00080
# Loads all cacheable messages from the database
00081 function
loadFromDB()
00082 {
00083 $fname =
"MessageCache::loadFromDB";
00084
$sql =
"SELECT cur_title,cur_text FROM cur WHERE cur_is_redirect=0 AND cur_namespace=" .
NS_MEDIAWIKI;
00085
$res =
wfQuery( $sql,
DB_READ, $fname );
00086
00087 $this->mCache = array();
00088
for (
$row =
wfFetchObject( $res );
$row;
$row =
wfFetchObject( $res ) ) {
00089 $this->mCache[
$row->cur_title] =
$row->cur_text;
00090 }
00091
00092
wfFreeResult( $res );
00093 }
00094
00095
# Not really needed anymore
00096 function
getKeys() {
00097 global
$wgAllMessagesEn,
$wgLang;
00098
if ( !$this->mKeys ) {
00099 $this->mKeys = array();
00100 foreach ( $wgAllMessagesEn as $key => $value ) {
00101 array_push( $this->mKeys, $wgLang->ucfirst( $key ) );
00102 }
00103 }
00104
return $this->mKeys;
00105 }
00106
00107
# Obsolete
00108 function
isCacheable( $key ) {
00109
return true;
00110
00111
00112
00113
00114
00115 }
00116
00117 function
replace( $title, $text ) {
00118 $this->
lock();
00119 $this->
load();
00120
if ( is_array( $this->mCache ) ) {
00121 $this->mCache[
$title] = $text;
00122 $this->mMemc->set( $this->mMemcKey, $this->mCache, $this->mExpiry );
00123 }
00124 $this->
unlock();
00125 }
00126
00127
# Returns success
00128
# Represents a write lock on the messages key
00129 function
lock() {
00130
if ( !$this->mUseCache ) {
00131
return true;
00132 }
00133
00134 $lockKey = $this->mMemcKey .
"lock";
00135
for (
$i=0;
$i <
MSG_WAIT_TIMEOUT && !$this->mMemc->add( $lockKey, 1,
MSG_LOCK_TIMEOUT );
$i++ ) {
00136 sleep(1);
00137 }
00138
00139
return $i >=
MSG_WAIT_TIMEOUT;
00140 }
00141
00142 function
unlock() {
00143
if ( !$this->mUseCache ) {
00144
return;
00145 }
00146
00147 $lockKey = $this->mMemcKey .
"lock";
00148 $this->mMemc->delete( $lockKey );
00149 }
00150
00151 function
get( $key, $useDB ) {
00152 global
$wgLang,
$wgLanguageCode;
00153
00154
# If uninitialised, someone is trying to call this halfway through Setup.php
00155
if ( !$this->mInitialised ) {
00156
return "<$key>";
00157 }
00158
00159 $message =
false;
00160
if ( !$this->mDisable ) {
00161
$title =
$wgLang->ucfirst( $key );
00162
00163
00164
# Try the cache
00165
if ( $this->mUseCache && $this->mCache && array_key_exists( $
title, $this->mCache ) ) {
00166 $message = $this->mCache[
$title];
00167 }
00168
00169
# If it wasn't in the cache, load each message from the DB individually
00170
if ( !$message && $useDB) {
00171 $result =
wfGetArray(
"cur", array(
"cur_text"),
00172 array(
"cur_namespace" =>
NS_MEDIAWIKI,
"cur_title" => $
title ),
00173
"MessageCache::get" );
00174
if ( $result ) {
00175 $message = $result->cur_text;
00176 }
00177 }
00178 }
00179
# Try the extension array
00180
if ( !$message ) {
00181 $message = @$this->mExtensionMessages[$key];
00182 }
00183
00184
# Try the array in $wgLang
00185
if ( !$message ) {
00186 $message =
$wgLang->getMessage( $key );
00187 }
00188
00189
# Try the English array
00190
if ( !$message &&
$wgLanguageCode !=
"en" ) {
00191 $message = Language::getMessage( $key );
00192 }
00193
00194
# Final fallback
00195
if ( !$message ) {
00196 $message =
"<$key>";
00197 }
00198
00199
# Replace brace tags
00200
$message = $this->
transform( $message );
00201
return $message;
00202 }
00203
00204 function
transform( $message ) {
00205
if( !$this->mDisableTransform ) {
00206
if ( strstr( $message,
"{{" ) !==
false ) {
00207 $message = $this->mParser->transformMsg( $message, $this->mParserOptions );
00208 }
00209 }
00210
return $message;
00211 }
00212
00213 function
disable() { $this->mDisable =
true; }
00214 function
enable() { $this->mDisable =
false; }
00215 function
disableTransform() { $this->mDisableTransform =
true; }
00216
00217 function
addMessage( $key, $value ) {
00218 $this->mExtensionMessages[$key] = $value;
00219 }
00220
00221 function
addMessages( $messages ) {
00222 foreach ( $messages as $key => $value ) {
00223 $this->mExtensionMessages[$key] = $value;
00224 }
00225 }
00226 }
00227 ?>