00001 <?php
00002
00003
# This class encapsulates "magic words" such as #redirect, __NOTOC__, etc.
00004
# Usage:
00005
# if (MagicWord::get( MAG_REDIRECT )->match( $text ) )
00006
#
00007
# Possible future improvements:
00008
# * Simultaneous searching for a number of magic words
00009
# * $wgMagicWords in shared memory
00010
#
00011
# Please avoid reading the data out of one of these objects and then writing
00012
# special case code. If possible, add another match()-like function here.
00013
00014 $wgMagicFound =
false;
00015
00016 define(
"MAG_REDIRECT", 0);
00017 define(
"MAG_NOTOC", 1);
00018 define(
"MAG_START", 2);
00019 define(
"MAG_CURRENTMONTH", 3);
00020 define(
"MAG_CURRENTMONTHNAME", 4);
00021 define(
"MAG_CURRENTDAY", 5);
00022 define(
"MAG_CURRENTDAYNAME", 6);
00023 define(
"MAG_CURRENTYEAR", 7);
00024 define(
"MAG_CURRENTTIME", 8);
00025 define(
"MAG_NUMBEROFARTICLES", 9);
00026 define(
"MAG_CURRENTMONTHNAMEGEN", 10);
00027 define(
"MAG_MSG", 11);
00028 define(
"MAG_SUBST", 12);
00029 define(
"MAG_MSGNW", 13);
00030 define(
"MAG_NOEDITSECTION", 14);
00031 define(
"MAG_END", 15);
00032 define(
"MAG_IMG_THUMBNAIL", 16);
00033 define(
"MAG_IMG_RIGHT", 17);
00034 define(
"MAG_IMG_LEFT", 18);
00035 define(
"MAG_IMG_NONE", 19);
00036 define(
"MAG_IMG_WIDTH", 20);
00037 define(
"MAG_IMG_CENTER", 21);
00038 define(
"MAG_INT", 22);
00039 define(
"MAG_FORCETOC", 23);
00040 define(
"MAG_SITENAME", 24);
00041 define(
"MAG_NS", 25);
00042 define(
"MAG_LOCALURL", 26);
00043 define(
"MAG_LOCALURLE", 27);
00044 define(
"MAG_SERVER", 28);
00045 define(
"MAG_IMG_FRAMED", 29);
00046 define(
"MAG_PAGENAME", 30);
00047 define(
"MAG_NAMESPACE", 31);
00048
00049 $wgVariableIDs = array(
00050 MAG_CURRENTMONTH,
00051 MAG_CURRENTMONTHNAME,
00052 MAG_CURRENTDAY,
00053 MAG_CURRENTDAYNAME,
00054 MAG_CURRENTYEAR,
00055 MAG_CURRENTTIME,
00056 MAG_NUMBEROFARTICLES,
00057 MAG_CURRENTMONTHNAMEGEN,
00058 MAG_SITENAME,
00059 MAG_SERVER,
00060 MAG_PAGENAME,
00061 MAG_NAMESPACE
00062 );
00063
00064
class MagicWord {
00065 var $mId, $mSynonyms, $mCaseSensitive, $mRegex;
00066 var $mRegexStart, $mBaseRegex, $mVariableRegex;
00067 var $mModified;
00068
00069 function MagicWord($
id = 0, $syn =
"", $cs =
false)
00070 {
00071 $this->mId = $id;
00072 $this->mSynonyms = (array)$syn;
00073 $this->mCaseSensitive = $cs;
00074 $this->mRegex =
"";
00075 $this->mRegexStart =
"";
00076 $this->mVariableRegex =
"";
00077 $this->mVariableStartToEndRegex =
"";
00078 $this->mModified =
false;
00079 }
00080
00081
# Factory: creates an object representing an ID
00082
function &get( $
id )
00083 {
00084 global
$wgMagicWords;
00085
00086
if (!array_key_exists( $
id, $wgMagicWords ) ) {
00087 $mw =
new MagicWord();
00088 $mw->load( $
id );
00089
$wgMagicWords[$id] = $mw;
00090 }
00091
return $wgMagicWords[$id];
00092 }
00093
00094
# Initialises this object with an ID
00095
function load( $
id )
00096 {
00097 global
$wgLang;
00098 $this->mId = $id;
00099
$wgLang->getMagic( $
this );
00100 }
00101
00102
# Preliminary initialisation
00103
function initRegex()
00104 {
00105 $variableClass = Title::legalChars();
00106 $escSyn = array_map(
"preg_quote", $this->mSynonyms );
00107 $this->mBaseRegex = implode(
"|", $escSyn );
00108 $case = $this->mCaseSensitive ?
"" :
"i";
00109 $this->mRegex =
"/{$this->mBaseRegex}/{$case}";
00110 $this->mRegexStart =
"/^{$this->mBaseRegex}/{$case}";
00111 $this->mVariableRegex = str_replace(
"\\$1",
"([$variableClass]*?)", $this->mRegex );
00112 $this->mVariableStartToEndRegex = str_replace(
"\\$1",
"([$variableClass]*?)",
00113
"/^({$this->mBaseRegex})$/{$case}" );
00114 }
00115
00116
# Gets a regex representing matching the word
00117
function getRegex()
00118 {
00119
if ($this->mRegex ==
"" ) {
00120 $this->initRegex();
00121 }
00122
return $this->mRegex;
00123 }
00124
00125
# Gets a regex matching the word, if it is at the
00126
# string start
00127
function getRegexStart()
00128 {
00129
if ($this->mRegex ==
"" ) {
00130 $this->initRegex();
00131 }
00132
return $this->mRegexStart;
00133 }
00134
00135
# regex without the slashes and what not
00136
function getBaseRegex()
00137 {
00138
if ($this->mRegex ==
"") {
00139 $this->initRegex();
00140 }
00141
return $this->mBaseRegex;
00142 }
00143
00144
# Returns true if the text contains the word
00145
function match( $text ) {
00146
return preg_match( $this->getRegex(), $text );
00147 }
00148
00149
# Returns true if the text starts with the word
00150
function matchStart( $text )
00151 {
00152
return preg_match( $this->getRegexStart(), $text );
00153 }
00154
00155
# Returns NULL if there's no match, the value of $1 otherwise
00156
# The return code is the matched string, if there's no variable
00157
# part in the regex and the matched variable part ($1) if there
00158
# is one.
00159
function matchVariableStartToEnd( $text ) {
00160 $matchcount = preg_match( $this->getVariableStartToEndRegex(), $text, $matches );
00161
if ( $matchcount == 0 ) {
00162
return NULL;
00163 } elseif ( count($matches) == 1 ) {
00164
return $matches[0];
00165 }
else {
00166
return $matches[1];
00167 }
00168 }
00169
00170
00171
# Returns true if the text matches the word, and alters the
00172
# input string, removing all instances of the word
00173
function matchAndRemove( &$text )
00174 {
00175 global $wgMagicFound;
00176 $wgMagicFound =
false;
00177 $text = preg_replace_callback( $this->getRegex(),
"pregRemoveAndRecord", $text );
00178
return $wgMagicFound;
00179 }
00180
00181 function matchStartAndRemove( &$text ) {
00182 global $wgMagicFound;
00183 $wgMagicFound =
false;
00184 $text = preg_replace_callback( $this->getRegexStart(),
"pregRemoveAndRecord", $text );
00185
return $wgMagicFound;
00186 }
00187
00188
00189
# Replaces the word with something else
00190
function replace( $replacement, $subject )
00191 {
00192
$res = preg_replace( $this->getRegex(), $replacement, $subject );
00193 $this->mModified = !(
$res === $subject);
00194
return $res;
00195 }
00196
00197
# Variable handling: {{SUBST:xxx}} style words
00198
# Calls back a function to determine what to replace xxx with
00199
# Input word must contain $1
00200
function substituteCallback( $text, $callback ) {
00201 $regex = $this->getVariableRegex();
00202
$res = preg_replace_callback( $this->getVariableRegex(), $callback, $text );
00203 $this->mModified = !(
$res === $text);
00204
return $res;
00205 }
00206
00207
# Matches the word, where $1 is a wildcard
00208
function getVariableRegex()
00209 {
00210
if ( $this->mVariableRegex ==
"" ) {
00211 $this->initRegex();
00212 }
00213
return $this->mVariableRegex;
00214 }
00215
00216
# Matches the entire string, where $1 is a wildcard
00217
function getVariableStartToEndRegex()
00218 {
00219
if ( $this->mVariableStartToEndRegex ==
"" ) {
00220 $this->initRegex();
00221 }
00222
return $this->mVariableStartToEndRegex;
00223 }
00224
00225
# Accesses the synonym list directly
00226
function getSynonym( $i ) {
00227
return $this->mSynonyms[
$i];
00228 }
00229
00230
# Returns true if the last call to replace() or substituteCallback()
00231
# returned a modified text, otherwise false.
00232
function getWasModified(){
00233
return $this->mModified;
00234 }
00235
00236
# $magicarr is an associative array of (magic word ID => replacement)
00237
# This method uses the php feature to do several replacements at the same time,
00238
# thereby gaining some efficiency. The result is placed in the out variable
00239
# $result. The return value is true if something was replaced.
00240
00241 function replaceMultiple( $magicarr, $subject, &$result ){
00242 $search = array();
00243 $replace = array();
00244 foreach( $magicarr as $
id => $replacement ){
00245 $mw = MagicWord::get( $
id );
00246 $search[] = $mw->getRegex();
00247 $replace[] = $replacement;
00248 }
00249
00250 $result = preg_replace( $search, $replace, $subject );
00251
return !($result === $subject);
00252 }
00253
00254
# Adds all the synonyms of this MagicWord to an array, to allow quick lookup in a list of magic words
00255
function addToArray( &$array, $value )
00256 {
00257 foreach ( $this->mSynonyms as $syn ) {
00258 $array[$syn] = $value;
00259 }
00260 }
00261 }
00262
00263
# Used in matchAndRemove()
00264
function pregRemoveAndRecord( $match )
00265 {
00266 global $wgMagicFound;
00267 $wgMagicFound =
true;
00268
return "";
00269 }
00270
00271 ?>