Index: MediaWiki/branches/1.11/includes/MagicWord.php
===================================================================
--- MediaWiki/branches/1.11/includes/MagicWord.php	(revision 1280)
+++ MediaWiki/branches/1.11/includes/MagicWord.php	(revision 1281)
@@ -87,5 +87,4 @@
 		'subjectpagenamee',
 		'numberofusers',
-		'rawsuffix',
 		'newsectionlink',
 		'numberofpages',
@@ -388,5 +387,180 @@
 		return $this->mCaseSensitive;
 	}
+
+	function getId() {
+		return $this->mId;
+	}
 }
 
-?>
+/**
+ * Class for handling an array of magic words
+ */
+class MagicWordArray {
+	var $names = array();
+	var $hash;
+	var $baseRegex, $regex;
+
+	function __construct( $names = array() ) {
+		$this->names = $names;
+	}
+
+	/**
+	 * Add a magic word by name
+	 */
+	public function add( $name ) {
+		global $wgContLang;
+		$this->names[] = $name;
+		$this->hash = $this->baseRegex = $this->regex = null;
+	}
+
+	/**
+	 * Add a number of magic words by name
+	 */
+	public function addArray( $names ) {
+		$this->names = array_merge( $this->names, array_values( $names ) );
+		$this->hash = $this->baseRegex = $this->regex = null;
+	}
+
+	/**
+	 * Get a 2-d hashtable for this array
+	 */
+	function getHash() {
+		if ( is_null( $this->hash ) ) {
+			global $wgContLang;
+			$this->hash = array( 0 => array(), 1 => array() );
+			foreach ( $this->names as $name ) {
+				$magic = MagicWord::get( $name );
+				$case = intval( $magic->isCaseSensitive() );
+				foreach ( $magic->getSynonyms() as $syn ) {
+					if ( !$case ) {
+						$syn = $wgContLang->lc( $syn );
+					}
+					$this->hash[$case][$syn] = $name;
+				}
+			}
+		}
+		return $this->hash;
+	}
+
+	/**
+	 * Get the base regex
+	 */
+	function getBaseRegex() {
+		if ( is_null( $this->baseRegex ) ) {
+			$this->baseRegex = array( 0 => '', 1 => '' );
+			foreach ( $this->names as $name ) {
+				$magic = MagicWord::get( $name );
+				$case = intval( $magic->isCaseSensitive() );
+				foreach ( $magic->getSynonyms() as $i => $syn ) {
+					$group = "(?P<{$i}_{$name}>" . preg_quote( $syn, '/' ) . ')';
+					if ( $this->baseRegex[$case] === '' ) {
+						$this->baseRegex[$case] = $group;
+					} else {
+						$this->baseRegex[$case] .= '|' . $group;
+					}
+				}
+			}
+		}
+		return $this->baseRegex;
+	}
+
+	/**
+	 * Get an unanchored regex
+	 */
+	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
+	 */
+	function getVariableRegex() {
+		return str_replace( "\\$1", "(.*?)", $this->getRegex() );
+	}
+
+	/**
+	 * Get an anchored regex for matching variables
+	 */
+	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
+	 */
+	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' );
+		return array( false, false );
+	}
+
+	/**
+	 * 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 ) {
+		global $wgContLang;
+		$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;
+	}
+}
