49 public function add( $name ): void {
50 $this->names[] = $name;
51 $this->hash = $this->baseRegex = $this->regex =
null;
60 if ( $this->hash === null ) {
61 $this->hash = [ 0 => [], 1 => [] ];
62 foreach ( $this->names as $name ) {
63 $magic = $this->factory->get( $name );
64 $case = intval( $magic->isCaseSensitive() );
65 foreach ( $magic->getSynonyms() as $syn ) {
67 $syn = $this->factory->getContentLanguage()->lc( $syn );
69 $this->hash[$case][$syn] = $name;
87 public function getBaseRegex(
bool $capture =
true,
string $delimiter =
'/' ): array {
88 if ( $capture && $delimiter ===
'/' && $this->baseRegex !== null ) {
89 return $this->baseRegex;
91 $regex = [ 0 => [], 1 => [] ];
92 foreach ( $this->names as $name ) {
93 $magic = $this->factory->get( $name );
94 $case = $magic->isCaseSensitive() ? 1 : 0;
95 foreach ( $magic->getSynonyms() as $i => $syn ) {
98 $it = strtr( $i,
'0123456789',
'abcdefghij' );
99 $groupName = $it .
'_' . $name;
100 $group =
'(?P<' . $groupName .
'>' . preg_quote( $syn, $delimiter ) .
')';
101 $regex[$case][] = $group;
103 $regex[$case][] = preg_quote( $syn, $delimiter );
107 '@phan-var array<int,string[]> $regex';
108 foreach ( $regex as $case => &$re ) {
109 $re = count( $re ) ? implode(
'|', $re ) :
'(?!)';
114 '@phan-var array<int,string> $regex';
116 if ( $capture && $delimiter ===
'/' ) {
117 $this->baseRegex = $regex;
127 private function getRegex(): array {
128 if ( $this->regex === null ) {
130 $base = $this->getBaseRegex(
true,
'/' );
131 foreach ( $base as $case => $re ) {
132 $this->regex[$case] =
"/$re/JS";
136 $this->regex[0] .=
'u';
146 private function getRegexStart(): array {
148 $base = $this->getBaseRegex(
true,
'/' );
149 foreach ( $base as $case => $re ) {
150 $newRegex[$case] =
"/^(?:$re)/JS";
163 private function getVariableStartToEndRegex(): array {
165 $base = $this->getBaseRegex(
true,
'/' );
166 foreach ( $base as $case => $re ) {
167 $newRegex[$case] = str_replace(
'\$1',
'(.*?)',
"/^(?:$re)$/JS" );
190 private function parseMatch( array
$matches ): array {
192 foreach (
$matches as $key => $match ) {
193 if ( $magicName !==
null ) {
199 return [ $magicName, $match,
$matches[$key + 1] ?? false ];
202 if ( $match !==
'' && $key !== 0 ) {
203 $parts = explode(
'_', $key, 2 );
204 if ( !isset( $parts[1] ) ) {
205 throw new LogicException(
'Unexpected group name' );
207 $magicName = $parts[1];
210 throw new LogicException(
'Unexpected $m array with no match' );
221 $regexes = $this->getVariableStartToEndRegex();
222 foreach ( $regexes as $regex ) {
224 if ( preg_match( $regex, $text, $m ) ) {
225 [ $id, $alias, $param ] = $this->parseMatch( $m );
226 return [ $id, $param ];
229 return [
false, false ];
240 $hash = $this->getHash();
241 if ( isset( $hash[1][$text] ) ) {
242 return $hash[1][$text];
244 $lc = $this->factory->getContentLanguage()->lc( $text );
245 return $hash[0][$lc] ??
false;
263 $regexes = $this->getRegex();
264 $res = preg_replace_callback( $regexes,
function ( $m ) use ( &$found, $returnAlias ) {
265 [ $name, $alias, $param ] = $this->parseMatch( $m );
266 $found[$name] = $returnAlias ? $alias : $param;
270 if ( $res !==
null ) {
287 $regexes = $this->getRegexStart();
288 foreach ( $regexes as $regex ) {
289 if ( preg_match( $regex, $text, $m ) ) {
290 [ $id, ] = $this->parseMatch( $m );
291 if ( strlen( $m[0] ) >= strlen( $text ) ) {
294 $text = substr( $text, strlen( $m[0] ) );
if(!defined('MW_SETUP_CALLBACK'))