APICHANGE: Renamed internal references of modules to entities and related method naming. FEATURE: added entity navigation in header. BUGFIX: fixed version links so that they redirect to the version of the current page rather than home page

This commit is contained in:
Will Rossiter 2011-07-01 18:49:31 +12:00
parent 4830e09bad
commit 762eb2323b
12 changed files with 316 additions and 373 deletions

View File

@ -1,4 +1,5 @@
<?php <?php
/** /**
* Parser wrapping the Markdown Extra parser (see http://michelf.com/projects/php-markdown/extra/). * Parser wrapping the Markdown Extra parser (see http://michelf.com/projects/php-markdown/extra/).
* *
@ -165,7 +166,7 @@ class DocumentationParser {
foreach($linksWithTitles[0] as $i => $match) { foreach($linksWithTitles[0] as $i => $match) {
$title = $linksWithTitles[1][$i]; $title = $linksWithTitles[1][$i];
$subject = $linksWithTitles[2][$i]; $subject = $linksWithTitles[2][$i];
$url = sprintf(self::$api_link_base, $subject, $page->getVersion(), $page->getEntity()->getModuleFolder()); $url = sprintf(self::$api_link_base, $subject, $page->getVersion(), $page->getEntity()->getFolder());
$md = str_replace( $md = str_replace(
$match, $match,
sprintf('[%s](%s)', $title, $url), sprintf('[%s](%s)', $title, $url),
@ -186,7 +187,7 @@ class DocumentationParser {
if($links) { if($links) {
foreach($links[0] as $i => $match) { foreach($links[0] as $i => $match) {
$subject = $links[1][$i]; $subject = $links[1][$i];
$url = sprintf(self::$api_link_base, $subject, $page->getVersion(), $page->getEntity()->getModuleFolder()); $url = sprintf(self::$api_link_base, $subject, $page->getVersion(), $page->getEntity()->getFolder());
$md = str_replace( $md = str_replace(
$match, $match,
sprintf('[%s](%s)', $subject, $url), sprintf('[%s](%s)', $subject, $url),

View File

@ -103,7 +103,7 @@ class DocumentationSearch {
public static function get_all_documentation_pages() { public static function get_all_documentation_pages() {
DocumentationService::load_automatic_registration(); DocumentationService::load_automatic_registration();
$modules = DocumentationService::get_registered_modules(); $modules = DocumentationService::get_registered_entities();
$output = new DataObjectSet(); $output = new DataObjectSet();
if($modules) { if($modules) {

View File

@ -3,26 +3,24 @@
/** /**
* DocumentationService * DocumentationService
* *
* Handles the management of the documentation services delivered by the module. * Handles the management of the documentation services delivered by the entity.
* Includes registering which components to document and handles the entities being * Includes registering which components to document and handles the entities being
* documented * documented
* *
* @todo - unregistering a lang / version from site does not update the registered_* arrays
* - handle modules (rather than core) differently
* @package sapphiredocs * @package sapphiredocs
*/ */
class DocumentationService { class DocumentationService {
/** /**
* A mapping of know / popular languages to nice titles. * A mapping of known / popular languages to nice titles.
* *
* @var Array * @var Array
*/ */
private static $language_mapping = array( private static $language_mapping = array(
'en' => 'English', 'en' => 'English',
'fr' => 'French', 'fr' => 'Français',
'de' => 'German' 'de' => 'Deutsch'
); );
/** /**
@ -33,40 +31,43 @@ class DocumentationService {
private static $ignored_files = array('.', '..', '.DS_Store', '.svn', '.git', 'assets', 'themes', '_images'); private static $ignored_files = array('.', '..', '.DS_Store', '.svn', '.git', 'assets', 'themes', '_images');
/** /**
* Case insenstive values to use as extensions on markdown pages. * Case insenstive values to use as extensions on markdown pages. The
* recommended extension is .md.
* *
* @var array * @var array
*/ */
public static $valid_markdown_extensions = array('.md', '.txt', '.markdown'); public static $valid_markdown_extensions = array('.md', '.txt', '.markdown');
/** /**
* Registered modules to include in the documentation. Either pre-filled by the * Registered {@link DocumentationEntity} objects to include in the documentation.
* automatic filesystem parser or via {@link DocumentationService::register()}. Stores * Either pre-filled by the automatic filesystem parser or via {@link DocumentationService::register()}.
* {@link DocumentEntity} objects which contain the languages and versions of each module. * Stores the {@link DocumentEntity} objects which contain the languages
* and versions of each entity.
* *
* You can remove registered modules using {@link DocumentationService::unregister()} * You can remove registered {@link DocumentationEntity} objects by using
* {@link DocumentationService::unregister()}
* *
* @var array * @var array
*/ */
private static $registered_modules = array(); private static $registered_entities = array();
/** /**
* Major Versions store. We don't want to register all versions of every module in * Should generation of documentation categories be automatic?
* the documentation but for sapphire/cms and overall we need to register major
* versions via {@link DocumentationService::register}
* *
* @var array * If this is set to true then it will generate {@link DocumentationEntity}
*/ * objects from the filesystem. This can be slow and also some projects
private static $major_versions = array(); * may want to restrict to specific project folders (rather than everything).
/**
* Return the major versions
* *
* @return array * You can also disable or remove a given folder from registration using
* {@link DocumentationService::unregister()}
*
* @see DocumentationService::$registered_entities
* @see DocumentationService::set_automatic_registration();
*
* @var bool
*/ */
public static function get_major_versions() { private static $automatic_registration = true;
return self::$major_versions;
}
/** /**
* Return the allowed extensions * Return the allowed extensions
@ -96,84 +97,7 @@ class DocumentationService {
} }
/** /**
* Check to see if a given language is registered in the system * Set automatic registration of entities and documentation folders
*
* @param string
* @return bool
*/
public static function is_registered_language($lang) {
$langs = self::get_registered_languages();
return (isset($langs[$lang]));
}
/**
* Get all the registered languages. Optionally limited to a module. Includes
* the nice titles
*
* @return Array
*/
public static function get_registered_languages($module = false) {
$langs = array();
if($module) {
if(isset(self::$registered_modules[$module])) {
$langs = self::$registered_modules[$module]->getLanguages();
}
}
else if($modules = self::get_registered_modules()) {
foreach($modules as $module) {
$langs = array_unique(array_merge($langs, $module->getLanguages()));
}
}
$output = array();
foreach($langs as $lang) {
$output[$lang] = self::get_language_title($lang);
}
return $output;
}
/**
* Returns all the registered versions in the system. Optionally only
* include versions from a module.
*
* @param String $module module to check for versions
* @return array
*/
public static function get_registered_versions($module = false) {
if($module) {
if(isset(self::$registered_modules[$module])) {
return self::$registered_modules[$module]->getVersions();
}
else {
return false;
}
}
return self::$major_versions;
}
/**
* Should generation of documentation categories be automatic. If this
* is set to true then it will generate documentation sections (modules) from
* the filesystem. This can be slow and also some projects may want to restrict
* to specific project folders (rather than everything).
*
* You can also disable or remove a given folder from registration using
* {@link DocumentationService::unregister()}
*
* @see DocumentationService::$registered_modules
* @see DocumentationService::set_automatic_registration();
*
* @var bool
*/
private static $automatic_registration = true;
/**
* Set automatic registration of modules and documentation folders
* *
* @see DocumentationService::$automatic_registration * @see DocumentationService::$automatic_registration
* @param bool * @param bool
@ -182,14 +106,14 @@ class DocumentationService {
self::$automatic_registration = $bool; self::$automatic_registration = $bool;
if(!$bool) { if(!$bool) {
// remove current registed modules when disabling automatic registration // remove current registed entities when disabling automatic registration
// needed to avoid caching issues when running all the tests // needed to avoid caching issues when running all the tests
self::$registered_modules = array(); self::$registered_entities = array();
} }
} }
/** /**
* Is automatic registration of modules enabled. * Is automatic registration of entities enabled.
* *
* @return bool * @return bool
*/ */
@ -198,24 +122,24 @@ class DocumentationService {
} }
/** /**
* Return the modules which are listed for documentation. Optionally only get * Return the entities which are listed for documentation. Optionally only get
* modules which have a version or language given * entities which have a version or language given
* *
* @return array * @return array
*/ */
public static function get_registered_modules($version = false, $lang = false) { public static function get_registered_entities($version = false, $lang = false) {
$output = array(); $output = array();
if($modules = self::$registered_modules) { if($entities = self::$registered_entities) {
if($version || $lang) { if($version || $lang) {
foreach($modules as $module) { foreach($entities as $entity) {
if(self::is_registered_module($module->getModuleFolder(), $version, $lang)) { if(self::is_registered_entity($entity->getFolder(), $version, $lang)) {
$output[] = $module; $output[] = $entity;
} }
} }
} }
else { else {
$output = $modules; $output = $entities;
} }
} }
@ -223,101 +147,90 @@ class DocumentationService {
} }
/** /**
* Check to see if a module is registered with the documenter * Check to see if a entity is registered with the documenter
* *
* @param String $module module name * @param String $entity entity name
* @param String $version version * @param String $version version
* @param String $lang language * @param String $lang language
* *
* @return DocumentationEntity $module the registered module * @return DocumentationEntity $entity the registered entity
*/ */
public static function is_registered_module($module, $version = false, $lang = false) { public static function is_registered_entity($entity, $version = false, $lang = false) {
$check = ($module instanceof DocumentationEntity) ? $module->getModuleFolder() : (string) $module; $check = ($entity instanceof DocumentationEntity) ? $entity->getFolder() : (string) $entity;
if(isset(self::$registered_modules[$check])) { if(isset(self::$registered_entities[$check])) {
$module = self::$registered_modules[$check]; $entity = self::$registered_entities[$check];
if(($lang && !$module->hasLanguage($lang)) || ($version && !$module->hasVersion($version))) { if(($lang && !$entity->hasLanguage($lang)) || ($version && !$entity->hasVersion($version))) {
return false; return false;
} }
return $module; return $entity;
} }
return false; return false;
} }
/** /**
* Register a module to be included in the documentation. To unregister a module * Register a entity to be included in the documentation. To unregister a entity
* use {@link DocumentationService::unregister()}. Must include the trailing slash * use {@link DocumentationService::unregister()}. Must include the trailing slash
* *
* @param String $module Name of module to register * @param String $entity Name of entity to register
* @param String $path Path to documentation root. * @param String $path Path to documentation root.
* @param Float $version Version of module. * @param Float $version Version of entity.
* @param String $title Nice title to use * @param String $title Nice title to use
* @param bool $major is this a major release
* @param bool $latest - return is this the latest release. * @param bool $latest - return is this the latest release.
* *
* @throws InvalidArgumentException * @throws InvalidArgumentException
* *
* @return DocumentationEntity * @return DocumentationEntity
*/ */
public static function register($module, $path, $version = '', $title = false, $major = false, $latest = false) { public static function register($entity, $path, $version = '', $title = false, $latest = false) {
if(!file_exists($path)) throw new InvalidArgumentException(sprintf('Path "%s" doesn\'t exist', $path)); if(!file_exists($path)) throw new InvalidArgumentException(sprintf('Path "%s" doesn\'t exist', $path));
// add the module to the registered array // add the entity to the registered array
if(!isset(self::$registered_modules[$module])) { if(!isset(self::$registered_entities[$entity])) {
// module is completely new // entity is completely new
$entity = new DocumentationEntity($module, $version, $path, $title); $output = new DocumentationEntity($entity, $version, $path, $title);
self::$registered_modules[$module] = $entity; self::$registered_entities[$entity] = $output;
} }
else { else {
// module exists so add the version to it // entity exists so add the version to it
$entity = self::$registered_modules[$module]; $output = self::$registered_entities[$entity];
$entity->addVersion($version, $path); $output->addVersion($version, $path);
} }
if($major) { if($latest)
if(!$version) $version = ''; $output->setLatestVersion($version);
if(!in_array($version, self::$major_versions)) { return $output;
self::$major_versions[] = $version;
}
}
if($latest) {
$entity->setLatestVersion($version);
}
return $entity;
} }
/** /**
* Unregister a module from being included in the documentation. Useful * Unregister a entity from being included in the documentation. Useful
* for keeping {@link DocumentationService::$automatic_registration} enabled * for keeping {@link DocumentationService::$automatic_registration} enabled
* but disabling modules which you do not want to show. Combined with a * but disabling entities which you do not want to show. Combined with a
* {@link Director::isLive()} you can hide modules you don't want a client to see. * {@link Director::isLive()} you can hide entities you don't want a client to see.
* *
* If no version or lang specified then the whole module is removed. Otherwise only * If no version or lang specified then the whole entity is removed. Otherwise only
* the specified version of the documentation. * the specified version of the documentation.
* *
* @param String $module * @param String $entity
* @param String $version * @param String $version
* *
* @return bool * @return bool
*/ */
public static function unregister($moduleName, $version = '') { public static function unregister($entityName, $version = false) {
if(isset(self::$registered_modules[$moduleName])) { if(isset(self::$registered_entities[$entityName])) {
$module = self::$registered_modules[$moduleName]; $entity = self::$registered_entities[$entityName];
if($version) { if($version) {
$module->removeVersion($version); $entity->removeVersion($version);
} }
else { else {
// only given a module so unset the whole module // only given a entity so unset the whole entity
unset(self::$registered_modules[$moduleName]); unset(self::$registered_entities[$entityName]);
} }
return true; return true;
@ -328,22 +241,24 @@ class DocumentationService {
/** /**
* Register the docs from off a file system if automatic registration is turned on. * Register the docs from off a file system if automatic registration is turned on.
*
* @see {@link DocumentationService::set_automatic_registration()}
*/ */
public static function load_automatic_registration() { public static function load_automatic_registration() {
if(self::automatic_registration_enabled()) { if(self::automatic_registration_enabled()) {
$modules = scandir(BASE_PATH); $entities = scandir(BASE_PATH);
if($modules) { if($entities) {
foreach($modules as $key => $module) { foreach($entities as $key => $entity) {
$dir = is_dir(Controller::join_links(BASE_PATH, $module)); $dir = is_dir(Controller::join_links(BASE_PATH, $entity));
$ignored = in_array($module, self::get_ignored_files(), true); $ignored = in_array($entity, self::get_ignored_files(), true);
if($dir && !$ignored) { if($dir && !$ignored) {
// check to see if it has docs // check to see if it has docs
$docs = Controller::join_links($dir, 'docs'); $docs = Controller::join_links($dir, 'docs');
if(is_dir($docs)) { if(is_dir($docs)) {
self::register($module, $docs, '', $module, true); self::register($entity, $docs, '', $entity, true);
} }
} }
} }
@ -381,9 +296,9 @@ class DocumentationService {
* *
* @return String|false - File path * @return String|false - File path
*/ */
static function find_page($module, $path, $version = '', $lang = 'en') { static function find_page($entity, $path, $version = '', $lang = 'en') {
if($module = self::is_registered_module($module, $version, $lang)) { if($entity = self::is_registered_entity($entity, $version, $lang)) {
return self::find_page_recursive($module->getPath($version, $lang), $path); return self::find_page_recursive($entity->getPath($version, $lang), $path);
} }
return false; return false;
@ -513,11 +428,11 @@ class DocumentationService {
/** /**
* Return the children from a given module sorted by Title using natural ordering. * Return the children from a given entity sorted by Title using natural ordering.
* It is used for building the tree of the page. * It is used for building the tree of the page.
* *
* @param DocumentationEntity path * @param DocumentationEntity path
* @param string - an optional path within a module * @param string - an optional path within a entity
* @param bool enable several recursive calls (more than 1 level) * @param bool enable several recursive calls (more than 1 level)
* @param string - version to use * @param string - version to use
* @param string - lang to use * @param string - lang to use
@ -525,21 +440,21 @@ class DocumentationService {
* @throws Exception * @throws Exception
* @return DataObjectSet * @return DataObjectSet
*/ */
public static function get_pages_from_folder($module, $relativePath = false, $recursive = true, $version = 'trunk', $lang = 'en') { public static function get_pages_from_folder($entity, $relativePath = false, $recursive = true, $version = 'trunk', $lang = 'en') {
$output = new DataObjectSet(); $output = new DataObjectSet();
$pages = array(); $pages = array();
if(!$module instanceof DocumentationEntity) if(!$entity instanceof DocumentationEntity)
user_error("get_pages_from_folder must be passed a module", E_USER_ERROR); user_error("get_pages_from_folder must be passed a entity", E_USER_ERROR);
$path = $module->getPath($version, $lang); $path = $entity->getPath($version, $lang);
if(self::is_registered_module($module)) { if(self::is_registered_entity($entity)) {
self::get_pages_from_folder_recursive($path, $relativePath, $recursive, $pages); self::get_pages_from_folder_recursive($path, $relativePath, $recursive, $pages);
} }
else { else {
return user_error("$module is not registered", E_USER_WARNING); return user_error("$entity is not registered", E_USER_WARNING);
} }
if(count($pages) > 0) { if(count($pages) > 0) {
@ -557,7 +472,7 @@ class DocumentationService {
// if no extension, put a slash on it // if no extension, put a slash on it
if(strpos($relative, '.') === false) $relative .= '/'; if(strpos($relative, '.') === false) $relative .= '/';
$page->setEntity($module); $page->setEntity($entity);
$page->setRelativePath($relative); $page->setRelativePath($relative);
$page->setVersion($version); $page->setVersion($version);
$page->setLang($lang); $page->setLang($lang);
@ -570,8 +485,9 @@ class DocumentationService {
} }
/** /**
* Recursively search through $folder * Recursively search through a given folder
* *
* @see {@link DocumentationService::get_pages_from_folder}
*/ */
private static function get_pages_from_folder_recursive($base, $relative, $recusive, &$pages) { private static function get_pages_from_folder_recursive($base, $relative, $recusive, &$pages) {
if(!is_dir($base)) throw new Exception(sprintf('%s is not a folder', $folder)); if(!is_dir($base)) throw new Exception(sprintf('%s is not a folder', $folder));

View File

@ -33,9 +33,11 @@ class DocumentationViewer extends Controller {
public $language = "en"; public $language = "en";
/** /**
* The string name of the currently accessed {@link DocumentationEntity}
* object. To access the entire object use {@link getEntity()}
* @var string * @var string
*/ */
public $module = ''; public $entity = '';
/** /**
* @var array * @var array
@ -59,7 +61,6 @@ class DocumentationViewer extends Controller {
// javascript // javascript
Requirements::javascript(THIRDPARTY_DIR .'/jquery/jquery.js'); Requirements::javascript(THIRDPARTY_DIR .'/jquery/jquery.js');
Requirements::javascript('sapphiredocs/javascript/shBrushSS.js');
Requirements::combine_files( Requirements::combine_files(
'syntaxhighlighter.js', 'syntaxhighlighter.js',
@ -133,7 +134,12 @@ class DocumentationViewer extends Controller {
$this->Remaining = $request->shift(10); $this->Remaining = $request->shift(10);
DocumentationService::load_automatic_registration(); DocumentationService::load_automatic_registration();
if(isset($firstParam)) { // if no params passed at all then it's the homepage
if(!$firstParam && !$secondParam && !$thirdParam) {
return parent::handleRequest($request);
}
if($firstParam) {
// allow assets // allow assets
if($firstParam == "assets") return parent::handleRequest($request); if($firstParam == "assets") return parent::handleRequest($request);
@ -150,11 +156,11 @@ class DocumentationViewer extends Controller {
// check to see if the module is a valid module. If it isn't, then we // check to see if the module is a valid module. If it isn't, then we
// need to throw a 404. // need to throw a 404.
if(!DocumentationService::is_registered_module($firstParam)) { if(!DocumentationService::is_registered_entity($firstParam)) {
return $this->throw404(); return $this->throw404();
} }
$this->module = $firstParam; $this->entity = $firstParam;
$this->language = $secondParam; $this->language = $secondParam;
if(isset($thirdParam) && (is_numeric($thirdParam) || in_array($thirdParam, array('master', 'trunk')))) { if(isset($thirdParam) && (is_numeric($thirdParam) || in_array($thirdParam, array('master', 'trunk')))) {
@ -169,7 +175,7 @@ class DocumentationViewer extends Controller {
} }
// 'current' version mapping // 'current' version mapping
$entity = DocumentationService::is_registered_module($this->module, null, $this->getLang()); $entity = DocumentationService::is_registered_entity($this->entity, null, $this->getLang());
if($entity) { if($entity) {
$current = $entity->getLatestVersion(); $current = $entity->getLatestVersion();
@ -215,14 +221,14 @@ class DocumentationViewer extends Controller {
// into account. This automatically includes ' ' so all the counts // into account. This automatically includes ' ' so all the counts
// are 1 more than what you would expect // are 1 more than what you would expect
if($this->module || $this->Remaining) { if($this->entity || $this->Remaining) {
$paramCount = count($this->Remaining); $paramCount = count($this->Remaining);
if($paramCount == 0) { if($paramCount == 0) {
return parent::getViewer('folder'); return parent::getViewer('folder');
} }
else if($module = $this->getModule()) { else if($entity = $this->getEntity()) {
// if this is a folder return the folder listing // if this is a folder return the folder listing
if($this->locationExists() == 2) { if($this->locationExists() == 2) {
return parent::getViewer('folder'); return parent::getViewer('folder');
@ -245,8 +251,8 @@ class DocumentationViewer extends Controller {
function getVersion() { function getVersion() {
if($this->version) return $this->version; if($this->version) return $this->version;
if($module = $this->getModule()) { if($entity = $this->getEntity()) {
$this->version = $module->getLatestVersion(); $this->version = $entity->getLatestVersion();
return $this->version; return $this->version;
} }
@ -264,69 +270,40 @@ class DocumentationViewer extends Controller {
} }
/** /**
* Return all the available languages. Optionally the languages which are * Return all the available languages for the module.
* available for a given module
* *
* @param String - The name of the module * @param String - The name of the module
* @return DataObjectSet * @return DataObjectSet
*/ */
function getLanguages($module = false) { function getLanguages() {
$output = new DataObjectSet(); $entity = $this->getEntity();
if($module) { if($entity) {
// lookup the module for the available languages return $entity->getLanguages();
// @todo
}
else {
$languages = DocumentationService::get_registered_languages();
if($languages) {
foreach($languages as $key => $lang) {
if(stripos($_SERVER['REQUEST_URI'], '/'. $this->Lang .'/') === false) {
// no language is in the URL currently. It needs to insert the language
// into the url like /sapphire/install to /en/sapphire/install
//
// @todo
} }
$link = str_ireplace('/'.$this->Lang .'/', '/'. $lang .'/', $_SERVER['REQUEST_URI']); return array('en' => 'English');
$output->push(new ArrayData(array(
'Title' => $lang,
'Link' => $link
)));
}
}
}
return $output;
} }
/** /**
* Get all the versions loaded into the module. If the project is only displaying from * Get all the versions loaded for the current {@link DocumentationEntity}.
* the filesystem then they are loaded under the 'Current' namespace. * the filesystem then they are loaded under the 'Current' namespace.
* *
* @todo Only show 'core' versions (2.3, 2.4) versions of the modules are going * @param String $entity name of module to limit it to eg sapphire
* to spam this
*
* @param String $module name of module to limit it to eg sapphire
* @return DataObjectSet * @return DataObjectSet
*/ */
function getVersions($module = false) { function getVersions($entity = false) {
if(!$module) $module = $this->module; if(!$entity) $entity = $this->entity;
$entity = DocumentationService::is_registered_module($module); $entity = DocumentationService::is_registered_entity($entity);
if(!$entity) return false; if(!$entity) return false;
$versions = DocumentationService::get_registered_versions($module); $versions = $entity->getVersions();
$output = new DataObjectSet(); $output = new DataObjectSet();
$currentVersion = $this->getVersion();
if($versions) { if($versions) {
$lang = $this->getLang(); $lang = $this->getLang();
$currentVersion = $this->getVersion();
foreach($versions as $key => $version) { foreach($versions as $key => $version) {
// work out the link to this version of the documentation. // work out the link to this version of the documentation.
@ -334,14 +311,10 @@ class DocumentationViewer extends Controller {
$linkingMode = ($currentVersion == $version) ? 'current' : 'link'; $linkingMode = ($currentVersion == $version) ? 'current' : 'link';
if(!$version) $version = 'Current'; if(!$version) $version = 'Current';
$major = (in_array($version, DocumentationService::get_major_versions())) ? true : false;
$output->push(new ArrayData(array( $output->push(new ArrayData(array(
'Title' => $version, 'Title' => $version,
'Link' => $entity->Link($version, $lang), 'Link' => $this->Link(implode('/',$this->Remaining), $entity->getFolder(), $version),
'LinkingMode' => $linkingMode, 'LinkingMode' => $linkingMode
'MajorRelease' => $major
))); )));
} }
} }
@ -350,43 +323,37 @@ class DocumentationViewer extends Controller {
} }
/** /**
* Generate the module which are to be documented. It filters * Generate a list of entities which have been registered and which can
* the list based on the current head version. It displays the contents * be documented.
* from the index.md file on the page to use.
* *
* @return DataObject * @return DataObject
*/ */
function getModules($version = false, $lang = false) { function getEntities($version = false, $lang = false) {
if(!$version) $version = $this->getVersion(); if(!$version) $version = $this->getVersion();
if(!$lang) $lang = $this->getLang(); if(!$lang) $lang = $this->getLang();
$modules = DocumentationService::get_registered_modules($version, $lang); $entities = DocumentationService::get_registered_entities($version, $lang);
$output = new DataObjectSet(); $output = new DataObjectSet();
if($modules) { $currentEntity = $this->getEntity();
foreach($modules as $module) {
$path = $module->getPath($version, $lang);
$absFilepath = $path . '/index.md';
$relativeFilePath = str_replace($path, '', $absFilepath);
if(file_exists($absFilepath)) { if($entities) {
$page = new DocumentationPage(); foreach($entities as $entity) {
$page->setRelativePath($relativeFilePath); $mode = ($entity === $currentEntity) ? 'current' : 'link';
$page->setEntity($module); $folder = $entity->getFolder();
$page->setLang($lang);
$page->setVersion($version);
$content = DocumentationParser::parse($page, $this->Link(array_slice($this->Remaining, -1, -1))); $link = $this->Link(array_slice($this->Remaining, -1, -1), $folder, $version, $lang);
} else {
$content = ''; $content = false;
if($page = $entity->getIndexPage($version, $lang)) {
$content = DBField::create('HTMLText', DocumentationParser::parse($page, $link));
} }
// build the dataset. Load the $Content from an index.md
$output->push(new ArrayData(array( $output->push(new ArrayData(array(
'Title' => $module->getTitle(), 'Title' => $entity->getTitle(),
'Code' => $module, 'Link' => $link,
'Link' => $this->Link(array_slice($this->Remaining, -1, -1), $module->moduleFolder), 'LinkingMode' => $mode,
'Content' => DBField::create("HTMLText", $content) 'Content' => $content
))); )));
} }
} }
@ -399,10 +366,10 @@ class DocumentationViewer extends Controller {
* *
* @return false|DocumentationEntity * @return false|DocumentationEntity
*/ */
function getModule() { function getEntity() {
if($this->module) { if($this->entity) {
return DocumentationService::is_registered_module( return DocumentationService::is_registered_entity(
$this->module, $this->entity,
$this->version, $this->version,
$this->language $this->language
); );
@ -420,19 +387,19 @@ class DocumentationViewer extends Controller {
* @return int * @return int
*/ */
function locationExists() { function locationExists() {
$module = $this->getModule(); $entity = $this->getEntity();
if($module) { if($entity) {
$has_dir = is_dir(Controller::join_links( $has_dir = is_dir(Controller::join_links(
$module->getPath($this->getVersion(), $this->getLang()), $entity->getPath($this->getVersion(), $this->getLang()),
implode('/', $this->Remaining) implode('/', $this->Remaining)
)); ));
if($has_dir) return 2; if($has_dir) return 2;
$has_page = DocumentationService::find_page( $has_page = DocumentationService::find_page(
$module, $entity,
$this->Remaining, $this->Remaining,
$this->getVersion(), $this->getVersion(),
$this->getLang() $this->getLang()
@ -448,15 +415,15 @@ class DocumentationViewer extends Controller {
* @return DocumentationPage * @return DocumentationPage
*/ */
function getPage() { function getPage() {
$module = $this->getModule(); $entity = $this->getEntity();
if(!$module) return false; if(!$entity) return false;
$version = $this->getVersion(); $version = $this->getVersion();
$lang = $this->getLang(); $lang = $this->getLang();
$absFilepath = DocumentationService::find_page( $absFilepath = DocumentationService::find_page(
$module, $entity,
$this->Remaining, $this->Remaining,
$version, $version,
$lang $lang
@ -464,14 +431,14 @@ class DocumentationViewer extends Controller {
if($absFilepath) { if($absFilepath) {
$relativeFilePath = str_replace( $relativeFilePath = str_replace(
$module->getPath($version, $lang), $entity->getPath($version, $lang),
'', '',
$absFilepath $absFilepath
); );
$page = new DocumentationPage(); $page = new DocumentationPage();
$page->setRelativePath($relativeFilePath); $page->setRelativePath($relativeFilePath);
$page->setEntity($module); $page->setEntity($entity);
$page->setLang($lang); $page->setLang($lang);
$page->setVersion($version); $page->setVersion($version);
@ -482,15 +449,16 @@ class DocumentationViewer extends Controller {
} }
/** /**
* Get the related pages to this module and the children to those pages * Get the related pages to the current {@link DocumentationEntity} and
* the children to those pages
* *
* @todo this only handles 2 levels. Could make it recursive * @todo this only handles 2 levels. Could make it recursive
* *
* @return false|DataObjectSet * @return false|DataObjectSet
*/ */
function getModulePages() { function getEntityPages() {
if($module = $this->getModule()) { if($entity = $this->getEntity()) {
$pages = DocumentationService::get_pages_from_folder($module, null, false, $this->getVersion(), $this->getLang()); $pages = DocumentationService::get_pages_from_folder($entity, null, false, $this->getVersion(), $this->getLang());
if($pages) { if($pages) {
foreach($pages as $page) { foreach($pages as $page) {
@ -501,7 +469,7 @@ class DocumentationViewer extends Controller {
} }
$page->LinkingMode = 'link'; $page->LinkingMode = 'link';
$page->Children = $this->_getModulePagesNested($page, $module); $page->Children = $this->_getEntityPagesNested($page, $entity);
} }
} }
@ -512,7 +480,7 @@ class DocumentationViewer extends Controller {
} }
/** /**
* Get the module pages under a given page. Recursive call for {@link getModulePages()} * Get the module pages under a given page. Recursive call for {@link getEntityPages()}
* *
* @todo Need to rethink how to support pages which are pulling content from their children * @todo Need to rethink how to support pages which are pulling content from their children
* i.e if a folder doesn't have 2 then it will load the first file in the folder * i.e if a folder doesn't have 2 then it will load the first file in the folder
@ -524,7 +492,7 @@ class DocumentationViewer extends Controller {
* *
* @return DataObjectSet|false * @return DataObjectSet|false
*/ */
private function _getModulePagesNested(&$page, $module, $level = 0) { private function _getEntityPagesNested(&$page, $entity, $level = 0) {
if(isset($this->Remaining[$level])) { if(isset($this->Remaining[$level])) {
// compare segment successively, e.g. with "changelogs/alpha/2.4.0-alpha", // compare segment successively, e.g. with "changelogs/alpha/2.4.0-alpha",
// first comparison on $level=0 is against "changelogs", // first comparison on $level=0 is against "changelogs",
@ -537,13 +505,13 @@ class DocumentationViewer extends Controller {
$page->LinkingMode = (isset($this->Remaining[$level + 1])) ? 'section' : 'current'; $page->LinkingMode = (isset($this->Remaining[$level + 1])) ? 'section' : 'current';
$relativePath = Controller::join_links( $relativePath = Controller::join_links(
$module->getPath($this->getVersion(), $this->getLang()), $entity->getPath($this->getVersion(), $this->getLang()),
$page->getRelativePath() $page->getRelativePath()
); );
if(is_dir($relativePath)) { if(is_dir($relativePath)) {
$children = DocumentationService::get_pages_from_folder( $children = DocumentationService::get_pages_from_folder(
$module, $entity,
$page->getRelativePath(), $page->getRelativePath(),
false, false,
$this->getVersion(), $this->getVersion(),
@ -563,7 +531,7 @@ class DocumentationViewer extends Controller {
} }
$child->LinkingMode = 'link'; $child->LinkingMode = 'link';
$child->Children = $this->_getModulePagesNested($child, $module, $level + 1); $child->Children = $this->_getEntityPagesNested($child, $entity, $level + 1);
} }
return $children; return $children;
@ -590,12 +558,12 @@ class DocumentationViewer extends Controller {
// If no page found then we may want to get the listing of the folder. // If no page found then we may want to get the listing of the folder.
// In case no folder exists, show a "not found" page. // In case no folder exists, show a "not found" page.
$module = $this->getModule(); $entity = $this->getEntity();
$url = $this->Remaining; $url = $this->Remaining;
if($url && $module) { if($url && $entity) {
$pages = DocumentationService::get_pages_from_folder( $pages = DocumentationService::get_pages_from_folder(
$module, $entity,
implode('/', $url), implode('/', $url),
false, false,
$this->getVersion(), $this->getVersion(),
@ -612,7 +580,7 @@ class DocumentationViewer extends Controller {
return $this->customise(array( return $this->customise(array(
'Content' => false, 'Content' => false,
'Title' => _t('DocumentationViewer.MODULES', 'Modules'), 'Title' => _t('DocumentationViewer.MODULES', 'Modules'),
'Pages' => $this->getModules() 'Pages' => $this->getEntities()
))->renderWith('DocFolderListing'); ))->renderWith('DocFolderListing');
} }
@ -628,7 +596,7 @@ class DocumentationViewer extends Controller {
function getBreadcrumbs() { function getBreadcrumbs() {
if(!$this->Remaining) $this->Remaining = array(); if(!$this->Remaining) $this->Remaining = array();
$pages = array_merge(array($this->module), $this->Remaining); $pages = array_merge(array($this->entity), $this->Remaining);
$output = new DataObjectSet(); $output = new DataObjectSet();
@ -673,24 +641,30 @@ class DocumentationViewer extends Controller {
/** /**
* Return the base link to this documentation location * Return the base link to this documentation location
* *
* @param string $path - subfolder path
* @param string $entity - name of entity
* @param float $version - optional version
* @param string $lang - optional lang
*
* @return String * @return String
*/ */
public function Link($path = false, $module = false) { public function Link($path = false, $entity = false, $version = false, $lang = false) {
$base = Director::absoluteBaseURL(); $base = Director::absoluteBaseURL();
$version = $this->getVersion(); $version = (!$version) ? $this->getVersion() : $version;
$lang = $this->getLang(); $lang = (!$lang) ? $this->getLang() : $lang;
$module = (!$module && $this->module) ? $this->module : $module;
$entity = (!$entity && $this->entity) ? $this->entity : $entity;
$action = ''; $action = '';
if(is_string($path)) $action = $path; if(is_string($path)) {
$action = $path;
}
else if(is_array($path)) { else if(is_array($path)) {
$action = implode('/', $path); $action = implode('/', $path);
} }
$link = Controller::join_links($base, self::get_link_base(), $module, $lang, $version, $action); $link = Controller::join_links($base, self::get_link_base(), $entity, $lang, $version, $action);
return $link; return $link;
} }
@ -703,8 +677,8 @@ class DocumentationViewer extends Controller {
* @return Form * @return Form
*/ */
function LanguageForm() { function LanguageForm() {
if($module = $this->getModule()) { if($entity = $this->getEntity()) {
$langs = DocumentationService::get_registered_languages($module->getModuleFolder()); $langs = DocumentationService::get_registered_languages($entity->getFolder());
} }
else { else {
$langs = DocumentationService::get_registered_languages(); $langs = DocumentationService::get_registered_languages();

View File

@ -1,20 +1,20 @@
<?php <?php
/** /**
* A wrapper for a documentation entity which is created when registering the * A {@link DocumentationEntity} is created when registering a module path
* path with {@link DocumentationService::register()}. This refers to a whole package * with {@link DocumentationService::register()}. A {@link DocumentationEntity}
* rather than a specific page but if we need page options we may need to introduce * represents a module or folder with documentation rather than a specific
* a class for that. * page. Individual pages are handled by {@link DocumentationPage}
* *
* Each folder must have at least one language subfolder, which is automatically * Each folder must have at least one language subfolder, which is automatically
* determined through {@link addVersion()} and should not be included in the $path argument. * determined through {@link addVersion()} and should not be included in the $path argument.
* *
* Versions are assumed to be in numeric format (e.g. '2.4'), * Versions are assumed to be in numeric format (e.g. '2.4'),
* mainly as an easy way to distinguish them from language codes in the routing logic. *
* They're also parsed through version_compare() in {@link getLatestVersion()} which assumes a certain format. * They're also parsed through version_compare() in {@link getLatestVersion()} which assumes a certain format.
* *
* @package sapphiredocs * @package sapphiredocs
* @subpackage model * @subpackage models
*/ */
class DocumentationEntity extends ViewableData { class DocumentationEntity extends ViewableData {
@ -24,9 +24,9 @@ class DocumentationEntity extends ViewableData {
); );
/** /**
* @var string $module folder name * @var string $folder folder name
*/ */
private $moduleFolder; private $folder;
/** /**
* @var string $title nice title * @var string $title nice title
@ -52,21 +52,21 @@ class DocumentationEntity extends ViewableData {
* Constructor. You do not need to pass the langs to this as * Constructor. You do not need to pass the langs to this as
* it will work out the languages from the filesystem * it will work out the languages from the filesystem
* *
* @param string $module name of module * @param string $folder folder name
* @param string $version version of this module * @param string $version version of this module
* @param string $path Absolute path to this module (excluding language folders) * @param string $path Absolute path to this module (excluding language folders)
* @param string $title * @param string $title
*/ */
function __construct($module, $version, $path, $title = false) { function __construct($folder, $version, $path, $title = false) {
$this->addVersion($version, $path); $this->addVersion($version, $path);
$this->title = (!$title) ? $module : $title; $this->title = (!$title) ? $folder : $title;
$this->moduleFolder = $module; $this->folder = $folder;
} }
/** /**
* Return the languages which are available * Return the languages which are available
* *
* @return Array * @return array
*/ */
public function getLanguages() { public function getLanguages() {
return $this->langs; return $this->langs;
@ -100,8 +100,8 @@ class DocumentationEntity extends ViewableData {
* *
* @return String * @return String
*/ */
public function getModuleFolder() { public function getFolder() {
return $this->moduleFolder; return $this->folder;
} }
/** /**
@ -114,9 +114,9 @@ class DocumentationEntity extends ViewableData {
} }
/** /**
* Return the versions which are available * Return the versions which have been registered for this entity.
* *
* @return Array * @return array
*/ */
public function getVersions() { public function getVersions() {
return array_keys($this->versions); return array_keys($this->versions);
@ -218,7 +218,7 @@ class DocumentationEntity extends ViewableData {
$path = $this->versions[$versions[0]]; $path = $this->versions[$versions[0]];
} }
return rtrim($path, '/') . '/' . rtrim($lang, '/') .'/'; return Controller::join_links($path, $lang);
} }
/** /**
@ -239,12 +239,37 @@ class DocumentationEntity extends ViewableData {
return Controller::join_links( return Controller::join_links(
DocumentationViewer::get_link_base(), DocumentationViewer::get_link_base(),
$this->moduleFolder, $this->getFolder(),
$lang, $lang,
$version $version
); );
} }
/**
* Return the summary / index text for this entity. Either pulled
* from an index file or some other summary field
*
* @return DocumentationPage
*/
function getIndexPage($version, $lang = 'en') {
$path = $this->getPath($version, $lang);
$absFilepath = Controller::join_links($path, 'index.md');
if(file_exists($absFilepath)) {
$relativeFilePath = str_replace($path, '', $absFilepath);
$page = new DocumentationPage();
$page->setRelativePath($relativeFilePath);
$page->setEntity($this);
$page->setLang($lang);
$page->setVersion($version);
return $page;
}
return false;
}
/** /**
* @return string * @return string
*/ */

View File

@ -145,7 +145,7 @@ class DocumentationPage extends ViewableData {
} }
/** /**
* Relative to the module base, not the webroot * Relative to the module base, not the webroot.
* *
* @return string * @return string
*/ */

View File

@ -69,12 +69,26 @@ fieldset { border: none; }
#content { } #content { }
/* Versions */ /* Versions */
#versions-nav { background: #121929; margin: 0 0 44px; padding: 10px 0 0 10px; overflow: hidden;} .documentation-nav {
#versions-nav h2 { font-size: 11px; color: #fff; font-weight: normal; float: left; margin-right: 5px;} clear: both;
#versions-nav ul { margin: 0; padding: 0; float: left;} margin: 0 0 5px;
#versions-nav li { list-style: none; } overflow: hidden; color: #999999;
#versions-nav li a { display: block; float: left; margin-left: 4px; padding: 11px; font-size: 14px;} font-size: 11px;
#versions-nav li a.current { background: #fff;} }
.documentation-nav h2 { font-size: 11px; font-weight: normal; float: left; margin-right: 5px;}
.documentation-nav ul { margin: 0; padding: 0; float: left;}
.documentation-nav li { display: inline; list-style: none; padding: 0; margin: 0; font-size: 11px; }
.documentation-nav li a { margin-left: 5px; padding: 0px; }
.documentation-nav li a.current {
background: #0973A6; color: #fff; font-weight: bold;
padding: 4px;
-moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px;
}
.documentation-nav li a.current:hover,
.documentation-nav li a.current:focus {
text-decoration: none;
}
#left-column { width: 640px; float: left; } #left-column { width: 640px; float: left; }
#right-column { #right-column {

View File

@ -20,34 +20,47 @@
<div id="language"> <div id="language">
$LanguageForm $LanguageForm
</div> </div>
<div id="breadcrumbs">
<% include DocBreadcrumbs %>
</div>
</div> </div>
<div id="layout"> <div id="layout">
<div id="versions-nav"> <div id="search-bar">
<h2>Versions:</h2> <div id="breadcrumbs">
<% include DocBreadcrumbs %>
</div>
<div id="search">
$DocumentationSearchForm
</div>
<% if Entities %>
<div id="entities-nav" class="documentation-nav">
<h2>Modules:</h2>
<ul> <ul>
<% control Versions %> <% control Entities %>
<% if MajorRelease %> <li><a href="$Link" class="$LinkingMode">$Title</a></li>
<li class="major-release"><a href="$Link" class="$LinkingMode">$Title</a></li>
<% else %>
<li class="module-only"><a href="$Link" class="$LinkingMode">$Title</a></li>
<% end_if %>
<% end_control %> <% end_control %>
</ul> </ul>
</div> </div>
<div id="content"> <% end_if %>
<% if Versions %>
<div id="versions-nav" class="documentation-nav">
<h2>Versions:</h2>
<ul>
<% control Versions %>
<li><a href="$Link" class="$LinkingMode">$Title</a></li>
<% end_control %>
</ul>
</div>
<% end_if %>
</div>
<div id="content" class="typography">
$Layout $Layout
</div> </div>
</div> </div>
</div> </div>
<div id="footer"> <% include DocumentationFooter %>
<p>Documentation powered by <a href="http://www.silverstripe.org">SilverStripe</a>.</p>
</div>
</body> </body>
</html> </html>

View File

@ -1,8 +1,6 @@
<div id="in-this-module" class="sidebar-box"> <div id="sibling-pages" class="sidebar-box">
<h4>In this module</h4>
<ul> <ul>
<% control ModulePages %> <% control EntityPages %>
<li> <li>
<a href="$Link" class="$LinkingMode">$Title</a> <a href="$Link" class="$LinkingMode">$Title</a>
<% if Children %> <% if Children %>
@ -14,8 +12,7 @@
<% control Children %> <% control Children %>
<li><a href="$Link" class="$LinkingMode">$Title</a></li> <li><a href="$Link" class="$LinkingMode">$Title</a></li>
<% end_control %> <% end_control %>
</ul> </ul><% end_if %>
<% end_if %>
</li> </li>
<% end_control %> <% end_control %>
</ul> </ul>

View File

@ -0,0 +1,3 @@
<div id="footer">
<p>Documentation powered by <a href="http://www.silverstripe.org">SilverStripe</a>.</p>
</div>

View File

@ -10,7 +10,7 @@ class DocumentationEntityTest extends SapphireTest {
$this->assertEquals($entity->getTitle(), 'My Test'); $this->assertEquals($entity->getTitle(), 'My Test');
$this->assertEquals($entity->getVersions(), array('1.0')); $this->assertEquals($entity->getVersions(), array('1.0'));
$this->assertEquals($entity->getLanguages(), array('en', 'de')); $this->assertEquals($entity->getLanguages(), array('en', 'de'));
$this->assertEquals($entity->getModuleFolder(), 'docs'); $this->assertEquals($entity->getFolder(), 'docs');
$this->assertTrue($entity->hasVersion('1.0')); $this->assertTrue($entity->hasVersion('1.0'));
$this->assertFalse($entity->hasVersion('2.0')); $this->assertFalse($entity->hasVersion('2.0'));

View File

@ -18,17 +18,17 @@ class DocumentationViewerTest extends FunctionalTest {
$this->origEnabled = DocumentationService::automatic_registration_enabled(); $this->origEnabled = DocumentationService::automatic_registration_enabled();
DocumentationService::set_automatic_registration(false); DocumentationService::set_automatic_registration(false);
$this->origModules = DocumentationService::get_registered_modules(); $this->origModules = DocumentationService::get_registered_entities();
$this->origLinkBase = DocumentationViewer::get_link_base(); $this->origLinkBase = DocumentationViewer::get_link_base();
DocumentationViewer::set_link_base('dev/docs/'); DocumentationViewer::set_link_base('dev/docs/');
foreach($this->origModules as $module) { foreach($this->origModules as $module) {
DocumentationService::unregister($module->getModuleFolder()); DocumentationService::unregister($module->getFolder());
} }
// We set 3.0 as current, and test most assertions against 2.4 - to avoid 'current' rewriting issues // We set 3.0 as current, and test most assertions against 2.4 - to avoid 'current' rewriting issues
DocumentationService::register("DocumentationViewerTests", BASE_PATH . "/sapphiredocs/tests/docs/", '2.3'); DocumentationService::register("DocumentationViewerTests", BASE_PATH . "/sapphiredocs/tests/docs/", '2.3');
DocumentationService::register("DocumentationViewerTests", BASE_PATH . "/sapphiredocs/tests/docs-v2.4/", '2.4', 'Doc Test', true); DocumentationService::register("DocumentationViewerTests", BASE_PATH . "/sapphiredocs/tests/docs-v2.4/", '2.4', 'Doc Test', true);
DocumentationService::register("DocumentationViewerTests", BASE_PATH . "/sapphiredocs/tests/docs-v3.0/", '3.0', 'Doc Test', true, true); DocumentationService::register("DocumentationViewerTests", BASE_PATH . "/sapphiredocs/tests/docs-v3.0/", '3.0', 'Doc Test');
} }
function tearDownOnce() { function tearDownOnce() {
@ -104,7 +104,7 @@ class DocumentationViewerTest extends FunctionalTest {
function testGetModulePagesShort() { function testGetModulePagesShort() {
$v = new DocumentationViewer(); $v = new DocumentationViewer();
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/2.3/subfolder/')); $response = $v->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/2.3/subfolder/'));
$pages = $v->getModulePages(); $pages = $v->getEntityPages();
$arr = $pages->toArray(); $arr = $pages->toArray();
@ -116,7 +116,7 @@ class DocumentationViewerTest extends FunctionalTest {
function testGetModulePages() { function testGetModulePages() {
$v = new DocumentationViewer(); $v = new DocumentationViewer();
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/2.3/subfolder/')); $response = $v->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/2.3/subfolder/'));
$pages = $v->getModulePages(); $pages = $v->getEntityPages();
$this->assertEquals( $this->assertEquals(
array('sort/', 'subfolder/', 'test.md'), array('sort/', 'subfolder/', 'test.md'),
$pages->column('Filename') $pages->column('Filename')
@ -169,16 +169,16 @@ class DocumentationViewerTest extends FunctionalTest {
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/2.3/test')); $response = $v->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/2.3/test'));
$this->assertEquals('2.3', $v->getVersion()); $this->assertEquals('2.3', $v->getVersion());
$this->assertEquals('en', $v->getLang()); $this->assertEquals('en', $v->getLang());
$this->assertEquals('DocumentationViewerTests', $v->module); $this->assertEquals('DocumentationViewerTests', $v->getEntity()->getTitle());
$this->assertEquals(array('test'), $v->Remaining); $this->assertEquals(array('test'), $v->Remaining);
// Module index without version and language. Should pick up the defaults // Module index without version and language. Should pick up the defaults
$v2 = new DocumentationViewer(); $v2 = new DocumentationViewer();
$response = $v2->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/test')); $response = $v2->handleRequest(new SS_HTTPRequest('GET', 'DocumentationViewerTests/en/test'));
$this->assertEquals('3.0', $v2->getVersion()); $this->assertEquals('2.4', $v2->getVersion());
$this->assertEquals('en', $v2->getLang()); $this->assertEquals('en', $v2->getLang());
$this->assertEquals('DocumentationViewerTests', $v2->module); $this->assertEquals('DocumentationViewerTests', $v2->getEntity()->getTitle());
$this->assertEquals(array('test'), $v2->Remaining); $this->assertEquals(array('test'), $v2->Remaining);
// Overall index // Overall index