public static function onArticleFromTitle_New(&$title, &$article)
 {
     global $wgScriptPath;
     global $wgArticlePath, $wgTitle, $wgOut, $wgHooks;
     $dbr = wfGetDB(DB_SLAVE);
     /**
      * We only care about Documentation namespace for rewrites and they must contain a slash, so scan for it.
      * $matches[1] = product
      * $matches[2] = latest|version
      * $matches[3] = manual
      * $matches[4] = topic
      */
     if (!preg_match('/^' . PONYDOCS_DOCUMENTATION_NAMESPACE_NAME . '\\/([' . PONYDOCS_PRODUCT_LEGALCHARS . ']*)\\/(.*)\\/(.*)\\/(.*)$/i', $title->__toString(), $matches)) {
         return false;
     }
     $defaultRedirect = PonyDocsExtension::getDefaultUrl();
     /**
      * At this point $matches contains:
      * 	0= Full title.
      *  1= Product name
      *  2= Version OR 'latest' as a string.
      *  3= Manual name (short name).
      *  4= Wiki topic name.
      */
     $productName = $matches[1];
     $versionName = $matches[2];
     $manualName = $matches[3];
     $topicName = $matches[4];
     $product = PonyDocsProduct::GetProductByShortName($productName);
     // If we don't have a valid product, display 404
     if (!$product instanceof PonyDocsProduct) {
         $wgHooks['BeforePageDisplay'][] = "PonyDocsExtension::handle404";
         return false;
     }
     // If this article doesn't have a valid manual, don't display the article
     if (!PonyDocsProductManual::IsManual($productName, $manualName)) {
         $wgHooks['BeforePageDisplay'][] = "PonyDocsExtension::handle404";
         return false;
     }
     // If this is a static product return because that should be handled by another function
     if ($product->isStatic()) {
         return true;
     }
     $versionSelectedName = PonyDocsProductVersion::GetSelectedVersion($productName);
     $version = '';
     PonyDocsProductVersion::LoadVersionsForProduct($productName);
     if (!strcasecmp('latest', $versionName)) {
         /**
          * This will be a DESCENDING mapping of version name to PonyDocsVersion object and will ONLY contain the
          * versions available to the current user (i.e. LoadVersions() only loads the ones permitted).
          */
         $releasedVersions = PonyDocsProductVersion::GetReleasedVersions($productName, true);
         if (empty($releasedVersions)) {
             return false;
         }
         $versionList = array_reverse($releasedVersions);
         $versionNameList = array();
         foreach ($versionList as $pV) {
             $versionNameList[] = $pV->getVersionName();
         }
         /**
          * Now get a list of version names to which the current topic is mapped in DESCENDING order as well
          * from the 'categorylinks' table.
          *
          * DB can't do descending order here, it depends on the order defined in versions page!  So we have to
          * do some magic sorting below.	
          */
         $res = $dbr->select('categorylinks', 'cl_to', array('cl_to LIKE "V:%:%"', 'cl_type = "page"', "cl_sortkey LIKE '" . $dbr->strencode(strtoupper("{$productName}:{$manualName}:{$topicName}")) . ":%'"), __METHOD__);
         if (!$res->numRows()) {
             /**
              * What happened here is we requested a topic that does not exist or is not linked to any version.
              * Perhaps setup a default redirect, Main_Page or something?
              */
             if (PONYDOCS_DEBUG) {
                 error_log("DEBUG [" . __METHOD__ . ":" . __LINE__ . "] redirecting to {$defaultRedirect}");
             }
             header("Location: " . $defaultRedirect);
             exit(0);
         }
         /**
          * Based on our list, get the PonyDocsVersion for each version tag and store in an array.  Then pass this array
          * to our custom sort function via usort() -- the ending result is a sorted list in $existingVersions, with the
          * LATEST version at the front.
          * 
          * @FIXME:  GetVersionByName is missing some versions?
          */
         $existingVersions = array();
         while ($row = $dbr->fetchObject($res)) {
             if (preg_match('/^V:(.*):(.*)/i', $row->cl_to, $vmatch)) {
                 $pVersion = PonyDocsProductVersion::GetVersionByName($vmatch[1], $vmatch[2]);
                 if ($pVersion && !in_array($pVersion, $existingVersions)) {
                     $existingVersions[] = $pVersion;
                 }
             }
         }
         usort($existingVersions, "PonyDocs_ProductVersionCmp");
         $existingVersions = array_reverse($existingVersions);
         // Okay, iterate through existingVersions.  If we can't see that
         // any of them belong to our latest released version, redirect to
         // our latest handler.
         $latestReleasedVersion = PonyDocsProductVersion::GetLatestReleasedVersion($productName)->getVersionName();
         $found = false;
         foreach ($existingVersions as $docVersion) {
             if ($docVersion->getVersionName() == $latestReleasedVersion) {
                 $found = true;
                 break;
             }
         }
         if (!$found) {
             if (PONYDOCS_DEBUG) {
                 error_log("DEBUG [" . __METHOD__ . ":" . __LINE__ . "] redirecting to {$wgScriptPath}/Special:PonyDocsLatestDoc?t={$title}");
             }
             header("Location: " . $wgScriptPath . "/Special:SpecialLatestDoc?t={$title}", true, 302);
             exit(0);
         }
         /**
          * Now we need to filter out any versions which this user has no access to.  The easiest way is to loop through
          * our resulting $existingVersions and see if each is in_array( $versionNameList );  if its NOT, continue looping.
          * Once we hit one, redirect.  if we exhaust our list, go to the main page or something.
          */
         foreach ($existingVersions as $pV) {
             if (in_array($pV->getVersionName(), $versionNameList)) {
                 /**
                  * Look up topic name and redirect to URL.
                  */
                 $res = $dbr->select(array('categorylinks', 'page'), 'page_title', array('cl_from = page_id', 'page_namespace = "' . NS_PONYDOCS . '"', "cl_to = 'V:" . $dbr->strencode($pV->getProductName() . ':' . $pV->getVersionName()) . "'", 'cl_type = "page"', "cl_sortkey LIKE '" . $dbr->strencode(strtoupper("{$productName}:{$manualName}:{$topicName}")) . ":%'"), __METHOD__);
                 if (!$res->numRows()) {
                     if (PONYDOCS_DEBUG) {
                         error_log("DEBUG [" . __METHOD__ . ":" . __LINE__ . "] redirecting to {$defaultRedirect}");
                     }
                     header("Location: " . $defaultRedirect);
                     exit(0);
                 }
                 $row = $dbr->fetchObject($res);
                 $title = Title::newFromText(PONYDOCS_DOCUMENTATION_NAMESPACE_NAME . ":{$row->page_title}");
                 $article = new Article($title);
                 $article->loadContent();
                 PonyDocsProductVersion::SetSelectedVersion($pV->getProductName(), $pV->getVersionName());
                 if (!$article->exists()) {
                     $article = NULL;
                 } else {
                     // Without this we lose SplunkComments and version switcher.
                     // Probably we can replace with a RequestContext in the future...
                     $wgTitle = $title;
                 }
                 return TRUE;
             }
         }
         /**
          * Invalid redirect -- go to Main_Page or something.
          */
         if (PONYDOCS_DEBUG) {
             error_log("DEBUG [" . __METHOD__ . ":" . __LINE__ . "] redirecting to {$defaultRedirect}");
         }
         header("Location: " . $defaultRedirect);
         exit(0);
     } else {
         /**
          * Ensure version specified in aliased URL is a valid version -- if it is not we just need to do our default
          * redirect here.
          */
         $version = PonyDocsProductVersion::GetVersionByName($productName, $versionName);
         if (!$version) {
             if (PONYDOCS_DEBUG) {
                 error_log("DEBUG [" . __METHOD__ . ":" . __LINE__ . "] unable to retrieve version ({$versionName}) for product ({$productName}); redirecting to {$defaultRedirect}");
             }
             header("Location: " . $defaultRedirect);
             exit(0);
         }
         /**
          * Look up the TOPIC in the categorylinks and find the one which is tagged with the version supplied.  This
          * is the URL to redirect to.  
          */
         $res = $dbr->select(array('categorylinks', 'page'), 'page_title', array('cl_from = page_id', 'page_namespace = "' . NS_PONYDOCS . '"', "cl_to = 'V:" . $dbr->strencode($productName . ':' . $versionSelectedName) . "'", 'cl_type = "page"', "cl_sortkey LIKE '" . $dbr->strencode(strtoupper("{$productName}:{$manualName}:{$topicName}")) . ":%'"), __METHOD__);
         if (!$res->numRows()) {
             /**
              * Handle invalid redirects?
              */
             $wgHooks['BeforePageDisplay'][] = "PonyDocsExtension::handle404";
             return false;
         }
         $row = $dbr->fetchObject($res);
         $title = Title::newFromText(PONYDOCS_DOCUMENTATION_NAMESPACE_NAME . ":{$row->page_title}");
         /// FIXME this shouldn't be necessary because selected version already comes from here
         PonyDocsProductVersion::SetSelectedVersion($productName, $versionSelectedName);
         $article = new Article($title);
         $article->loadContent();
         if (!$article->exists()) {
             $article = NULL;
         } else {
             // Without this we lose SplunkComments and version switcher.
             // Probably we can replace with a RequestContext in the future...
             $wgTitle = $title;
         }
         return TRUE;
     }
     return FALSE;
 }
Example #2
0
 /**
  * This function returns information about the versions on this topic.
  * - Version permissions: unreleased, preview, or released
  * - Version age: older, latest, or newer
  * Since a Topic can have multiple versions, it's possible for a single topic to be in unreleased, preview, released, older, 
  * latest, AND newer versions AT THE SAME TIME!
  * This information can be used by skins to change UI based on the version features.
  *  
  * @return array
  */
 public function getVersionClasses()
 {
     $productName = PonyDocsProduct::getSelectedProduct();
     $versionClasses = array();
     $releasedVersions = PonyDocsProductVersion::GetReleasedVersions($productName);
     // Just the names of our released versions
     $releasedNames = array();
     foreach ($releasedVersions as $ver) {
         $releasedNames[] = strtolower($ver->getVersionName());
     }
     $previewVersions = PonyDocsProductVersion::GetPreviewVersions($productName);
     // Just the names of our preview versions
     $previewNames = array();
     foreach ($previewVersions as $ver) {
         $previewNames[] = strtolower($ver->getVersionName());
     }
     $latestVersion = PonyDocsProductVersion::GetLatestReleasedVersion($productName);
     foreach ($this->versions as $version) {
         $versionName = strtolower($version->getVersionName());
         // Is this version released, preview, or unreleased?
         if (in_array($versionName, $releasedNames)) {
             $versionClasses['released'] = TRUE;
         } elseif (in_array($versionName, $previewNames)) {
             $versionClasses['preview'] = TRUE;
         } else {
             $versionClasses['unreleased'] = TRUE;
         }
         // Is this version older or later or equal to the current version?
         if ($latestVersion) {
             if (PonyDocs_ProductVersionCmp($version, $latestVersion) < 0) {
                 $versionClasses['older'] = TRUE;
             } elseif (PonyDocs_ProductVersionCmp($version, $latestVersion) > 0) {
                 $versionClasses['newer'] = TRUE;
             } else {
                 $versionClasses['latest'] = TRUE;
             }
         }
     }
     return array_keys($versionClasses);
 }