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
/**
* 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) {
$title = $linksWithTitles[1][$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(
$match,
sprintf('[%s](%s)', $title, $url),
@ -186,7 +187,7 @@ class DocumentationParser {
if($links) {
foreach($links[0] as $i => $match) {
$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(
$match,
sprintf('[%s](%s)', $subject, $url),

View File

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

View File

@ -3,26 +3,24 @@
/**
* 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
* documented
*
* @todo - unregistering a lang / version from site does not update the registered_* arrays
* - handle modules (rather than core) differently
* @package sapphiredocs
*/
class DocumentationService {
/**
* A mapping of know / popular languages to nice titles.
* A mapping of known / popular languages to nice titles.
*
* @var Array
*/
private static $language_mapping = array(
'en' => 'English',
'fr' => 'French',
'de' => 'German'
'fr' => 'Français',
'de' => 'Deutsch'
);
/**
@ -33,40 +31,43 @@ class DocumentationService {
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
*/
public static $valid_markdown_extensions = array('.md', '.txt', '.markdown');
/**
* Registered modules to include in the documentation. Either pre-filled by the
* automatic filesystem parser or via {@link DocumentationService::register()}. Stores
* {@link DocumentEntity} objects which contain the languages and versions of each module.
* Registered {@link DocumentationEntity} objects to include in the documentation.
* Either pre-filled by the automatic filesystem parser or via {@link DocumentationService::register()}.
* 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
*/
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
* the documentation but for sapphire/cms and overall we need to register major
* versions via {@link DocumentationService::register}
* Should generation of documentation categories be automatic?
*
* @var array
*/
private static $major_versions = array();
/**
* Return the major versions
* If this is set to true then it will generate {@link DocumentationEntity}
* objects from the filesystem. This can be slow and also some projects
* may want to restrict to specific project folders (rather than everything).
*
* @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() {
return self::$major_versions;
}
private static $automatic_registration = true;
/**
* Return the allowed extensions
@ -94,86 +95,9 @@ class DocumentationService {
public function get_ignored_files() {
return self::$ignored_files;
}
/**
* Check to see if a given language is registered in the system
*
* @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
* Set automatic registration of entities and documentation folders
*
* @see DocumentationService::$automatic_registration
* @param bool
@ -182,14 +106,14 @@ class DocumentationService {
self::$automatic_registration = $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
self::$registered_modules = array();
self::$registered_entities = array();
}
}
/**
* Is automatic registration of modules enabled.
* Is automatic registration of entities enabled.
*
* @return bool
*/
@ -198,24 +122,24 @@ class DocumentationService {
}
/**
* Return the modules which are listed for documentation. Optionally only get
* modules which have a version or language given
* Return the entities which are listed for documentation. Optionally only get
* entities which have a version or language given
*
* @return array
*/
public static function get_registered_modules($version = false, $lang = false) {
public static function get_registered_entities($version = false, $lang = false) {
$output = array();
if($modules = self::$registered_modules) {
if($entities = self::$registered_entities) {
if($version || $lang) {
foreach($modules as $module) {
if(self::is_registered_module($module->getModuleFolder(), $version, $lang)) {
$output[] = $module;
foreach($entities as $entity) {
if(self::is_registered_entity($entity->getFolder(), $version, $lang)) {
$output[] = $entity;
}
}
}
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 $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) {
$check = ($module instanceof DocumentationEntity) ? $module->getModuleFolder() : (string) $module;
public static function is_registered_entity($entity, $version = false, $lang = false) {
$check = ($entity instanceof DocumentationEntity) ? $entity->getFolder() : (string) $entity;
if(isset(self::$registered_modules[$check])) {
$module = self::$registered_modules[$check];
if(isset(self::$registered_entities[$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 $module;
return $entity;
}
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
*
* @param String $module Name of module to register
* @param String $entity Name of entity to register
* @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 bool $major is this a major release
* @param bool $latest - return is this the latest release.
*
* @throws InvalidArgumentException
*
* @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));
// add the module to the registered array
if(!isset(self::$registered_modules[$module])) {
// module is completely new
$entity = new DocumentationEntity($module, $version, $path, $title);
// add the entity to the registered array
if(!isset(self::$registered_entities[$entity])) {
// entity is completely new
$output = new DocumentationEntity($entity, $version, $path, $title);
self::$registered_modules[$module] = $entity;
self::$registered_entities[$entity] = $output;
}
else {
// module exists so add the version to it
$entity = self::$registered_modules[$module];
$entity->addVersion($version, $path);
// entity exists so add the version to it
$output = self::$registered_entities[$entity];
$output->addVersion($version, $path);
}
if($major) {
if(!$version) $version = '';
if(!in_array($version, self::$major_versions)) {
self::$major_versions[] = $version;
}
}
if($latest)
$output->setLatestVersion($version);
if($latest) {
$entity->setLatestVersion($version);
}
return $entity;
return $output;
}
/**
* 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
* but disabling modules 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.
* but disabling entities which you do not want to show. Combined with a
* {@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.
*
* @param String $module
* @param String $entity
* @param String $version
*
* @return bool
*/
public static function unregister($moduleName, $version = '') {
if(isset(self::$registered_modules[$moduleName])) {
$module = self::$registered_modules[$moduleName];
public static function unregister($entityName, $version = false) {
if(isset(self::$registered_entities[$entityName])) {
$entity = self::$registered_entities[$entityName];
if($version) {
$module->removeVersion($version);
$entity->removeVersion($version);
}
else {
// only given a module so unset the whole module
unset(self::$registered_modules[$moduleName]);
// only given a entity so unset the whole entity
unset(self::$registered_entities[$entityName]);
}
return true;
@ -328,22 +241,24 @@ class DocumentationService {
/**
* 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() {
if(self::automatic_registration_enabled()) {
$modules = scandir(BASE_PATH);
$entities = scandir(BASE_PATH);
if($modules) {
foreach($modules as $key => $module) {
$dir = is_dir(Controller::join_links(BASE_PATH, $module));
$ignored = in_array($module, self::get_ignored_files(), true);
if($entities) {
foreach($entities as $key => $entity) {
$dir = is_dir(Controller::join_links(BASE_PATH, $entity));
$ignored = in_array($entity, self::get_ignored_files(), true);
if($dir && !$ignored) {
// check to see if it has docs
$docs = Controller::join_links($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
*/
static function find_page($module, $path, $version = '', $lang = 'en') {
if($module = self::is_registered_module($module, $version, $lang)) {
return self::find_page_recursive($module->getPath($version, $lang), $path);
static function find_page($entity, $path, $version = '', $lang = 'en') {
if($entity = self::is_registered_entity($entity, $version, $lang)) {
return self::find_page_recursive($entity->getPath($version, $lang), $path);
}
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.
*
* @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 string - version to use
* @param string - lang to use
@ -525,21 +440,21 @@ class DocumentationService {
* @throws Exception
* @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();
$pages = array();
if(!$module instanceof DocumentationEntity)
user_error("get_pages_from_folder must be passed a module", E_USER_ERROR);
if(!$entity instanceof DocumentationEntity)
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);
}
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) {
@ -557,7 +472,7 @@ class DocumentationService {
// if no extension, put a slash on it
if(strpos($relative, '.') === false) $relative .= '/';
$page->setEntity($module);
$page->setEntity($entity);
$page->setRelativePath($relative);
$page->setVersion($version);
$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) {
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";
/**
* The string name of the currently accessed {@link DocumentationEntity}
* object. To access the entire object use {@link getEntity()}
* @var string
*/
public $module = '';
public $entity = '';
/**
* @var array
@ -59,7 +61,6 @@ class DocumentationViewer extends Controller {
// javascript
Requirements::javascript(THIRDPARTY_DIR .'/jquery/jquery.js');
Requirements::javascript('sapphiredocs/javascript/shBrushSS.js');
Requirements::combine_files(
'syntaxhighlighter.js',
@ -133,7 +134,12 @@ class DocumentationViewer extends Controller {
$this->Remaining = $request->shift(10);
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
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
// need to throw a 404.
if(!DocumentationService::is_registered_module($firstParam)) {
if(!DocumentationService::is_registered_entity($firstParam)) {
return $this->throw404();
}
$this->module = $firstParam;
$this->entity = $firstParam;
$this->language = $secondParam;
if(isset($thirdParam) && (is_numeric($thirdParam) || in_array($thirdParam, array('master', 'trunk')))) {
@ -169,7 +175,7 @@ class DocumentationViewer extends Controller {
}
// '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) {
$current = $entity->getLatestVersion();
@ -215,14 +221,14 @@ class DocumentationViewer extends Controller {
// into account. This automatically includes ' ' so all the counts
// are 1 more than what you would expect
if($this->module || $this->Remaining) {
if($this->entity || $this->Remaining) {
$paramCount = count($this->Remaining);
if($paramCount == 0) {
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->locationExists() == 2) {
return parent::getViewer('folder');
@ -245,8 +251,8 @@ class DocumentationViewer extends Controller {
function getVersion() {
if($this->version) return $this->version;
if($module = $this->getModule()) {
$this->version = $module->getLatestVersion();
if($entity = $this->getEntity()) {
$this->version = $entity->getLatestVersion();
return $this->version;
}
@ -264,69 +270,40 @@ class DocumentationViewer extends Controller {
}
/**
* Return all the available languages. Optionally the languages which are
* available for a given module
* Return all the available languages for the module.
*
* @param String - The name of the module
* @return DataObjectSet
*/
function getLanguages($module = false) {
$output = new DataObjectSet();
function getLanguages() {
$entity = $this->getEntity();
if($entity) {
return $entity->getLanguages();
}
if($module) {
// lookup the module for the available languages
// @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']);
$output->push(new ArrayData(array(
'Title' => $lang,
'Link' => $link
)));
}
}
}
return $output;
return array('en' => 'English');
}
/**
* 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.
*
* @todo Only show 'core' versions (2.3, 2.4) versions of the modules are going
* to spam this
*
* @param String $module name of module to limit it to eg sapphire
* @param String $entity name of module to limit it to eg sapphire
* @return DataObjectSet
*/
function getVersions($module = false) {
if(!$module) $module = $this->module;
function getVersions($entity = false) {
if(!$entity) $entity = $this->entity;
$entity = DocumentationService::is_registered_module($module);
$entity = DocumentationService::is_registered_entity($entity);
if(!$entity) return false;
$versions = DocumentationService::get_registered_versions($module);
$versions = $entity->getVersions();
$output = new DataObjectSet();
$currentVersion = $this->getVersion();
if($versions) {
$lang = $this->getLang();
$currentVersion = $this->getVersion();
foreach($versions as $key => $version) {
// work out the link to this version of the documentation.
@ -334,14 +311,10 @@ class DocumentationViewer extends Controller {
$linkingMode = ($currentVersion == $version) ? 'current' : 'link';
if(!$version) $version = 'Current';
$major = (in_array($version, DocumentationService::get_major_versions())) ? true : false;
$output->push(new ArrayData(array(
'Title' => $version,
'Link' => $entity->Link($version, $lang),
'LinkingMode' => $linkingMode,
'MajorRelease' => $major
'Link' => $this->Link(implode('/',$this->Remaining), $entity->getFolder(), $version),
'LinkingMode' => $linkingMode
)));
}
}
@ -350,43 +323,37 @@ class DocumentationViewer extends Controller {
}
/**
* Generate the module which are to be documented. It filters
* the list based on the current head version. It displays the contents
* from the index.md file on the page to use.
* Generate a list of entities which have been registered and which can
* be documented.
*
* @return DataObject
*/
function getModules($version = false, $lang = false) {
function getEntities($version = false, $lang = false) {
if(!$version) $version = $this->getVersion();
if(!$lang) $lang = $this->getLang();
$modules = DocumentationService::get_registered_modules($version, $lang);
$entities = DocumentationService::get_registered_entities($version, $lang);
$output = new DataObjectSet();
$currentEntity = $this->getEntity();
if($modules) {
foreach($modules as $module) {
$path = $module->getPath($version, $lang);
$absFilepath = $path . '/index.md';
$relativeFilePath = str_replace($path, '', $absFilepath);
if(file_exists($absFilepath)) {
$page = new DocumentationPage();
$page->setRelativePath($relativeFilePath);
$page->setEntity($module);
$page->setLang($lang);
$page->setVersion($version);
$content = DocumentationParser::parse($page, $this->Link(array_slice($this->Remaining, -1, -1)));
} else {
$content = '';
if($entities) {
foreach($entities as $entity) {
$mode = ($entity === $currentEntity) ? 'current' : 'link';
$folder = $entity->getFolder();
$link = $this->Link(array_slice($this->Remaining, -1, -1), $folder, $version, $lang);
$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(
'Title' => $module->getTitle(),
'Code' => $module,
'Link' => $this->Link(array_slice($this->Remaining, -1, -1), $module->moduleFolder),
'Content' => DBField::create("HTMLText", $content)
'Title' => $entity->getTitle(),
'Link' => $link,
'LinkingMode' => $mode,
'Content' => $content
)));
}
}
@ -399,10 +366,10 @@ class DocumentationViewer extends Controller {
*
* @return false|DocumentationEntity
*/
function getModule() {
if($this->module) {
return DocumentationService::is_registered_module(
$this->module,
function getEntity() {
if($this->entity) {
return DocumentationService::is_registered_entity(
$this->entity,
$this->version,
$this->language
);
@ -420,19 +387,19 @@ class DocumentationViewer extends Controller {
* @return int
*/
function locationExists() {
$module = $this->getModule();
$entity = $this->getEntity();
if($module) {
if($entity) {
$has_dir = is_dir(Controller::join_links(
$module->getPath($this->getVersion(), $this->getLang()),
$entity->getPath($this->getVersion(), $this->getLang()),
implode('/', $this->Remaining)
));
if($has_dir) return 2;
$has_page = DocumentationService::find_page(
$module,
$entity,
$this->Remaining,
$this->getVersion(),
$this->getLang()
@ -448,15 +415,15 @@ class DocumentationViewer extends Controller {
* @return DocumentationPage
*/
function getPage() {
$module = $this->getModule();
$entity = $this->getEntity();
if(!$module) return false;
if(!$entity) return false;
$version = $this->getVersion();
$lang = $this->getLang();
$absFilepath = DocumentationService::find_page(
$module,
$entity,
$this->Remaining,
$version,
$lang
@ -464,14 +431,14 @@ class DocumentationViewer extends Controller {
if($absFilepath) {
$relativeFilePath = str_replace(
$module->getPath($version, $lang),
$entity->getPath($version, $lang),
'',
$absFilepath
);
$page = new DocumentationPage();
$page->setRelativePath($relativeFilePath);
$page->setEntity($module);
$page->setEntity($entity);
$page->setLang($lang);
$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
*
* @return false|DataObjectSet
*/
function getModulePages() {
if($module = $this->getModule()) {
$pages = DocumentationService::get_pages_from_folder($module, null, false, $this->getVersion(), $this->getLang());
function getEntityPages() {
if($entity = $this->getEntity()) {
$pages = DocumentationService::get_pages_from_folder($entity, null, false, $this->getVersion(), $this->getLang());
if($pages) {
foreach($pages as $page) {
@ -501,7 +469,7 @@ class DocumentationViewer extends Controller {
}
$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
* 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
*/
private function _getModulePagesNested(&$page, $module, $level = 0) {
private function _getEntityPagesNested(&$page, $entity, $level = 0) {
if(isset($this->Remaining[$level])) {
// compare segment successively, e.g. with "changelogs/alpha/2.4.0-alpha",
// 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';
$relativePath = Controller::join_links(
$module->getPath($this->getVersion(), $this->getLang()),
$entity->getPath($this->getVersion(), $this->getLang()),
$page->getRelativePath()
);
if(is_dir($relativePath)) {
$children = DocumentationService::get_pages_from_folder(
$module,
$entity,
$page->getRelativePath(),
false,
$this->getVersion(),
@ -563,7 +531,7 @@ class DocumentationViewer extends Controller {
}
$child->LinkingMode = 'link';
$child->Children = $this->_getModulePagesNested($child, $module, $level + 1);
$child->Children = $this->_getEntityPagesNested($child, $entity, $level + 1);
}
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.
// In case no folder exists, show a "not found" page.
$module = $this->getModule();
$entity = $this->getEntity();
$url = $this->Remaining;
if($url && $module) {
if($url && $entity) {
$pages = DocumentationService::get_pages_from_folder(
$module,
$entity,
implode('/', $url),
false,
$this->getVersion(),
@ -612,7 +580,7 @@ class DocumentationViewer extends Controller {
return $this->customise(array(
'Content' => false,
'Title' => _t('DocumentationViewer.MODULES', 'Modules'),
'Pages' => $this->getModules()
'Pages' => $this->getEntities()
))->renderWith('DocFolderListing');
}
@ -628,7 +596,7 @@ class DocumentationViewer extends Controller {
function getBreadcrumbs() {
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();
@ -673,24 +641,30 @@ class DocumentationViewer extends Controller {
/**
* 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
*/
public function Link($path = false, $module = false) {
public function Link($path = false, $entity = false, $version = false, $lang = false) {
$base = Director::absoluteBaseURL();
$version = $this->getVersion();
$lang = $this->getLang();
$module = (!$module && $this->module) ? $this->module : $module;
$version = (!$version) ? $this->getVersion() : $version;
$lang = (!$lang) ? $this->getLang() : $lang;
$entity = (!$entity && $this->entity) ? $this->entity : $entity;
$action = '';
if(is_string($path)) $action = $path;
if(is_string($path)) {
$action = $path;
}
else if(is_array($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;
}
@ -703,8 +677,8 @@ class DocumentationViewer extends Controller {
* @return Form
*/
function LanguageForm() {
if($module = $this->getModule()) {
$langs = DocumentationService::get_registered_languages($module->getModuleFolder());
if($entity = $this->getEntity()) {
$langs = DocumentationService::get_registered_languages($entity->getFolder());
}
else {
$langs = DocumentationService::get_registered_languages();

View File

@ -1,20 +1,20 @@
<?php
/**
* A wrapper for a documentation entity which is created when registering the
* path with {@link DocumentationService::register()}. This refers to a whole package
* rather than a specific page but if we need page options we may need to introduce
* a class for that.
*
* A {@link DocumentationEntity} is created when registering a module path
* with {@link DocumentationService::register()}. A {@link DocumentationEntity}
* represents a module or folder with documentation rather than a specific
* page. Individual pages are handled by {@link DocumentationPage}
*
* 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.
*
* 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.
*
* @package sapphiredocs
* @subpackage model
* @subpackage models
*/
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
@ -52,21 +52,21 @@ class DocumentationEntity extends ViewableData {
* Constructor. You do not need to pass the langs to this as
* 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 $path Absolute path to this module (excluding language folders)
* @param string $title
*/
function __construct($module, $version, $path, $title = false) {
function __construct($folder, $version, $path, $title = false) {
$this->addVersion($version, $path);
$this->title = (!$title) ? $module : $title;
$this->moduleFolder = $module;
$this->title = (!$title) ? $folder : $title;
$this->folder = $folder;
}
/**
* Return the languages which are available
*
* @return Array
* @return array
*/
public function getLanguages() {
return $this->langs;
@ -100,8 +100,8 @@ class DocumentationEntity extends ViewableData {
*
* @return String
*/
public function getModuleFolder() {
return $this->moduleFolder;
public function getFolder() {
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() {
return array_keys($this->versions);
@ -218,7 +218,7 @@ class DocumentationEntity extends ViewableData {
$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(
DocumentationViewer::get_link_base(),
$this->moduleFolder,
$this->getFolder(),
$lang,
$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
*/

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
*/

View File

@ -69,12 +69,26 @@ fieldset { border: none; }
#content { }
/* Versions */
#versions-nav { background: #121929; margin: 0 0 44px; padding: 10px 0 0 10px; overflow: hidden;}
#versions-nav h2 { font-size: 11px; color: #fff; font-weight: normal; float: left; margin-right: 5px;}
#versions-nav ul { margin: 0; padding: 0; float: left;}
#versions-nav li { list-style: none; }
#versions-nav li a { display: block; float: left; margin-left: 4px; padding: 11px; font-size: 14px;}
#versions-nav li a.current { background: #fff;}
.documentation-nav {
clear: both;
margin: 0 0 5px;
overflow: hidden; color: #999999;
font-size: 11px;
}
.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; }
#right-column {

View File

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

View File

@ -1,21 +1,18 @@
<div id="in-this-module" class="sidebar-box">
<h4>In this module</h4>
<div id="sibling-pages" class="sidebar-box">
<ul>
<% control ModulePages %>
<% control EntityPages %>
<li>
<a href="$Link" class="$LinkingMode">$Title</a>
<% if Children %>
<ul>
<% control Children %>
<li><a href="$Link" class="$LinkingMode">$Title</a>
<% if Children %>
<ul>
<% control Children %>
<li><a href="$Link" class="$LinkingMode">$Title</a></li>
<% end_control %>
</ul>
<% end_if %>
<% if Children %>
<ul>
<% control Children %>
<li><a href="$Link" class="$LinkingMode">$Title</a></li>
<% end_control %>
</ul><% end_if %>
</li>
<% end_control %>
</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->getVersions(), array('1.0'));
$this->assertEquals($entity->getLanguages(), array('en', 'de'));
$this->assertEquals($entity->getModuleFolder(), 'docs');
$this->assertEquals($entity->getFolder(), 'docs');
$this->assertTrue($entity->hasVersion('1.0'));
$this->assertFalse($entity->hasVersion('2.0'));

View File

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