ENHANCEMENT: cleaned up logic around Link() and Path() attributes throughout. FEATURE: added search pagination and rough templates for the search results

This commit is contained in:
Will Rossiter 2010-12-22 08:21:49 +00:00
parent fede2626fc
commit 842043a8e3
12 changed files with 441 additions and 206 deletions

View File

@ -205,26 +205,45 @@ class DocumentationEntity extends ViewableData {
} }
/** /**
* Return the absolute path to this documentation entity. * Return the absolute path to this documentation entity on the
* filesystem
* *
* @return String * @return string
*/ */
public function getPath($version = false, $lang = false) { public function getPath($version = false, $lang = false) {
if(!$version) $version = ''; if(!$version) $version = '';
if(!$lang) $lang = 'en'; if(!$lang) $lang = 'en';
// Get version, or fall back to first available
if($this->hasVersion($version)) { if($this->hasVersion($version)) {
$path = $this->versions[$version]; $path = $this->versions[$version];
} else { }
else {
$versions = $this->getVersions(); $versions = $this->getVersions();
$path = $this->versions[$versions[0]]; $path = $this->versions[$versions[0]];
} }
return rtrim($path, '/') . '/' . rtrim($lang, '/') .'/'; return rtrim($path, '/') . '/' . rtrim($lang, '/') .'/';
} }
/**
* Returns the web accessible link to this Entity
*
* @return string
*/
public function Link($version = false, $lang = false) {
if(!$version) $version = '';
if(!$lang) $lang = 'en';
return Controller::join_links(
Director::absoluteBaseURL(),
DocumentationViewer::get_link_base(),
$version,
$lang,
$this->moduleFolder
);
}
/** /**
* @return string * @return string
*/ */

View File

@ -14,10 +14,12 @@ class DocumentationPage extends ViewableData {
protected $entity; protected $entity;
/** /**
* Stores the relative path (from the {@link DocumentationEntity} to
* this page. The actual file name can be accessed via {@link $this->getFilename()}
*
* @var String * @var String
*/ */
protected $relativePath; protected $relativePath;
protected $fullPath; // needed for the search
/** /**
* @var String * @var String
@ -73,49 +75,54 @@ class DocumentationPage extends ViewableData {
* @return string * @return string
*/ */
function getPath($defaultFile = false) { function getPath($defaultFile = false) {
if($this->fullPath) { if($this->entity) {
$path = $this->fullPath; $path = rtrim($this->entity->getPath($this->version, $this->lang), '/') . '/' . trim($this->getRelativePath(), '/');
}
elseif($this->entity) { if(!is_dir($path)) $path = realpath($path);
$path = realpath(rtrim($this->entity->getPath($this->version, $this->lang), '/') . '/' . trim($this->getRelativePath(), '/')); else if($defaultFile) {
$file = DocumentationService::find_page($this->entity, explode('/', $this->getRelativePath()));
if($file) $path = $file;
}
} }
else { else {
$path = $this->relativePath; $path = $this->getRelativePath();
}
if(!is_dir($path)) return $path;
if($defaultFile && ($entity = $this->getEntity())) {
if($relative = $this->getRelativePath()) {
return DocumentationService::find_page($entity, explode($relative, '/'));
}
else {
$parts = str_replace($entity->getPath($this->version, $this->lang), '', $this->fullPath);
return DocumentationService::find_page($entity, explode($parts, '/'));
}
} }
if(!file_exists($path)) { if(!file_exists($path)) {
throw new InvalidArgumentException(sprintf( throw new InvalidArgumentException(sprintf(
'Path could not be found. Module path: %s, file path: %s', 'Path could not be found. Module path: %s, file path: %s',
$this->entity->getPath(), $this->entity->getPath(),
$this->relativePath $this->getRelativePath()
)); ));
} }
return $path;
return (is_dir($path)) ? rtrim($path, '/') . '/' : $path;
} }
/** /**
* Returns the link for the webbrowser * Returns the link for the web browser
* *
* @return string * @return string
*/ */
function getLink() { function Link() {
$web = Director::absoluteBaseUrl() . DocumentationViewer::get_link_base(); if($entity = $this->getEntity()) {
$link = Controller::join_links($entity->Link($this->version, $this->lang), $this->getRelativePath());
return (str_replace(BASE_PATH, $web , $this->getPath(true)));
$link = rtrim(DocumentationService::trim_extension_off($link), '/');
// folders should have a / on them. Looks nicer
try {
if(is_dir($this->getPath())) $link .= '/';
}
catch (Exception $e) {}
}
else {
$link = $this->getPath(true);
}
return $link;
} }
function setFullPath($path) { function setFullPath($path) {
@ -147,10 +154,17 @@ class DocumentationPage extends ViewableData {
} }
/** /**
* @return bool * @return string
*/ */
function isFolder() { function getFilename() {
return (is_dir($this->getPath())); $path = rtrim($this->relativePath, '/');
try {
return (is_dir($this->getPath())) ? $path . '/' : $path;
}
catch (Exception $e) {}
return $path;
} }
/** /**

View File

@ -12,6 +12,8 @@ class DocumentationSearch {
private static $enabled = false; private static $enabled = false;
private $query;
private $results; private $results;
private $totalResults; private $totalResults;
@ -103,33 +105,121 @@ class DocumentationSearch {
* Rebuilds the index if it out of date * Rebuilds the index if it out of date
*/ */
public function performSearch($query) { public function performSearch($query) {
$this->query = $query;
$index = Zend_Search_Lucene::open(self::get_index_location()); $index = Zend_Search_Lucene::open(self::get_index_location());
Zend_Search_Lucene::setResultSetLimit(200); Zend_Search_Lucene::setResultSetLimit(200);
$results = $index->find($query); $this->results = $index->find($query);
$this->results = new DataObjectSet();
$this->totalResults = $index->numDocs(); $this->totalResults = $index->numDocs();
foreach($results as $result) {
$data = $result->getDocument();
$this->results->push(new ArrayData(array(
'Title' => DBField::create('Varchar', $data->Title),
'Link' => DBField::create('Varchar',$data->Link),
'Language' => DBField::create('Varchar',$data->Language),
'Version' => DBField::create('Varchar',$data->Version),
'Content' => DBField::create('Text', $data->content)
)));
}
} }
/** /**
* @return DataObjectSet * @return DataObjectSet
*/ */
public function getResults($start) { public function getDataArrayFromHits($start) {
return $this->results; $data = array(
'Results' => null,
'Query' => null,
'Title' => _t('DocumentationSearch.SEARCHRESULTS', 'Search Results'),
'TotalResults' => null,
'TotalPages' => null,
'ThisPage' => null,
'StartResult' => null,
'EndResult' => null,
'PrevUrl' => DBField::create('Text', 'false'),
'NextUrl' => DBField::create('Text', 'false'),
'SearchPages' => new DataObjectSet()
);
$pageLength = 10;
$currentPage = floor( $start / $pageLength ) + 1;
$totalPages = ceil(count($this->results) / $pageLength );
if ($totalPages == 0) $totalPages = 1;
if ($currentPage > $totalPages) $currentPage = $totalPages;
$results = new DataObjectSet();
foreach($this->results as $k => $hit) {
if($k < ($currentPage-1)*$pageLength || $k >= ($currentPage*$pageLength)) continue;
$doc = $hit->getDocument();
$content = $hit->content;
// do a simple markdown parse of the file
$obj = new ArrayData(array(
'Title' => DBField::create('Varchar', $doc->getFieldValue('Title')),
'Link' => DBField::create('Varchar',$doc->getFieldValue('Link')),
'Language' => DBField::create('Varchar',$doc->getFieldValue('Language')),
'Version' => DBField::create('Varchar',$doc->getFieldValue('Version')),
'Content' => DBField::create('HTMLText', $content),
'Score' => $hit->score,
'Number' => $k + 1
));
$results->push($obj);
}
$data['Results'] = $results;
$data['Query'] = DBField::create('Text', $this->query);
$data['TotalResults'] = DBField::create('Text', count($this->results));
$data['TotalPages'] = DBField::create('Text', $totalPages);
$data['ThisPage'] = DBField::create('Text', $currentPage);
$data['StartResult'] = $start + 1;
$data['EndResult'] = $start + count($results);
// Pagination links
if($currentPage > 1) {
$data['PrevUrl'] = DBField::create('Text',
$this->buildQueryUrl(array('start' => ($currentPage - 2) * $pageLength))
);
}
if($currentPage < $totalPages) {
$data['NextUrl'] = DBField::create('Text',
$this->buildQueryUrl(array('start' => $currentPage * $pageLength))
);
}
if($totalPages > 1) {
// Always show a certain number of pages at the start
for ( $i = 1; $i <= $totalPages; $i++ ) {
$obj = new DataObject();
$obj->IsEllipsis = false;
$obj->PageNumber = $i;
$obj->Link = $this->buildQueryUrl(array(
'start' => ($i - 1) * $pageLength
));
$obj->Current = false;
if ( $i == $currentPage ) $obj->Current = true;
$data['SearchPages']->push($obj);
}
}
return $data;
}
/**
* @return string
*/
private function buildQueryUrl($params) {
$url = parse_url($_SERVER['REQUEST_URI']);
if ( ! array_key_exists('query', $url) ) $url['query'] = '';
parse_str($url['query'], $url['query']);
if ( ! is_array($url['query']) ) $url['query'] = array();
// Remove 'start parameter if it exists
if ( array_key_exists('start', $url['query']) ) unset( $url['query']['start'] );
// Add extra parameters from argument
$url['query'] = array_merge($url['query'], $params);
$url['query'] = http_build_query($url['query']);
$url = $url['path'] . ($url['query'] ? '?'.$url['query'] : '');
return $url;
} }
/** /**

View File

@ -255,6 +255,10 @@ class DocumentationService {
* @param Float $version Version of module. * @param Float $version Version of module.
* @param String $title Nice title to use * @param String $title Nice title to use
* @param bool $major is this a major release * @param bool $major is this a major release
*
* @throws InvalidArgumentException
*
* @return DocumentationEntity
*/ */
public static function register($module, $path, $version = '', $title = false, $major = false) { public static function register($module, $path, $version = '', $title = false, $major = 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));
@ -270,7 +274,7 @@ class DocumentationService {
// module exists so add the version to it // module exists so add the version to it
$entity = self::$registered_modules[$module]; $entity = self::$registered_modules[$module];
$entity->addVersion($version, $path); $entity->addVersion($version, $path, true);
} }
if($major) { if($major) {
@ -280,6 +284,8 @@ class DocumentationService {
self::$major_versions[] = $version; self::$major_versions[] = $version;
} }
} }
return $entity;
} }
/** /**
@ -450,6 +456,16 @@ class DocumentationService {
// remove extension // remove extension
$name = self::trim_extension_off($name); $name = self::trim_extension_off($name);
// if it starts with a number strip and contains a space strip it off
if(strpos($name, ' ') !== false) {
$space = strpos($name, ' ');
$short = substr($name, 0, $space);
if(is_numeric($short)) {
$name = substr($name, $space);
}
}
// convert first letter // convert first letter
return ucfirst(trim($name)); return ucfirst(trim($name));
} }
@ -465,7 +481,13 @@ class DocumentationService {
$hasExtension = strrpos($name, '.'); $hasExtension = strrpos($name, '.');
if($hasExtension !== false && $hasExtension > 0) { if($hasExtension !== false && $hasExtension > 0) {
$name = substr($name, 0, $hasExtension); $shorted = substr($name, $hasExtension);
// can remove the extension only if we know how
// to read it again
if(in_array(rtrim($shorted, '/'), self::get_valid_extensions())) {
$name = substr($name, 0, $hasExtension);
}
} }
return $name; return $name;
@ -476,61 +498,60 @@ class DocumentationService {
* Return the children from a given module sorted by Title using natural ordering. * Return the children from a given module 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 string|DocumentationEntity path * @param DocumentationEntity path
* @param string - an optional path within a module
* @param bool enable several recursive calls (more than 1 level) * @param bool enable several recursive calls (more than 1 level)
*
* @throws Exception * @throws Exception
* @return DataObjectSet * @return DataObjectSet
*/ */
public static function get_pages_from_folder($module, $recursive = true) { public static function get_pages_from_folder($module, $relativePath = false, $recursive = true) {
// var_dump("START: get pages from $module | $relativePath");
$output = new DataObjectSet(); $output = new DataObjectSet();
$pages = array(); $pages = array();
if($module instanceof DocumentationEntity) { if(!$module instanceof DocumentationEntity) user_error("get_pages_from_folder must be passed a module", E_USER_ERROR);
if(self::is_registered_module($module)) {
self::get_pages_from_folder_recursive($module->getPath(), $module, $recursive, $pages); if(self::is_registered_module($module)) {
} self::get_pages_from_folder_recursive($module->getPath(), $relativePath, $recursive, $pages);
else {
return user_error("$module is not registered", E_USER_WARNING);
}
} }
else { else {
self::get_pages_from_folder_recursive($module, false, $recursive, $pages); return user_error("$module is not registered", E_USER_WARNING);
} }
if(count($pages) > 0) { if(count($pages) > 0) {
natsort($pages); natsort($pages);
foreach($pages as $key => $path) { foreach($pages as $key => $path) {
// get file name from the path // get file name from the path
$file = ($pos = strrpos($path, '/')) ? substr($path, $pos + 1) : $path; $file = ($pos = strrpos($path, '/')) ? substr($path, $pos + 1) : $path;
// trim off the extension
$page = new DocumentationPage(); $page = new DocumentationPage();
$page->setTitle(self::clean_page_name($file)); $page->setTitle(self::clean_page_name($file));
$page->setFullPath($path); $relative = str_replace($module->getPath(), '', $path);
$page->Filename = self::trim_extension_off($file); $page->setEntity($module);
$page->setRelativePath($relative);
if($module instanceof DocumentationEntity) { // var_dump("ADDING FILE: ". $relative . " [$path]");
$page->setEntity($module);
}
$output->push($page); $output->push($page);
} }
} }
// var_dump("END get pages");
return $output; return $output;
} }
/** /**
* Recursively search through $folder * Recursively search through $folder
*
*/ */
private static function get_pages_from_folder_recursive($folder, $module = false, $recusive, &$pages) { private static function get_pages_from_folder_recursive($base, $relative, $recusive, &$pages) {
if(!is_dir($folder)) throw new Exception(sprintf('%s is not a folder', $folder)); if(!is_dir($base)) throw new Exception(sprintf('%s is not a folder', $folder));
$handle = opendir($folder); $folder = Controller::join_links($base, $relative);
$handle = opendir($folder);
if($handle) { if($handle) {
$extensions = self::get_valid_extensions(); $extensions = self::get_valid_extensions();
$ignore = self::get_ignored_files(); $ignore = self::get_ignored_files();
@ -538,16 +559,17 @@ class DocumentationService {
while (false !== ($file = readdir($handle))) { while (false !== ($file = readdir($handle))) {
if(!in_array($file, $ignore)) { if(!in_array($file, $ignore)) {
$file = trim(strtolower($file), '/');
$path = rtrim($folder, '/') . '/'. $file;
$path = Controller::join_links($folder, $file);
$relativeFilePath = Controller::join_links($relative, $file);
if(is_dir($path)) { if(is_dir($path)) {
$pages[] = $path; $pages[] = $relativeFilePath;
if($recusive) self::get_pages_from_folder_recursive($path, $module, $recusive, $pages); if($recusive) self::get_pages_from_folder_recursive($base, $relativeFilePath, $recusive, $pages);
} }
else if(in_array(substr($file, (strrpos($file, '.'))), $extensions)) { else if(in_array(substr($file, (strrpos($file, '.'))), $extensions)) {
$pages[] = $path; $pages[] = $relativeFilePath;
} }
} }
} }

View File

@ -343,14 +343,14 @@ class DocumentationViewer extends Controller {
*/ */
function getPage() { function getPage() {
$module = $this->getModule(); $module = $this->getModule();
if(!$module) return false; if(!$module) return false;
$absFilepath = DocumentationService::find_page($module, $this->Remaining); $absFilepath = DocumentationService::find_page($module, $this->Remaining);
if($absFilepath) { if($absFilepath) {
$relativeFilePath = str_replace($module->getPath(), '', $absFilepath); $relativeFilePath = str_replace($module->getPath(), '', $absFilepath);
$page = new DocumentationPage(); $page = new DocumentationPage();
$page->setRelativePath($relativeFilePath); $page->setRelativePath($relativeFilePath);
$page->setEntity($module); $page->setEntity($module);
@ -372,7 +372,7 @@ class DocumentationViewer extends Controller {
*/ */
function getModulePages() { function getModulePages() {
if($module = $this->getModule()) { if($module = $this->getModule()) {
$pages = DocumentationService::get_pages_from_folder($module, false); $pages = DocumentationService::get_pages_from_folder($module, null, false);
if($pages) { if($pages) {
foreach($pages as $page) { foreach($pages as $page) {
@ -382,14 +382,9 @@ class DocumentationViewer extends Controller {
continue; continue;
} }
$linkParts = array();
// don't include the 'index in the url
if(strtolower($page->Title) != "index") $linkParts[] = $page->Filename;
$page->Link = $this->Link($linkParts);
$page->LinkingMode = 'link'; $page->LinkingMode = 'link';
$page->Children = $this->_getModulePagesNested($page);
$page->Children = $this->_getModulePagesNested($page, $module);
} }
} }
@ -403,21 +398,21 @@ 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 getModulePages()}
* *
* @param ArrayData CurrentPage * @param ArrayData CurrentPage
* @param DocumentationEntity
* @param int Depth of page in the tree * @param int Depth of page in the tree
* *
* @return DataObjectSet|false * @return DataObjectSet|false
*/ */
private function _getModulePagesNested(&$page, $level = 0) { private function _getModulePagesNested(&$page, $module, $level = 0) {
// only support 2 more levels // only support 2 more levels
if(isset($this->Remaining[$level])) { if(isset($this->Remaining[$level])) {
if(strtolower($this->Remaining[$level]) == trim($page->Filename, '/')) {
if(strtolower($this->Remaining[$level]) == $page->Filename) {
// its either in this section or is the actual link // its either in this section or is the actual link
$page->LinkingMode = (isset($this->Remaining[$level + 1])) ? 'section' : 'current'; $page->LinkingMode = (isset($this->Remaining[$level + 1])) ? 'section' : 'current';
if(is_dir($page->getPath())) { if(is_dir($page->getPath())) {
$children = DocumentationService::get_pages_from_folder($page->getPath(), false); $children = DocumentationService::get_pages_from_folder($module, $page->getRelativePath(), false);
$segments = array(); $segments = array();
for($x = 0; $x <= $level; $x++) { for($x = 0; $x <= $level; $x++) {
@ -430,10 +425,9 @@ class DocumentationViewer extends Controller {
continue; continue;
} }
$child->Link = $this->Link(array_merge($segments, array($child->Filename)));
$child->LinkingMode = 'link'; $child->LinkingMode = 'link';
$child->Children = $this->_getModulePagesNested($child, $level + 1); $child->Children = $this->_getModulePagesNested($child, $module, $level + 1);
} }
return $children; return $children;
@ -453,6 +447,7 @@ class DocumentationViewer extends Controller {
*/ */
function getContent() { function getContent() {
if($page = $this->getPage()) { if($page = $this->getPage()) {
// Remove last portion of path (filename), we want a link to the folder base // Remove last portion of path (filename), we want a link to the folder base
$html = DocumentationParser::parse($page, $this->Link(array_slice($this->Remaining, -1, -1))); $html = DocumentationParser::parse($page, $this->Link(array_slice($this->Remaining, -1, -1)));
return DBField::create("HTMLText", $html); return DBField::create("HTMLText", $html);
@ -523,7 +518,9 @@ class DocumentationViewer extends Controller {
} }
} }
return $base . self::$link_base . $version . $lang . $module . $action; $link = Controller::join_links($base, self::get_link_base(), $version, $lang, $module, $action);
return $link;
} }
/** /**
@ -627,14 +624,8 @@ class DocumentationViewer extends Controller {
$search = new DocumentationSearch(); $search = new DocumentationSearch();
$search->performSearch($query); $search->performSearch($query);
$results = $search->getResults($start); $data = $search->getDataArrayFromHits($start);
$total = $search->getTotalResults();
echo $this->customise(array( return $this->customise($data)->renderWith(array('DocumentationViewer_results', 'DocumentationViewer'));
'Results' => $results,
'Query' => DBField::create('HTMLVarchar', $query),
'Start' => DBField::create('HTMLVarchar', $start),
'TotalResults'
))->renderWith(array('DocumentationViewer_results', 'DocumentationViewer'));
} }
} }

View File

@ -14,7 +14,7 @@ class RebuildLuceneDocsIndex extends BuildTask {
* based on the user. It's a * based on the user. It's a
*/ */
function run($request) { function run($request) {
require_once('../sapphiredocs/thirdparty/markdown.php');
ini_set("memory_limit", -1); ini_set("memory_limit", -1);
ini_set('max_execution_time', 0); ini_set('max_execution_time', 0);
@ -55,11 +55,14 @@ class RebuildLuceneDocsIndex extends BuildTask {
if(!is_dir($page->getPath())) { if(!is_dir($page->getPath())) {
$doc = new Zend_Search_Lucene_Document(); $doc = new Zend_Search_Lucene_Document();
$doc->addField(Zend_Search_Lucene_Field::Text('content', $page->getMarkdown())); $content = $page->getMarkdown();
if($content) $content = Markdown($content);
$doc->addField(Zend_Search_Lucene_Field::Text('content', $content));
$doc->addField(Zend_Search_Lucene_Field::Text('Title', $page->getTitle())); $doc->addField(Zend_Search_Lucene_Field::Text('Title', $page->getTitle()));
$doc->addField(Zend_Search_Lucene_Field::Keyword('Version', $page->getVersion())); $doc->addField(Zend_Search_Lucene_Field::Keyword('Version', $page->getVersion()));
$doc->addField(Zend_Search_Lucene_Field::Keyword('Language', $page->getLang())); $doc->addField(Zend_Search_Lucene_Field::Keyword('Language', $page->getLang()));
$doc->addField(Zend_Search_Lucene_Field::Keyword('Link', $page->getLink())); $doc->addField(Zend_Search_Lucene_Field::Keyword('Link', $page->Link()));
$index->addDocument($doc); $index->addDocument($doc);
} }

View File

@ -1,10 +1,39 @@
<div id="documentation-page"> <div id="documentation-page">
<div id="left-column"> <div id="left-column">
<p>Your search for <strong>&quot;$Query.XML&quot;</strong> found $TotalResults result<% if TotalResults != 1 %>s<% end_if %>.</p>
<% if Results %> <% if Results %>
<p>Showing page $ThisPage of $TotalPages</p>
<% control Results %> <% control Results %>
<h2><a href="$Link">$Title</a></h2> <h2><a href="$Link">$Title</a></h2>
$Content.Summary $Content.LimitWordCountXML
<% end_control %> <% end_control %>
<% if SearchPages %>
<ul class="pagination">
<% if PrevUrl = false %><% else %>
<li class="prev"><a href="$PrevUrl">Prev</a></li>
<% end_if %>
<% control SearchPages %>
<% if IsEllipsis %>
<li class="ellipsis">...</li>
<% else %>
<% if Current %>
<li class="active"><strong>$PageNumber</strong></li>
<% else %>
<li><a href="$Link">$PageNumber</a></li>
<% end_if %>
<% end_if %>
<% end_control %>
<% if NextUrl = false %>
<% else %>
<li class="next"><a href="$NextUrl">Next</a></li>
<% end_if %>
</ul>
<% end_if %>
<% else %> <% else %>
<p>No Results</p> <p>No Results</p>
<% end_if %> <% end_if %>

View File

@ -29,6 +29,5 @@ class DocumentationEntityTest extends SapphireTest {
$entity->addVersion('1.1.', '../sapphiredocs/tests/docs-2/'); $entity->addVersion('1.1.', '../sapphiredocs/tests/docs-2/');
$entity->setCurrentVersion('1.0'); $entity->setCurrentVersion('1.0');
$this->assertEquals('1.0', $entity->getCurrentVersion(), 'Manual setting'); $this->assertEquals('1.0', $entity->getCurrentVersion(), 'Manual setting');
} }
} }

View File

@ -1,6 +1,46 @@
<?php <?php
/**
* @package sapphiredocs
* @subpackage tests
*/
class DocumentationPageTest extends SapphireTest { class DocumentationPageTest extends SapphireTest {
function testGetLink() {
$entity = new DocumentationEntity('testmodule', null, BASE_PATH . '/sapphiredocs/tests/docs/');
$page = new DocumentationPage();
$page->setRelativePath('test.md');
$page->setEntity($entity);
// single layer
$this->assertStringEndsWith('en/testmodule/test', $page->Link(), 'The page link should have no extension and have a language');
$folder = new DocumentationPage();
$folder->setRelativePath('sort');
$folder->setEntity($entity);
// folder, should have a trailing slash
$this->assertStringEndsWith('en/testmodule/sort/', $folder->Link());
// second
$nested = new DocumentationPage();
$nested->setRelativePath('subfolder/subpage.md');
$nested->setEntity($entity);
$this->assertStringEndsWith('en/testmodule/subfolder/subpage', $nested->Link());
// test with version.
$entity = DocumentationService::register("versionlinks", BASE_PATH . "/sapphiredocs/tests/docs-2/", '1');
$page = new DocumentationPage();
$page->setRelativePath('test.md');
$page->setEntity($entity);
$page->setVersion('1');
$this->assertStringEndsWith('1/en/versionlinks/test', $page->Link());
}
function testGetRelativePath() { function testGetRelativePath() {
$page = new DocumentationPage(); $page = new DocumentationPage();
$page->setRelativePath('test.md'); $page->setRelativePath('test.md');

View File

@ -31,6 +31,7 @@ class DocumentationParserTest extends SapphireTest {
$page->setVersion('2.4'); $page->setVersion('2.4');
$result = DocumentationParser::rewrite_image_links($page->getMarkdown(), $page, 'mycontroller/cms/2.4/en/'); $result = DocumentationParser::rewrite_image_links($page->getMarkdown(), $page, 'mycontroller/cms/2.4/en/');
$this->assertContains( $this->assertContains(
'[relative image link](' . Director::absoluteBaseURL() . '/sapphiredocs/tests/docs/en/subfolder/_images/image.png)', '[relative image link](' . Director::absoluteBaseURL() . '/sapphiredocs/tests/docs/en/subfolder/_images/image.png)',
$result $result
@ -183,28 +184,4 @@ class DocumentationParserTest extends SapphireTest {
$result $result
); );
} }
function testCleanPageNames() {
$names = array(
'documentation-Page',
'documentation_Page',
'documentation.md',
'documentation.pdf',
'documentation.file.txt',
'.hidden'
);
$should = array(
'Documentation Page',
'Documentation Page',
'Documentation',
'Documentation',
'Documentation.file',
'.hidden' // don't display something without a title
);
foreach($names as $key => $value) {
$this->assertEquals(DocumentationService::clean_page_name($value), $should[$key]);
}
}
} }

View File

@ -7,6 +7,42 @@
class DocumentationServiceTest extends SapphireTest { class DocumentationServiceTest extends SapphireTest {
function testGetPagesFromFolder() {
$entity = DocumentationService::register('testdocs', BASE_PATH . '/sapphiredocs/tests/docs/');
$pages = DocumentationService::get_pages_from_folder($entity);
// check folders and files exist as their filenames
$this->assertContains('index.md', $pages->column('Filename'), 'The tests/docs/en folder should contain a index file');
$this->assertContains('subfolder/', $pages->column('Filename'), 'The tests/docs/en folder should contain a subfolder called subfolder');
$this->assertContains('test.md', $pages->column('Filename'), 'The tests/docs/en folder should contain a test file');
$this->assertNotContains('_images', $pages->column('Filename'), 'It should not include hidden files');
$this->assertNotContains('.svn', $pages->column('Filename'), 'It should not include hidden files');
// test the order of pages
$pages = DocumentationService::get_pages_from_folder($entity, 'sort');
$this->assertEquals(
array('Basic', 'Intermediate', 'Advanced', 'Some page', 'Another page'),
$pages->column('Title')
);
}
function testGetPagesFromFolderRecursive() {
$entity = DocumentationService::register('testdocsrecursive', BASE_PATH . '/sapphiredocs/tests/docs-recursive/');
$pages = DocumentationService::get_pages_from_folder($entity, null, true);
// check to see all the pages are found, we don't care about order
$this->assertEquals($pages->Count(), 9);
$pages = $pages->column('Title');
foreach(array('Index', 'SubFolder TestFile', 'SubSubFolder TestFile', 'TestFile') as $expected) {
$this->assertContains($expected, $pages);
}
}
function testFindPath() { function testFindPath() {
DocumentationService::register("DocumentationViewerTests", BASE_PATH . "/sapphiredocs/tests/docs/"); DocumentationService::register("DocumentationViewerTests", BASE_PATH . "/sapphiredocs/tests/docs/");
@ -34,35 +70,28 @@ class DocumentationServiceTest extends SapphireTest {
$this->assertEquals(BASE_PATH . "/sapphiredocs/tests/docs/en/subfolder/subsubfolder/subsubpage.md", $path); $this->assertEquals(BASE_PATH . "/sapphiredocs/tests/docs/en/subfolder/subsubfolder/subsubpage.md", $path);
} }
function testGetPagesFromFolder() {
$pages = DocumentationService::get_pages_from_folder(BASE_PATH . '/sapphiredocs/tests/docs/en/');
$this->assertContains('index', $pages->column('Filename'), 'The tests/docs/en folder should contain a index file');
$this->assertContains('subfolder', $pages->column('Filename'), 'The tests/docs/en folder should contain a subfolder called subfolder');
$this->assertContains('test', $pages->column('Filename'), 'The tests/docs/en folder should contain a test file');
$this->assertNotContains('_images', $pages->column('Filename'), 'It should not include hidden files');
$this->assertNotContains('.svn', $pages->column('Filename'), 'It should not include hidden files');
// test the order of pages
$pages = DocumentationService::get_pages_from_folder(BASE_PATH . '/sapphiredocs/tests/docs/en/sort');
$this->assertEquals(
array('1 basic', '2 intermediate', '3 advanced', '10 some page', '21 another page'),
$pages->column('Title')
);
}
function testGetPagesFromFolderRecursive() { function testCleanPageNames() {
$pages = DocumentationService::get_pages_from_folder(BASE_PATH . '/sapphiredocs/tests/docs-recursive/en/'); $names = array(
'documentation-Page',
'documentation_Page',
'documentation.md',
'documentation.pdf',
'documentation.file.txt',
'.hidden'
);
// check to see all the pages are found, we don't care about order $should = array(
$this->assertEquals($pages->Count(), 9); 'Documentation Page',
'Documentation Page',
$pages = $pages->column('Title'); 'Documentation',
'Documentation.pdf', // do not remove an extension we don't know
'Documentation.file', // .txt we do know about
'.hidden' // don't display something without a title
);
foreach(array('Index', 'Subfolder testfile', 'Subsubfolder testfile', 'Testfile') as $expected) { foreach($names as $key => $value) {
$this->assertContains($expected, $pages); $this->assertEquals(DocumentationService::clean_page_name($value), $should[$key]);
} }
} }
} }

View File

@ -7,7 +7,7 @@
* @package sapphiredocs * @package sapphiredocs
*/ */
class DocumentationViewerTests extends FunctionalTest { class DocumentationViewerTest extends FunctionalTest {
static $fixture_file = 'sapphiredocs/tests/DocumentTests.yml'; static $fixture_file = 'sapphiredocs/tests/DocumentTests.yml';
@ -39,6 +39,67 @@ class DocumentationViewerTests extends FunctionalTest {
DocumentationViewer::set_link_base($this->origLinkBase); DocumentationViewer::set_link_base($this->origLinkBase);
} }
function testGetModulePagesShort() {
$v = new DocumentationViewer();
$response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/subfolder/'));
$pages = $v->getModulePages();
$arr = $pages->toArray();
$page = $arr[2];
$this->assertEquals('Subfolder', $page->Title);
}
function testGetModulePages() {
$v = new DocumentationViewer();
$response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/subfolder/'));
$pages = $v->getModulePages();
$this->assertEquals(
array('sort/', 'subfolder/', 'test.md'),
$pages->column('Filename')
);
$this->assertEquals(
array('link','current', 'link'),
$pages->column('LinkingMode')
);
foreach($pages as $page) {
$page->setVersion('2.4');
}
$links = $pages->column('Link');
$this->assertStringEndsWith('2.4/en/DocumentationViewerTests/sort/', $links[0]);
$this->assertStringEndsWith('2.4/en/DocumentationViewerTests/subfolder/', $links[1]);
$this->assertStringEndsWith('2.4/en/DocumentationViewerTests/test', $links[2]);
// Children
$pagesArr = $pages->toArray();
$child1 = $pagesArr[1];
$this->assertFalse($child1->Children);
$child2 = $pagesArr[2];
$this->assertType('DataObjectSet', $child2->Children);
$this->assertEquals(
array('subfolder/subpage.md', 'subfolder/subsubfolder/'),
$child2->Children->column('Filename')
);
$children = $child2->Children;
foreach($children as $child) {
$child->setVersion('2.4');
}
$child2Links = $children->column('Link');
$subpage = $children->First();
$this->assertStringEndsWith('2.4/en/DocumentationViewerTests/subfolder/subpage', $child2Links[0]);
$this->assertStringEndsWith('2.4/en/DocumentationViewerTests/subfolder/subsubfolder/', $child2Links[1]);
}
function testCurrentRedirection() { function testCurrentRedirection() {
$response = $this->get('dev/docs/3.0/en/DocumentationViewerTests/test'); $response = $this->get('dev/docs/3.0/en/DocumentationViewerTests/test');
@ -118,45 +179,6 @@ class DocumentationViewerTests extends FunctionalTest {
$this->assertStringEndsWith('DocumentationViewerTests/subfolder/subpage/', $crumbLinks[2]); $this->assertStringEndsWith('DocumentationViewerTests/subfolder/subpage/', $crumbLinks[2]);
} }
function testGetModulePages() {
$v = new DocumentationViewer();
$response = $v->handleRequest(new SS_HTTPRequest('GET', '2.4/en/DocumentationViewerTests/subfolder/'));
$pages = $v->getModulePages();
$this->assertEquals(
array('sort', 'subfolder', 'test'),
$pages->column('Filename')
);
$this->assertEquals(
array('link','current', 'link'),
$pages->column('LinkingMode')
);
$links = $pages->column('Link');
$this->assertStringEndsWith('2.4/en/DocumentationViewerTests/sort/', $links[0]);
$this->assertStringEndsWith('2.4/en/DocumentationViewerTests/subfolder/', $links[1]);
$this->assertStringEndsWith('2.4/en/DocumentationViewerTests/test/', $links[2]);
// Children
$pagesArr = $pages->toArray();
$child1 = $pagesArr[1];
$this->assertFalse($child1->Children);
$child2 = $pagesArr[2];
$this->assertType('DataObjectSet', $child2->Children);
$this->assertEquals(
array('subpage', 'subsubfolder'),
$child2->Children->column('Filename')
);
$child2Links = $child2->Children->column('Link');
$this->assertStringEndsWith('2.4/en/DocumentationViewerTests/subfolder/subpage/', $child2Links[0]);
$this->assertStringEndsWith('2.4/en/DocumentationViewerTests/subfolder/subsubfolder/', $child2Links[1]);
}
function testRouting() { function testRouting() {
$response = $this->get('dev/docs/2.4/en/DocumentationViewerTests/test'); $response = $this->get('dev/docs/2.4/en/DocumentationViewerTests/test');
$this->assertEquals(200, $response->getStatusCode()); $this->assertEquals(200, $response->getStatusCode());