MediaWiki  master
MagicWord.php
Go to the documentation of this file.
1 <?php
25 
57 class MagicWord {
61  public $mId;
62 
64  public $mSynonyms;
65 
68 
70  private $mRegex = '';
71 
73  private $mRegexStart = '';
74 
76  private $mRegexStartToEnd = '';
77 
79  private $mBaseRegex = '';
80 
82  private $mVariableRegex = '';
83 
86 
88  private $mModified = false;
89 
91  private $mFound = false;
92 
94  private $contLang;
95 
108  public function __construct( $id = null, $syn = [], $cs = false, Language $contLang = null ) {
109  $this->mId = $id;
110  $this->mSynonyms = (array)$syn;
111  $this->mCaseSensitive = $cs;
112  $this->contLang = $contLang ?: MediaWikiServices::getInstance()->getContentLanguage();
113  }
114 
121  public function load( $id ) {
122  $this->mId = $id;
123  $this->contLang->getMagic( $this );
124  if ( !$this->mSynonyms ) {
125  $this->mSynonyms = [ 'brionmademeputthishere' ];
126  throw new MWException( "Error: invalid magic word '$id'" );
127  }
128  }
129 
134  public function initRegex() {
135  // Sort the synonyms by length, descending, so that the longest synonym
136  // matches in precedence to the shortest
137  $synonyms = $this->mSynonyms;
138  usort( $synonyms, [ $this, 'compareStringLength' ] );
139 
140  $escSyn = [];
141  foreach ( $synonyms as $synonym ) {
142  // In case a magic word contains /, like that's going to happen;)
143  $escSyn[] = preg_quote( $synonym, '/' );
144  }
145  $this->mBaseRegex = implode( '|', $escSyn );
146 
147  $case = $this->mCaseSensitive ? '' : 'iu';
148  $this->mRegex = "/{$this->mBaseRegex}/{$case}";
149  $this->mRegexStart = "/^(?:{$this->mBaseRegex})/{$case}";
150  $this->mRegexStartToEnd = "/^(?:{$this->mBaseRegex})$/{$case}";
151  $this->mVariableRegex = str_replace( "\\$1", "(.*?)", $this->mRegex );
152  $this->mVariableStartToEndRegex = str_replace( "\\$1", "(.*?)",
153  "/^(?:{$this->mBaseRegex})$/{$case}" );
154  }
155 
166  public function compareStringLength( $s1, $s2 ) {
167  $l1 = strlen( $s1 );
168  $l2 = strlen( $s2 );
169  return $l2 <=> $l1; // descending
170  }
171 
177  public function getRegex() {
178  if ( $this->mRegex == '' ) {
179  $this->initRegex();
180  }
181  return $this->mRegex;
182  }
183 
191  public function getRegexCase() {
192  if ( $this->mRegex === '' ) {
193  $this->initRegex();
194  }
195 
196  return $this->mCaseSensitive ? '' : 'iu';
197  }
198 
204  public function getRegexStart() {
205  if ( $this->mRegex == '' ) {
206  $this->initRegex();
207  }
208  return $this->mRegexStart;
209  }
210 
217  public function getRegexStartToEnd() {
218  if ( $this->mRegexStartToEnd == '' ) {
219  $this->initRegex();
220  }
222  }
223 
229  public function getBaseRegex() {
230  if ( $this->mRegex == '' ) {
231  $this->initRegex();
232  }
233  return $this->mBaseRegex;
234  }
235 
243  public function match( $text ) {
244  return (bool)preg_match( $this->getRegex(), $text );
245  }
246 
254  public function matchStart( $text ) {
255  return (bool)preg_match( $this->getRegexStart(), $text );
256  }
257 
266  public function matchStartToEnd( $text ) {
267  return (bool)preg_match( $this->getRegexStartToEnd(), $text );
268  }
269 
280  public function matchVariableStartToEnd( $text ) {
281  $matches = [];
282  $matchcount = preg_match( $this->getVariableStartToEndRegex(), $text, $matches );
283  if ( $matchcount == 0 ) {
284  return null;
285  } else {
286  # multiple matched parts (variable match); some will be empty because of
287  # synonyms. The variable will be the second non-empty one so remove any
288  # blank elements and re-sort the indices.
289  # See also T8526
290 
291  $matches = array_values( array_filter( $matches ) );
292 
293  if ( count( $matches ) == 1 ) {
294  return $matches[0];
295  } else {
296  return $matches[1];
297  }
298  }
299  }
300 
309  public function matchAndRemove( &$text ) {
310  $this->mFound = false;
311  $text = preg_replace_callback(
312  $this->getRegex(),
313  [ $this, 'pregRemoveAndRecord' ],
314  $text
315  );
316 
317  return $this->mFound;
318  }
319 
324  public function matchStartAndRemove( &$text ) {
325  $this->mFound = false;
326  $text = preg_replace_callback(
327  $this->getRegexStart(),
328  [ $this, 'pregRemoveAndRecord' ],
329  $text
330  );
331 
332  return $this->mFound;
333  }
334 
340  public function pregRemoveAndRecord() {
341  $this->mFound = true;
342  return '';
343  }
344 
354  public function replace( $replacement, $subject, $limit = -1 ) {
355  $res = preg_replace(
356  $this->getRegex(),
357  StringUtils::escapeRegexReplacement( $replacement ),
358  $subject,
359  $limit
360  );
361  $this->mModified = $res !== $subject;
362  return $res;
363  }
364 
375  public function substituteCallback( $text, $callback ) {
376  $res = preg_replace_callback( $this->getVariableRegex(), $callback, $text );
377  $this->mModified = $res !== $text;
378  return $res;
379  }
380 
386  public function getVariableRegex() {
387  if ( $this->mVariableRegex == '' ) {
388  $this->initRegex();
389  }
390  return $this->mVariableRegex;
391  }
392 
398  public function getVariableStartToEndRegex() {
399  if ( $this->mVariableStartToEndRegex == '' ) {
400  $this->initRegex();
401  }
403  }
404 
412  public function getSynonym( $i ) {
413  return $this->mSynonyms[$i];
414  }
415 
419  public function getSynonyms() {
420  return $this->mSynonyms;
421  }
422 
429  public function getWasModified() {
430  return $this->mModified;
431  }
432 
440  public function addToArray( &$array, $value ) {
441  foreach ( $this->mSynonyms as $syn ) {
442  $array[$this->contLang->lc( $syn )] = $value;
443  }
444  }
445 
449  public function isCaseSensitive() {
450  return $this->mCaseSensitive;
451  }
452 
456  public function getId() {
457  return $this->mId;
458  }
459 }
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:130
MagicWord\$contLang
Language $contLang
Definition: MagicWord.php:94
MagicWord\substituteCallback
substituteCallback( $text, $callback)
Variable handling: {{SUBST:xxx}} style words Calls back a function to determine what to replace xxx w...
Definition: MagicWord.php:375
MagicWord\matchVariableStartToEnd
matchVariableStartToEnd( $text)
Returns NULL if there's no match, the value of $1 otherwise The return code is the matched string,...
Definition: MagicWord.php:280
MagicWord\getSynonyms
getSynonyms()
Definition: MagicWord.php:419
MagicWord\load
load( $id)
Initialises this object with an ID.
Definition: MagicWord.php:121
MagicWord\isCaseSensitive
isCaseSensitive()
Definition: MagicWord.php:449
MagicWord\getRegexStartToEnd
getRegexStartToEnd()
Gets a regex matching the word from start to end of a string.
Definition: MagicWord.php:217
MagicWord\$mRegex
string $mRegex
Definition: MagicWord.php:70
StringUtils\escapeRegexReplacement
static escapeRegexReplacement( $string)
Escape a string to make it suitable for inclusion in a preg_replace() replacement parameter.
Definition: StringUtils.php:343
MagicWord\getRegex
getRegex()
Gets a regex representing matching the word.
Definition: MagicWord.php:177
MagicWord\$mRegexStartToEnd
string $mRegexStartToEnd
Definition: MagicWord.php:76
MagicWord\__construct
__construct( $id=null, $syn=[], $cs=false, Language $contLang=null)
#-
Definition: MagicWord.php:108
MagicWord\getId
getId()
Definition: MagicWord.php:456
MagicWord\$mBaseRegex
string $mBaseRegex
Definition: MagicWord.php:79
$res
$res
Definition: testCompression.php:54
MagicWord\$mSynonyms
string[] $mSynonyms
Definition: MagicWord.php:64
MagicWord\initRegex
initRegex()
Preliminary initialisation.
Definition: MagicWord.php:134
MagicWord\replace
replace( $replacement, $subject, $limit=-1)
Replaces the word with something else.
Definition: MagicWord.php:354
MagicWord\matchStartToEnd
matchStartToEnd( $text)
Returns true if the text matched the word.
Definition: MagicWord.php:266
MagicWord\$mId
string $mId
#-
Definition: MagicWord.php:61
MWException
MediaWiki exception.
Definition: MWException.php:26
$matches
$matches
Definition: NoLocalSettings.php:24
MagicWord\getWasModified
getWasModified()
Returns true if the last call to replace() or substituteCallback() returned a modified text,...
Definition: MagicWord.php:429
MagicWord\$mVariableStartToEndRegex
string $mVariableStartToEndRegex
Definition: MagicWord.php:85
MagicWord\$mModified
bool $mModified
Definition: MagicWord.php:88
MagicWord\$mFound
bool $mFound
Definition: MagicWord.php:91
MagicWord\pregRemoveAndRecord
pregRemoveAndRecord()
Used in matchAndRemove()
Definition: MagicWord.php:340
MagicWord
This class encapsulates "magic words" such as "#redirect", NOTOC, etc.
Definition: MagicWord.php:57
MagicWord\getRegexStart
getRegexStart()
Gets a regex matching the word, if it is at the string start.
Definition: MagicWord.php:204
MagicWord\getBaseRegex
getBaseRegex()
regex without the slashes and what not
Definition: MagicWord.php:229
MagicWord\matchStartAndRemove
matchStartAndRemove(&$text)
Definition: MagicWord.php:324
MagicWord\getVariableRegex
getVariableRegex()
Matches the word, where $1 is a wildcard.
Definition: MagicWord.php:386
MagicWord\$mCaseSensitive
bool $mCaseSensitive
Definition: MagicWord.php:67
MagicWord\addToArray
addToArray(&$array, $value)
Adds all the synonyms of this MagicWord to an array, to allow quick lookup in a list of magic words.
Definition: MagicWord.php:440
MagicWord\$mRegexStart
string $mRegexStart
Definition: MagicWord.php:73
MagicWord\$mVariableRegex
string $mVariableRegex
Definition: MagicWord.php:82
MagicWord\matchStart
matchStart( $text)
Returns true if the text starts with the word.
Definition: MagicWord.php:254
MagicWord\getRegexCase
getRegexCase()
Gets the regexp case modifier to use, i.e.
Definition: MagicWord.php:191
MagicWord\getVariableStartToEndRegex
getVariableStartToEndRegex()
Matches the entire string, where $1 is a wildcard.
Definition: MagicWord.php:398
MagicWord\getSynonym
getSynonym( $i)
Accesses the synonym list directly.
Definition: MagicWord.php:412
MagicWord\compareStringLength
compareStringLength( $s1, $s2)
A comparison function that returns -1, 0 or 1 depending on whether the first string is longer,...
Definition: MagicWord.php:166
MagicWord\matchAndRemove
matchAndRemove(&$text)
Returns true if the text matches the word, and alters the input string, removing all instances of the...
Definition: MagicWord.php:309
MagicWord\match
match( $text)
Returns true if the text contains the word.
Definition: MagicWord.php:243
Language
Internationalisation code.
Definition: Language.php:39