+ /**
+ * Get an unanchored regex that does not match parameters
+ */
+ function getRegex() {
+ if ( is_null( $this->regex ) ) {
+ $base = $this->getBaseRegex();
+ $this->regex = array( '', '' );
+ if ( $this->baseRegex[0] !== '' ) {
+ $this->regex[0] = "/{$base[0]}/iuS";
+ }
+ if ( $this->baseRegex[1] !== '' ) {
+ $this->regex[1] = "/{$base[1]}/S";
+ }
+ }
+ return $this->regex;
+ }
+
+ /**
+ * Get a regex for matching variables with parameters
+ */
+ function getVariableRegex() {
+ return str_replace( "\\$1", "(.*?)", $this->getRegex() );
+ }
+
+ /**
+ * Get a regex anchored to the start of the string that does not match parameters
+ */
+ function getRegexStart() {
+ $base = $this->getBaseRegex();
+ $newRegex = array( '', '' );
+ if ( $base[0] !== '' ) {
+ $newRegex[0] = "/^(?:{$base[0]})/iuS";
+ }
+ if ( $base[1] !== '' ) {
+ $newRegex[1] = "/^(?:{$base[1]})/S";
+ }
+ return $newRegex;
+ }
+
+ /**
+ * Get an anchored regex for matching variables with parameters
+ */
+ function getVariableStartToEndRegex() {
+ $base = $this->getBaseRegex();
+ $newRegex = array( '', '' );
+ if ( $base[0] !== '' ) {
+ $newRegex[0] = str_replace( "\\$1", "(.*?)", "/^(?:{$base[0]})$/iuS" );
+ }
+ if ( $base[1] !== '' ) {
+ $newRegex[1] = str_replace( "\\$1", "(.*?)", "/^(?:{$base[1]})$/S" );
+ }
+ return $newRegex;
+ }
+
+ /**
+ * Parse a match array from preg_match
+ * Returns array(magic word ID, parameter value)
+ * If there is no parameter value, that element will be false.
+ */
+ function parseMatch( $m ) {
+ reset( $m );
+ while ( list( $key, $value ) = each( $m ) ) {
+ if ( $key === 0 || $value === '' ) {
+ continue;
+ }
+ $parts = explode( '_', $key, 2 );
+ if ( count( $parts ) != 2 ) {
+ // This shouldn't happen
+ // continue;
+ throw new MWException( __METHOD__ . ': bad parameter name' );
+ }
+ list( /* $synIndex */, $magicName ) = $parts;
+ $paramValue = next( $m );
+ return array( $magicName, $paramValue );
+ }
+ // This shouldn't happen either
+ throw new MWException( __METHOD__.': parameter not found' );
+ }
+
+ /**
+ * Match some text, with parameter capture
+ * Returns an array with the magic word name in the first element and the
+ * parameter in the second element.
+ * Both elements are false if there was no match.
+ */
+ public function matchVariableStartToEnd( $text ) {
+ $regexes = $this->getVariableStartToEndRegex();
+ foreach ( $regexes as $regex ) {
+ if ( $regex !== '' ) {
+ $m = false;
+ if ( preg_match( $regex, $text, $m ) ) {
+ return $this->parseMatch( $m );
+ }
+ }
+ }
+ return array( false, false );
+ }
+
+ /**
+ * Match some text, without parameter capture
+ * Returns the magic word name, or false if there was no capture
+ */
+ public function matchStartToEnd( $text ) {
+ $hash = $this->getHash();
+ if ( isset( $hash[1][$text] ) ) {
+ return $hash[1][$text];
+ }
+ global $wgContLang;
+ $lc = $wgContLang->lc( $text );
+ if ( isset( $hash[0][$lc] ) ) {
+ return $hash[0][$lc];
+ }
+ return false;
+ }
+
+ /**
+ * Returns an associative array, ID => param value, for all items that match
+ * Removes the matched items from the input string (passed by reference)
+ */
+ public function matchAndRemove( &$text ) {
+ $found = array();
+ $regexes = $this->getRegex();
+ foreach ( $regexes as $regex ) {
+ if ( $regex === '' ) {
+ continue;
+ }
+ preg_match_all( $regex, $text, $matches, PREG_SET_ORDER );
+ foreach ( $matches as $m ) {
+ list( $name, $param ) = $this->parseMatch( $m );
+ $found[$name] = $param;
+ }
+ $text = preg_replace( $regex, '', $text );
+ }
+ return $found;
+ }
+
+ /**
+ * Return the ID of the magic word at the start of $text, and remove
+ * the prefix from $text.
+ * Return false if no match found and $text is not modified.
+ * Does not match parameters.
+ */
+ public function matchStartAndRemove( &$text ) {
+ $regexes = $this->getRegexStart();
+ foreach ( $regexes as $regex ) {
+ if ( $regex === '' ) {
+ continue;
+ }
+ if ( preg_match( $regex, $text, $m ) ) {
+ list( $id, ) = $this->parseMatch( $m );
+ if ( strlen( $m[0] ) >= strlen( $text ) ) {
+ $text = '';
+ } else {
+ $text = substr( $text, strlen( $m[0] ) );
+ }
+ return $id;
+ }
+ }
+ return false;
+ }
+}