/**
  * Loads our version data from the special page.
  * These are defined in the form: {{#version:name|status}}
  *
  * There is a special parser hook to handle outputting this in a clean form when viewing the page.
  * This updates our internal static maps and lists of versions (total and by each state) from this page.
  * The first call will load from the file, subsequent will just return the stored list (unless $reload=true).
  *
  * The list created does NOT simply contain all versions in the defined page
  * it is dependent upon the GROUPS to which the current user belongs.
  *
  *	- Anonymous (all):  Released ONLY.
  *  - Customers/users:  Released AND preview ONLY.
  *  - Emp/Author:		All.
  *
  * @static
  * @param boolean $reload True to force reload from the wiki page.
  * @return array LIST of all versions (not map!).
  * 
  * TODO: Cache this?
  */
 public static function LoadVersionsForProduct($productName, $reload = false, $ignorePermissions = false)
 {
     global $wgPonyDocsEmployeeGroup, $wgUser;
     /**
      * If we have content in our list, just return that unless $reload is true.
      */
     if (isset(self::$sVersionList[$productName]) && !$reload) {
         return self::$sVersionList[$productName];
     }
     $groups = $wgUser->getGroups();
     self::$sVersionList[$productName] = array();
     $article = new Article(Title::newFromText(PONYDOCS_DOCUMENTATION_NAMESPACE_NAME . ':' . $productName . PONYDOCS_PRODUCTVERSION_SUFFIX), 0);
     $content = $article->getContent();
     if (!$content) {
         /**
          * There is no versions file found -- just return.
          */
         return array();
     }
     /**
      * Parse our versions content which should be of the form:
      * {{#version:name|status}}
      * ...
      * Validate 'STATUS' is valid; if it is not, we ignore it.  THis will populate
      * $this->versionsList (and others) properly and return it.
      */
     $authProductGroup = PonyDocsExtension::getDerivedGroup(PonyDocsExtension::ACCESS_GROUP_PRODUCT, $productName);
     $authPreviewGroup = PonyDocsExtension::getDerivedGroup(PonyDocsExtension::ACCESS_GROUP_VERSION, $productName);
     $versions = explode("\n", $content);
     $currentGroup = NULL;
     $currentGroupMessage = NULL;
     foreach ($versions as $v) {
         // versiongroup
         if (preg_match('/{{#versiongroup:\\s*([^}]*)\\s*}}/i', $v)) {
             $matches = preg_replace('/{{#versiongroup:\\s*([^}]*)\\s*}}/i', '\\1', $v);
             $pcs = explode('|', trim($matches), 2);
             if (count($pcs) === 1 && trim($pcs[0]) === '') {
                 // reset group and message
                 $currentGroup = NULL;
                 $currentGroupMessage = NULL;
             } else {
                 // set group name and message, if present
                 $currentGroup = $pcs[0];
                 if (isset($pcs[1])) {
                     $currentGroupMessage = $pcs[1];
                 }
             }
             // version (if it's neither versiongroup nor version it's a blank line or other garbage and we can skip it)
         } elseif (preg_match('/{{#version:/', $v)) {
             $matches = preg_replace('/{{#version:\\s*(.*)\\s*}}/i', '\\1', $v);
             $pcs = explode('|', trim($matches), 2);
             $pVersion = new PonyDocsProductVersion($productName, $pcs[0], $pcs[1]);
             if (!$pVersion->isValid()) {
                 continue;
             }
             if (isset($currentGroup)) {
                 $pVersion->setVersionGroup($currentGroup, $currentGroupMessage);
             }
             if (!strcasecmp($pcs[1], 'UNRELEASED')) {
                 if (in_array($wgPonyDocsEmployeeGroup, $groups) || in_array($authProductGroup, $groups) || PonyDocsCrawlerPassthrough::isAllowedCrawler() || $ignorePermissions) {
                     self::$sVersionList[$productName][] = self::$sVersionListUnreleased[$productName][] = self::$sVersionMap[$productName][$pcs[0]] = self::$sVersionMapUnreleased[$productName][$pcs[0]] = $pVersion;
                 }
             } elseif (!strcasecmp($pcs[1], 'RELEASED')) {
                 self::$sVersionList[$productName][] = self::$sVersionListReleased[$productName][] = self::$sVersionMap[$productName][$pcs[0]] = self::$sVersionMapReleased[$productName][$pcs[0]] = $pVersion;
             } elseif (!strcasecmp($pcs[1], 'PREVIEW')) {
                 if (in_array($wgPonyDocsEmployeeGroup, $groups) || in_array($authProductGroup, $groups) || in_array($authPreviewGroup, $groups) || PonyDocsCrawlerPassthrough::isAllowedCrawler() || $ignorePermissions) {
                     self::$sVersionList[$productName][] = self::$sVersionListPreview[$productName][] = self::$sVersionMap[$productName][$pcs[0]] = self::$sVersionMapPreview[$productName][$pcs[0]] = $pVersion;
                 }
             }
         }
     }
     return self::$sVersionList[$productName];
 }