/** * Updates or deletes Doc Links for the article being passed in. * @param string $updateOrDelete possible values: "update" or "delete" * @param Article $article the article to be updated or deleted * @param string $content content of the article to be updated or deleted */ public static function updateOrDeleteDocLinks($updateOrDelete, $article, $content = NULL) { $dbh = wfGetDB(DB_MASTER); if ($updateOrDelete == "update") { // Match all links in the article /* Breakdown of the regex below: * two left brackets * followed by zero or more misc chars ($match[1]), until * a pound followed by one or more misc chars ($match[2]) -- but this section is optional * followed by an optional | * followed by zero or more misc chars ($match[4]) ($match[3] is the misc chars plus the |) * followed by two right brackets * Things that would match: * [[TextHere:OtherTextHere#MoreText|StillMoreText]] * [[TextHere:MoreText:Text:Text|StillMoreText]] * [[TextHere:MoreText:Text:Text:Text|StillMoreText]] * [[TextHere:OtherTextHere|StillMoreText]] * [[TextHereStillMoreText]] * etc. * For PonyDocs, this maps to: * [[Topic]] * [[Documentation:Product:Manual:Topic]] * [[Documentation:Product:Manual:Topic:Version]] * [[OtherNamespace:Topic]] */ // TODO we really should refactor this regex; for now, leaving intact $regex = "/\\[\\[([A-Za-z0-9,:._ -]*)(\\#[A-Za-z0-9 _-]+)?([|]?([A-Za-z0-9,:.'_?!@\\/\"()#\$ -]*))\\]\\]/"; preg_match_all($regex, $content, $matches, PREG_SET_ORDER); } // Get the title of the article $title = $article->getTitle()->getFullText(); $titlePieces = explode(':', $title); $fromNamespace = $titlePieces[0]; $toAndFromLinksToInsert = array(); $fromLinksToDelete = array(); // $titlePieces[3] is the version // if this is not set, we're not looking at a Topic (probably we're looking at a TOC) and we don't need doclinks if ($fromNamespace == PONYDOCS_DOCUMENTATION_NAMESPACE_NAME && isset($titlePieces[3])) { // TODO only process this topic if it's not a TOC. // Do PonyDocs-specific stuff (loop through all inherited versions) // Get the versions associated with this topic $topic = new PonyDocsTopic($article); PonyDocsProductVersion::LoadVersionsForProduct($titlePieces[1], true, true); $ponydocsVersions = $topic->getProductVersions(); // Add a link to the database for each version foreach ($ponydocsVersions as $ver) { // Make a pretty PonyDocs URL (with slashes) out of the mediawiki title (with colons) // Put this $ver in the version spot. We want one URL per inherited version $titleNoVersion = $fromNamespace . ":" . $titlePieces[1] . ":" . $titlePieces[2] . ":" . $titlePieces[3]; $humanReadableTitle = self::translateTopicTitleForDocLinks($titleNoVersion, $fromNamespace, $ver, $topic); // this will add the version // Add this title to the array of titles to be deleted from the database $fromLinksToDelete[] = $humanReadableTitle; if ($updateOrDelete == "update") { // Add links in article to database foreach ($matches as $match) { // Get pretty to_link $toUrl = self::translateTopicTitleForDocLinks($match[1], $fromNamespace, $ver, $topic); // Add this from_link and to_link to array to be inserted into the database if ($toUrl) { $toAndFromLinksToInsert[] = array('from_link' => $humanReadableTitle, 'to_link' => $toUrl); } } } } } elseif ($fromNamespace != PONYDOCS_DOCUMENTATION_NAMESPACE_NAME) { // Do generic mediawiki stuff for non-PonyDocs namespaces // Add this title to the array of titles to be deleted from the database // We don't need to translate title here since we're not in the PonyDocs namespace $fromLinksToDelete[] = $title; if ($updateOrDelete == "update") { // Add links in article to database foreach ($matches as $match) { // Get pretty to_link $toUrl = self::translateTopicTitleForDocLinks($match[1]); // Add this from_link and to_link to array to be inserted into the database if ($toUrl) { $toAndFromLinksToInsert[] = array('from_link' => $title, 'to_link' => $toUrl); } } } } // Perform database queries using arrays populated above // First, delete to clear old data out of the database if (!empty($fromLinksToDelete)) { foreach ($fromLinksToDelete as &$fromLinkToDelete) { $fromLinkToDelete = $dbh->strencode($fromLinkToDelete); } $deleteWhereConds = implode("' OR from_link = '", $fromLinksToDelete); $deleteQuery = "DELETE FROM ponydocs_doclinks WHERE from_link = '" . $deleteWhereConds . "'"; $dbh->query($deleteQuery); } // Now insert new data, if we have any if (!empty($toAndFromLinksToInsert)) { $insertValuesAry = array(); foreach ($toAndFromLinksToInsert as $toAndFromLink) { $insertValuesAry[] = "'" . $dbh->strencode($toAndFromLink['from_link']) . "', '" . $dbh->strencode($toAndFromLink['to_link']) . "'"; } $insertValuesString = implode("), (", $insertValuesAry); $insertQuery = "INSERT INTO ponydocs_doclinks (from_link, to_link) VALUES (" . $insertValuesString . ")"; $dbh->query($insertQuery); } return true; }
/** * This is called upon loading the special page. It should write output to * the page with $wgOut */ public function execute() { global $wgOut, $wgArticlePath, $wgScriptPath, $wgUser; global $wgRequest; global $wgDBprefix; $currentProduct = ''; $currentVersion = ''; $collapseAll = FALSE; $dbr = wfGetDB(DB_SLAVE); // Set headers and title of the page, get value of "t" from GET/POST $this->setHeaders(); $title = $wgRequest->getVal('t'); if (empty($title)) { $wgOut->setPagetitle("Documentation Linkage"); $wgOut->addHTML('No topic specified.'); return; } $wgOut->setPagetitle("Documentation Linkage For " . $title); // Parse "t" (the title we're looking for inbound links to) // Find titles for all inherited versions, etc. $titlePieces = explode(':', $title); $plainTitle = $title; // Create a new Title from text, such as what one would find in a link. Decodes any HTML entities in the text. $title = Title::newFromText($title); $toUrls = array(); // Do PonyDocs-specific stuff (loop through all inherited versions) if ($titlePieces[0] == PONYDOCS_DOCUMENTATION_NAMESPACE_NAME) { // Get all the versions in the product $versions = PonyDocsProductVersion::LoadVersionsForProduct($titlePieces[1], true); if (empty($versions)) { error_log('WARNING [PonyDocs] [' . __CLASS__ . '] Unable to find product versions for this topic: ' . $title); } $currentProduct = $titlePieces[1]; $currentVersion = $titlePieces[4]; // Get the latest released version of this product $latestVersionObj = PonyDocsProductVersion::GetLatestReleasedVersion($titlePieces[1]); if (is_object($latestVersionObj)) { $latestVersion = $latestVersionObj->getVersionName(); } else { error_log('WARNING [PonyDocs] [' . __CLASS__ . '] Unable to find latest released version of ' . $titlePieces[1]); } // Generate a title without the version so we can dynamically generate a list of titles with all inherited versions $titleNoVersion = $titlePieces[0] . ":" . $titlePieces[1] . ":" . $titlePieces[2] . ":" . $titlePieces[3]; // Search the database for matching to_links for each inherited version if (is_array($versions)) { foreach ($versions as $ver) { // Add this URL to array of URLs to search db for $toUrls[] = PonyDocsExtension::translateTopicTitleForDocLinks($titleNoVersion, NULL, $ver); // Compare this version with latest version. If they're the same, add the URL with "latest" too. $thisVersion = $ver->getVersionName(); if ($thisVersion == $latestVersion) { $titleLatestVersion = $titlePieces[0] . ':' . $titlePieces[1] . ':' . $titlePieces[2] . ':' . $titlePieces[3] . ':latest'; $toUrls[] = PonyDocsExtension::translateTopicTitleForDocLinks($titleLatestVersion); } } } else { error_log('WARNING [PonyDocs] [' . __CLASS__ . '] Unable to find versions for ' . $title); } } else { // Do generic mediawiki stuff for non-PonyDocs namespaces $collapseAll = TRUE; $toUrls[] = PonyDocsExtension::translateTopicTitleForDocLinks($title); } // Query the database for the list of toUrls we've collated if (!empty($toUrls)) { foreach ($toUrls as &$toUrl) { $toUrl = $dbr->strencode($toUrl); } $inUrls = "'" . implode("','", $toUrls) . "'"; $query = "SELECT * FROM " . $wgDBprefix . "ponydocs_doclinks WHERE to_link IN ({$inUrls})"; $results = $dbr->query($query); } // Create array of links, sorted by product and version $links = array(); // Loop through results and save into handy dandy links array if (!empty($results)) { foreach ($results as $result) { $fromProduct = ''; $fromVersion = ''; $displayUrl = ''; if (strpos($result->from_link, PONYDOCS_DOCUMENTATION_NAMESPACE_NAME) !== false) { // If this is a PonyDocs style links, with slashes, // save product, version, display URL accordingly. $pieces = explode('/', $result->from_link); $fromProduct = $pieces[1]; $fromVersion = $pieces[2]; $displayUrl = $result->from_link; } else { // If this is a generic mediawiki style link, with colons (or not), // set product to the namespace, and remove namespace // from the display URL. Leave version blank. if (strpos($result->from_link, ':') !== false) { $pieces = explode(':', $result->from_link); $fromProduct = $pieces[0]; // The "product" will be the namespace $displayUrl = $pieces[1]; // So the namespace doesn't show in every URL } else { // it's possible to have a link with no colons $fromProduct = 'Other'; // No namespace, so the "product" will be the string "Other" $displayUrl = $result->from_link; } $fromVersion = 'None'; // No concept of versions outside of PonyDocs } // Put all this stuff in an array that we can use to generate HTML $links[$fromProduct][$fromVersion][] = array('from_link' => $result->from_link, 'to_link' => $result->to_link, 'display_url' => $displayUrl); } } // Make HTML go! ob_start(); ?> <div class="doclinks"> <h2>Inbound links to <?php echo $plainTitle; ?> from other topics.</h2> <?php // If there are no links, display a message saying as much if (empty($links)) { ?> <p>No links to <?php echo $plainTitle; ?> (and its inherited versions) from other topics.</p> <?php } else { // Display all links, ordered by product then version foreach ($links as $fromProduct => $fromVersions) { // If this is a PonyDocs Product if (PonyDocsProduct::IsProduct($fromProduct)) { // Get versions for this product, so we can display the versions in the correct order PonyDocsProductVersion::LoadVersionsForProduct($fromProduct, true); $fromProductVersions = PonyDocsProductVersion::GetVersions($fromProduct); // If there are no valid versions for this product/user, then skip the product name header. if (!count($fromProductVersions)) { continue; } ?> <h2><?php echo $fromProduct; ?> </h2> <?php foreach ($fromProductVersions as $fromProductVersionObj) { $fromProductVersionName = $fromProductVersionObj->getVersionName(); // If there are doclinks from this version, print them if (array_key_exists($fromProductVersionName, $fromVersions)) { // Expand containers of incoming links from the current Product and Version // Expand containers of incoming links from other Products // But don't expand any containers if this is not a PonyDocs product $selected = ''; if (($currentProduct != $fromProduct || $currentVersion == $fromProductVersionName) && !$collapseAll) { $selected = 'selected'; } ?> <h3 class="doclinks-collapsible <?php print $selected; ?> "> <?php echo $fromProduct . ' ' . $fromProductVersionName; ?> </h3> <ul> <?php foreach ($fromVersions[$fromProductVersionName] as $linkAry) { ?> <li> <a href="<?php echo str_replace('$1', $linkAry['from_link'], $wgArticlePath); ?> "> <?php echo $linkAry['display_url']; ?> </a> </li> <?php } ?> </ul> <?php } } } else { ?> <h2><?php echo $fromProduct; ?> </h2> <h3 class="doclinks-collapsible selected">Latest</h3> <?php // This is not a PonyDocs product, don't worry about sorting foreach ($fromVersions as $fromVersion => $fromVersionData) { ?> <ul> <?php foreach ($fromVersionData as $linkAry) { ?> <li> <a href="<?php echo str_replace('$1', $linkAry['from_link'], $wgArticlePath); ?> "> <?php echo $linkAry['display_url']; ?> </a> </li> <?php } ?> </ul> <?php } } } } ?> </div> <?php $htmlContent = ob_get_contents(); ob_end_clean(); $wgOut->addHTML($htmlContent); return true; }
/** * This returns the list of available manuals (active ones) in a more useful way for templates. It is an associative array * where the key is the short name of the manual and the value is the display/long name. * * @return array */ public function getManualsForProduct($product) { PonyDocsProductVersion::LoadVersionsForProduct($product); // Dependency PonyDocsProductVersion::getSelectedVersion($product); $manuals = PonyDocsProductManual::LoadManualsForProduct($product); // Dependency $out = array(); foreach ($manuals as $m) { $out[$m->getShortName()] = $m->getLongName(); } return $out; }
/** * * @global OutputPage $wgOut * @param string $action * @param PonyDocsProduct $product * @param mixed $manual PonyDocsManual or NULL */ private function processImportForm($action, $product, $manual) { global $wgOut, $wgUser; $importer = new PonyDocsStaticDocImporter(PONYDOCS_STATIC_DIR); if (isset($_POST['version']) && isset($_POST['product']) && (is_null($manual) || isset($_POST['manual']))) { switch ($action) { case "add": if (PonyDocsProductVersion::IsVersion($_POST['product'], $_POST['version'])) { $wgOut->addHTML('<h3>Results of Import</h3>'); // Okay, let's make sure we have file provided if (!isset($_FILES['archivefile']) || $_FILES['archivefile']['error'] != 0) { $wgOut->addHTML('There was a problem using your uploaded file. Make sure you uploaded a file and try again.'); } else { try { if (is_null($manual)) { $importer->importFile($_FILES['archivefile']['tmp_name'], $_POST['product'], $_POST['version']); $wgOut->addHTML("Success: imported archive for {$_POST['product']} version {$_POST['version']}"); } else { $importer->importFile($_FILES['archivefile']['tmp_name'], $_POST['product'], $_POST['version'], $_POST['manual']); $wgOut->addHTML("Success: imported archive for {$_POST['product']} version {$_POST['version']}" . " manual {$_POST['manual']}"); } } catch (Exception $e) { $wgOut->addHTML('Error: ' . $e->getMessage()); error_log('WARNING [ponydocs] [staticdocs] [' . __METHOD__ . '] action="add" status="error"' . ' message="' . addcslashes($e->getMessage(), '"') . '"'); } } } break; case "remove": //Loading product versions for WEB-10732 PonyDocsProductVersion::LoadVersionsForProduct($_POST['product']); if (PonyDocsProductVersion::IsVersion($_POST['product'], $_POST['version'])) { $wgOut->addHTML('<h3>Results of Deletion</h3>'); try { if (is_null($manual)) { $importer->removeVersion($_POST['product'], $_POST['version']); $wgOut->addHTML("Successfully deleted {$_POST['product']} version {$_POST['version']}"); } else { $importer->removeVersion($_POST['product'], $_POST['version'], $_POST['manual']); $wgOut->addHTML("Successfully deleted {$_POST['product']} version {$_POST['version']}" . " manual {$_POST['manual']}"); } } catch (Exception $e) { $wgOut->addHTML('Error: ' . $e->getMessage()); error_log('WARNING [ponydocs] [staticdocs] [' . __METHOD__ . '] action="remove" status="error"' . ' message="' . addcslashes($e->getMessage(), '"') . '"'); } } else { $wgOut->addHTML("Error: Version {$_POST['version']} does not exist, or is not accessible"); error_log('WARNING [ponydocs] [staticdocs] [' . __METHOD__ . '] action="remove" status="error"' . ' message="version ' . $_POST['version'] . ' does not exist, or is not accessible"' . ' username="******"' . ' ip="' . IP::sanitizeIP(wfGetIP()) . '"'); } break; } $this->clearProductCache($_POST['product'], $_POST['version']); } }
function execute() { global $action, $IP, $wgArticlePath, $wgContLang, $wgExtraNamespaces, $wgRequest, $wgRevision, $wgTitle, $wgUser; PonyDocsProduct::LoadProducts(); $this->data['selectedProduct'] = PonyDocsProduct::GetSelectedProduct(); PonyDocsProductVersion::LoadVersionsForProduct($this->data['selectedProduct']); PonyDocsProductManual::LoadManualsForProduct($this->data['selectedProduct']); $ponydocs = PonyDocsWiki::getInstance($this->data['selectedProduct']); $this->data['products'] = $ponydocs->getProductsForTemplate(); $this->data['versions'] = $ponydocs->getVersionsForProduct($this->data['selectedProduct']); $this->data['namespaces'] = $wgExtraNamespaces; $this->data['selectedVersion'] = PonyDocsProductVersion::GetSelectedVersion($this->data['selectedProduct']); $this->data['pVersion'] = PonyDocsProductVersion::GetVersionByName($this->data['selectedProduct'], $this->data['selectedVersion']); if (PONYDOCS_DEBUG) { error_log("DEBUG [" . __METHOD__ . "] selected product/version is set to " . $this->data['selectedProduct'] . "/" . $this->data['selectedVersion']); } $this->data['versionurl'] = $this->data['wgScript'] . '?title=' . $this->data['thispage'] . '&action=changeversion'; $this->skin = $this->data['skin']; // TODO remove this, and replace elsewhere (template files mostly) with $this->skin $skin = $this->data['skin']; if ($this->skin->getTitle()) { $this->data['canonicalURI'] = $this->skin->getTitle()->getFullURL(); } $action = $wgRequest->getText('action'); // Suppress warnings to prevent notices about missing indexes in $this->data wfSuppressWarnings(); /** * When displaying a page we output header.php, then a sub-template, and then footer.php. The namespace * which we are in determines the sub-template, which is named 'ns<Namespace>'. It defaults to our * nsDefault.php template. */ $this->data['namespace'] = $wgContLang->getNsText($wgTitle->getNamespace()); $idx = $this->data['namespace'] ? "NS:{$this->data['namespace']}" : 'T:' . $wgTitle->__toString(); if (!isset($this->_methodMappings[$idx])) { $idx = 0; } $inDocumentation = FALSE; if ($this->data['namespace'] == PONYDOCS_DOCUMENTATION_NAMESPACE_NAME || $wgTitle->__toString() == PONYDOCS_DOCUMENTATION_NAMESPACE_NAME || preg_match('/^' . PONYDOCS_DOCUMENTATION_NAMESPACE_NAME . ':/', $wgTitle->__toString())) { $inDocumentation = TRUE; $this->prepareDocumentation(); } $this->data['versions'] = $ponydocs->getVersionsForProduct($this->data['selectedProduct']); $this->html('headelement'); ?> <script type="text/javascript"> function AjaxChangeProduct_callback( o ) { document.getElementById( 'docsProductSelect' ).disabled = true; var s = new String( o.responseText ); document.getElementById( 'docsProductSelect' ).disabled = false; window.location.href = s; } function AjaxChangeProduct() { var productIndex = document.getElementById( 'docsProductSelect' ).selectedIndex; var product = document.getElementById( 'docsProductSelect' )[productIndex].value; var title = '<?php Xml::escapeJsString($this->data['thispage']); ?> '; sajax_do_call( 'efPonyDocsAjaxChangeProduct', [product,title], AjaxChangeProduct_callback ); } function AjaxChangeVersion_callback( o ) { document.getElementById( 'docsVersionSelect' ).disabled = true; var s = new String( o.responseText ); document.getElementById( 'docsVersionSelect' ).disabled = false; window.location.href = s; } function AjaxChangeVersion() { var productIndex = document.getElementById( 'docsProductSelect' ).selectedIndex; var product = document.getElementById( 'docsProductSelect' )[productIndex].value; var versionIndex = document.getElementById( 'docsVersionSelect' ).selectedIndex; var version = document.getElementById( 'docsVersionSelect' )[versionIndex].value; var title = '<?php Xml::escapeJsString($this->data['thispage']); ?> '; sajax_do_call( 'efPonyDocsAjaxChangeVersion', [product,version,title], AjaxChangeVersion_callback ); } function changeManual(){ var url = $( "#docsManualSelect" ).val(); if ( url != "" ){ window.location.href = url; } } </script> <div id="globalWrapper"> <div id="column-content"> <div id="content" <?php $this->html("specialpageattributes"); ?> > <a id="top"></a> <?php if ($this->data['sitenotice']) { ?> <div id="siteNotice"><?php $this->html('sitenotice'); ?> </div> <?php } ?> <?php if (!$inDocumentation) { ?> <h1 id="firstHeading" class="firstHeading"><?php $this->html('title'); ?> </h1> <?php } ?> <div id="bodyContent"> <h3 id="siteSub"><?php $this->msg('tagline'); ?> </h3> <div id="contentSub"<?php $this->html('userlangattributes'); ?> ><?php $this->html('subtitle'); ?> </div> <?php if ($this->data['undelete']) { ?> <div id="contentSub2"><?php $this->html('undelete'); ?> </div> <?php } if ($this->data['newtalk']) { ?> <div class="usermessage"><?php $this->html('newtalk'); ?> </div> <?php } if ($this->data['showjumplinks']) { ?> <div id="jump-to-nav"> <?php $this->msg('jumpto'); ?> <a href="#column-one"><?php $this->msg('jumptonavigation'); ?> </a>, <a href="#searchInput"><?php $this->msg('jumptosearch'); ?> </a> </div> <?php } // Version group message, if any if ($this->data['versionGroupMessage'] !== null) { ?> <div class="affectedVersions <?php echo implode(" ", $this->data['versionclasses']); ?> "> <p class="bannerVersion"> <?php echo $this->data['versionGroupMessage']; ?> </p> </div> <?php } ?> <!-- start content --> <?php $this->html('bodytext'); if ($this->data['catlinks']) { $this->html('catlinks'); } ?> <!-- end content --> <?php if ($this->data['dataAfterContent']) { $this->html('dataAfterContent'); } ?> <div class="visualClear"></div> </div> </div> </div> <div id="column-one"<?php $this->html('userlangattributes'); ?> > <div id="p-cactions" class="portlet"> <h5><?php $this->msg('views'); ?> </h5> <div class="pBody"> <ul><?php foreach ($this->data['content_actions'] as $key => $tab) { echo ' <li id="' . Sanitizer::escapeId("ca-{$key}") . '"'; if ($tab['class']) { echo ' class="' . htmlspecialchars($tab['class']) . '"'; } echo '><a href="' . htmlspecialchars($tab['href']) . '"'; # We don't want to give the watch tab an accesskey if the # page is being edited, because that conflicts with the # accesskey on the watch checkbox. We also don't want to # give the edit tab an accesskey, because that's fairly su- # perfluous and conflicts with an accesskey (Ctrl-E) often # used for editing in Safari. if (in_array($action, array('edit', 'submit')) && in_array($key, array('edit', 'watch', 'unwatch'))) { echo $skin->tooltip("ca-{$key}"); } else { echo Xml::expandAttributes($skin->tooltipAndAccesskeyAttribs("ca-{$key}")); } echo '>' . htmlspecialchars($tab['text']) . '</a></li>'; } ?> </ul> </div> </div> <div class="portlet" id="p-personal"> <h5><?php $this->msg('personaltools'); ?> </h5> <div class="pBody"> <ul<?php $this->html('userlangattributes'); ?> > <?php foreach ($this->data['personal_urls'] as $key => $item) { ?> <li id="<?php echo Sanitizer::escapeId("pt-{$key}"); ?> " <?php if ($item['active']) { ?> class="active" <?php } ?> > <a href="<?php echo htmlspecialchars($item['href']); ?> " <?php echo Xml::expandAttributes($skin->tooltipAndAccesskeyAttribs('pt-' . $key)); if (!empty($item['class'])) { ?> class="<?php echo htmlspecialchars($item['class']); ?> " <?php } ?> > <?php echo htmlspecialchars($item['text']); ?> </a> </li> <?php } ?> </ul> </div> </div> <div class="portlet" id="p-logo"> <a style="background-image: url(<?php $this->text('logopath'); ?> );" href="<?php echo htmlspecialchars($this->data['nav_urls']['mainpage']['href']); ?> " <?php echo Xml::expandAttributes($skin->tooltipAndAccesskeyAttribs('p-logo')); ?> ></a><br /> </div> <script type="<?php $this->text('jsmimetype'); ?> "> if ( window.isMSIE55 ) { fixalpha(); } </script> <div id="p-documentation" class="portlet"> <h5>documentation</h5> <div id="documentationBody" class="pBody"> <?php if (!count($this->data['products'])) { ?> <p>No products defined.</p> <?php } else { ?> <div class="product"> <label for='docsProductSelect' class="navlabels">Product: </label><br /> <select id="docsProductSelect" name="selectedProduct" onChange="AjaxChangeProduct();"> <?php $this->hierarchicalProductSelect(); ?> </select> </div> <?php $versions = PonyDocsProductVersion::GetVersions($this->data['selectedProduct'], TRUE); if (!count($versions)) { ?> <p>No Product Versions Defined.</p> <?php } else { $manuals = PonyDocsProductManual::GetDefinedManuals($this->data['selectedProduct'], TRUE); if (!count($manuals)) { ?> <p>The product manual you requested is not defined, you are not logged in, or you do not have the correct permissions to view this content.</p> <?php } else { ?> <p> <div class="productVersion"> <?php // do quick manip $found = FALSE; for ($i = count($this->data['versions']) - 1; $i >= 0; $i--) { $this->data['versions'][$i]['label'] = $this->data['versions'][$i]['name']; if (!$found && $this->data['versions'][$i]['status'] == "released") { $this->data['versions'][$i]['label'] .= " (latest release)"; $found = TRUE; } } ?> <label for='docsVersionSelect' class="navlabels">Product version: </label><br /> <select id="docsVersionSelect" name="selectedVersion" onChange="AjaxChangeVersion();"> <?php foreach ($this->data['versions'] as $idx => $data) { echo '<option value="' . $data['name'] . '" '; if (!strcmp($data['name'], $this->data['selectedVersion'])) { echo 'selected'; } echo '>' . $data['label'] . '</option>'; } ?> </select> </div> <div class="productManual"> <label for="docsManualSelect" class="navlabels">Select manual: </label><br /> <select id="docsManualSelect" name="selectedManual" onChange="changeManual();"> <?php $navData = PonyDocsExtension::fetchNavDataForVersion($this->data['selectedProduct'], $this->data['selectedVersion']); print "<option value=''>Pick One...</option>"; //loop through nav array and look for current URL foreach ($navData as $manual) { $selected = ""; if (!strcmp($this->data['manualname'], $manual['longName'])) { $selected = " selected "; } print "<option value='" . $manual['firstUrl'] . "' {$selected}>"; print $manual['longName']; print "<!-- categories: {$manual['categories']} -->"; print '</option>'; } ?> </select> </div> </p> <p> <?php if (sizeof($this->data['manualtoc'])) { ?> <p> <a href="<?php echo str_replace('$1', '', $wgArticlePath); ?> index.php?title=<?php echo $wgTitle->__toString(); ?> &action=pdfbook">Pdf Version</a> </p> <?php $inUL = FALSE; $listid = ""; foreach ($this->data['manualtoc'] as $idx => $data) { if (0 == $data['level']) { if ($inUL) { echo '</ul></div>'; $inUL = FALSE; } $listid = "list" . $idx; echo '<div class="wikiSidebarBox collapsible">'; echo '<h3>' . $data['text'] . '</h3>'; echo '<ul>'; $inUL = TRUE; } elseif (1 == $data['level']) { if ($data['current']) { echo '<li class="expanded">' . $data['text'] . '</li>'; } else { echo '<li><a href="' . wfUrlencode($data['link']) . '">' . $data['text'] . '</a></li>'; } } else { if ($data['current']) { echo '<li class="expanded" style="margin-left: 13px;">' . $data['text'] . '</li>'; } else { echo '<li style="margin-left: 13px;"><a href="' . wfUrlencode($data['link']) . '">' . $data['text'] . '</a></li>'; } } } if ($inUL) { echo '</ul></div>'; } } ?> </p> <?php } } } ?> </div> </div> <?php $sidebar = $this->data['sidebar']; if (!isset($sidebar['SEARCH'])) { $sidebar['SEARCH'] = TRUE; } if (!isset($sidebar['TOOLBOX'])) { $sidebar['TOOLBOX'] = TRUE; } if (!isset($sidebar['LANGUAGES'])) { $sidebar['LANGUAGES'] = TRUE; } foreach ($sidebar as $boxName => $cont) { if ($boxName == 'SEARCH') { $this->searchBox(); } elseif ($boxName == 'TOOLBOX') { $this->toolbox(); } elseif ($boxName == 'LANGUAGES') { $this->languageBox(); } else { $this->customBox($boxName, $cont); } } ?> </div><!-- end of the left (by default at least) column --> <div class="visualClear"></div> <div id="footer"<?php $this->html('userlangattributes'); ?> > <?php if ($this->data['poweredbyico']) { ?> <div id="f-poweredbyico"><?php $this->html('poweredbyico'); ?> </div> <?php } if ($this->data['copyrightico']) { ?> <div id="f-copyrightico"><?php $this->html('copyrightico'); ?> </div> <?php } // Generate additional footer links $footerlinks = array('lastmod', 'viewcount', 'numberofwatchingusers', 'credits', 'copyright', 'privacy', 'about', 'disclaimer', 'tagline'); $validFooterLinks = array(); foreach ($footerlinks as $aLink) { if (isset($this->data[$aLink]) && $this->data[$aLink]) { $validFooterLinks[] = $aLink; } } if (count($validFooterLinks) > 0) { ?> <ul id="f-list"> <?php foreach ($validFooterLinks as $aLink) { if (isset($this->data[$aLink]) && $this->data[$aLink]) { ?> <li id="<?php echo $aLink; ?> "><?php $this->html($aLink); ?> </li> <?php } } ?> </ul> <?php } ?> </div> </div> <?php $this->html('bottomscripts'); /* JS call to runBodyOnloadHook */ ?> <?php $this->html('reporttime'); ?> <?php if ($this->data['debug']) { ?> <!-- Debug output: <?php $this->text('debug'); ?> --> <?php } ?> </body> </html> <?php wfRestoreWarnings(); }
/** * AJAX method to fetch topics for a specified version and manuals * * @param $productName string product short name * @param $sourceVersion string String representation of the source version * @param $targetVersion string String representation of the target version * @param $manuals string Comma seperated list of manuals to retrieve from * @param $forcedTitle string A specific title to pull from and nothing else * (for individual branch/inherit) * @returns string JSON representation of all titles requested */ public static function ajaxFetchTopics($productName, $sourceVersion, $targetVersion, $manuals, $forcedTitle = null) { PonyDocsProduct::LoadProducts(true); $product = PonyDocsProduct::GetProductByShortName($productName); PonyDocsProductVersion::LoadVersionsForProduct(true, true); $sourceVersion = PonyDocsProductVersion::GetVersionByName($productName, $sourceVersion); $targetVersion = PonyDocsProductVersion::GetVersionByName($productName, $targetVersion); if (!$sourceVersion || !$targetVersion) { $result = array("success", false); $result = json_encode($result); return $result; } $result = array(); // Okay, get manual by name. $manuals = explode(",", $manuals); foreach ($manuals as $manualName) { $manual = PonyDocsProductManual::GetManualByShortName($productName, $manualName); $result[$manualName] = array(); $result[$manualName]['meta'] = array(); // Load up meta. $result[$manualName]['meta']['text'] = $manual->getLongName(); // See if TOC exists for target version. $result[$manualName]['meta']['toc_exists'] = PonyDocsBranchInheritEngine::TOCExists($product, $manual, $targetVersion); $result[$manualName]['sections'] = array(); // Got the version and manual, load the TOC. $ponyTOC = new PonyDocsTOC($manual, $sourceVersion, $product); list($toc, $prev, $next, $start) = $ponyTOC->loadContent(); // Time to iterate through all the items. $section = ''; foreach ($toc as $tocItem) { if ($tocItem['level'] == 0) { $section = $tocItem['text']; $result[$manualName]['sections'][$section] = array(); $result[$manualName]['sections'][$section]['meta'] = array(); $result[$manualName]['sections'][$section]['topics'] = array(); } if ($tocItem['level'] == 1) { // actual topic if ($forcedTitle == null || $tocItem['title'] == $forcedTitle) { $tempEntry = array('title' => $tocItem['title'], 'text' => $tocItem['text'], 'toctitle' => $tocItem['toctitle'], 'conflicts' => PonyDocsBranchInheritEngine::getConflicts($product, $tocItem['title'], $targetVersion)); /** * We want to set to empty, so the UI javascript doesn't * bork out on this. */ if ($tempEntry['conflicts'] == false) { $tempEntry['conflicts'] = ''; } $result[$manualName]['sections'][$section]['topics'][] = $tempEntry; } } } foreach ($result as $manualName => $manual) { foreach ($manual['sections'] as $sectionIndex => $section) { if (count($section['topics']) == 0) { unset($result[$manualName]['sections'][$sectionIndex]); } } } } $result = json_encode($result); return $result; }