f8b47c35f33d4ff74c3c7c918b3a76f6984bd9df
11 $wgMagicFound = false;
13 /** Actual keyword to be used is set in Language.php */
20 'MAG_CURRENTMONTHNAME',
21 'MAG_CURRENTMONTHNAMEGEN',
22 'MAG_CURRENTMONTHABBREV',
28 'MAG_NUMBEROFARTICLES',
55 'MAG_NOCONTENTCONVERT',
62 'MAG_IMG_MANUALTHUMB',
82 'MAG_SUBJECTPAGENAME',
83 'MAG_SUBJECTPAGENAMEE',
92 'MAG_CURRENTTIMESTAMP',
94 if ( ! defined( 'MEDIAWIKI_INSTALL' ) )
95 wfRunHooks( 'MagicWordMagicWords', array( &$magicWords ) );
97 for ( $i = 0; $i < count( $magicWords ); ++
$i )
98 define( $magicWords[$i], $i );
100 $wgVariableIDs = array(
102 MAG_CURRENTMONTHNAME
,
103 MAG_CURRENTMONTHNAMEGEN
,
104 MAG_CURRENTMONTHABBREV
,
110 MAG_NUMBEROFARTICLES
,
135 MAG_SUBJECTPAGENAMEE
,
144 MAG_CURRENTTIMESTAMP
,
146 if ( ! defined( 'MEDIAWIKI_INSTALL' ) )
147 wfRunHooks( 'MagicWordwgVariableIDs', array( &$wgVariableIDs ) );
150 * This class encapsulates "magic words" such as #redirect, __NOTOC__, etc.
152 * if (MagicWord::get( MAG_REDIRECT )->match( $text ) )
154 * Possible future improvements:
155 * * Simultaneous searching for a number of magic words
156 * * $wgMagicWords in shared memory
158 * Please avoid reading the data out of one of these objects and then writing
159 * special case code. If possible, add another match()-like function here.
167 var $mId, $mSynonyms, $mCaseSensitive, $mRegex;
168 var $mRegexStart, $mBaseRegex, $mVariableRegex;
172 function MagicWord($id = 0, $syn = '', $cs = false) {
174 $this->mSynonyms
= (array)$syn;
175 $this->mCaseSensitive
= $cs;
177 $this->mRegexStart
= '';
178 $this->mVariableRegex
= '';
179 $this->mVariableStartToEndRegex
= '';
180 $this->mModified
= false;
184 * Factory: creates an object representing an ID
187 function &get( $id ) {
188 global $wgMagicWords;
190 if ( !is_array( $wgMagicWords ) ) {
191 wfDebugDieBacktrace( "Incorrect initialisation order, \$wgMagicWords does not exist\n" );
193 if (!array_key_exists( $id, $wgMagicWords ) ) {
194 $mw = new MagicWord();
196 $wgMagicWords[$id] = $mw;
198 return $wgMagicWords[$id];
201 # Initialises this object with an ID
202 function load( $id ) {
205 $wgContLang->getMagic( $this );
209 * Preliminary initialisation
212 function initRegex() {
213 #$variableClass = Title::legalChars();
214 # This was used for matching "$1" variables, but different uses of the feature will have
215 # different restrictions, which should be checked *after* the MagicWord has been matched,
219 foreach ( $this->mSynonyms
as $synonym )
220 // In case a magic word contains /, like that's going to happen;)
221 $escSyn[] = preg_quote( $synonym, '/' );
222 $this->mBaseRegex
= implode( '|', $escSyn );
224 $case = $this->mCaseSensitive ?
'' : 'i';
225 $this->mRegex
= "/{$this->mBaseRegex}/{$case}";
226 $this->mRegexStart
= "/^(?:{$this->mBaseRegex})/{$case}";
227 $this->mVariableRegex
= str_replace( "\\$1", "(.*?)", $this->mRegex
);
228 $this->mVariableStartToEndRegex
= str_replace( "\\$1", "(.*?)",
229 "/^(?:{$this->mBaseRegex})$/{$case}" );
233 * Gets a regex representing matching the word
235 function getRegex() {
236 if ($this->mRegex
== '' ) {
239 return $this->mRegex
;
243 * Gets the regexp case modifier to use, i.e. i or nothing, to be used if
244 * one is using MagicWord::getBaseRegex(), otherwise it'll be included in
245 * the complete expression
247 function getRegexCase() {
248 if ( $this->mRegex
=== '' )
251 return $this->mCaseSensitive ?
'' : 'i';
255 * Gets a regex matching the word, if it is at the string start
257 function getRegexStart() {
258 if ($this->mRegex
== '' ) {
261 return $this->mRegexStart
;
265 * regex without the slashes and what not
267 function getBaseRegex() {
268 if ($this->mRegex
== '') {
271 return $this->mBaseRegex
;
275 * Returns true if the text contains the word
278 function match( $text ) {
279 return preg_match( $this->getRegex(), $text );
283 * Returns true if the text starts with the word
286 function matchStart( $text ) {
287 return preg_match( $this->getRegexStart(), $text );
291 * Returns NULL if there's no match, the value of $1 otherwise
292 * The return code is the matched string, if there's no variable
293 * part in the regex and the matched variable part ($1) if there
296 function matchVariableStartToEnd( $text ) {
298 $matchcount = preg_match( $this->getVariableStartToEndRegex(), $text, $matches );
299 if ( $matchcount == 0 ) {
301 } elseif ( count($matches) == 1 ) {
304 # multiple matched parts (variable match); some will be empty because of synonyms
305 # the variable will be the second non-empty one so remove any blank elements and re-sort the indices
306 $matches = array_values(array_filter($matches));
313 * Returns true if the text matches the word, and alters the
314 * input string, removing all instances of the word
316 function matchAndRemove( &$text ) {
317 global $wgMagicFound;
318 $wgMagicFound = false;
319 $text = preg_replace_callback( $this->getRegex(), 'pregRemoveAndRecord', $text );
320 return $wgMagicFound;
323 function matchStartAndRemove( &$text ) {
324 global $wgMagicFound;
325 $wgMagicFound = false;
326 $text = preg_replace_callback( $this->getRegexStart(), 'pregRemoveAndRecord', $text );
327 return $wgMagicFound;
332 * Replaces the word with something else
334 function replace( $replacement, $subject, $limit=-1 ) {
335 $res = preg_replace( $this->getRegex(), wfRegexReplacement( $replacement ), $subject, $limit );
336 $this->mModified
= !($res === $subject);
341 * Variable handling: {{SUBST:xxx}} style words
342 * Calls back a function to determine what to replace xxx with
343 * Input word must contain $1
345 function substituteCallback( $text, $callback ) {
346 $res = preg_replace_callback( $this->getVariableRegex(), $callback, $text );
347 $this->mModified
= !($res === $text);
352 * Matches the word, where $1 is a wildcard
354 function getVariableRegex() {
355 if ( $this->mVariableRegex
== '' ) {
358 return $this->mVariableRegex
;
362 * Matches the entire string, where $1 is a wildcard
364 function getVariableStartToEndRegex() {
365 if ( $this->mVariableStartToEndRegex
== '' ) {
368 return $this->mVariableStartToEndRegex
;
372 * Accesses the synonym list directly
374 function getSynonym( $i ) {
375 return $this->mSynonyms
[$i];
379 * Returns true if the last call to replace() or substituteCallback()
380 * returned a modified text, otherwise false.
382 function getWasModified(){
383 return $this->mModified
;
387 * $magicarr is an associative array of (magic word ID => replacement)
388 * This method uses the php feature to do several replacements at the same time,
389 * thereby gaining some efficiency. The result is placed in the out variable
390 * $result. The return value is true if something was replaced.
393 function replaceMultiple( $magicarr, $subject, &$result ){
396 foreach( $magicarr as $id => $replacement ){
397 $mw = MagicWord
::get( $id );
398 $search[] = $mw->getRegex();
399 $replace[] = $replacement;
402 $result = preg_replace( $search, $replace, $subject );
403 return !($result === $subject);
407 * Adds all the synonyms of this MagicWord to an array, to allow quick
408 * lookup in a list of magic words
410 function addToArray( &$array, $value ) {
411 foreach ( $this->mSynonyms
as $syn ) {
412 $array[$syn] = $value;
418 * Used in matchAndRemove()
421 function pregRemoveAndRecord( $match ) {
422 global $wgMagicFound;
423 $wgMagicFound = true;