66 public function add( $name ) {
67 $this->names[] = $name;
68 $this->hash = $this->baseRegex = $this->regex =
null;
77 $this->names = array_merge( $this->names, array_values(
$names ) );
78 $this->hash = $this->baseRegex = $this->regex =
null;
86 if ( $this->hash ===
null ) {
87 $this->hash = [ 0 => [], 1 => [] ];
88 foreach ( $this->names as $name ) {
89 $magic = $this->factory->get( $name );
90 $case = intval( $magic->isCaseSensitive() );
91 foreach ( $magic->getSynonyms() as $syn ) {
93 $syn = $this->factory->getContentLanguage()->lc( $syn );
95 $this->hash[$case][$syn] = $name;
112 public function getBaseRegex(
bool $capture =
true,
string $delimiter =
'/' ): array {
113 if ( $capture && $delimiter ===
'/' && $this->baseRegex !== null ) {
114 return $this->baseRegex;
116 $regex = [ 0 => [], 1 => [] ];
118 foreach ( $this->names as $name ) {
119 $magic = $this->factory->get( $name );
120 $case = $magic->isCaseSensitive() ? 1 : 0;
121 foreach ( $magic->getSynonyms() as $i => $syn ) {
124 $it = strtr( $i,
'0123456789',
'abcdefghij' );
125 $groupName = $it .
'_' . $name;
126 $group =
'(?P<' . $groupName .
'>' . preg_quote( $syn, $delimiter ) .
')';
128 if ( isset( $allGroups[$groupName] ) ) {
130 __METHOD__ .
': duplicate internal name in magic word array: ' . $name
133 $allGroups[$groupName] =
true;
134 $regex[$case][] = $group;
136 $regex[$case][] = preg_quote( $syn, $delimiter );
140 '@phan-var array<int,string[]> $regex';
141 foreach ( $regex as $case => &$re ) {
142 $re = count( $re ) ? implode(
'|', $re ) :
'(?!)';
147 '@phan-var array<int,string> $regex';
149 if ( $capture && $delimiter ===
'/' ) {
150 $this->baseRegex = $regex;
161 if ( $this->regex ===
null ) {
163 $base = $this->getBaseRegex(
true,
'/' );
164 foreach (
$base as $case => $re ) {
165 $this->regex[$case] =
"/{$re}/S";
169 $this->regex[0] .=
'u';
183 return str_replace(
"\\$1",
"(.*?)", $this->getRegex() );
194 $base = $this->getBaseRegex(
true,
'/' );
195 foreach (
$base as $case => $re ) {
196 $newRegex[$case] =
"/^(?:{$re})/S";
212 $base = $this->getBaseRegex(
true,
'/' );
213 foreach (
$base as $case => $re ) {
214 $newRegex[$case] = str_replace(
"\\$1",
"(.*?)",
"/^(?:{$re})$/S" );
242 while ( ( $key = key( $m ) ) !==
null ) {
243 $value = current( $m );
245 if ( $key === 0 || $value ===
'' ) {
248 $parts = explode(
'_', $key, 2 );
249 if ( count( $parts ) != 2 ) {
252 throw new MWException( __METHOD__ .
': bad parameter name' );
254 [ , $magicName ] = $parts;
255 $paramValue = next( $m );
256 return [ $magicName, $paramValue ];
259 throw new MWException( __METHOD__ .
': parameter not found' );
273 $regexes = $this->getVariableStartToEndRegex();
274 foreach ( $regexes as $regex ) {
276 if ( preg_match( $regex, $text, $m ) ) {
277 return $this->parseMatch( $m );
280 return [
false, false ];
292 $hash = $this->getHash();
293 if ( isset( $hash[1][$text] ) ) {
294 return $hash[1][$text];
296 $lc = $this->factory->getContentLanguage()->lc( $text );
297 return $hash[0][$lc] ??
false;
310 $regexes = $this->getRegex();
311 foreach ( $regexes as $regex ) {
313 $res = preg_match_all( $regex, $text,
$matches, PREG_SET_ORDER );
314 if (
$res ===
false ) {
315 $error = preg_last_error();
317 $errorText = function_exists(
'preg_last_error_msg' ) ? preg_last_error_msg() :
'';
318 LoggerFactory::getInstance(
'parser' )->warning(
'preg_match_all error: {code} {errorText}', [
322 'errorText' => $errorText
325 if ( $error === PREG_BAD_UTF8_ERROR ) {
328 throw new Exception(
"preg_match_all error $error: $errorText" );
331 [ $name, $param ] = $this->parseMatch( $m );
332 $found[$name] = $param;
335 $res = preg_replace( $regex,
'', $text );
336 if (
$res ===
null ) {
337 $error = preg_last_error();
339 $errorText = function_exists(
'preg_last_error_msg' ) ? preg_last_error_msg() :
'';
340 LoggerFactory::getInstance(
'parser' )->warning(
'preg_replace error: {code} {errorText}', [
344 'errorText' => $errorText
346 throw new Exception(
"preg_replace error $error: $errorText" );
364 $regexes = $this->getRegexStart();
365 foreach ( $regexes as $regex ) {
366 if ( preg_match( $regex, $text, $m ) ) {
367 [ $id, ] = $this->parseMatch( $m );
368 if ( strlen( $m[0] ) >= strlen( $text ) ) {
371 $text = substr( $text, strlen( $m[0] ) );
380class_alias( MagicWordArray::class,
'MagicWordArray' );
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
if(!defined('MW_SETUP_CALLBACK'))
The persistent session ID (if any) loaded at startup.