52 $this->names = $names;
53 $this->factory = $factory ?: MediaWikiServices::getInstance()->getMagicWordFactory();
61 public function add( $name ) {
62 $this->names[] = $name;
63 $this->hash = $this->baseRegex = $this->regex =
null;
72 $this->names = array_merge( $this->names, array_values( $names ) );
73 $this->hash = $this->baseRegex = $this->regex =
null;
81 if ( $this->hash ===
null ) {
82 $this->hash = [ 0 => [], 1 => [] ];
83 foreach ( $this->names as $name ) {
84 $magic = $this->factory->get( $name );
85 $case = intval( $magic->isCaseSensitive() );
86 foreach ( $magic->getSynonyms() as $syn ) {
88 $syn = $this->factory->getContentLanguage()->lc( $syn );
90 $this->hash[$case][$syn] = $name;
107 public function getBaseRegex(
bool $capture =
true,
string $delimiter =
'/' ): array {
108 if ( $capture && $delimiter ===
'/' && $this->baseRegex !== null ) {
109 return $this->baseRegex;
111 $regex = [ 0 => [], 1 => [] ];
113 foreach ( $this->names as $name ) {
114 $magic = $this->factory->get( $name );
115 $case = $magic->isCaseSensitive() ? 1 : 0;
116 foreach ( $magic->getSynonyms() as $i => $syn ) {
119 $it = strtr( $i,
'0123456789',
'abcdefghij' );
120 $groupName = $it .
'_' . $name;
121 $group =
'(?P<' . $groupName .
'>' . preg_quote( $syn, $delimiter ) .
')';
123 if ( isset( $allGroups[$groupName] ) ) {
125 __METHOD__ .
': duplicate internal name in magic word array: ' . $name
128 $allGroups[$groupName] =
true;
129 $regex[$case][] = $group;
131 $regex[$case][] = preg_quote( $syn, $delimiter );
135 '@phan-var array<int,string[]> $regex';
136 foreach ( $regex as $case => &$re ) {
137 $re = count( $re ) ? implode(
'|', $re ) :
'(?!)';
142 '@phan-var array<int,string> $regex';
144 if ( $capture && $delimiter ===
'/' ) {
145 $this->baseRegex = $regex;
156 if ( $this->regex ===
null ) {
158 $base = $this->getBaseRegex(
true,
'/' );
159 foreach (
$base as $case => $re ) {
160 $this->regex[$case] =
"/{$re}/S";
164 $this->regex[0] .=
'u';
177 return str_replace(
"\\$1",
"(.*?)", $this->getRegex() );
188 $base = $this->getBaseRegex(
true,
'/' );
189 foreach (
$base as $case => $re ) {
190 $newRegex[$case] =
"/^(?:{$re})/S";
206 $base = $this->getBaseRegex(
true,
'/' );
207 foreach (
$base as $case => $re ) {
208 $newRegex[$case] = str_replace(
"\\$1",
"(.*?)",
"/^(?:{$re})$/S" );
233 private function parseMatch( array
$matches ): array {
235 foreach (
$matches as $key => $match ) {
236 if ( $magicName !==
null ) {
242 return [ $magicName, $match,
$matches[$key + 1] ?? false ];
245 if ( $match !==
'' && $key !== 0 ) {
246 $parts = explode(
'_', $key, 2 );
247 if ( !isset( $parts[1] ) ) {
249 throw new MWException( __METHOD__ .
': Unexpected group name' );
251 $magicName = $parts[1];
255 throw new MWException( __METHOD__ .
': parameter not found' );
269 $regexes = $this->getVariableStartToEndRegex();
270 foreach ( $regexes as $regex ) {
272 if ( preg_match( $regex, $text, $m ) ) {
273 [ $id, $alias, $param ] = $this->parseMatch( $m );
274 return [ $id, $param ];
277 return [
false, false ];
289 $hash = $this->getHash();
290 if ( isset( $hash[1][$text] ) ) {
291 return $hash[1][$text];
293 $lc = $this->factory->getContentLanguage()->lc( $text );
294 return $hash[0][$lc] ??
false;
309 $regexes = $this->getRegex();
310 $res = preg_replace_callback( $regexes,
function ( $m ) use ( &$found, $returnAlias ) {
311 [ $name, $alias, $param ] = $this->parseMatch( $m );
312 $found[$name] = $returnAlias ? $alias : $param;
316 if (
$res !==
null ) {
333 $regexes = $this->getRegexStart();
334 foreach ( $regexes as $regex ) {
335 if ( preg_match( $regex, $text, $m ) ) {
336 list( $id, ) = $this->parseMatch( $m );
337 if ( strlen( $m[0] ) >= strlen( $text ) ) {
340 $text = substr( $text, strlen( $m[0] ) );
if(!defined('MW_SETUP_CALLBACK'))
The persistent session ID (if any) loaded at startup.
Class for handling an array of magic words.
getBaseRegex(bool $capture=true, string $delimiter='/')
Get the base regex.
matchVariableStartToEnd( $text)
Match some text, with parameter capture Returns an array with the magic word name in the first elemen...
add( $name)
Add a magic word by name.
getVariableRegex()
Get a regex for matching variables with parameters.
__construct( $names=[], MagicWordFactory $factory=null)
matchStartToEnd( $text)
Match some text, without parameter capture Returns the magic word name, or false if there was no capt...
matchAndRemove(&$text, bool $returnAlias=false)
Returns an associative array, ID => param value, for all items that match Removes the matched items f...
getRegexStart()
Get a regex anchored to the start of the string that does not match parameters.
matchStartAndRemove(&$text)
Return the ID of the magic word at the start of $text, and remove the prefix from $text.
getRegex()
Get an unanchored regex that does not match parameters.
getVariableStartToEndRegex()
Get an anchored regex for matching variables with parameters.
getHash()
Get a 2-d hashtable for this array.
addArray( $names)
Add a number of magic words by name.
A factory that stores information about MagicWords, and creates them on demand with caching.