MediaWiki REL1_39
MagicWord.php
Go to the documentation of this file.
1<?php
25
60class MagicWord {
64 public $mId;
65
67 public $mSynonyms;
68
71
73 private $mRegex = '';
74
76 private $mRegexStart = '';
77
79 private $mRegexStartToEnd = '';
80
82 private $mBaseRegex = '';
83
85 private $mVariableRegex = '';
86
88 private $mVariableStartToEndRegex = '';
89
91 private $mModified = false;
92
94 private $mFound = false;
95
97 private $contLang;
98
111 public function __construct( $id = null, $syn = [], $cs = false, Language $contLang = null ) {
112 $this->mId = $id;
113 $this->mSynonyms = (array)$syn;
114 $this->mCaseSensitive = $cs;
115 $this->contLang = $contLang ?: MediaWikiServices::getInstance()->getContentLanguage();
116 }
117
124 public function load( $id ) {
125 $this->mId = $id;
126 $this->contLang->getMagic( $this );
127 if ( !$this->mSynonyms ) {
128 $this->mSynonyms = [ 'brionmademeputthishere' ];
129 throw new MWException( "Error: invalid magic word '$id'" );
130 }
131 }
132
137 public function initRegex() {
138 // Sort the synonyms by length, descending, so that the longest synonym
139 // matches in precedence to the shortest
140 $synonyms = $this->mSynonyms;
141 usort( $synonyms, [ $this, 'compareStringLength' ] );
142
143 $escSyn = [];
144 foreach ( $synonyms as $synonym ) {
145 // In case a magic word contains /, like that's going to happen;)
146 $escSyn[] = preg_quote( $synonym, '/' );
147 }
148 $this->mBaseRegex = implode( '|', $escSyn );
149
150 $case = $this->mCaseSensitive ? '' : 'iu';
151 $this->mRegex = "/{$this->mBaseRegex}/{$case}";
152 $this->mRegexStart = "/^(?:{$this->mBaseRegex})/{$case}";
153 $this->mRegexStartToEnd = "/^(?:{$this->mBaseRegex})$/{$case}";
154 $this->mVariableRegex = str_replace( "\\$1", "(.*?)", $this->mRegex );
155 $this->mVariableStartToEndRegex = str_replace( "\\$1", "(.*?)",
156 "/^(?:{$this->mBaseRegex})$/{$case}" );
157 }
158
169 public function compareStringLength( $s1, $s2 ) {
170 $l1 = strlen( $s1 );
171 $l2 = strlen( $s2 );
172 return $l2 <=> $l1; // descending
173 }
174
180 public function getRegex() {
181 if ( $this->mRegex == '' ) {
182 $this->initRegex();
183 }
184 return $this->mRegex;
185 }
186
194 public function getRegexCase() {
195 if ( $this->mRegex === '' ) {
196 $this->initRegex();
197 }
198
199 return $this->mCaseSensitive ? '' : 'iu';
200 }
201
207 public function getRegexStart() {
208 if ( $this->mRegex == '' ) {
209 $this->initRegex();
210 }
211 return $this->mRegexStart;
212 }
213
220 public function getRegexStartToEnd() {
221 if ( $this->mRegexStartToEnd == '' ) {
222 $this->initRegex();
223 }
224 return $this->mRegexStartToEnd;
225 }
226
232 public function getBaseRegex() {
233 if ( $this->mRegex == '' ) {
234 $this->initRegex();
235 }
236 return $this->mBaseRegex;
237 }
238
246 public function match( $text ) {
247 return (bool)preg_match( $this->getRegex(), $text );
248 }
249
257 public function matchStart( $text ) {
258 return (bool)preg_match( $this->getRegexStart(), $text );
259 }
260
269 public function matchStartToEnd( $text ) {
270 return (bool)preg_match( $this->getRegexStartToEnd(), $text );
271 }
272
283 public function matchVariableStartToEnd( $text ) {
284 $matches = [];
285 $matchcount = preg_match( $this->getVariableStartToEndRegex(), $text, $matches );
286 if ( $matchcount == 0 ) {
287 return null;
288 } else {
289 # multiple matched parts (variable match); some will be empty because of
290 # synonyms. The variable will be the second non-empty one so remove any
291 # blank elements and re-sort the indices.
292 # See also T8526
293
294 $matches = array_values( array_filter( $matches ) );
295
296 if ( count( $matches ) == 1 ) {
297 return $matches[0];
298 } else {
299 return $matches[1];
300 }
301 }
302 }
303
312 public function matchAndRemove( &$text ) {
313 $this->mFound = false;
314 $text = preg_replace_callback(
315 $this->getRegex(),
316 [ $this, 'pregRemoveAndRecord' ],
317 $text
318 );
319
320 return $this->mFound;
321 }
322
327 public function matchStartAndRemove( &$text ) {
328 $this->mFound = false;
329 $text = preg_replace_callback(
330 $this->getRegexStart(),
331 [ $this, 'pregRemoveAndRecord' ],
332 $text
333 );
334
335 return $this->mFound;
336 }
337
343 public function pregRemoveAndRecord() {
344 $this->mFound = true;
345 return '';
346 }
347
357 public function replace( $replacement, $subject, $limit = -1 ) {
358 $res = preg_replace(
359 $this->getRegex(),
361 $subject,
362 $limit
363 );
364 $this->mModified = $res !== $subject;
365 return $res;
366 }
367
378 public function substituteCallback( $text, $callback ) {
379 $res = preg_replace_callback( $this->getVariableRegex(), $callback, $text );
380 $this->mModified = $res !== $text;
381 return $res;
382 }
383
389 public function getVariableRegex() {
390 if ( $this->mVariableRegex == '' ) {
391 $this->initRegex();
392 }
393 return $this->mVariableRegex;
394 }
395
401 public function getVariableStartToEndRegex() {
402 if ( $this->mVariableStartToEndRegex == '' ) {
403 $this->initRegex();
404 }
405 return $this->mVariableStartToEndRegex;
406 }
407
415 public function getSynonym( $i ) {
416 return $this->mSynonyms[$i];
417 }
418
422 public function getSynonyms() {
423 return $this->mSynonyms;
424 }
425
432 public function getWasModified() {
433 return $this->mModified;
434 }
435
443 public function addToArray( &$array, $value ) {
444 foreach ( $this->mSynonyms as $syn ) {
445 $array[$this->contLang->lc( $syn )] = $value;
446 }
447 }
448
452 public function isCaseSensitive() {
454 }
455
459 public function getId() {
460 return $this->mId;
461 }
462}
Base class for language-specific code.
Definition Language.php:53
MediaWiki exception.
This class encapsulates "magic words" such as "#redirect", NOTOC, etc.
Definition MagicWord.php:60
getVariableRegex()
Matches the word, where $1 is a wildcard.
compareStringLength( $s1, $s2)
A comparison function that returns -1, 0 or 1 depending on whether the first string is longer,...
initRegex()
Preliminary initialisation.
getWasModified()
Returns true if the last call to replace() or substituteCallback() returned a modified text,...
replace( $replacement, $subject, $limit=-1)
Replaces the word with something else.
getVariableStartToEndRegex()
Matches the entire string, where $1 is a wildcard.
getRegexStartToEnd()
Gets a regex matching the word from start to end of a string.
__construct( $id=null, $syn=[], $cs=false, Language $contLang=null)
#-
bool $mCaseSensitive
Definition MagicWord.php:70
isCaseSensitive()
substituteCallback( $text, $callback)
Variable handling: {{SUBST:xxx}} style words Calls back a function to determine what to replace xxx w...
getBaseRegex()
regex without the slashes and what not
matchStartAndRemove(&$text)
getRegexStart()
Gets a regex matching the word, if it is at the string start.
string[] $mSynonyms
Definition MagicWord.php:67
matchStart( $text)
Returns true if the text starts with the word.
getSynonym( $i)
Accesses the synonym list directly.
getRegex()
Gets a regex representing matching the word.
load( $id)
Initialises this object with an ID.
matchVariableStartToEnd( $text)
Returns NULL if there's no match, the value of $1 otherwise The return code is the matched string,...
getRegexCase()
Gets the regexp case modifier to use, i.e.
addToArray(&$array, $value)
Adds all the synonyms of this MagicWord to an array, to allow quick lookup in a list of magic words.
matchStartToEnd( $text)
Returns true if the text matched the word.
string $mId
#-
Definition MagicWord.php:64
match( $text)
Returns true if the text contains the word.
pregRemoveAndRecord()
Used in matchAndRemove()
matchAndRemove(&$text)
Returns true if the text matches the word, and alters the input string, removing all instances of the...
Service locator for MediaWiki core services.
static escapeRegexReplacement( $string)
Escape a string to make it suitable for inclusion in a preg_replace() replacement parameter.