mirror of
https://github.com/silverstripe/silverstripe-docsviewer
synced 2024-10-22 11:05:56 +02:00
Converted to PSR-2
This commit is contained in:
parent
2f0cbfe4f6
commit
ced8128190
@ -5,86 +5,91 @@
|
|||||||
*
|
*
|
||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
*/
|
*/
|
||||||
class DocumentationHelper {
|
class DocumentationHelper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* String helper for cleaning a file name to a readable version.
|
||||||
|
*
|
||||||
|
* @param string $name to convert
|
||||||
|
*
|
||||||
|
* @return string $name output
|
||||||
|
*/
|
||||||
|
public static function clean_page_name($name)
|
||||||
|
{
|
||||||
|
$name = self::trim_extension_off($name);
|
||||||
|
$name = self::trim_sort_number($name);
|
||||||
|
|
||||||
/**
|
$name = str_replace(array('-', '_'), ' ', $name);
|
||||||
* String helper for cleaning a file name to a readable version.
|
|
||||||
*
|
|
||||||
* @param string $name to convert
|
|
||||||
*
|
|
||||||
* @return string $name output
|
|
||||||
*/
|
|
||||||
public static function clean_page_name($name) {
|
|
||||||
$name = self::trim_extension_off($name);
|
|
||||||
$name = self::trim_sort_number($name);
|
|
||||||
|
|
||||||
$name = str_replace(array('-', '_'), ' ', $name);
|
return ucfirst(trim($name));
|
||||||
|
}
|
||||||
|
|
||||||
return ucfirst(trim($name));
|
/**
|
||||||
}
|
* String helper for cleaning a file name to a URL safe version.
|
||||||
|
*
|
||||||
|
* @param string $name to convert
|
||||||
|
*
|
||||||
|
* @return string $name output
|
||||||
|
*/
|
||||||
|
public static function clean_page_url($name)
|
||||||
|
{
|
||||||
|
$name = str_replace(array(' '), '_', $name);
|
||||||
|
|
||||||
/**
|
$name = self::trim_extension_off($name);
|
||||||
* String helper for cleaning a file name to a URL safe version.
|
$name = self::trim_sort_number($name);
|
||||||
*
|
|
||||||
* @param string $name to convert
|
|
||||||
*
|
|
||||||
* @return string $name output
|
|
||||||
*/
|
|
||||||
public static function clean_page_url($name) {
|
|
||||||
$name = str_replace(array(' '), '_', $name);
|
|
||||||
|
|
||||||
$name = self::trim_extension_off($name);
|
if (preg_match('/^[\/]?index[\/]?/', $name)) {
|
||||||
$name = self::trim_sort_number($name);
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
if(preg_match('/^[\/]?index[\/]?/', $name)) {
|
return strtolower($name);
|
||||||
return '';
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return strtolower($name);
|
/**
|
||||||
}
|
* Removes leading numbers from pages (used to control sort order).
|
||||||
|
*
|
||||||
|
* @param string
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function trim_sort_number($name)
|
||||||
|
{
|
||||||
|
$name = preg_replace("/^[0-9]*[_-]+/", '', $name);
|
||||||
|
|
||||||
/**
|
return $name;
|
||||||
* Removes leading numbers from pages (used to control sort order).
|
}
|
||||||
*
|
|
||||||
* @param string
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function trim_sort_number($name) {
|
|
||||||
$name = preg_replace("/^[0-9]*[_-]+/", '', $name);
|
|
||||||
|
|
||||||
return $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to strip the extension off and return the name without
|
* Helper function to strip the extension off and return the name without
|
||||||
* the extension.
|
* the extension.
|
||||||
*
|
*
|
||||||
* @param string
|
* @param string
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function trim_extension_off($name) {
|
public static function trim_extension_off($name)
|
||||||
if(strrpos($name,'.') !== false) {
|
{
|
||||||
return substr($name, 0, strrpos($name,'.'));
|
if (strrpos($name, '.') !== false) {
|
||||||
}
|
return substr($name, 0, strrpos($name, '.'));
|
||||||
|
}
|
||||||
|
|
||||||
return $name;
|
return $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function to get the extension of the filename.
|
* Helper function to get the extension of the filename.
|
||||||
*
|
*
|
||||||
* @param string
|
* @param string
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function get_extension($name) {
|
public static function get_extension($name)
|
||||||
if(preg_match('/\.[a-z]+$/', $name)) {
|
{
|
||||||
return substr($name, strrpos($name,'.') + 1);
|
if (preg_match('/\.[a-z]+$/', $name)) {
|
||||||
}
|
return substr($name, strrpos($name, '.') + 1);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,715 +27,737 @@
|
|||||||
* @package framework
|
* @package framework
|
||||||
* @subpackage manifest
|
* @subpackage manifest
|
||||||
*/
|
*/
|
||||||
class DocumentationManifest {
|
class DocumentationManifest
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
*
|
*
|
||||||
* @var boolean $automatic_registration
|
* @var boolean $automatic_registration
|
||||||
*/
|
*/
|
||||||
private static $automatic_registration = true;
|
private static $automatic_registration = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
*
|
*
|
||||||
* @var array $registered_entities
|
* @var array $registered_entities
|
||||||
*/
|
*/
|
||||||
private static $register_entities = array();
|
private static $register_entities = array();
|
||||||
|
|
||||||
protected $cache;
|
protected $cache;
|
||||||
protected $cacheKey;
|
protected $cacheKey;
|
||||||
|
|
||||||
protected $inited;
|
protected $inited;
|
||||||
protected $forceRegen;
|
protected $forceRegen;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array $pages
|
* @var array $pages
|
||||||
*/
|
*/
|
||||||
protected $pages = array();
|
protected $pages = array();
|
||||||
|
|
||||||
protected $redirects = array();
|
protected $redirects = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var DocumentationEntity
|
* @var DocumentationEntity
|
||||||
*/
|
*/
|
||||||
private $entity;
|
private $entity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var boolean
|
* @var boolean
|
||||||
*/
|
*/
|
||||||
private $automaticallyPopulated = false;
|
private $automaticallyPopulated = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ArrayList
|
* @var ArrayList
|
||||||
*/
|
*/
|
||||||
private $registeredEntities;
|
private $registeredEntities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new template manifest. The manifest is not actually built
|
* Constructs a new template manifest. The manifest is not actually built
|
||||||
* or loaded from cache until needed.
|
* or loaded from cache until needed.
|
||||||
*
|
*
|
||||||
* @param bool $includeTests Include tests in the manifest.
|
* @param bool $includeTests Include tests in the manifest.
|
||||||
* @param bool $forceRegen Force the manifest to be regenerated.
|
* @param bool $forceRegen Force the manifest to be regenerated.
|
||||||
*/
|
*/
|
||||||
public function __construct($forceRegen = false) {
|
public function __construct($forceRegen = false)
|
||||||
$this->cacheKey = 'manifest';
|
{
|
||||||
$this->forceRegen = $forceRegen;
|
$this->cacheKey = 'manifest';
|
||||||
$this->registeredEntities = new ArrayList();
|
$this->forceRegen = $forceRegen;
|
||||||
|
$this->registeredEntities = new ArrayList();
|
||||||
$this->cache = SS_Cache::factory('DocumentationManifest', 'Core', array(
|
|
||||||
'automatic_serialization' => true,
|
$this->cache = SS_Cache::factory('DocumentationManifest', 'Core', array(
|
||||||
'lifetime' => null
|
'automatic_serialization' => true,
|
||||||
));
|
'lifetime' => null
|
||||||
|
));
|
||||||
$this->setupEntities();
|
|
||||||
}
|
$this->setupEntities();
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Sets up the top level entities.
|
/**
|
||||||
*
|
* Sets up the top level entities.
|
||||||
* Either manually registered through the YAML syntax or automatically
|
*
|
||||||
* loaded through investigating the file system for `docs` folder.
|
* Either manually registered through the YAML syntax or automatically
|
||||||
*/
|
* loaded through investigating the file system for `docs` folder.
|
||||||
public function setupEntities() {
|
*/
|
||||||
if($this->registeredEntities->Count() > 0) {
|
public function setupEntities()
|
||||||
return;
|
{
|
||||||
}
|
if ($this->registeredEntities->Count() > 0) {
|
||||||
|
return;
|
||||||
if(Config::inst()->get('DocumentationManifest', 'automatic_registration')) {
|
}
|
||||||
$this->populateEntitiesFromInstall();
|
|
||||||
}
|
if (Config::inst()->get('DocumentationManifest', 'automatic_registration')) {
|
||||||
|
$this->populateEntitiesFromInstall();
|
||||||
$registered = Config::inst()->get('DocumentationManifest', 'register_entities');
|
}
|
||||||
|
|
||||||
foreach($registered as $details) {
|
$registered = Config::inst()->get('DocumentationManifest', 'register_entities');
|
||||||
// validate the details provided through the YAML configuration
|
|
||||||
$required = array('Path', 'Title');
|
foreach ($registered as $details) {
|
||||||
|
// validate the details provided through the YAML configuration
|
||||||
foreach($required as $require) {
|
$required = array('Path', 'Title');
|
||||||
if(!isset($details[$require])) {
|
|
||||||
throw new Exception("$require is a required key in DocumentationManifest.register_entities");
|
foreach ($required as $require) {
|
||||||
}
|
if (!isset($details[$require])) {
|
||||||
}
|
throw new Exception("$require is a required key in DocumentationManifest.register_entities");
|
||||||
|
}
|
||||||
// if path is not an absolute value then assume it is relative from
|
}
|
||||||
// the BASE_PATH.
|
|
||||||
$path = $this->getRealPath($details['Path']);
|
// if path is not an absolute value then assume it is relative from
|
||||||
|
// the BASE_PATH.
|
||||||
$key = (isset($details['Key'])) ? $details['Key'] : $details['Title'];
|
$path = $this->getRealPath($details['Path']);
|
||||||
|
|
||||||
if(!$path || !is_dir($path)) {
|
$key = (isset($details['Key'])) ? $details['Key'] : $details['Title'];
|
||||||
throw new Exception($details['Path'] . ' is not a valid documentation directory');
|
|
||||||
}
|
if (!$path || !is_dir($path)) {
|
||||||
|
throw new Exception($details['Path'] . ' is not a valid documentation directory');
|
||||||
$version = (isset($details['Version'])) ? $details['Version'] : '';
|
}
|
||||||
|
|
||||||
$branch = (isset($details['Branch'])) ? $details['Branch'] : '';
|
$version = (isset($details['Version'])) ? $details['Version'] : '';
|
||||||
|
|
||||||
$langs = scandir($path);
|
$branch = (isset($details['Branch'])) ? $details['Branch'] : '';
|
||||||
|
|
||||||
if($langs) {
|
$langs = scandir($path);
|
||||||
$possible = i18n::get_common_languages(true);
|
|
||||||
|
if ($langs) {
|
||||||
foreach($langs as $k => $lang) {
|
$possible = i18n::get_common_languages(true);
|
||||||
if(isset($possible[$lang])) {
|
|
||||||
$entity = Injector::inst()->create(
|
foreach ($langs as $k => $lang) {
|
||||||
'DocumentationEntity', $key
|
if (isset($possible[$lang])) {
|
||||||
);
|
$entity = Injector::inst()->create(
|
||||||
|
'DocumentationEntity', $key
|
||||||
$entity->setPath(Controller::join_links($path, $lang, '/'));
|
);
|
||||||
$entity->setTitle($details['Title']);
|
|
||||||
$entity->setLanguage($lang);
|
$entity->setPath(Controller::join_links($path, $lang, '/'));
|
||||||
$entity->setVersion($version);
|
$entity->setTitle($details['Title']);
|
||||||
$entity->setBranch($branch);
|
$entity->setLanguage($lang);
|
||||||
|
$entity->setVersion($version);
|
||||||
if(isset($details['Stable'])) {
|
$entity->setBranch($branch);
|
||||||
$entity->setIsStable($details['Stable']);
|
|
||||||
}
|
if (isset($details['Stable'])) {
|
||||||
|
$entity->setIsStable($details['Stable']);
|
||||||
if(isset($details['DefaultEntity'])) {
|
}
|
||||||
$entity->setIsDefaultEntity($details['DefaultEntity']);
|
|
||||||
}
|
if (isset($details['DefaultEntity'])) {
|
||||||
|
$entity->setIsDefaultEntity($details['DefaultEntity']);
|
||||||
$this->registeredEntities->push($entity);
|
}
|
||||||
}
|
|
||||||
}
|
$this->registeredEntities->push($entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
public function getRealPath($path) {
|
}
|
||||||
if(substr($path, 0, 1) != '/') {
|
|
||||||
$path = Controller::join_links(BASE_PATH, $path);
|
public function getRealPath($path)
|
||||||
}
|
{
|
||||||
|
if (substr($path, 0, 1) != '/') {
|
||||||
return $path;
|
$path = Controller::join_links(BASE_PATH, $path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return $path;
|
||||||
* @return ArrayList
|
}
|
||||||
*/
|
|
||||||
public function getEntities() {
|
/**
|
||||||
return $this->registeredEntities;
|
* @return ArrayList
|
||||||
}
|
*/
|
||||||
|
public function getEntities()
|
||||||
/**
|
{
|
||||||
* Scans the current installation and picks up all the SilverStripe modules
|
return $this->registeredEntities;
|
||||||
* that contain a `docs` folder.
|
}
|
||||||
*
|
|
||||||
* @return void
|
/**
|
||||||
*/
|
* Scans the current installation and picks up all the SilverStripe modules
|
||||||
public function populateEntitiesFromInstall() {
|
* that contain a `docs` folder.
|
||||||
if($this->automaticallyPopulated) {
|
*
|
||||||
// already run
|
* @return void
|
||||||
return;
|
*/
|
||||||
}
|
public function populateEntitiesFromInstall()
|
||||||
|
{
|
||||||
foreach(scandir(BASE_PATH) as $key => $entity) {
|
if ($this->automaticallyPopulated) {
|
||||||
if($key == "themes") {
|
// already run
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$dir = Controller::join_links(BASE_PATH, $entity);
|
foreach (scandir(BASE_PATH) as $key => $entity) {
|
||||||
|
if ($key == "themes") {
|
||||||
if(is_dir($dir)) {
|
continue;
|
||||||
// check to see if it has docs
|
}
|
||||||
$docs = Controller::join_links($dir, 'docs');
|
|
||||||
|
$dir = Controller::join_links(BASE_PATH, $entity);
|
||||||
if(is_dir($docs)) {
|
|
||||||
$entities[] = array(
|
if (is_dir($dir)) {
|
||||||
'Path' => $docs,
|
// check to see if it has docs
|
||||||
'Title' => DocumentationHelper::clean_page_name($entity),
|
$docs = Controller::join_links($dir, 'docs');
|
||||||
'Version' => 'master',
|
|
||||||
'Branch' => 'master',
|
if (is_dir($docs)) {
|
||||||
'Stable' => true
|
$entities[] = array(
|
||||||
);
|
'Path' => $docs,
|
||||||
}
|
'Title' => DocumentationHelper::clean_page_name($entity),
|
||||||
}
|
'Version' => 'master',
|
||||||
}
|
'Branch' => 'master',
|
||||||
|
'Stable' => true
|
||||||
Config::inst()->update(
|
);
|
||||||
'DocumentationManifest', 'register_entities', $entities
|
}
|
||||||
);
|
}
|
||||||
|
}
|
||||||
$this->automaticallyPopulated = true;
|
|
||||||
}
|
Config::inst()->update(
|
||||||
|
'DocumentationManifest', 'register_entities', $entities
|
||||||
/**
|
);
|
||||||
*
|
|
||||||
*/
|
$this->automaticallyPopulated = true;
|
||||||
protected function init() {
|
}
|
||||||
if (!$this->forceRegen && $data = $this->cache->load($this->cacheKey)) {
|
|
||||||
$this->pages = $data['pages'];
|
/**
|
||||||
$this->redirects = $data['redirects'];
|
*
|
||||||
$this->inited = true;
|
*/
|
||||||
} else {
|
protected function init()
|
||||||
$this->regenerate();
|
{
|
||||||
}
|
if (!$this->forceRegen && $data = $this->cache->load($this->cacheKey)) {
|
||||||
}
|
$this->pages = $data['pages'];
|
||||||
|
$this->redirects = $data['redirects'];
|
||||||
|
$this->inited = true;
|
||||||
/**
|
} else {
|
||||||
* Returns a map of all documentation pages.
|
$this->regenerate();
|
||||||
*
|
}
|
||||||
* @return array
|
}
|
||||||
*/
|
|
||||||
public function getPages() {
|
|
||||||
if (!$this->inited) {
|
/**
|
||||||
$this->init();
|
* Returns a map of all documentation pages.
|
||||||
}
|
*
|
||||||
|
* @return array
|
||||||
return $this->pages;
|
*/
|
||||||
}
|
public function getPages()
|
||||||
|
{
|
||||||
public function getRedirects() {
|
if (!$this->inited) {
|
||||||
if(!$this->inited) {
|
$this->init();
|
||||||
$this->init();
|
}
|
||||||
}
|
|
||||||
|
return $this->pages;
|
||||||
return $this->redirects;
|
}
|
||||||
}
|
|
||||||
|
public function getRedirects()
|
||||||
/**
|
{
|
||||||
* Returns a particular page for the requested URL.
|
if (!$this->inited) {
|
||||||
*
|
$this->init();
|
||||||
* @return DocumentationPage
|
}
|
||||||
*/
|
|
||||||
public function getPage($url) {
|
return $this->redirects;
|
||||||
$pages = $this->getPages();
|
}
|
||||||
$url = $this->normalizeUrl($url);
|
|
||||||
|
/**
|
||||||
if(!isset($pages[$url])) {
|
* Returns a particular page for the requested URL.
|
||||||
return null;
|
*
|
||||||
}
|
* @return DocumentationPage
|
||||||
|
*/
|
||||||
|
public function getPage($url)
|
||||||
$record = $pages[$url];
|
{
|
||||||
|
$pages = $this->getPages();
|
||||||
foreach($this->getEntities() as $entity) {
|
$url = $this->normalizeUrl($url);
|
||||||
if(strpos($record['filepath'], $entity->getPath()) !== false) {
|
|
||||||
$page = Injector::inst()->create(
|
if (!isset($pages[$url])) {
|
||||||
$record['type'],
|
return null;
|
||||||
$entity,
|
}
|
||||||
$record['basename'],
|
|
||||||
$record['filepath']
|
|
||||||
);
|
$record = $pages[$url];
|
||||||
|
|
||||||
return $page;
|
foreach ($this->getEntities() as $entity) {
|
||||||
}
|
if (strpos($record['filepath'], $entity->getPath()) !== false) {
|
||||||
}
|
$page = Injector::inst()->create(
|
||||||
}
|
$record['type'],
|
||||||
|
$entity,
|
||||||
/**
|
$record['basename'],
|
||||||
* Get any redirect for the given url
|
$record['filepath']
|
||||||
*
|
);
|
||||||
* @param type $url
|
|
||||||
* @return string
|
return $page;
|
||||||
*/
|
}
|
||||||
public function getRedirect($url) {
|
}
|
||||||
$pages = $this->getRedirects();
|
}
|
||||||
$url = $this->normalizeUrl($url);
|
|
||||||
|
/**
|
||||||
if(isset($pages[$url])) {
|
* Get any redirect for the given url
|
||||||
return $pages[$url];
|
*
|
||||||
}
|
* @param type $url
|
||||||
}
|
* @return string
|
||||||
|
*/
|
||||||
/**
|
public function getRedirect($url)
|
||||||
* Regenerates the manifest by scanning the base path.
|
{
|
||||||
*
|
$pages = $this->getRedirects();
|
||||||
* @param bool $cache
|
$url = $this->normalizeUrl($url);
|
||||||
*/
|
|
||||||
public function regenerate($cache = true) {
|
if (isset($pages[$url])) {
|
||||||
$finder = new DocumentationManifestFileFinder();
|
return $pages[$url];
|
||||||
$finder->setOptions(array(
|
}
|
||||||
'dir_callback' => array($this, 'handleFolder'),
|
}
|
||||||
'file_callback' => array($this, 'handleFile')
|
|
||||||
));
|
/**
|
||||||
|
* Regenerates the manifest by scanning the base path.
|
||||||
$this->redirects = array();
|
*
|
||||||
foreach($this->getEntities() as $entity) {
|
* @param bool $cache
|
||||||
$this->entity = $entity;
|
*/
|
||||||
|
public function regenerate($cache = true)
|
||||||
$this->handleFolder('', $this->entity->getPath(), 0);
|
{
|
||||||
$finder->find($this->entity->getPath());
|
$finder = new DocumentationManifestFileFinder();
|
||||||
}
|
$finder->setOptions(array(
|
||||||
|
'dir_callback' => array($this, 'handleFolder'),
|
||||||
// groupds
|
'file_callback' => array($this, 'handleFile')
|
||||||
$grouped = array();
|
));
|
||||||
|
|
||||||
foreach($this->pages as $url => $page) {
|
$this->redirects = array();
|
||||||
if(!isset($grouped[$page['entitypath']])) {
|
foreach ($this->getEntities() as $entity) {
|
||||||
$grouped[$page['entitypath']] = array();
|
$this->entity = $entity;
|
||||||
}
|
|
||||||
|
$this->handleFolder('', $this->entity->getPath(), 0);
|
||||||
$grouped[$page['entitypath']][$url] = $page;
|
$finder->find($this->entity->getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->pages = array();
|
// groupds
|
||||||
|
$grouped = array();
|
||||||
foreach($grouped as $entity) {
|
|
||||||
uasort($entity, function($a, $b) {
|
foreach ($this->pages as $url => $page) {
|
||||||
// ensure parent directories are first
|
if (!isset($grouped[$page['entitypath']])) {
|
||||||
$a['filepath'] = str_replace('index.md', '', $a['filepath']);
|
$grouped[$page['entitypath']] = array();
|
||||||
$b['filepath'] = str_replace('index.md', '', $b['filepath']);
|
}
|
||||||
|
|
||||||
if(strpos($b['filepath'], $a['filepath']) === 0) {
|
$grouped[$page['entitypath']][$url] = $page;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
$this->pages = array();
|
||||||
if ($a['filepath'] == $b['filepath']) {
|
|
||||||
return 0;
|
foreach ($grouped as $entity) {
|
||||||
}
|
uasort($entity, function ($a, $b) {
|
||||||
|
// ensure parent directories are first
|
||||||
return ($a['filepath'] < $b['filepath']) ? -1 : 1;
|
$a['filepath'] = str_replace('index.md', '', $a['filepath']);
|
||||||
});
|
$b['filepath'] = str_replace('index.md', '', $b['filepath']);
|
||||||
|
|
||||||
$this->pages = array_merge($this->pages, $entity);
|
if (strpos($b['filepath'], $a['filepath']) === 0) {
|
||||||
}
|
return -1;
|
||||||
|
}
|
||||||
if ($cache) {
|
|
||||||
$this->cache->save(
|
if ($a['filepath'] == $b['filepath']) {
|
||||||
array(
|
return 0;
|
||||||
'pages' => $this->pages,
|
}
|
||||||
'redirects' => $this->redirects
|
|
||||||
),
|
return ($a['filepath'] < $b['filepath']) ? -1 : 1;
|
||||||
$this->cacheKey
|
});
|
||||||
);
|
|
||||||
}
|
$this->pages = array_merge($this->pages, $entity);
|
||||||
|
}
|
||||||
$this->inited = true;
|
|
||||||
}
|
if ($cache) {
|
||||||
|
$this->cache->save(
|
||||||
/**
|
array(
|
||||||
* Remove the link_base from the start of a link
|
'pages' => $this->pages,
|
||||||
*
|
'redirects' => $this->redirects
|
||||||
* @param string $link
|
),
|
||||||
* @return string
|
$this->cacheKey
|
||||||
*/
|
);
|
||||||
protected function stripLinkBase($link) {
|
}
|
||||||
return ltrim(str_replace(
|
|
||||||
Config::inst()->get('DocumentationViewer', 'link_base'),
|
$this->inited = true;
|
||||||
'',
|
}
|
||||||
$link
|
|
||||||
), '/');
|
/**
|
||||||
}
|
* Remove the link_base from the start of a link
|
||||||
|
*
|
||||||
/**
|
* @param string $link
|
||||||
*
|
* @return string
|
||||||
* @param DocumentationPage $page
|
*/
|
||||||
* @param string $basename
|
protected function stripLinkBase($link)
|
||||||
* @param string $path
|
{
|
||||||
*/
|
return ltrim(str_replace(
|
||||||
protected function addPage($page, $basename, $path) {
|
Config::inst()->get('DocumentationViewer', 'link_base'),
|
||||||
$link = $this->stripLinkBase($page->Link());
|
'',
|
||||||
|
$link
|
||||||
$this->pages[$link] = array(
|
), '/');
|
||||||
'title' => $page->getTitle(),
|
}
|
||||||
'basename' => $basename,
|
|
||||||
'filepath' => $path,
|
/**
|
||||||
'type' => get_class($page),
|
*
|
||||||
'entitypath' => $this->entity->getPath(),
|
* @param DocumentationPage $page
|
||||||
'summary' => $page->getSummary()
|
* @param string $basename
|
||||||
);
|
* @param string $path
|
||||||
}
|
*/
|
||||||
|
protected function addPage($page, $basename, $path)
|
||||||
/**
|
{
|
||||||
* Add a redirect
|
$link = $this->stripLinkBase($page->Link());
|
||||||
*
|
|
||||||
* @param string $from
|
$this->pages[$link] = array(
|
||||||
* @param string $to
|
'title' => $page->getTitle(),
|
||||||
*/
|
'basename' => $basename,
|
||||||
protected function addRedirect($from, $to) {
|
'filepath' => $path,
|
||||||
$fromLink = $this->stripLinkBase($from);
|
'type' => get_class($page),
|
||||||
$toLink = $this->stripLinkBase($to);
|
'entitypath' => $this->entity->getPath(),
|
||||||
$this->redirects[$fromLink] = $toLink;
|
'summary' => $page->getSummary()
|
||||||
}
|
);
|
||||||
|
}
|
||||||
/**
|
|
||||||
*
|
/**
|
||||||
*/
|
* Add a redirect
|
||||||
public function handleFolder($basename, $path, $depth) {
|
*
|
||||||
$folder = Injector::inst()->create(
|
* @param string $from
|
||||||
'DocumentationFolder', $this->entity, $basename, $path
|
* @param string $to
|
||||||
);
|
*/
|
||||||
|
protected function addRedirect($from, $to)
|
||||||
// Add main folder link
|
{
|
||||||
$fullLink = $folder->Link();
|
$fromLink = $this->stripLinkBase($from);
|
||||||
$this->addPage($folder, $basename, $path);
|
$toLink = $this->stripLinkBase($to);
|
||||||
|
$this->redirects[$fromLink] = $toLink;
|
||||||
// Add alternative link
|
}
|
||||||
$shortLink = $folder->Link(true);
|
|
||||||
if($shortLink != $fullLink) {
|
/**
|
||||||
$this->addRedirect($shortLink, $fullLink);
|
*
|
||||||
}
|
*/
|
||||||
}
|
public function handleFolder($basename, $path, $depth)
|
||||||
|
{
|
||||||
/**
|
$folder = Injector::inst()->create(
|
||||||
* Individual files can optionally provide a nice title and a better URL
|
'DocumentationFolder', $this->entity, $basename, $path
|
||||||
* through the use of markdown meta data. This creates a new
|
);
|
||||||
* {@link DocumentationPage} instance for the file.
|
|
||||||
*
|
// Add main folder link
|
||||||
* If the markdown does not specify the title in the meta data it falls back
|
$fullLink = $folder->Link();
|
||||||
* to using the file name.
|
$this->addPage($folder, $basename, $path);
|
||||||
*
|
|
||||||
* @param string $basename
|
// Add alternative link
|
||||||
* @param string $path
|
$shortLink = $folder->Link(true);
|
||||||
* @param int $depth
|
if ($shortLink != $fullLink) {
|
||||||
*/
|
$this->addRedirect($shortLink, $fullLink);
|
||||||
public function handleFile($basename, $path, $depth) {
|
}
|
||||||
$page = Injector::inst()->create(
|
}
|
||||||
'DocumentationPage',
|
|
||||||
$this->entity, $basename, $path
|
/**
|
||||||
);
|
* Individual files can optionally provide a nice title and a better URL
|
||||||
|
* through the use of markdown meta data. This creates a new
|
||||||
// populate any meta data
|
* {@link DocumentationPage} instance for the file.
|
||||||
$page->getMarkdown();
|
*
|
||||||
|
* If the markdown does not specify the title in the meta data it falls back
|
||||||
// Add main link
|
* to using the file name.
|
||||||
$fullLink = $page->Link();
|
*
|
||||||
$this->addPage($page, $basename, $path);
|
* @param string $basename
|
||||||
|
* @param string $path
|
||||||
// If this is a stable version, add the short link
|
* @param int $depth
|
||||||
$shortLink = $page->Link(true);
|
*/
|
||||||
if($fullLink != $shortLink) {
|
public function handleFile($basename, $path, $depth)
|
||||||
$this->addRedirect($shortLink, $fullLink);
|
{
|
||||||
}
|
$page = Injector::inst()->create(
|
||||||
}
|
'DocumentationPage',
|
||||||
|
$this->entity, $basename, $path
|
||||||
/**
|
);
|
||||||
* Generate an {@link ArrayList} of the pages to the given page.
|
|
||||||
*
|
// populate any meta data
|
||||||
* @param DocumentationPage
|
$page->getMarkdown();
|
||||||
* @param DocumentationEntityLanguage
|
|
||||||
*
|
// Add main link
|
||||||
* @return ArrayList
|
$fullLink = $page->Link();
|
||||||
*/
|
$this->addPage($page, $basename, $path);
|
||||||
public function generateBreadcrumbs($record, $base) {
|
|
||||||
$output = new ArrayList();
|
// If this is a stable version, add the short link
|
||||||
|
$shortLink = $page->Link(true);
|
||||||
$parts = explode('/', trim($record->getRelativeLink(), '/'));
|
if ($fullLink != $shortLink) {
|
||||||
|
$this->addRedirect($shortLink, $fullLink);
|
||||||
// Add the base link.
|
}
|
||||||
$output->push(new ArrayData(array(
|
}
|
||||||
'Link' => $base->Link(),
|
|
||||||
'Title' => $base->Title
|
/**
|
||||||
)));
|
* Generate an {@link ArrayList} of the pages to the given page.
|
||||||
|
*
|
||||||
$progress = $base->Link();
|
* @param DocumentationPage
|
||||||
|
* @param DocumentationEntityLanguage
|
||||||
foreach($parts as $part) {
|
*
|
||||||
if($part) {
|
* @return ArrayList
|
||||||
$progress = Controller::join_links($progress, $part, '/');
|
*/
|
||||||
|
public function generateBreadcrumbs($record, $base)
|
||||||
$output->push(new ArrayData(array(
|
{
|
||||||
'Link' => $progress,
|
$output = new ArrayList();
|
||||||
'Title' => DocumentationHelper::clean_page_name($part)
|
|
||||||
)));
|
$parts = explode('/', trim($record->getRelativeLink(), '/'));
|
||||||
}
|
|
||||||
}
|
// Add the base link.
|
||||||
|
$output->push(new ArrayData(array(
|
||||||
return $output;
|
'Link' => $base->Link(),
|
||||||
}
|
'Title' => $base->Title
|
||||||
|
)));
|
||||||
/**
|
|
||||||
* Determine the next page from the given page.
|
$progress = $base->Link();
|
||||||
*
|
|
||||||
* Relies on the fact when the manifest was built, it was generated in
|
foreach ($parts as $part) {
|
||||||
* order.
|
if ($part) {
|
||||||
*
|
$progress = Controller::join_links($progress, $part, '/');
|
||||||
* @param string $filepath
|
|
||||||
* @param string $entityBase
|
$output->push(new ArrayData(array(
|
||||||
*
|
'Link' => $progress,
|
||||||
* @return ArrayData
|
'Title' => DocumentationHelper::clean_page_name($part)
|
||||||
*/
|
)));
|
||||||
public function getNextPage($filepath, $entityBase) {
|
}
|
||||||
$grabNext = false;
|
}
|
||||||
$fallback = null;
|
|
||||||
|
return $output;
|
||||||
foreach($this->getPages() as $url => $page) {
|
}
|
||||||
if($grabNext && strpos($page['filepath'], $entityBase) !== false) {
|
|
||||||
return new ArrayData(array(
|
/**
|
||||||
'Link' => $url,
|
* Determine the next page from the given page.
|
||||||
'Title' => $page['title']
|
*
|
||||||
));
|
* Relies on the fact when the manifest was built, it was generated in
|
||||||
}
|
* order.
|
||||||
|
*
|
||||||
if($filepath == $page['filepath']) {
|
* @param string $filepath
|
||||||
$grabNext = true;
|
* @param string $entityBase
|
||||||
} else if(!$fallback && strpos($page['filepath'], $filepath) !== false) {
|
*
|
||||||
$fallback = new ArrayData(array(
|
* @return ArrayData
|
||||||
'Link' => $url,
|
*/
|
||||||
'Title' => $page['title'],
|
public function getNextPage($filepath, $entityBase)
|
||||||
'Fallback' => true
|
{
|
||||||
));
|
$grabNext = false;
|
||||||
}
|
$fallback = null;
|
||||||
}
|
|
||||||
|
foreach ($this->getPages() as $url => $page) {
|
||||||
if(!$grabNext) {
|
if ($grabNext && strpos($page['filepath'], $entityBase) !== false) {
|
||||||
return $fallback;
|
return new ArrayData(array(
|
||||||
}
|
'Link' => $url,
|
||||||
|
'Title' => $page['title']
|
||||||
return null;
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
if ($filepath == $page['filepath']) {
|
||||||
* Determine the previous page from the given page.
|
$grabNext = true;
|
||||||
*
|
} elseif (!$fallback && strpos($page['filepath'], $filepath) !== false) {
|
||||||
* Relies on the fact when the manifest was built, it was generated in
|
$fallback = new ArrayData(array(
|
||||||
* order.
|
'Link' => $url,
|
||||||
*
|
'Title' => $page['title'],
|
||||||
* @param string $filepath
|
'Fallback' => true
|
||||||
* @param string $entityBase
|
));
|
||||||
*
|
}
|
||||||
* @return ArrayData
|
}
|
||||||
*/
|
|
||||||
public function getPreviousPage($filepath, $entityPath) {
|
if (!$grabNext) {
|
||||||
$previousUrl = $previousPage = null;
|
return $fallback;
|
||||||
|
}
|
||||||
foreach($this->getPages() as $url => $page) {
|
|
||||||
if($filepath == $page['filepath']) {
|
return null;
|
||||||
if($previousUrl) {
|
}
|
||||||
return new ArrayData(array(
|
|
||||||
'Link' => $previousUrl,
|
/**
|
||||||
'Title' => $previousPage['title']
|
* Determine the previous page from the given page.
|
||||||
));
|
*
|
||||||
}
|
* Relies on the fact when the manifest was built, it was generated in
|
||||||
}
|
* order.
|
||||||
|
*
|
||||||
if(strpos($page['filepath'], $entityPath) !== false) {
|
* @param string $filepath
|
||||||
$previousUrl = $url;
|
* @param string $entityBase
|
||||||
$previousPage = $page;
|
*
|
||||||
}
|
* @return ArrayData
|
||||||
}
|
*/
|
||||||
|
public function getPreviousPage($filepath, $entityPath)
|
||||||
return null;
|
{
|
||||||
}
|
$previousUrl = $previousPage = null;
|
||||||
|
|
||||||
/**
|
foreach ($this->getPages() as $url => $page) {
|
||||||
* @param string
|
if ($filepath == $page['filepath']) {
|
||||||
*
|
if ($previousUrl) {
|
||||||
* @return string
|
return new ArrayData(array(
|
||||||
*/
|
'Link' => $previousUrl,
|
||||||
public function normalizeUrl($url) {
|
'Title' => $previousPage['title']
|
||||||
$url = trim($url, '/') .'/';
|
));
|
||||||
|
}
|
||||||
// if the page is the index page then hide it from the menu
|
}
|
||||||
if(strpos(strtolower($url), '/index.md/')) {
|
|
||||||
$url = substr($url, 0, strpos($url, "index.md/"));
|
if (strpos($page['filepath'], $entityPath) !== false) {
|
||||||
}
|
$previousUrl = $url;
|
||||||
|
$previousPage = $page;
|
||||||
return $url;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return null;
|
||||||
* Return the children of the provided record path.
|
}
|
||||||
*
|
|
||||||
* Looks for any pages in the manifest which have one more slash attached.
|
/**
|
||||||
*
|
* @param string
|
||||||
* @param string $path
|
*
|
||||||
*
|
* @return string
|
||||||
* @return ArrayList
|
*/
|
||||||
*/
|
public function normalizeUrl($url)
|
||||||
public function getChildrenFor($entityPath, $recordPath = null) {
|
{
|
||||||
if(!$recordPath) {
|
$url = trim($url, '/') .'/';
|
||||||
$recordPath = $entityPath;
|
|
||||||
}
|
// if the page is the index page then hide it from the menu
|
||||||
|
if (strpos(strtolower($url), '/index.md/')) {
|
||||||
$output = new ArrayList();
|
$url = substr($url, 0, strpos($url, "index.md/"));
|
||||||
$base = Config::inst()->get('DocumentationViewer', 'link_base');
|
}
|
||||||
$entityPath = $this->normalizeUrl($entityPath);
|
|
||||||
$recordPath = $this->normalizeUrl($recordPath);
|
return $url;
|
||||||
$recordParts = explode(DIRECTORY_SEPARATOR, trim($recordPath,'/'));
|
}
|
||||||
$currentRecordPath = end($recordParts);
|
|
||||||
$depth = substr_count($entityPath, '/');
|
/**
|
||||||
|
* Return the children of the provided record path.
|
||||||
foreach($this->getPages() as $url => $page) {
|
*
|
||||||
$pagePath = $this->normalizeUrl($page['filepath']);
|
* Looks for any pages in the manifest which have one more slash attached.
|
||||||
|
*
|
||||||
// check to see if this page is under the given path
|
* @param string $path
|
||||||
if(strpos($pagePath, $entityPath) === false) {
|
*
|
||||||
continue;
|
* @return ArrayList
|
||||||
}
|
*/
|
||||||
|
public function getChildrenFor($entityPath, $recordPath = null)
|
||||||
// only pull it up if it's one more level depth
|
{
|
||||||
if(substr_count($pagePath, DIRECTORY_SEPARATOR) == ($depth + 1)) {
|
if (!$recordPath) {
|
||||||
$pagePathParts = explode(DIRECTORY_SEPARATOR, trim($pagePath,'/'));
|
$recordPath = $entityPath;
|
||||||
$currentPagePath = end($pagePathParts);
|
}
|
||||||
if($currentPagePath == $currentRecordPath) {
|
|
||||||
$mode = 'current';
|
$output = new ArrayList();
|
||||||
}
|
$base = Config::inst()->get('DocumentationViewer', 'link_base');
|
||||||
else if(strpos($recordPath, $pagePath) !== false) {
|
$entityPath = $this->normalizeUrl($entityPath);
|
||||||
$mode = 'section';
|
$recordPath = $this->normalizeUrl($recordPath);
|
||||||
}
|
$recordParts = explode(DIRECTORY_SEPARATOR, trim($recordPath, '/'));
|
||||||
else {
|
$currentRecordPath = end($recordParts);
|
||||||
$mode = 'link';
|
$depth = substr_count($entityPath, '/');
|
||||||
}
|
|
||||||
|
foreach ($this->getPages() as $url => $page) {
|
||||||
$children = new ArrayList();
|
$pagePath = $this->normalizeUrl($page['filepath']);
|
||||||
|
|
||||||
if($mode == 'section' || $mode == 'current') {
|
// check to see if this page is under the given path
|
||||||
$children = $this->getChildrenFor($pagePath, $recordPath);
|
if (strpos($pagePath, $entityPath) === false) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
$output->push(new ArrayData(array(
|
|
||||||
'Link' => Controller::join_links($base, $url, '/'),
|
// only pull it up if it's one more level depth
|
||||||
'Title' => $page['title'],
|
if (substr_count($pagePath, DIRECTORY_SEPARATOR) == ($depth + 1)) {
|
||||||
'LinkingMode' => $mode,
|
$pagePathParts = explode(DIRECTORY_SEPARATOR, trim($pagePath, '/'));
|
||||||
'Summary' => $page['summary'],
|
$currentPagePath = end($pagePathParts);
|
||||||
'Children' => $children
|
if ($currentPagePath == $currentRecordPath) {
|
||||||
)));
|
$mode = 'current';
|
||||||
}
|
} elseif (strpos($recordPath, $pagePath) !== false) {
|
||||||
}
|
$mode = 'section';
|
||||||
|
} else {
|
||||||
return $output;
|
$mode = 'link';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
$children = new ArrayList();
|
||||||
* @param DocumentationEntity
|
|
||||||
*
|
if ($mode == 'section' || $mode == 'current') {
|
||||||
* @return ArrayList
|
$children = $this->getChildrenFor($pagePath, $recordPath);
|
||||||
*/
|
}
|
||||||
public function getAllVersionsOfEntity(DocumentationEntity $entity) {
|
|
||||||
$all = new ArrayList();
|
$output->push(new ArrayData(array(
|
||||||
|
'Link' => Controller::join_links($base, $url, '/'),
|
||||||
foreach($this->getEntities() as $check) {
|
'Title' => $page['title'],
|
||||||
if($check->getKey() == $entity->getKey()) {
|
'LinkingMode' => $mode,
|
||||||
if($check->getLanguage() == $entity->getLanguage()) {
|
'Summary' => $page['summary'],
|
||||||
$all->push($check);
|
'Children' => $children
|
||||||
}
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $all;
|
return $output;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param DocumentationEntity
|
* @param DocumentationEntity
|
||||||
*
|
*
|
||||||
* @return DocumentationEntity
|
* @return ArrayList
|
||||||
*/
|
*/
|
||||||
public function getStableVersion(DocumentationEntity $entity) {
|
public function getAllVersionsOfEntity(DocumentationEntity $entity)
|
||||||
foreach($this->getEntities() as $check) {
|
{
|
||||||
if($check->getKey() == $entity->getKey()) {
|
$all = new ArrayList();
|
||||||
if($check->getLanguage() == $entity->getLanguage()) {
|
|
||||||
if($check->getIsStable()) {
|
foreach ($this->getEntities() as $check) {
|
||||||
return $check;
|
if ($check->getKey() == $entity->getKey()) {
|
||||||
}
|
if ($check->getLanguage() == $entity->getLanguage()) {
|
||||||
}
|
$all->push($check);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return $entity;
|
|
||||||
}
|
return $all;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @param DocumentationEntity
|
/**
|
||||||
*
|
* @param DocumentationEntity
|
||||||
* @return ArrayList
|
*
|
||||||
*/
|
* @return DocumentationEntity
|
||||||
public function getVersions($entity) {
|
*/
|
||||||
if(!$entity) {
|
public function getStableVersion(DocumentationEntity $entity)
|
||||||
return null;
|
{
|
||||||
}
|
foreach ($this->getEntities() as $check) {
|
||||||
|
if ($check->getKey() == $entity->getKey()) {
|
||||||
$output = new ArrayList();
|
if ($check->getLanguage() == $entity->getLanguage()) {
|
||||||
|
if ($check->getIsStable()) {
|
||||||
foreach($this->getEntities() as $check) {
|
return $check;
|
||||||
if($check->getKey() == $entity->getKey()) {
|
}
|
||||||
if($check->getLanguage() == $entity->getLanguage()) {
|
}
|
||||||
$same = ($check->getVersion() == $entity->getVersion());
|
}
|
||||||
|
}
|
||||||
$output->push(new ArrayData(array(
|
|
||||||
'Title' => $check->getVersion(),
|
return $entity;
|
||||||
'Link' => $check->Link(),
|
}
|
||||||
'LinkingMode' => ($same) ? 'current' : 'link',
|
|
||||||
'IsStable' => $check->getIsStable()
|
/**
|
||||||
)));
|
* @param DocumentationEntity
|
||||||
|
*
|
||||||
}
|
* @return ArrayList
|
||||||
}
|
*/
|
||||||
}
|
public function getVersions($entity)
|
||||||
|
{
|
||||||
return $output;
|
if (!$entity) {
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Returns a sorted array of all the unique versions registered
|
$output = new ArrayList();
|
||||||
*/
|
|
||||||
public function getAllVersions() {
|
foreach ($this->getEntities() as $check) {
|
||||||
$versions = array();
|
if ($check->getKey() == $entity->getKey()) {
|
||||||
|
if ($check->getLanguage() == $entity->getLanguage()) {
|
||||||
foreach($this->getEntities() as $entity) {
|
$same = ($check->getVersion() == $entity->getVersion());
|
||||||
if($entity->getVersion()) {
|
|
||||||
$versions[$entity->getVersion()] = $entity->getVersion();
|
$output->push(new ArrayData(array(
|
||||||
} else {
|
'Title' => $check->getVersion(),
|
||||||
$versions['0.0'] = _t('DocumentationManifest.MASTER', 'Master');
|
'Link' => $check->Link(),
|
||||||
}
|
'LinkingMode' => ($same) ? 'current' : 'link',
|
||||||
}
|
'IsStable' => $check->getIsStable()
|
||||||
|
)));
|
||||||
asort($versions);
|
}
|
||||||
|
}
|
||||||
return $versions;
|
}
|
||||||
}
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a sorted array of all the unique versions registered
|
||||||
|
*/
|
||||||
|
public function getAllVersions()
|
||||||
|
{
|
||||||
|
$versions = array();
|
||||||
|
|
||||||
|
foreach ($this->getEntities() as $entity) {
|
||||||
|
if ($entity->getVersion()) {
|
||||||
|
$versions[$entity->getVersion()] = $entity->getVersion();
|
||||||
|
} else {
|
||||||
|
$versions['0.0'] = _t('DocumentationManifest.MASTER', 'Master');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
asort($versions);
|
||||||
|
|
||||||
|
return $versions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,38 +1,38 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class DocumentationManifestFileFinder extends SS_FileFinder {
|
class DocumentationManifestFileFinder extends SS_FileFinder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $ignored_files = array(
|
||||||
|
'.', '..', '.ds_store',
|
||||||
|
'.svn', '.git', 'assets', 'themes', '_images'
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $ignored_files = array(
|
protected static $default_options = array(
|
||||||
'.', '..', '.ds_store',
|
'name_regex' => '/\.(md|markdown)$/i',
|
||||||
'.svn', '.git', 'assets', 'themes', '_images'
|
'file_callback' => null,
|
||||||
);
|
'dir_callback' => null,
|
||||||
|
'ignore_vcs' => true
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
*
|
||||||
*/
|
*/
|
||||||
protected static $default_options = array(
|
public function acceptDir($basename, $pathname, $depth)
|
||||||
'name_regex' => '/\.(md|markdown)$/i',
|
{
|
||||||
'file_callback' => null,
|
$ignored = Config::inst()->get('DocumentationManifestFileFinder', 'ignored_files');
|
||||||
'dir_callback' => null,
|
|
||||||
'ignore_vcs' => true
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
if ($ignored) {
|
||||||
*
|
if (in_array(strtolower($basename), $ignored)) {
|
||||||
*/
|
return false;
|
||||||
public function acceptDir($basename, $pathname, $depth) {
|
}
|
||||||
$ignored = Config::inst()->get('DocumentationManifestFileFinder', 'ignored_files');
|
}
|
||||||
|
|
||||||
if($ignored) {
|
|
||||||
if(in_array(strtolower($basename), $ignored)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,201 +7,219 @@
|
|||||||
*
|
*
|
||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
*/
|
*/
|
||||||
class DocumentationParser {
|
class DocumentationParser
|
||||||
|
{
|
||||||
|
const CODE_BLOCK_BACKTICK = 1;
|
||||||
|
const CODE_BLOCK_COLON = 2;
|
||||||
|
|
||||||
const CODE_BLOCK_BACKTICK = 1;
|
/**
|
||||||
const CODE_BLOCK_COLON = 2;
|
* @var string Rewriting of api links in the format "[api:MyClass]" or "[api:MyClass::$my_property]".
|
||||||
|
*/
|
||||||
|
public static $api_link_base = 'http://api.silverstripe.org/search/lookup/?q=%s&version=%s&module=%s';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string Rewriting of api links in the format "[api:MyClass]" or "[api:MyClass::$my_property]".
|
* @var array
|
||||||
*/
|
*/
|
||||||
public static $api_link_base = 'http://api.silverstripe.org/search/lookup/?q=%s&version=%s&module=%s';
|
public static $heading_counts = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* Parse a given path to the documentation for a file. Performs a case
|
||||||
*/
|
* insensitive lookup on the file system. Automatically appends the file
|
||||||
public static $heading_counts = array();
|
* extension to one of the markdown extensions as well so /install/ in a
|
||||||
|
* web browser will match /install.md or /INSTALL.md.
|
||||||
|
*
|
||||||
|
* Filepath: /var/www/myproject/src/cms/en/folder/subfolder/page.md
|
||||||
|
* URL: http://myhost/mywebroot/dev/docs/2.4/cms/en/folder/subfolder/page
|
||||||
|
* Webroot: http://myhost/mywebroot/
|
||||||
|
* Baselink: dev/docs/2.4/cms/en/
|
||||||
|
* Pathparts: folder/subfolder/page
|
||||||
|
*
|
||||||
|
* @param DocumentationPage $page
|
||||||
|
* @param String $baselink Link relative to webroot, up until the "root"
|
||||||
|
* of the module. Necessary to rewrite relative
|
||||||
|
* links
|
||||||
|
*
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static function parse(DocumentationPage $page, $baselink = null)
|
||||||
|
{
|
||||||
|
if (!$page || (!$page instanceof DocumentationPage)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
$md = $page->getMarkdown(true);
|
||||||
* Parse a given path to the documentation for a file. Performs a case
|
|
||||||
* insensitive lookup on the file system. Automatically appends the file
|
|
||||||
* extension to one of the markdown extensions as well so /install/ in a
|
|
||||||
* web browser will match /install.md or /INSTALL.md.
|
|
||||||
*
|
|
||||||
* Filepath: /var/www/myproject/src/cms/en/folder/subfolder/page.md
|
|
||||||
* URL: http://myhost/mywebroot/dev/docs/2.4/cms/en/folder/subfolder/page
|
|
||||||
* Webroot: http://myhost/mywebroot/
|
|
||||||
* Baselink: dev/docs/2.4/cms/en/
|
|
||||||
* Pathparts: folder/subfolder/page
|
|
||||||
*
|
|
||||||
* @param DocumentationPage $page
|
|
||||||
* @param String $baselink Link relative to webroot, up until the "root"
|
|
||||||
* of the module. Necessary to rewrite relative
|
|
||||||
* links
|
|
||||||
*
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public static function parse(DocumentationPage $page, $baselink = null) {
|
|
||||||
if(!$page || (!$page instanceof DocumentationPage)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$md = $page->getMarkdown(true);
|
// Pre-processing
|
||||||
|
$md = self::rewrite_image_links($md, $page);
|
||||||
|
$md = self::rewrite_relative_links($md, $page, $baselink);
|
||||||
|
|
||||||
// Pre-processing
|
$md = self::rewrite_api_links($md, $page);
|
||||||
$md = self::rewrite_image_links($md, $page);
|
$md = self::rewrite_heading_anchors($md, $page);
|
||||||
$md = self::rewrite_relative_links($md, $page, $baselink);
|
|
||||||
|
|
||||||
$md = self::rewrite_api_links($md, $page);
|
$md = self::rewrite_code_blocks($md);
|
||||||
$md = self::rewrite_heading_anchors($md, $page);
|
|
||||||
|
|
||||||
$md = self::rewrite_code_blocks($md);
|
$parser = new ParsedownExtra();
|
||||||
|
$parser->setBreaksEnabled(false);
|
||||||
|
|
||||||
$parser = new ParsedownExtra();
|
$text = $parser->text($md);
|
||||||
$parser->setBreaksEnabled(false);
|
|
||||||
|
|
||||||
$text = $parser->text($md);
|
return $text;
|
||||||
|
}
|
||||||
|
|
||||||
return $text;
|
public static function rewrite_code_blocks($md)
|
||||||
}
|
{
|
||||||
|
$started = false;
|
||||||
|
$inner = false;
|
||||||
|
$mode = false;
|
||||||
|
$end = false;
|
||||||
|
$debug = false;
|
||||||
|
|
||||||
public static function rewrite_code_blocks($md) {
|
$lines = explode("\n", $md);
|
||||||
$started = false;
|
$output = array();
|
||||||
$inner = false;
|
|
||||||
$mode = false;
|
|
||||||
$end = false;
|
|
||||||
$debug = false;
|
|
||||||
|
|
||||||
$lines = explode("\n", $md);
|
foreach ($lines as $i => $line) {
|
||||||
$output = array();
|
if ($debug) {
|
||||||
|
var_dump('Line '. ($i + 1) . ' '. $line);
|
||||||
|
}
|
||||||
|
|
||||||
foreach($lines as $i => $line) {
|
// if line just contains whitespace, continue down the page.
|
||||||
if($debug) var_dump('Line '. ($i + 1) . ' '. $line);
|
// Prevents code blocks with leading tabs adding an extra line.
|
||||||
|
if (preg_match('/^\s$/', $line) && !$started) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// if line just contains whitespace, continue down the page.
|
if (!$started && preg_match('/^[\t]*:::\s*(.*)/', $line, $matches)) {
|
||||||
// Prevents code blocks with leading tabs adding an extra line.
|
// first line with custom formatting
|
||||||
if(preg_match('/^\s$/', $line) && !$started) {
|
if ($debug) {
|
||||||
continue;
|
var_dump('Starts a new block with :::');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$started && preg_match('/^[\t]*:::\s*(.*)/', $line, $matches)) {
|
$started = true;
|
||||||
// first line with custom formatting
|
$mode = self::CODE_BLOCK_COLON;
|
||||||
if($debug) var_dump('Starts a new block with :::');
|
|
||||||
|
|
||||||
$started = true;
|
$output[$i] = sprintf('```%s', (isset($matches[1])) ? trim($matches[1]) : "");
|
||||||
$mode = self::CODE_BLOCK_COLON;
|
} elseif (!$started && preg_match('/^\t*```\s*(.*)/', $line, $matches)) {
|
||||||
|
if ($debug) {
|
||||||
|
var_dump('Starts a new block with ```');
|
||||||
|
}
|
||||||
|
|
||||||
$output[$i] = sprintf('```%s', (isset($matches[1])) ? trim($matches[1]) : "");
|
$started = true;
|
||||||
|
$mode = self::CODE_BLOCK_BACKTICK;
|
||||||
|
|
||||||
} else if(!$started && preg_match('/^\t*```\s*(.*)/', $line, $matches)) {
|
$output[$i] = sprintf('```%s', (isset($matches[1])) ? trim($matches[1]) : "");
|
||||||
if($debug) var_dump('Starts a new block with ```');
|
} elseif ($started && $mode == self::CODE_BLOCK_BACKTICK) {
|
||||||
|
// inside a backtick fenced box
|
||||||
|
if (preg_match('/^\t*```\s*/', $line, $matches)) {
|
||||||
|
if ($debug) {
|
||||||
|
var_dump('End a block with ```');
|
||||||
|
}
|
||||||
|
|
||||||
$started = true;
|
// end of the backtick fenced box. Unset the line that contains the backticks
|
||||||
$mode = self::CODE_BLOCK_BACKTICK;
|
$end = true;
|
||||||
|
} else {
|
||||||
|
if ($debug) {
|
||||||
|
var_dump('Still in a block with ```');
|
||||||
|
}
|
||||||
|
|
||||||
$output[$i] = sprintf('```%s', (isset($matches[1])) ? trim($matches[1]) : "");
|
// still inside the line.
|
||||||
} else if($started && $mode == self::CODE_BLOCK_BACKTICK) {
|
if (!$started) {
|
||||||
// inside a backtick fenced box
|
$output[$i - 1] = '```';
|
||||||
if(preg_match('/^\t*```\s*/', $line, $matches)) {
|
}
|
||||||
if($debug) var_dump('End a block with ```');
|
|
||||||
|
|
||||||
// end of the backtick fenced box. Unset the line that contains the backticks
|
$output[$i] = $line;
|
||||||
$end = true;
|
$inner = true;
|
||||||
}
|
}
|
||||||
else {
|
} elseif (preg_match('/^[\ ]{0,3}?[\t](.*)/', $line, $matches)) {
|
||||||
if($debug) var_dump('Still in a block with ```');
|
|
||||||
|
|
||||||
// still inside the line.
|
// inner line of block, or first line of standard markdown code block
|
||||||
if(!$started) {
|
// regex removes first tab (any following tabs are part of the code).
|
||||||
$output[$i - 1] = '```';
|
if (!$started) {
|
||||||
}
|
if ($debug) {
|
||||||
|
var_dump('Start code block because of tab. No fence');
|
||||||
|
}
|
||||||
|
|
||||||
$output[$i] = $line;
|
$output[$i - 1] = '```';
|
||||||
$inner = true;
|
} else {
|
||||||
}
|
if ($debug) {
|
||||||
} else if(preg_match('/^[\ ]{0,3}?[\t](.*)/', $line, $matches)) {
|
var_dump('Content is still tabbed so still inner');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// inner line of block, or first line of standard markdown code block
|
$output[$i] = $matches[1];
|
||||||
// regex removes first tab (any following tabs are part of the code).
|
$inner = true;
|
||||||
if(!$started) {
|
$started = true;
|
||||||
if($debug) var_dump('Start code block because of tab. No fence');
|
} elseif ($started && $inner && trim($line) === "") {
|
||||||
|
if ($debug) {
|
||||||
|
var_dump('Inner line of code block');
|
||||||
|
}
|
||||||
|
|
||||||
$output[$i - 1] = '```';
|
// still inside a colon based block, if the line is only whitespace
|
||||||
} else {
|
// then continue with with it. We can continue with it for now as
|
||||||
if($debug) var_dump('Content is still tabbed so still inner');
|
// it'll be tidied up later in the $end section.
|
||||||
}
|
$inner = true;
|
||||||
|
$output[$i] = $line;
|
||||||
|
} elseif ($started && $inner) {
|
||||||
|
// line contains something other than whitespace, or tabbed. E.g
|
||||||
|
// > code
|
||||||
|
// > \n
|
||||||
|
// > some message
|
||||||
|
//
|
||||||
|
// So actually want to reset $i to the line before this new line
|
||||||
|
// and include this line. The edge case where this will fail is
|
||||||
|
// new the following segment contains a code block as well as it
|
||||||
|
// will not open.
|
||||||
|
if ($debug) {
|
||||||
|
var_dump('Contains something that isnt code. So end the code.');
|
||||||
|
}
|
||||||
|
|
||||||
$output[$i] = $matches[1];
|
$end = true;
|
||||||
$inner = true;
|
$output[$i] = $line;
|
||||||
$started = true;
|
$i = $i - 1;
|
||||||
} else if($started && $inner && trim($line) === "") {
|
} else {
|
||||||
if($debug) var_dump('Inner line of code block');
|
$output[$i] = $line;
|
||||||
|
}
|
||||||
|
|
||||||
// still inside a colon based block, if the line is only whitespace
|
if ($end) {
|
||||||
// then continue with with it. We can continue with it for now as
|
if ($debug) {
|
||||||
// it'll be tidied up later in the $end section.
|
var_dump('End of code block');
|
||||||
$inner = true;
|
}
|
||||||
$output[$i] = $line;
|
$output = self::finalize_code_output($i, $output);
|
||||||
} else if($started && $inner) {
|
|
||||||
// line contains something other than whitespace, or tabbed. E.g
|
|
||||||
// > code
|
|
||||||
// > \n
|
|
||||||
// > some message
|
|
||||||
//
|
|
||||||
// So actually want to reset $i to the line before this new line
|
|
||||||
// and include this line. The edge case where this will fail is
|
|
||||||
// new the following segment contains a code block as well as it
|
|
||||||
// will not open.
|
|
||||||
if($debug) {
|
|
||||||
var_dump('Contains something that isnt code. So end the code.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$end = true;
|
// reset state
|
||||||
$output[$i] = $line;
|
$started = $inner = $mode = $end = false;
|
||||||
$i = $i - 1;
|
}
|
||||||
} else {
|
}
|
||||||
$output[$i] = $line;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($end) {
|
if ($started) {
|
||||||
if($debug) var_dump('End of code block');
|
$output = self::finalize_code_output($i+1, $output);
|
||||||
$output = self::finalize_code_output($i, $output);
|
}
|
||||||
|
|
||||||
// reset state
|
return implode("\n", $output);
|
||||||
$started = $inner = $mode = $end = false;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($started) {
|
/**
|
||||||
$output = self::finalize_code_output($i+1, $output);
|
* Adds the closing code backticks. Removes trailing whitespace.
|
||||||
}
|
*
|
||||||
|
* @param int
|
||||||
|
* @param array
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private static function finalize_code_output($i, $output)
|
||||||
|
{
|
||||||
|
if (isset($output[$i]) && trim($output[$i])) {
|
||||||
|
$output[$i] .= "\n```\n";
|
||||||
|
} else {
|
||||||
|
$output[$i] = "```";
|
||||||
|
}
|
||||||
|
|
||||||
return implode("\n", $output);
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
public static function rewrite_image_links($md, $page)
|
||||||
|
{
|
||||||
/**
|
// Links with titles
|
||||||
* Adds the closing code backticks. Removes trailing whitespace.
|
$re = '/
|
||||||
*
|
|
||||||
* @param int
|
|
||||||
* @param array
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private static function finalize_code_output($i, $output) {
|
|
||||||
if(isset($output[$i]) && trim($output[$i])) {
|
|
||||||
$output[$i] .= "\n```\n";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$output[$i] = "```";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function rewrite_image_links($md, $page) {
|
|
||||||
// Links with titles
|
|
||||||
$re = '/
|
|
||||||
!
|
!
|
||||||
\[
|
\[
|
||||||
(.*?) # image title (non greedy)
|
(.*?) # image title (non greedy)
|
||||||
@ -210,77 +228,78 @@ class DocumentationParser {
|
|||||||
(.*?) # image url (non greedy)
|
(.*?) # image url (non greedy)
|
||||||
\)
|
\)
|
||||||
/x';
|
/x';
|
||||||
preg_match_all($re, $md, $images);
|
preg_match_all($re, $md, $images);
|
||||||
|
|
||||||
if($images) {
|
if ($images) {
|
||||||
foreach($images[0] as $i => $match) {
|
foreach ($images[0] as $i => $match) {
|
||||||
$title = $images[1][$i];
|
$title = $images[1][$i];
|
||||||
$url = $images[2][$i];
|
$url = $images[2][$i];
|
||||||
|
|
||||||
// Don't process absolute links (based on protocol detection)
|
// Don't process absolute links (based on protocol detection)
|
||||||
$urlParts = parse_url($url);
|
$urlParts = parse_url($url);
|
||||||
|
|
||||||
if($urlParts && isset($urlParts['scheme'])) {
|
if ($urlParts && isset($urlParts['scheme'])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite URL (relative or absolute)
|
// Rewrite URL (relative or absolute)
|
||||||
$baselink = Director::makeRelative(
|
$baselink = Director::makeRelative(
|
||||||
dirname($page->getPath())
|
dirname($page->getPath())
|
||||||
);
|
);
|
||||||
|
|
||||||
// if the image starts with a slash, it's absolute
|
// if the image starts with a slash, it's absolute
|
||||||
if(substr($url, 0, 1) == '/') {
|
if (substr($url, 0, 1) == '/') {
|
||||||
$relativeUrl = str_replace(BASE_PATH, '', Controller::join_links(
|
$relativeUrl = str_replace(BASE_PATH, '', Controller::join_links(
|
||||||
$page->getEntity()->getPath(),
|
$page->getEntity()->getPath(),
|
||||||
$url
|
$url
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
$relativeUrl = rtrim($baselink, '/') . '/' . ltrim($url, '/');
|
$relativeUrl = rtrim($baselink, '/') . '/' . ltrim($url, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve relative paths
|
// Resolve relative paths
|
||||||
while(strpos($relativeUrl, '/..') !== FALSE) {
|
while (strpos($relativeUrl, '/..') !== false) {
|
||||||
$relativeUrl = preg_replace('/\w+\/\.\.\//', '', $relativeUrl);
|
$relativeUrl = preg_replace('/\w+\/\.\.\//', '', $relativeUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make it absolute again
|
// Make it absolute again
|
||||||
$absoluteUrl = Controller::join_links(
|
$absoluteUrl = Controller::join_links(
|
||||||
Director::absoluteBaseURL(),
|
Director::absoluteBaseURL(),
|
||||||
$relativeUrl
|
$relativeUrl
|
||||||
);
|
);
|
||||||
|
|
||||||
// Replace any double slashes (apart from protocol)
|
// Replace any double slashes (apart from protocol)
|
||||||
// $absoluteUrl = preg_replace('/([^:])\/{2,}/', '$1/', $absoluteUrl);
|
// $absoluteUrl = preg_replace('/([^:])\/{2,}/', '$1/', $absoluteUrl);
|
||||||
|
|
||||||
// Replace in original content
|
// Replace in original content
|
||||||
$md = str_replace(
|
$md = str_replace(
|
||||||
$match,
|
$match,
|
||||||
sprintf('![%s](%s)', $title, $absoluteUrl),
|
sprintf('![%s](%s)', $title, $absoluteUrl),
|
||||||
$md
|
$md
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $md;
|
return $md;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rewrite links with special "api:" prefix, from two possible formats:
|
* Rewrite links with special "api:" prefix, from two possible formats:
|
||||||
* 1. [api:DataObject]
|
* 1. [api:DataObject]
|
||||||
* 2. (My Title)(api:DataObject)
|
* 2. (My Title)(api:DataObject)
|
||||||
*
|
*
|
||||||
* Hack: Replaces any backticks with "<code>" blocks,
|
* Hack: Replaces any backticks with "<code>" blocks,
|
||||||
* as the currently used markdown parser doesn't resolve links in backticks,
|
* as the currently used markdown parser doesn't resolve links in backticks,
|
||||||
* but does resolve in "<code>" blocks.
|
* but does resolve in "<code>" blocks.
|
||||||
*
|
*
|
||||||
* @param String $md
|
* @param String $md
|
||||||
* @param DocumentationPage $page
|
* @param DocumentationPage $page
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
public static function rewrite_api_links($md, $page) {
|
public static function rewrite_api_links($md, $page)
|
||||||
// Links with titles
|
{
|
||||||
$re = '/
|
// Links with titles
|
||||||
|
$re = '/
|
||||||
`?
|
`?
|
||||||
\[
|
\[
|
||||||
(.*?) # link title (non greedy)
|
(.*?) # link title (non greedy)
|
||||||
@ -290,116 +309,121 @@ class DocumentationParser {
|
|||||||
\)
|
\)
|
||||||
`?
|
`?
|
||||||
/x';
|
/x';
|
||||||
preg_match_all($re, $md, $linksWithTitles);
|
preg_match_all($re, $md, $linksWithTitles);
|
||||||
if($linksWithTitles) {
|
if ($linksWithTitles) {
|
||||||
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(
|
$url = sprintf(
|
||||||
self::$api_link_base,
|
self::$api_link_base,
|
||||||
urlencode($subject),
|
urlencode($subject),
|
||||||
urlencode($page->getVersion()),
|
urlencode($page->getVersion()),
|
||||||
urlencode($page->getEntity()->getKey())
|
urlencode($page->getEntity()->getKey())
|
||||||
);
|
);
|
||||||
|
|
||||||
$md = str_replace(
|
$md = str_replace(
|
||||||
$match,
|
$match,
|
||||||
sprintf('[%s](%s)', $title, $url),
|
sprintf('[%s](%s)', $title, $url),
|
||||||
$md
|
$md
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bare links
|
// Bare links
|
||||||
$re = '/
|
$re = '/
|
||||||
`?
|
`?
|
||||||
\[
|
\[
|
||||||
api:(.*?)
|
api:(.*?)
|
||||||
\]
|
\]
|
||||||
`?
|
`?
|
||||||
/x';
|
/x';
|
||||||
preg_match_all($re, $md, $links);
|
preg_match_all($re, $md, $links);
|
||||||
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(
|
$url = sprintf(
|
||||||
self::$api_link_base,
|
self::$api_link_base,
|
||||||
$subject,
|
$subject,
|
||||||
$page->getVersion(),
|
$page->getVersion(),
|
||||||
$page->getEntity()->getKey()
|
$page->getEntity()->getKey()
|
||||||
);
|
);
|
||||||
|
|
||||||
$md = str_replace(
|
$md = str_replace(
|
||||||
$match,
|
$match,
|
||||||
sprintf('[%s](%s)', $subject, $url),
|
sprintf('[%s](%s)', $subject, $url),
|
||||||
$md
|
$md
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $md;
|
return $md;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static function rewrite_heading_anchors($md, $page) {
|
public static function rewrite_heading_anchors($md, $page)
|
||||||
$re = '/^\#+(.*)/m';
|
{
|
||||||
$md = preg_replace_callback($re, array('DocumentationParser', '_rewrite_heading_anchors_callback'), $md);
|
$re = '/^\#+(.*)/m';
|
||||||
|
$md = preg_replace_callback($re, array('DocumentationParser', '_rewrite_heading_anchors_callback'), $md);
|
||||||
|
|
||||||
return $md;
|
return $md;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static function _rewrite_heading_anchors_callback($matches) {
|
public static function _rewrite_heading_anchors_callback($matches)
|
||||||
$heading = $matches[0];
|
{
|
||||||
$headingText = $matches[1];
|
$heading = $matches[0];
|
||||||
|
$headingText = $matches[1];
|
||||||
|
|
||||||
if(preg_match('/\{\#.*\}/', $headingText)) return $heading;
|
if (preg_match('/\{\#.*\}/', $headingText)) {
|
||||||
|
return $heading;
|
||||||
|
}
|
||||||
|
|
||||||
if(!isset(self::$heading_counts[$headingText])) {
|
if (!isset(self::$heading_counts[$headingText])) {
|
||||||
self::$heading_counts[$headingText] = 1;
|
self::$heading_counts[$headingText] = 1;
|
||||||
}
|
} else {
|
||||||
else {
|
self::$heading_counts[$headingText]++;
|
||||||
self::$heading_counts[$headingText]++;
|
$headingText .= "-" . self::$heading_counts[$headingText];
|
||||||
$headingText .= "-" . self::$heading_counts[$headingText];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return sprintf("%s {#%s}", preg_replace('/\n/', '', $heading), self::generate_html_id($headingText));
|
return sprintf("%s {#%s}", preg_replace('/\n/', '', $heading), self::generate_html_id($headingText));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate an html element id from a string
|
* Generate an html element id from a string
|
||||||
*
|
*
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
public static function generate_html_id($title) {
|
public static function generate_html_id($title)
|
||||||
$t = $title;
|
{
|
||||||
$t = str_replace('&','-and-',$t);
|
$t = $title;
|
||||||
$t = str_replace('&','-and-',$t);
|
$t = str_replace('&', '-and-', $t);
|
||||||
$t = preg_replace('/[^A-Za-z0-9]+/','-',$t);
|
$t = str_replace('&', '-and-', $t);
|
||||||
$t = preg_replace('/-+/','-',$t);
|
$t = preg_replace('/[^A-Za-z0-9]+/', '-', $t);
|
||||||
$t = trim($t, '-');
|
$t = preg_replace('/-+/', '-', $t);
|
||||||
$t = strtolower($t);
|
$t = trim($t, '-');
|
||||||
|
$t = strtolower($t);
|
||||||
|
|
||||||
return $t;
|
return $t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves all relative links within markdown.
|
* Resolves all relative links within markdown.
|
||||||
*
|
*
|
||||||
* @param String $md Markdown content
|
* @param String $md Markdown content
|
||||||
* @param DocumentationPage $page
|
* @param DocumentationPage $page
|
||||||
*
|
*
|
||||||
* @return String Markdown
|
* @return String Markdown
|
||||||
*/
|
*/
|
||||||
public static function rewrite_relative_links($md, $page) {
|
public static function rewrite_relative_links($md, $page)
|
||||||
$baselink = $page->getEntity()->Link();
|
{
|
||||||
|
$baselink = $page->getEntity()->Link();
|
||||||
|
|
||||||
$re = '/
|
$re = '/
|
||||||
([^\!]?) # exclude image format
|
([^\!]?) # exclude image format
|
||||||
\[
|
\[
|
||||||
(.*?) # link title (non greedy)
|
(.*?) # link title (non greedy)
|
||||||
@ -408,100 +432,104 @@ class DocumentationParser {
|
|||||||
(.*?) # link url (non greedy)
|
(.*?) # link url (non greedy)
|
||||||
\)
|
\)
|
||||||
/x';
|
/x';
|
||||||
preg_match_all($re, $md, $matches);
|
preg_match_all($re, $md, $matches);
|
||||||
|
|
||||||
// relative path (relative to module base folder), without the filename.
|
// relative path (relative to module base folder), without the filename.
|
||||||
// For "sapphire/en/current/topics/templates", this would be "templates"
|
// For "sapphire/en/current/topics/templates", this would be "templates"
|
||||||
$relativePath = dirname($page->getRelativePath());
|
$relativePath = dirname($page->getRelativePath());
|
||||||
|
|
||||||
if(strpos($page->getRelativePath(), 'index.md')) {
|
if (strpos($page->getRelativePath(), 'index.md')) {
|
||||||
$relativeLink = $page->getRelativeLink();
|
$relativeLink = $page->getRelativeLink();
|
||||||
} else {
|
} else {
|
||||||
$relativeLink = dirname($page->getRelativeLink());
|
$relativeLink = dirname($page->getRelativeLink());
|
||||||
}
|
}
|
||||||
|
|
||||||
if($relativePath == '.') {
|
if ($relativePath == '.') {
|
||||||
$relativePath = '';
|
$relativePath = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if($relativeLink == ".") {
|
if ($relativeLink == ".") {
|
||||||
$relativeLink = '';
|
$relativeLink = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// file base link
|
// file base link
|
||||||
$fileBaseLink = Director::makeRelative(dirname($page->getPath()));
|
$fileBaseLink = Director::makeRelative(dirname($page->getPath()));
|
||||||
|
|
||||||
if($matches) {
|
if ($matches) {
|
||||||
foreach($matches[0] as $i => $match) {
|
foreach ($matches[0] as $i => $match) {
|
||||||
$title = $matches[2][$i];
|
$title = $matches[2][$i];
|
||||||
$url = $matches[3][$i];
|
$url = $matches[3][$i];
|
||||||
|
|
||||||
// Don't process API links
|
// Don't process API links
|
||||||
if(preg_match('/^api:/', $url)) continue;
|
if (preg_match('/^api:/', $url)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Don't process absolute links (based on protocol detection)
|
// Don't process absolute links (based on protocol detection)
|
||||||
$urlParts = parse_url($url);
|
$urlParts = parse_url($url);
|
||||||
if($urlParts && isset($urlParts['scheme'])) continue;
|
if ($urlParts && isset($urlParts['scheme'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// for images we need to use the file base path
|
// for images we need to use the file base path
|
||||||
if(preg_match('/_images/', $url)) {
|
if (preg_match('/_images/', $url)) {
|
||||||
$relativeUrl = Controller::join_links(
|
$relativeUrl = Controller::join_links(
|
||||||
Director::absoluteBaseURL(),
|
Director::absoluteBaseURL(),
|
||||||
$fileBaseLink,
|
$fileBaseLink,
|
||||||
$url
|
$url
|
||||||
);
|
);
|
||||||
}
|
} else {
|
||||||
else {
|
// Rewrite public URL
|
||||||
// Rewrite public URL
|
if (preg_match('/^\//', $url)) {
|
||||||
if(preg_match('/^\//', $url)) {
|
// Absolute: Only path to module base
|
||||||
// Absolute: Only path to module base
|
$relativeUrl = Controller::join_links($baselink, $url, '/');
|
||||||
$relativeUrl = Controller::join_links($baselink, $url, '/');
|
} else {
|
||||||
} else {
|
// Relative: Include path to module base and any folders
|
||||||
// Relative: Include path to module base and any folders
|
$relativeUrl = Controller::join_links($baselink, $relativeLink, $url, '/');
|
||||||
$relativeUrl = Controller::join_links($baselink, $relativeLink, $url, '/');
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve relative paths
|
// Resolve relative paths
|
||||||
while(strpos($relativeUrl, '..') !== FALSE) {
|
while (strpos($relativeUrl, '..') !== false) {
|
||||||
$relativeUrl = preg_replace('/[-\w]+\/\.\.\//', '', $relativeUrl);
|
$relativeUrl = preg_replace('/[-\w]+\/\.\.\//', '', $relativeUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace any double slashes (apart from protocol)
|
// Replace any double slashes (apart from protocol)
|
||||||
$relativeUrl = preg_replace('/([^:])\/{2,}/', '$1/', $relativeUrl);
|
$relativeUrl = preg_replace('/([^:])\/{2,}/', '$1/', $relativeUrl);
|
||||||
|
|
||||||
// Replace in original content
|
// Replace in original content
|
||||||
$md = str_replace(
|
$md = str_replace(
|
||||||
$match,
|
$match,
|
||||||
sprintf('%s[%s](%s)', $matches[1][$i], $title, $relativeUrl),
|
sprintf('%s[%s](%s)', $matches[1][$i], $title, $relativeUrl),
|
||||||
$md
|
$md
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $md;
|
return $md;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Strips out the metadata for a page
|
* Strips out the metadata for a page
|
||||||
*
|
*
|
||||||
* @param DocumentationPage
|
* @param DocumentationPage
|
||||||
*/
|
*/
|
||||||
public static function retrieve_meta_data(DocumentationPage &$page) {
|
public static function retrieve_meta_data(DocumentationPage &$page)
|
||||||
if($md = $page->getMarkdown()) {
|
{
|
||||||
$matches = preg_match_all('/
|
if ($md = $page->getMarkdown()) {
|
||||||
|
$matches = preg_match_all('/
|
||||||
(?<key>[A-Za-z0-9_-]+):
|
(?<key>[A-Za-z0-9_-]+):
|
||||||
\s*
|
\s*
|
||||||
(?<value>.*)
|
(?<value>.*)
|
||||||
/x', $md, $meta);
|
/x', $md, $meta);
|
||||||
|
|
||||||
if($matches) {
|
if ($matches) {
|
||||||
foreach($meta['key'] as $index => $key) {
|
foreach ($meta['key'] as $index => $key) {
|
||||||
if(isset($meta['value'][$index])) {
|
if (isset($meta['value'][$index])) {
|
||||||
$page->setMetaData($key, $meta['value'][$index]);
|
$page->setMetaData($key, $meta['value'][$index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,42 +9,43 @@
|
|||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DocumentationPermalinks {
|
class DocumentationPermalinks
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private static $mapping = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* Add a mapping of nice short permalinks to a full long path
|
||||||
*/
|
*
|
||||||
private static $mapping = array();
|
* <code>
|
||||||
|
* DocumentationPermalinks::add(array(
|
||||||
|
* 'debugging' => 'current/en/sapphire/topics/debugging'
|
||||||
|
* ));
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* Do not need to include the language or the version current as it
|
||||||
|
* will add it based off the language or version in the session
|
||||||
|
*
|
||||||
|
* @param array
|
||||||
|
*/
|
||||||
|
public static function add($map = array())
|
||||||
|
{
|
||||||
|
if (ArrayLib::is_associative($map)) {
|
||||||
|
self::$mapping = array_merge(self::$mapping, $map);
|
||||||
|
} else {
|
||||||
|
user_error("DocumentationPermalinks::add() requires an associative array", E_USER_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a mapping of nice short permalinks to a full long path
|
* Return the location for a given short value.
|
||||||
*
|
*
|
||||||
* <code>
|
* @return string|false
|
||||||
* DocumentationPermalinks::add(array(
|
*/
|
||||||
* 'debugging' => 'current/en/sapphire/topics/debugging'
|
public static function map($url)
|
||||||
* ));
|
{
|
||||||
* </code>
|
return (isset(self::$mapping[$url])) ? self::$mapping[$url] : false;
|
||||||
*
|
}
|
||||||
* Do not need to include the language or the version current as it
|
|
||||||
* will add it based off the language or version in the session
|
|
||||||
*
|
|
||||||
* @param array
|
|
||||||
*/
|
|
||||||
public static function add($map = array()) {
|
|
||||||
if(ArrayLib::is_associative($map)) {
|
|
||||||
self::$mapping = array_merge(self::$mapping, $map);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
user_error("DocumentationPermalinks::add() requires an associative array", E_USER_ERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the location for a given short value.
|
|
||||||
*
|
|
||||||
* @return string|false
|
|
||||||
*/
|
|
||||||
public static function map($url) {
|
|
||||||
return (isset(self::$mapping[$url])) ? self::$mapping[$url] : false;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
set_include_path(
|
set_include_path(
|
||||||
dirname(dirname(__FILE__)) . '/thirdparty/'. PATH_SEPARATOR .
|
dirname(dirname(__FILE__)) . '/thirdparty/'. PATH_SEPARATOR .
|
||||||
get_include_path()
|
get_include_path()
|
||||||
);
|
);
|
||||||
|
|
||||||
require_once 'Zend/Search/Lucene.php';
|
require_once 'Zend/Search/Lucene.php';
|
||||||
@ -31,382 +31,406 @@ require_once 'Zend/Search/Lucene.php';
|
|||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DocumentationSearch {
|
class DocumentationSearch
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* @var bool - Is search enabled
|
* @var bool - Is search enabled
|
||||||
*/
|
*/
|
||||||
private static $enabled = false;
|
private static $enabled = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool - Is advanced search enabled
|
* @var bool - Is advanced search enabled
|
||||||
*/
|
*/
|
||||||
private static $advanced_search_enabled = true;
|
private static $advanced_search_enabled = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string - OpenSearch metadata. Please use {@link DocumentationSearch::set_meta_data()}
|
* @var string - OpenSearch metadata. Please use {@link DocumentationSearch::set_meta_data()}
|
||||||
*/
|
*/
|
||||||
private static $meta_data = array();
|
private static $meta_data = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Array Regular expression mapped to a "boost factor" for the searched document.
|
* @var Array Regular expression mapped to a "boost factor" for the searched document.
|
||||||
* Defaults to 1.0, lower to decrease relevancy. Requires reindex.
|
* Defaults to 1.0, lower to decrease relevancy. Requires reindex.
|
||||||
* Uses {@link DocumentationPage->getRelativePath()} for comparison.
|
* Uses {@link DocumentationPage->getRelativePath()} for comparison.
|
||||||
*/
|
*/
|
||||||
private static $boost_by_path = array();
|
private static $boost_by_path = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ArrayList - Results
|
* @var ArrayList - Results
|
||||||
*/
|
*/
|
||||||
private $results;
|
private $results;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $totalResults;
|
private $totalResults;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $query;
|
private $query;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Controller
|
* @var Controller
|
||||||
*/
|
*/
|
||||||
private $outputController;
|
private $outputController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optionally filter by module and version
|
* Optionally filter by module and version
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $modules, $versions;
|
private $modules, $versions;
|
||||||
|
|
||||||
public function setModules($modules) {
|
public function setModules($modules)
|
||||||
$this->modules = $modules;
|
{
|
||||||
}
|
$this->modules = $modules;
|
||||||
|
}
|
||||||
public function setVersions($versions) {
|
|
||||||
$this->versions = $versions;
|
public function setVersions($versions)
|
||||||
}
|
{
|
||||||
|
$this->versions = $versions;
|
||||||
/**
|
}
|
||||||
* Set the current search query
|
|
||||||
*
|
/**
|
||||||
* @param string
|
* Set the current search query
|
||||||
*/
|
*
|
||||||
public function setQuery($query) {
|
* @param string
|
||||||
$this->query = $query;
|
*/
|
||||||
}
|
public function setQuery($query)
|
||||||
|
{
|
||||||
/**
|
$this->query = $query;
|
||||||
* Returns the current search query
|
}
|
||||||
*
|
|
||||||
* @return string
|
/**
|
||||||
*/
|
* Returns the current search query
|
||||||
public function getQuery() {
|
*
|
||||||
return $this->query;
|
* @return string
|
||||||
}
|
*/
|
||||||
|
public function getQuery()
|
||||||
/**
|
{
|
||||||
* Sets the {@link DocumentationViewer} or {@link DocumentationSearch} instance which this search is rendering
|
return $this->query;
|
||||||
* on based on whether it is the results display or RSS feed
|
}
|
||||||
*
|
|
||||||
* @param Controller
|
/**
|
||||||
*/
|
* Sets the {@link DocumentationViewer} or {@link DocumentationSearch} instance which this search is rendering
|
||||||
public function setOutputController($controller) {
|
* on based on whether it is the results display or RSS feed
|
||||||
$this->outputController = $controller;
|
*
|
||||||
}
|
* @param Controller
|
||||||
|
*/
|
||||||
/**
|
public function setOutputController($controller)
|
||||||
* Folder name for indexes (in the temp folder).
|
{
|
||||||
*
|
$this->outputController = $controller;
|
||||||
* @config
|
}
|
||||||
* @var string
|
|
||||||
*/
|
/**
|
||||||
private static $index_location;
|
* Folder name for indexes (in the temp folder).
|
||||||
|
*
|
||||||
/**
|
* @config
|
||||||
* @return string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public static function get_index_location() {
|
private static $index_location;
|
||||||
$location = Config::inst()->get('DocumentationSearch', 'index_location');
|
|
||||||
|
/**
|
||||||
if(!$location) {
|
* @return string
|
||||||
return Controller::join_links(TEMP_FOLDER, 'RebuildLuceneDocsIndex');
|
*/
|
||||||
}
|
public static function get_index_location()
|
||||||
|
{
|
||||||
return $location;
|
$location = Config::inst()->get('DocumentationSearch', 'index_location');
|
||||||
}
|
|
||||||
|
if (!$location) {
|
||||||
/**
|
return Controller::join_links(TEMP_FOLDER, 'RebuildLuceneDocsIndex');
|
||||||
* Perform a search query on the index
|
}
|
||||||
*/
|
|
||||||
public function performSearch() {
|
return $location;
|
||||||
|
}
|
||||||
try {
|
|
||||||
$index = Zend_Search_Lucene::open(self::get_index_location());
|
/**
|
||||||
|
* Perform a search query on the index
|
||||||
Zend_Search_Lucene::setResultSetLimit(100);
|
*/
|
||||||
|
public function performSearch()
|
||||||
$query = new Zend_Search_Lucene_Search_Query_Boolean();
|
{
|
||||||
$term = Zend_Search_Lucene_Search_QueryParser::parse($this->getQuery());
|
try {
|
||||||
$query->addSubquery($term, true);
|
$index = Zend_Search_Lucene::open(self::get_index_location());
|
||||||
|
|
||||||
if($this->modules) {
|
Zend_Search_Lucene::setResultSetLimit(100);
|
||||||
$moduleQuery = new Zend_Search_Lucene_Search_Query_MultiTerm();
|
|
||||||
|
$query = new Zend_Search_Lucene_Search_Query_Boolean();
|
||||||
foreach($this->modules as $module) {
|
$term = Zend_Search_Lucene_Search_QueryParser::parse($this->getQuery());
|
||||||
$moduleQuery->addTerm(new Zend_Search_Lucene_Index_Term($module, 'Entity'));
|
$query->addSubquery($term, true);
|
||||||
}
|
|
||||||
|
if ($this->modules) {
|
||||||
$query->addSubquery($moduleQuery, true);
|
$moduleQuery = new Zend_Search_Lucene_Search_Query_MultiTerm();
|
||||||
}
|
|
||||||
|
foreach ($this->modules as $module) {
|
||||||
if($this->versions) {
|
$moduleQuery->addTerm(new Zend_Search_Lucene_Index_Term($module, 'Entity'));
|
||||||
$versionQuery = new Zend_Search_Lucene_Search_Query_MultiTerm();
|
}
|
||||||
|
|
||||||
foreach($this->versions as $version) {
|
$query->addSubquery($moduleQuery, true);
|
||||||
$versionQuery->addTerm(new Zend_Search_Lucene_Index_Term($version, 'Version'));
|
}
|
||||||
}
|
|
||||||
|
if ($this->versions) {
|
||||||
$query->addSubquery($versionQuery, true);
|
$versionQuery = new Zend_Search_Lucene_Search_Query_MultiTerm();
|
||||||
}
|
|
||||||
|
foreach ($this->versions as $version) {
|
||||||
$er = error_reporting();
|
$versionQuery->addTerm(new Zend_Search_Lucene_Index_Term($version, 'Version'));
|
||||||
error_reporting('E_ALL ^ E_NOTICE');
|
}
|
||||||
$this->results = $index->find($query);
|
|
||||||
error_reporting($er);
|
$query->addSubquery($versionQuery, true);
|
||||||
$this->totalResults = $index->numDocs();
|
}
|
||||||
}
|
|
||||||
catch(Zend_Search_Lucene_Exception $e) {
|
$er = error_reporting();
|
||||||
user_error($e .'. Ensure you have run the rebuld task (/dev/tasks/RebuildLuceneDocsIndex)', E_USER_ERROR);
|
error_reporting('E_ALL ^ E_NOTICE');
|
||||||
}
|
$this->results = $index->find($query);
|
||||||
}
|
error_reporting($er);
|
||||||
|
$this->totalResults = $index->numDocs();
|
||||||
/**
|
} catch (Zend_Search_Lucene_Exception $e) {
|
||||||
* @return ArrayData
|
user_error($e .'. Ensure you have run the rebuld task (/dev/tasks/RebuildLuceneDocsIndex)', E_USER_ERROR);
|
||||||
*/
|
}
|
||||||
public function getSearchResults($request) {
|
}
|
||||||
$pageLength = (isset($_GET['length'])) ? (int) $_GET['length'] : 10;
|
|
||||||
|
/**
|
||||||
$data = array(
|
* @return ArrayData
|
||||||
'Results' => null,
|
*/
|
||||||
'Query' => null,
|
public function getSearchResults($request)
|
||||||
'Versions' => DBField::create_field('Text', implode(', ', $this->versions)),
|
{
|
||||||
'Modules' => DBField::create_field('Text', implode(', ', $this->modules)),
|
$pageLength = (isset($_GET['length'])) ? (int) $_GET['length'] : 10;
|
||||||
'Title' => _t('DocumentationSearch.SEARCHRESULTS', 'Search Results'),
|
|
||||||
'TotalResults' => null,
|
$data = array(
|
||||||
'TotalPages' => null,
|
'Results' => null,
|
||||||
'ThisPage' => null,
|
'Query' => null,
|
||||||
'StartResult' => null,
|
'Versions' => DBField::create_field('Text', implode(', ', $this->versions)),
|
||||||
'PageLength' => $pageLength,
|
'Modules' => DBField::create_field('Text', implode(', ', $this->modules)),
|
||||||
'EndResult' => null,
|
'Title' => _t('DocumentationSearch.SEARCHRESULTS', 'Search Results'),
|
||||||
'PrevUrl' => DBField::create_field('Text', 'false'),
|
'TotalResults' => null,
|
||||||
'NextUrl' => DBField::create_field('Text', 'false'),
|
'TotalPages' => null,
|
||||||
'SearchPages' => new ArrayList()
|
'ThisPage' => null,
|
||||||
);
|
'StartResult' => null,
|
||||||
|
'PageLength' => $pageLength,
|
||||||
$start = ($request->requestVar('start')) ? (int)$request->requestVar('start') : 0;
|
'EndResult' => null,
|
||||||
$query = ($request->requestVar('q')) ? $request->requestVar('q') : '';
|
'PrevUrl' => DBField::create_field('Text', 'false'),
|
||||||
|
'NextUrl' => DBField::create_field('Text', 'false'),
|
||||||
$currentPage = floor( $start / $pageLength ) + 1;
|
'SearchPages' => new ArrayList()
|
||||||
|
);
|
||||||
$totalPages = ceil(count($this->results) / $pageLength );
|
|
||||||
|
$start = ($request->requestVar('start')) ? (int)$request->requestVar('start') : 0;
|
||||||
if ($totalPages == 0) {
|
$query = ($request->requestVar('q')) ? $request->requestVar('q') : '';
|
||||||
$totalPages = 1;
|
|
||||||
}
|
$currentPage = floor($start / $pageLength) + 1;
|
||||||
|
|
||||||
if ($currentPage > $totalPages) {
|
$totalPages = ceil(count($this->results) / $pageLength);
|
||||||
$currentPage = $totalPages;
|
|
||||||
}
|
if ($totalPages == 0) {
|
||||||
|
$totalPages = 1;
|
||||||
$results = new ArrayList();
|
}
|
||||||
|
|
||||||
if($this->results) {
|
if ($currentPage > $totalPages) {
|
||||||
foreach($this->results as $k => $hit) {
|
$currentPage = $totalPages;
|
||||||
if($k < ($currentPage-1)*$pageLength || $k >= ($currentPage*$pageLength)) {
|
}
|
||||||
continue;
|
|
||||||
}
|
$results = new ArrayList();
|
||||||
|
|
||||||
$doc = $hit->getDocument();
|
if ($this->results) {
|
||||||
|
foreach ($this->results as $k => $hit) {
|
||||||
$content = $hit->content;
|
if ($k < ($currentPage-1)*$pageLength || $k >= ($currentPage*$pageLength)) {
|
||||||
|
continue;
|
||||||
$obj = new ArrayData(array(
|
}
|
||||||
'Title' => DBField::create_field('Varchar', $doc->getFieldValue('Title')),
|
|
||||||
'BreadcrumbTitle' => DBField::create_field('HTMLText', $doc->getFieldValue('BreadcrumbTitle')),
|
$doc = $hit->getDocument();
|
||||||
'Link' => DBField::create_field('Varchar',$doc->getFieldValue('Link')),
|
|
||||||
'Language' => DBField::create_field('Varchar',$doc->getFieldValue('Language')),
|
$content = $hit->content;
|
||||||
'Version' => DBField::create_field('Varchar',$doc->getFieldValue('Version')),
|
|
||||||
'Entity' => DBField::create_field('Varchar', $doc->getFieldValue('Entity')),
|
$obj = new ArrayData(array(
|
||||||
'Content' => DBField::create_field('HTMLText', $content),
|
'Title' => DBField::create_field('Varchar', $doc->getFieldValue('Title')),
|
||||||
'Score' => $hit->score,
|
'BreadcrumbTitle' => DBField::create_field('HTMLText', $doc->getFieldValue('BreadcrumbTitle')),
|
||||||
'Number' => $k + 1,
|
'Link' => DBField::create_field('Varchar', $doc->getFieldValue('Link')),
|
||||||
'ID' => md5($doc->getFieldValue('Link'))
|
'Language' => DBField::create_field('Varchar', $doc->getFieldValue('Language')),
|
||||||
));
|
'Version' => DBField::create_field('Varchar', $doc->getFieldValue('Version')),
|
||||||
|
'Entity' => DBField::create_field('Varchar', $doc->getFieldValue('Entity')),
|
||||||
$results->push($obj);
|
'Content' => DBField::create_field('HTMLText', $content),
|
||||||
}
|
'Score' => $hit->score,
|
||||||
}
|
'Number' => $k + 1,
|
||||||
|
'ID' => md5($doc->getFieldValue('Link'))
|
||||||
$data['Results'] = $results;
|
));
|
||||||
$data['Query'] = DBField::create_field('Text', $query);
|
|
||||||
$data['TotalResults'] = DBField::create_field('Text', count($this->results));
|
$results->push($obj);
|
||||||
$data['TotalPages'] = DBField::create_field('Text', $totalPages);
|
}
|
||||||
$data['ThisPage'] = DBField::create_field('Text', $currentPage);
|
}
|
||||||
$data['StartResult'] = $start + 1;
|
|
||||||
$data['EndResult'] = $start + count($results);
|
$data['Results'] = $results;
|
||||||
|
$data['Query'] = DBField::create_field('Text', $query);
|
||||||
// Pagination links
|
$data['TotalResults'] = DBField::create_field('Text', count($this->results));
|
||||||
if($currentPage > 1) {
|
$data['TotalPages'] = DBField::create_field('Text', $totalPages);
|
||||||
$data['PrevUrl'] = DBField::create_field('Text',
|
$data['ThisPage'] = DBField::create_field('Text', $currentPage);
|
||||||
$this->buildQueryUrl(array('start' => ($currentPage - 2) * $pageLength))
|
$data['StartResult'] = $start + 1;
|
||||||
);
|
$data['EndResult'] = $start + count($results);
|
||||||
}
|
|
||||||
|
// Pagination links
|
||||||
if($currentPage < $totalPages) {
|
if ($currentPage > 1) {
|
||||||
$data['NextUrl'] = DBField::create_field('Text',
|
$data['PrevUrl'] = DBField::create_field('Text',
|
||||||
$this->buildQueryUrl(array('start' => $currentPage * $pageLength))
|
$this->buildQueryUrl(array('start' => ($currentPage - 2) * $pageLength))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($totalPages > 1) {
|
if ($currentPage < $totalPages) {
|
||||||
// Always show a certain number of pages at the start
|
$data['NextUrl'] = DBField::create_field('Text',
|
||||||
for ( $i = 1; $i <= $totalPages; $i++ ) {
|
$this->buildQueryUrl(array('start' => $currentPage * $pageLength))
|
||||||
$obj = new DataObject();
|
);
|
||||||
$obj->IsEllipsis = false;
|
}
|
||||||
$obj->PageNumber = $i;
|
|
||||||
$obj->Link = $this->buildQueryUrl(array(
|
if ($totalPages > 1) {
|
||||||
'start' => ($i - 1) * $pageLength
|
// Always show a certain number of pages at the start
|
||||||
));
|
for ($i = 1; $i <= $totalPages; $i++) {
|
||||||
|
$obj = new DataObject();
|
||||||
$obj->Current = false;
|
$obj->IsEllipsis = false;
|
||||||
if ( $i == $currentPage ) $obj->Current = true;
|
$obj->PageNumber = $i;
|
||||||
$data['SearchPages']->push($obj);
|
$obj->Link = $this->buildQueryUrl(array(
|
||||||
}
|
'start' => ($i - 1) * $pageLength
|
||||||
}
|
));
|
||||||
|
|
||||||
return new ArrayData($data);
|
$obj->Current = false;
|
||||||
}
|
if ($i == $currentPage) {
|
||||||
|
$obj->Current = true;
|
||||||
/**
|
}
|
||||||
* Build a nice query string for the results
|
$data['SearchPages']->push($obj);
|
||||||
*
|
}
|
||||||
* @return string
|
}
|
||||||
*/
|
|
||||||
private function buildQueryUrl($params) {
|
return new ArrayData($data);
|
||||||
$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();
|
* Build a nice query string for the results
|
||||||
// Remove 'start parameter if it exists
|
*
|
||||||
if ( array_key_exists('start', $url['query']) ) unset( $url['query']['start'] );
|
* @return string
|
||||||
// Add extra parameters from argument
|
*/
|
||||||
$url['query'] = array_merge($url['query'], $params);
|
private function buildQueryUrl($params)
|
||||||
$url['query'] = http_build_query($url['query']);
|
{
|
||||||
$url = $url['path'] . ($url['query'] ? '?'.$url['query'] : '');
|
$url = parse_url($_SERVER['REQUEST_URI']);
|
||||||
|
if (! array_key_exists('query', $url)) {
|
||||||
return $url;
|
$url['query'] = '';
|
||||||
}
|
}
|
||||||
|
parse_str($url['query'], $url['query']);
|
||||||
/**
|
if (! is_array($url['query'])) {
|
||||||
* @return int
|
$url['query'] = array();
|
||||||
*/
|
}
|
||||||
public function getTotalResults() {
|
// Remove 'start parameter if it exists
|
||||||
return (int) $this->totalResults;
|
if (array_key_exists('start', $url['query'])) {
|
||||||
}
|
unset($url['query']['start']);
|
||||||
|
}
|
||||||
/**
|
// Add extra parameters from argument
|
||||||
* Optimizes the search indexes on the File System
|
$url['query'] = array_merge($url['query'], $params);
|
||||||
*
|
$url['query'] = http_build_query($url['query']);
|
||||||
* @return void
|
$url = $url['path'] . ($url['query'] ? '?'.$url['query'] : '');
|
||||||
*/
|
|
||||||
public function optimizeIndex() {
|
return $url;
|
||||||
$index = Zend_Search_Lucene::open(self::get_index_location());
|
}
|
||||||
|
|
||||||
if($index) $index->optimize();
|
/**
|
||||||
}
|
* @return int
|
||||||
|
*/
|
||||||
/**
|
public function getTotalResults()
|
||||||
* @return String
|
{
|
||||||
*/
|
return (int) $this->totalResults;
|
||||||
public function getTitle() {
|
}
|
||||||
return ($this->outputController) ? $this->outputController->Title : _t('DocumentationSearch.SEARCH', 'Search');
|
|
||||||
}
|
/**
|
||||||
|
* Optimizes the search indexes on the File System
|
||||||
/**
|
*
|
||||||
* OpenSearch MetaData fields. For a list of fields consult
|
* @return void
|
||||||
* {@link self::get_meta_data()}
|
*/
|
||||||
*
|
public function optimizeIndex()
|
||||||
* @param array
|
{
|
||||||
*/
|
$index = Zend_Search_Lucene::open(self::get_index_location());
|
||||||
public static function set_meta_data($data) {
|
|
||||||
if(is_array($data)) {
|
if ($index) {
|
||||||
foreach($data as $key => $value) {
|
$index->optimize();
|
||||||
self::$meta_data[strtolower($key)] = $value;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
/**
|
||||||
user_error("set_meta_data must be passed an array", E_USER_ERROR);
|
* @return String
|
||||||
}
|
*/
|
||||||
}
|
public function getTitle()
|
||||||
|
{
|
||||||
/**
|
return ($this->outputController) ? $this->outputController->Title : _t('DocumentationSearch.SEARCH', 'Search');
|
||||||
* Returns the meta data needed by opensearch.
|
}
|
||||||
*
|
|
||||||
* @return array
|
/**
|
||||||
*/
|
* OpenSearch MetaData fields. For a list of fields consult
|
||||||
public static function get_meta_data() {
|
* {@link self::get_meta_data()}
|
||||||
$data = self::$meta_data;
|
*
|
||||||
|
* @param array
|
||||||
$defaults = array(
|
*/
|
||||||
'Description' => _t('DocumentationViewer.OPENSEARCHDESC', 'Search the documentation'),
|
public static function set_meta_data($data)
|
||||||
'Tags' => _t('DocumentationViewer.OPENSEARCHTAGS', 'documentation'),
|
{
|
||||||
'Contact' => Config::inst()->get('Email', 'admin_email'),
|
if (is_array($data)) {
|
||||||
'ShortName' => _t('DocumentationViewer.OPENSEARCHNAME', 'Documentation Search'),
|
foreach ($data as $key => $value) {
|
||||||
'Author' => 'SilverStripe'
|
self::$meta_data[strtolower($key)] = $value;
|
||||||
);
|
}
|
||||||
|
} else {
|
||||||
foreach($defaults as $key => $value) {
|
user_error("set_meta_data must be passed an array", E_USER_ERROR);
|
||||||
if(isset($data[$key])) $defaults[$key] = $data[$key];
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $defaults;
|
/**
|
||||||
}
|
* Returns the meta data needed by opensearch.
|
||||||
|
*
|
||||||
/**
|
* @return array
|
||||||
* Renders the search results into a template. Either the search results
|
*/
|
||||||
* template or the Atom feed.
|
public static function get_meta_data()
|
||||||
*/
|
{
|
||||||
public function renderResults() {
|
$data = self::$meta_data;
|
||||||
if(!$this->results && $this->query) {
|
|
||||||
$this->performSearch();
|
$defaults = array(
|
||||||
}
|
'Description' => _t('DocumentationViewer.OPENSEARCHDESC', 'Search the documentation'),
|
||||||
|
'Tags' => _t('DocumentationViewer.OPENSEARCHTAGS', 'documentation'),
|
||||||
if(!$this->outputController) {
|
'Contact' => Config::inst()->get('Email', 'admin_email'),
|
||||||
return user_error('Call renderResults() on a DocumentationViewer instance.', E_USER_ERROR);
|
'ShortName' => _t('DocumentationViewer.OPENSEARCHNAME', 'Documentation Search'),
|
||||||
}
|
'Author' => 'SilverStripe'
|
||||||
|
);
|
||||||
$request = $this->outputController->getRequest();
|
|
||||||
$data = $this->getSearchResults($request);
|
foreach ($defaults as $key => $value) {
|
||||||
$templates = array('DocumentationViewer_search');
|
if (isset($data[$key])) {
|
||||||
|
$defaults[$key] = $data[$key];
|
||||||
if($request->requestVar('format') && $request->requestVar('format') == "atom") {
|
}
|
||||||
// alter the fields for the opensearch xml.
|
}
|
||||||
$title = ($title = $this->getTitle()) ? ' - '. $title : "";
|
|
||||||
|
return $defaults;
|
||||||
$link = Controller::join_links(
|
}
|
||||||
$this->outputController->Link(), 'DocumentationOpenSearchController/description/'
|
|
||||||
);
|
/**
|
||||||
|
* Renders the search results into a template. Either the search results
|
||||||
$data->setField('Title', $data->Title . $title);
|
* template or the Atom feed.
|
||||||
$data->setField('DescriptionURL', $link);
|
*/
|
||||||
|
public function renderResults()
|
||||||
array_unshift($templates, 'OpenSearchResults');
|
{
|
||||||
}
|
if (!$this->results && $this->query) {
|
||||||
|
$this->performSearch();
|
||||||
return $this->outputController->customise($data)->renderWith($templates);
|
}
|
||||||
}
|
|
||||||
|
if (!$this->outputController) {
|
||||||
|
return user_error('Call renderResults() on a DocumentationViewer instance.', E_USER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = $this->outputController->getRequest();
|
||||||
|
$data = $this->getSearchResults($request);
|
||||||
|
$templates = array('DocumentationViewer_search');
|
||||||
|
|
||||||
|
if ($request->requestVar('format') && $request->requestVar('format') == "atom") {
|
||||||
|
// alter the fields for the opensearch xml.
|
||||||
|
$title = ($title = $this->getTitle()) ? ' - '. $title : "";
|
||||||
|
|
||||||
|
$link = Controller::join_links(
|
||||||
|
$this->outputController->Link(), 'DocumentationOpenSearchController/description/'
|
||||||
|
);
|
||||||
|
|
||||||
|
$data->setField('Title', $data->Title . $title);
|
||||||
|
$data->setField('DescriptionURL', $link);
|
||||||
|
|
||||||
|
array_unshift($templates, 'OpenSearchResults');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->outputController->customise($data)->renderWith($templates);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,40 +7,42 @@
|
|||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DocumentationOpenSearchController extends Controller {
|
class DocumentationOpenSearchController extends Controller
|
||||||
|
{
|
||||||
|
private static $allowed_actions = array(
|
||||||
|
'description'
|
||||||
|
);
|
||||||
|
|
||||||
private static $allowed_actions = array(
|
public function index()
|
||||||
'description'
|
{
|
||||||
);
|
return $this->httpError(404);
|
||||||
|
}
|
||||||
|
|
||||||
public function index() {
|
public function description()
|
||||||
return $this->httpError(404);
|
{
|
||||||
}
|
$viewer = new DocumentationViewer();
|
||||||
|
|
||||||
public function description() {
|
if (!$viewer->canView()) {
|
||||||
$viewer = new DocumentationViewer();
|
return Security::permissionFailure($this);
|
||||||
|
}
|
||||||
|
|
||||||
if(!$viewer->canView()) {
|
if (!Config::inst()->get('DocumentationSearch', 'enabled')) {
|
||||||
return Security::permissionFailure($this);
|
return $this->httpError('404');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Config::inst()->get('DocumentationSearch', 'enabled')) {
|
$data = DocumentationSearch::get_meta_data();
|
||||||
return $this->httpError('404');
|
$link = Director::absoluteBaseUrl() .
|
||||||
}
|
$data['SearchPageLink'] = Controller::join_links(
|
||||||
|
$viewer->Link(),
|
||||||
|
'results/?Search={searchTerms}&start={startIndex}&length={count}&action_results=1'
|
||||||
|
);
|
||||||
|
|
||||||
$data = DocumentationSearch::get_meta_data();
|
$data['SearchPageAtom'] = $data['SearchPageLink'] . '&format=atom';
|
||||||
$link = Director::absoluteBaseUrl() .
|
|
||||||
$data['SearchPageLink'] = Controller::join_links(
|
|
||||||
$viewer->Link(),
|
|
||||||
'results/?Search={searchTerms}&start={startIndex}&length={count}&action_results=1'
|
|
||||||
);
|
|
||||||
|
|
||||||
$data['SearchPageAtom'] = $data['SearchPageLink'] . '&format=atom';
|
return $this->customise(
|
||||||
|
new ArrayData($data)
|
||||||
return $this->customise(
|
)->renderWith(array(
|
||||||
new ArrayData($data)
|
'OpenSearchDescription'
|
||||||
)->renderWith(array(
|
));
|
||||||
'OpenSearchDescription'
|
}
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -12,665 +12,691 @@
|
|||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DocumentationViewer extends Controller {
|
class DocumentationViewer extends Controller
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $extensions = array(
|
private static $extensions = array(
|
||||||
'DocumentationViewerVersionWarning',
|
'DocumentationViewerVersionWarning',
|
||||||
'DocumentationSearchExtension'
|
'DocumentationSearchExtension'
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private static $google_analytics_code = '';
|
private static $google_analytics_code = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private static $documentation_title = 'SilverStripe Documentation';
|
private static $documentation_title = 'SilverStripe Documentation';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private static $allowed_actions = array(
|
private static $allowed_actions = array(
|
||||||
'all',
|
'all',
|
||||||
'results',
|
'results',
|
||||||
'handleAction'
|
'handleAction'
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The string name of the currently accessed {@link DocumentationEntity}
|
* The string name of the currently accessed {@link DocumentationEntity}
|
||||||
* object. To access the entire object use {@link getEntity()}
|
* object. To access the entire object use {@link getEntity()}
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $entity = '';
|
protected $entity = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var DocumentationPage
|
* @var DocumentationPage
|
||||||
*/
|
*/
|
||||||
protected $record;
|
protected $record;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var DocumentationManifest
|
* @var DocumentationManifest
|
||||||
*/
|
*/
|
||||||
protected $manifest;
|
protected $manifest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
*
|
*
|
||||||
* @var string same as the routing pattern set through Director::addRules().
|
* @var string same as the routing pattern set through Director::addRules().
|
||||||
*/
|
*/
|
||||||
private static $link_base = 'dev/docs/';
|
private static $link_base = 'dev/docs/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @config
|
* @config
|
||||||
*
|
*
|
||||||
* @var string|array Optional permission check
|
* @var string|array Optional permission check
|
||||||
*/
|
*/
|
||||||
private static $check_permission = 'ADMIN';
|
private static $check_permission = 'ADMIN';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array map of modules to edit links.
|
* @var array map of modules to edit links.
|
||||||
* @see {@link getEditLink()}
|
* @see {@link getEditLink()}
|
||||||
*/
|
*/
|
||||||
private static $edit_links = array();
|
private static $edit_links = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function init() {
|
public function init()
|
||||||
parent::init();
|
{
|
||||||
|
parent::init();
|
||||||
if(!$this->canView()) {
|
|
||||||
return Security::permissionFailure($this);
|
if (!$this->canView()) {
|
||||||
}
|
return Security::permissionFailure($this);
|
||||||
Requirements::javascript('//use.typekit.net/emt4dhq.js');
|
}
|
||||||
Requirements::customScript('try{Typekit.load();}catch(e){}');
|
Requirements::javascript('//use.typekit.net/emt4dhq.js');
|
||||||
|
Requirements::customScript('try{Typekit.load();}catch(e){}');
|
||||||
Requirements::javascript(THIRDPARTY_DIR .'/jquery/jquery.js');
|
|
||||||
Requirements::javascript('https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js');
|
Requirements::javascript(THIRDPARTY_DIR .'/jquery/jquery.js');
|
||||||
|
Requirements::javascript('https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js');
|
||||||
Requirements::javascript(DOCSVIEWER_DIR .'/javascript/DocumentationViewer.js');
|
|
||||||
Requirements::combine_files('docs.css', array(
|
Requirements::javascript(DOCSVIEWER_DIR .'/javascript/DocumentationViewer.js');
|
||||||
DOCSVIEWER_DIR .'/css/normalize.css',
|
Requirements::combine_files('docs.css', array(
|
||||||
DOCSVIEWER_DIR .'/css/utilities.css',
|
DOCSVIEWER_DIR .'/css/normalize.css',
|
||||||
DOCSVIEWER_DIR .'/css/typography.css',
|
DOCSVIEWER_DIR .'/css/utilities.css',
|
||||||
DOCSVIEWER_DIR .'/css/forms.css',
|
DOCSVIEWER_DIR .'/css/typography.css',
|
||||||
DOCSVIEWER_DIR .'/css/layout.css',
|
DOCSVIEWER_DIR .'/css/forms.css',
|
||||||
DOCSVIEWER_DIR .'/css/small.css'
|
DOCSVIEWER_DIR .'/css/layout.css',
|
||||||
));
|
DOCSVIEWER_DIR .'/css/small.css'
|
||||||
}
|
));
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Can the user view this documentation. Hides all functionality for private
|
/**
|
||||||
* wikis.
|
* Can the user view this documentation. Hides all functionality for private
|
||||||
*
|
* wikis.
|
||||||
* @return bool
|
*
|
||||||
*/
|
* @return bool
|
||||||
public function canView() {
|
*/
|
||||||
return (Director::isDev() || Director::is_cli() ||
|
public function canView()
|
||||||
!$this->config()->get('check_permission') ||
|
{
|
||||||
Permission::check($this->config()->get('check_permission'))
|
return (Director::isDev() || Director::is_cli() ||
|
||||||
);
|
!$this->config()->get('check_permission') ||
|
||||||
}
|
Permission::check($this->config()->get('check_permission'))
|
||||||
|
);
|
||||||
public function hasAction($action) {
|
}
|
||||||
return true;
|
|
||||||
}
|
public function hasAction($action)
|
||||||
|
{
|
||||||
public function checkAccessAction($action) {
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
public function checkAccessAction($action)
|
||||||
/**
|
{
|
||||||
* Overloaded to avoid "action doesn't exist" errors - all URL parts in
|
return true;
|
||||||
* this controller are virtual and handled through handleRequest(), not
|
}
|
||||||
* controller methods.
|
|
||||||
*
|
/**
|
||||||
* @param $request
|
* Overloaded to avoid "action doesn't exist" errors - all URL parts in
|
||||||
* @param $action
|
* this controller are virtual and handled through handleRequest(), not
|
||||||
*
|
* controller methods.
|
||||||
* @return SS_HTTPResponse
|
*
|
||||||
*/
|
* @param $request
|
||||||
public function handleAction($request, $action) {
|
* @param $action
|
||||||
// if we submitted a form, let that pass
|
*
|
||||||
if(!$request->isGET()) {
|
* @return SS_HTTPResponse
|
||||||
return parent::handleAction($request, $action);
|
*/
|
||||||
}
|
public function handleAction($request, $action)
|
||||||
|
{
|
||||||
$url = $request->getURL();
|
// if we submitted a form, let that pass
|
||||||
|
if (!$request->isGET()) {
|
||||||
//
|
return parent::handleAction($request, $action);
|
||||||
// If the current request has an extension attached to it, strip that
|
}
|
||||||
// off and redirect the user to the page without an extension.
|
|
||||||
//
|
$url = $request->getURL();
|
||||||
if(DocumentationHelper::get_extension($url)) {
|
|
||||||
$this->response = new SS_HTTPResponse();
|
//
|
||||||
$this->response->redirect(
|
// If the current request has an extension attached to it, strip that
|
||||||
DocumentationHelper::trim_extension_off($url) .'/',
|
// off and redirect the user to the page without an extension.
|
||||||
301
|
//
|
||||||
);
|
if (DocumentationHelper::get_extension($url)) {
|
||||||
|
$this->response = new SS_HTTPResponse();
|
||||||
$request->shift();
|
$this->response->redirect(
|
||||||
$request->shift();
|
DocumentationHelper::trim_extension_off($url) .'/',
|
||||||
|
301
|
||||||
return $this->response;
|
);
|
||||||
}
|
|
||||||
|
$request->shift();
|
||||||
//
|
$request->shift();
|
||||||
// Strip off the base url
|
|
||||||
//
|
return $this->response;
|
||||||
$base = ltrim(
|
}
|
||||||
Config::inst()->get('DocumentationViewer', 'link_base'), '/'
|
|
||||||
);
|
//
|
||||||
|
// Strip off the base url
|
||||||
if($base && strpos($url, $base) !== false) {
|
//
|
||||||
$url = substr(
|
$base = ltrim(
|
||||||
ltrim($url, '/'),
|
Config::inst()->get('DocumentationViewer', 'link_base'), '/'
|
||||||
strlen($base)
|
);
|
||||||
);
|
|
||||||
} else {
|
if ($base && strpos($url, $base) !== false) {
|
||||||
|
$url = substr(
|
||||||
}
|
ltrim($url, '/'),
|
||||||
|
strlen($base)
|
||||||
//
|
);
|
||||||
// Handle any permanent redirections that the developer has defined.
|
} else {
|
||||||
//
|
}
|
||||||
if($link = DocumentationPermalinks::map($url)) {
|
|
||||||
// the first param is a shortcode for a page so redirect the user to
|
//
|
||||||
// the short code.
|
// Handle any permanent redirections that the developer has defined.
|
||||||
$this->response = new SS_HTTPResponse();
|
//
|
||||||
$this->response->redirect($link, 301);
|
if ($link = DocumentationPermalinks::map($url)) {
|
||||||
|
// the first param is a shortcode for a page so redirect the user to
|
||||||
$request->shift();
|
// the short code.
|
||||||
$request->shift();
|
$this->response = new SS_HTTPResponse();
|
||||||
|
$this->response->redirect($link, 301);
|
||||||
return $this->response;
|
|
||||||
}
|
$request->shift();
|
||||||
|
$request->shift();
|
||||||
//
|
|
||||||
// Validate the language provided. Language is a required URL parameter.
|
return $this->response;
|
||||||
// as we use it for generic interfaces and language selection. If
|
}
|
||||||
// language is not set, redirects to 'en'
|
|
||||||
//
|
//
|
||||||
$languages = i18n::get_common_languages();
|
// Validate the language provided. Language is a required URL parameter.
|
||||||
|
// as we use it for generic interfaces and language selection. If
|
||||||
if(!$lang = $request->param('Lang')) {
|
// language is not set, redirects to 'en'
|
||||||
$lang = $request->param('Action');
|
//
|
||||||
$action = $request->param('ID');
|
$languages = i18n::get_common_languages();
|
||||||
} else {
|
|
||||||
$action = $request->param('Action');
|
if (!$lang = $request->param('Lang')) {
|
||||||
}
|
$lang = $request->param('Action');
|
||||||
|
$action = $request->param('ID');
|
||||||
if(!$lang) {
|
} else {
|
||||||
return $this->redirect($this->Link('en'));
|
$action = $request->param('Action');
|
||||||
} else if(!isset($languages[$lang])) {
|
}
|
||||||
return $this->httpError(404);
|
|
||||||
}
|
if (!$lang) {
|
||||||
|
return $this->redirect($this->Link('en'));
|
||||||
$request->shift(10);
|
} elseif (!isset($languages[$lang])) {
|
||||||
|
return $this->httpError(404);
|
||||||
$allowed = $this->config()->allowed_actions;
|
}
|
||||||
|
|
||||||
if(in_array($action, $allowed)) {
|
$request->shift(10);
|
||||||
//
|
|
||||||
// if it's one of the allowed actions such as search or all then the
|
$allowed = $this->config()->allowed_actions;
|
||||||
// URL must be prefixed with one of the allowed languages.
|
|
||||||
//
|
if (in_array($action, $allowed)) {
|
||||||
return parent::handleAction($request, $action);
|
//
|
||||||
} else {
|
// if it's one of the allowed actions such as search or all then the
|
||||||
//
|
// URL must be prefixed with one of the allowed languages.
|
||||||
// look up the manifest to see find the nearest match against the
|
//
|
||||||
// list of the URL. If the URL exists then set that as the current
|
return parent::handleAction($request, $action);
|
||||||
// page to match against.
|
} else {
|
||||||
|
//
|
||||||
// strip off any extensions.
|
// look up the manifest to see find the nearest match against the
|
||||||
|
// list of the URL. If the URL exists then set that as the current
|
||||||
|
// page to match against.
|
||||||
// if($cleaned !== $url) {
|
|
||||||
// $redirect = new SS_HTTPResponse();
|
// strip off any extensions.
|
||||||
|
|
||||||
// return $redirect->redirect($cleaned, 302);
|
|
||||||
// }
|
// if($cleaned !== $url) {
|
||||||
if($record = $this->getManifest()->getPage($url)) {
|
// $redirect = new SS_HTTPResponse();
|
||||||
$this->record = $record;
|
|
||||||
$this->init();
|
// return $redirect->redirect($cleaned, 302);
|
||||||
|
// }
|
||||||
$type = get_class($this->record);
|
if ($record = $this->getManifest()->getPage($url)) {
|
||||||
$body = $this->renderWith(array(
|
$this->record = $record;
|
||||||
"DocumentationViewer_{$type}",
|
$this->init();
|
||||||
"DocumentationViewer"
|
|
||||||
));
|
$type = get_class($this->record);
|
||||||
|
$body = $this->renderWith(array(
|
||||||
return new SS_HTTPResponse($body, 200);
|
"DocumentationViewer_{$type}",
|
||||||
} else if($redirect = $this->getManifest()->getRedirect($url)) {
|
"DocumentationViewer"
|
||||||
$response = new SS_HTTPResponse();
|
));
|
||||||
$to = Controller::join_links(Director::baseURL(), $base, $redirect);
|
|
||||||
return $response->redirect($to, 301);
|
return new SS_HTTPResponse($body, 200);
|
||||||
} else if(!$url || $url == $lang) {
|
} elseif ($redirect = $this->getManifest()->getRedirect($url)) {
|
||||||
$body = $this->renderWith(array(
|
$response = new SS_HTTPResponse();
|
||||||
"DocumentationViewer_DocumentationFolder",
|
$to = Controller::join_links(Director::baseURL(), $base, $redirect);
|
||||||
"DocumentationViewer"
|
return $response->redirect($to, 301);
|
||||||
));
|
} elseif (!$url || $url == $lang) {
|
||||||
|
$body = $this->renderWith(array(
|
||||||
return new SS_HTTPResponse($body, 200);
|
"DocumentationViewer_DocumentationFolder",
|
||||||
}
|
"DocumentationViewer"
|
||||||
}
|
));
|
||||||
|
|
||||||
return $this->httpError(404);
|
return new SS_HTTPResponse($body, 200);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @param int $status
|
return $this->httpError(404);
|
||||||
* @param string $message
|
}
|
||||||
*
|
|
||||||
* @return SS_HTTPResponse
|
/**
|
||||||
*/
|
* @param int $status
|
||||||
public function httpError($status, $message = null) {
|
* @param string $message
|
||||||
$this->init();
|
*
|
||||||
|
* @return SS_HTTPResponse
|
||||||
$class = get_class($this);
|
*/
|
||||||
$body = $this->customise(new ArrayData(array(
|
public function httpError($status, $message = null)
|
||||||
'Message' => $message
|
{
|
||||||
)))->renderWith(array("{$class}_error", $class));
|
$this->init();
|
||||||
|
|
||||||
return new SS_HTTPResponse($body, $status);
|
$class = get_class($this);
|
||||||
}
|
$body = $this->customise(new ArrayData(array(
|
||||||
|
'Message' => $message
|
||||||
/**
|
)))->renderWith(array("{$class}_error", $class));
|
||||||
* @return DocumentationManifest
|
|
||||||
*/
|
return new SS_HTTPResponse($body, $status);
|
||||||
public function getManifest() {
|
}
|
||||||
if(!$this->manifest) {
|
|
||||||
$flush = SapphireTest::is_running_test() || (isset($_GET['flush']));
|
/**
|
||||||
|
* @return DocumentationManifest
|
||||||
$this->manifest = new DocumentationManifest($flush);
|
*/
|
||||||
}
|
public function getManifest()
|
||||||
|
{
|
||||||
return $this->manifest;
|
if (!$this->manifest) {
|
||||||
}
|
$flush = SapphireTest::is_running_test() || (isset($_GET['flush']));
|
||||||
|
|
||||||
/**
|
$this->manifest = new DocumentationManifest($flush);
|
||||||
* @return string
|
}
|
||||||
*/
|
|
||||||
public function getLanguage() {
|
return $this->manifest;
|
||||||
if(!$lang = $this->request->param('Lang')) {
|
}
|
||||||
$lang = $this->request->param('Action');
|
|
||||||
}
|
/**
|
||||||
|
* @return string
|
||||||
return $lang;
|
*/
|
||||||
}
|
public function getLanguage()
|
||||||
|
{
|
||||||
|
if (!$lang = $this->request->param('Lang')) {
|
||||||
|
$lang = $this->request->param('Action');
|
||||||
/**
|
}
|
||||||
* Generate a list of {@link Documentation } which have been registered and which can
|
|
||||||
* be documented.
|
return $lang;
|
||||||
*
|
}
|
||||||
* @return DataObject
|
|
||||||
*/
|
|
||||||
public function getMenu() {
|
|
||||||
$entities = $this->getManifest()->getEntities();
|
/**
|
||||||
$output = new ArrayList();
|
* Generate a list of {@link Documentation } which have been registered and which can
|
||||||
$record = $this->getPage();
|
* be documented.
|
||||||
$current = $this->getEntity();
|
*
|
||||||
|
* @return DataObject
|
||||||
foreach($entities as $entity) {
|
*/
|
||||||
$checkLang = $entity->getLanguage();
|
public function getMenu()
|
||||||
$checkVers = $entity->getVersion();
|
{
|
||||||
|
$entities = $this->getManifest()->getEntities();
|
||||||
// only show entities with the same language or any entity that
|
$output = new ArrayList();
|
||||||
// isn't registered under any particular language (auto detected)
|
$record = $this->getPage();
|
||||||
if($checkLang && $checkLang !== $this->getLanguage()) {
|
$current = $this->getEntity();
|
||||||
continue;
|
|
||||||
}
|
foreach ($entities as $entity) {
|
||||||
|
$checkLang = $entity->getLanguage();
|
||||||
if($current && $checkVers) {
|
$checkVers = $entity->getVersion();
|
||||||
if($entity->getVersion() !== $current->getVersion()) {
|
|
||||||
continue;
|
// only show entities with the same language or any entity that
|
||||||
}
|
// isn't registered under any particular language (auto detected)
|
||||||
}
|
if ($checkLang && $checkLang !== $this->getLanguage()) {
|
||||||
|
continue;
|
||||||
$mode = 'link';
|
}
|
||||||
$children = new ArrayList();
|
|
||||||
|
if ($current && $checkVers) {
|
||||||
if($entity->hasRecord($record) || $entity->getIsDefaultEntity()) {
|
if ($entity->getVersion() !== $current->getVersion()) {
|
||||||
$mode = 'current';
|
continue;
|
||||||
|
}
|
||||||
// add children
|
}
|
||||||
$children = $this->getManifest()->getChildrenFor(
|
|
||||||
$entity->getPath(), ($record) ? $record->getPath() : $entity->getPath()
|
$mode = 'link';
|
||||||
);
|
$children = new ArrayList();
|
||||||
} else {
|
|
||||||
if($current && $current->getKey() == $entity->getKey()) {
|
if ($entity->hasRecord($record) || $entity->getIsDefaultEntity()) {
|
||||||
continue;
|
$mode = 'current';
|
||||||
}
|
|
||||||
}
|
// add children
|
||||||
|
$children = $this->getManifest()->getChildrenFor(
|
||||||
$link = $entity->Link();
|
$entity->getPath(), ($record) ? $record->getPath() : $entity->getPath()
|
||||||
|
);
|
||||||
$output->push(new ArrayData(array(
|
} else {
|
||||||
'Title' => $entity->getTitle(),
|
if ($current && $current->getKey() == $entity->getKey()) {
|
||||||
'Link' => $link,
|
continue;
|
||||||
'LinkingMode' => $mode,
|
}
|
||||||
'DefaultEntity' => $entity->getIsDefaultEntity(),
|
}
|
||||||
'Children' => $children
|
|
||||||
)));
|
$link = $entity->Link();
|
||||||
}
|
|
||||||
|
$output->push(new ArrayData(array(
|
||||||
return $output;
|
'Title' => $entity->getTitle(),
|
||||||
}
|
'Link' => $link,
|
||||||
|
'LinkingMode' => $mode,
|
||||||
/**
|
'DefaultEntity' => $entity->getIsDefaultEntity(),
|
||||||
* Return the content for the page. If its an actual documentation page then
|
'Children' => $children
|
||||||
* display the content from the page, otherwise display the contents from
|
)));
|
||||||
* the index.md file if its a folder
|
}
|
||||||
*
|
|
||||||
* @return HTMLText
|
return $output;
|
||||||
*/
|
}
|
||||||
public function getContent() {
|
|
||||||
$page = $this->getPage();
|
/**
|
||||||
$html = $page->getHTML();
|
* Return the content for the page. If its an actual documentation page then
|
||||||
$html = $this->replaceChildrenCalls($html);
|
* display the content from the page, otherwise display the contents from
|
||||||
|
* the index.md file if its a folder
|
||||||
return $html;
|
*
|
||||||
}
|
* @return HTMLText
|
||||||
|
*/
|
||||||
public function replaceChildrenCalls($html) {
|
public function getContent()
|
||||||
$codes = new ShortcodeParser();
|
{
|
||||||
$codes->register('CHILDREN', array($this, 'includeChildren'));
|
$page = $this->getPage();
|
||||||
|
$html = $page->getHTML();
|
||||||
return $codes->parse($html);
|
$html = $this->replaceChildrenCalls($html);
|
||||||
}
|
|
||||||
|
return $html;
|
||||||
/**
|
}
|
||||||
* Short code parser
|
|
||||||
*/
|
public function replaceChildrenCalls($html)
|
||||||
public function includeChildren($args) {
|
{
|
||||||
if(isset($args['Folder'])) {
|
$codes = new ShortcodeParser();
|
||||||
$children = $this->getManifest()->getChildrenFor(
|
$codes->register('CHILDREN', array($this, 'includeChildren'));
|
||||||
Controller::join_links(dirname($this->record->getPath()), $args['Folder'])
|
|
||||||
);
|
return $codes->parse($html);
|
||||||
} else {
|
}
|
||||||
$children = $this->getManifest()->getChildrenFor(
|
|
||||||
dirname($this->record->getPath())
|
/**
|
||||||
);
|
* Short code parser
|
||||||
}
|
*/
|
||||||
|
public function includeChildren($args)
|
||||||
if(isset($args['Exclude'])) {
|
{
|
||||||
$exclude = explode(',', $args['Exclude']);
|
if (isset($args['Folder'])) {
|
||||||
|
$children = $this->getManifest()->getChildrenFor(
|
||||||
foreach($children as $k => $child) {
|
Controller::join_links(dirname($this->record->getPath()), $args['Folder'])
|
||||||
foreach($exclude as $e) {
|
);
|
||||||
if($child->Link == Controller::join_links($this->record->Link(), strtolower($e), '/')) {
|
} else {
|
||||||
unset($children[$k]);
|
$children = $this->getManifest()->getChildrenFor(
|
||||||
}
|
dirname($this->record->getPath())
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (isset($args['Exclude'])) {
|
||||||
return $this->customise(new ArrayData(array(
|
$exclude = explode(',', $args['Exclude']);
|
||||||
'Children' => $children
|
|
||||||
)))->renderWith('Includes/DocumentationPages');
|
foreach ($children as $k => $child) {
|
||||||
}
|
foreach ($exclude as $e) {
|
||||||
|
if ($child->Link == Controller::join_links($this->record->Link(), strtolower($e), '/')) {
|
||||||
/**
|
unset($children[$k]);
|
||||||
* @return ArrayList
|
}
|
||||||
*/
|
}
|
||||||
public function getChildren() {
|
}
|
||||||
if($this->record instanceof DocumentationFolder) {
|
}
|
||||||
return $this->getManifest()->getChildrenFor(
|
|
||||||
$this->record->getPath()
|
return $this->customise(new ArrayData(array(
|
||||||
);
|
'Children' => $children
|
||||||
} else if($this->record) {
|
)))->renderWith('Includes/DocumentationPages');
|
||||||
return $this->getManifest()->getChildrenFor(
|
}
|
||||||
dirname($this->record->getPath())
|
|
||||||
);
|
/**
|
||||||
}
|
* @return ArrayList
|
||||||
|
*/
|
||||||
return new ArrayList();
|
public function getChildren()
|
||||||
}
|
{
|
||||||
|
if ($this->record instanceof DocumentationFolder) {
|
||||||
/**
|
return $this->getManifest()->getChildrenFor(
|
||||||
* Generate a list of breadcrumbs for the user.
|
$this->record->getPath()
|
||||||
*
|
);
|
||||||
* @return ArrayList
|
} elseif ($this->record) {
|
||||||
*/
|
return $this->getManifest()->getChildrenFor(
|
||||||
public function getBreadcrumbs() {
|
dirname($this->record->getPath())
|
||||||
if($this->record) {
|
);
|
||||||
return $this->getManifest()->generateBreadcrumbs(
|
}
|
||||||
$this->record,
|
|
||||||
$this->record->getEntity()
|
return new ArrayList();
|
||||||
);
|
}
|
||||||
}
|
|
||||||
}
|
/**
|
||||||
|
* Generate a list of breadcrumbs for the user.
|
||||||
/**
|
*
|
||||||
* @return DocumentationPage
|
* @return ArrayList
|
||||||
*/
|
*/
|
||||||
public function getPage() {
|
public function getBreadcrumbs()
|
||||||
return $this->record;
|
{
|
||||||
}
|
if ($this->record) {
|
||||||
|
return $this->getManifest()->generateBreadcrumbs(
|
||||||
/**
|
$this->record,
|
||||||
* @return DocumentationEntity
|
$this->record->getEntity()
|
||||||
*/
|
);
|
||||||
public function getEntity() {
|
}
|
||||||
return ($this->record) ? $this->record->getEntity() : null;
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* @return DocumentationPage
|
||||||
* @return ArrayList
|
*/
|
||||||
*/
|
public function getPage()
|
||||||
public function getVersions() {
|
{
|
||||||
return $this->getManifest()->getVersions($this->getEntity());
|
return $this->record;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a string for the title tag in the URL.
|
* @return DocumentationEntity
|
||||||
*
|
*/
|
||||||
* @return string
|
public function getEntity()
|
||||||
*/
|
{
|
||||||
public function getTitle() {
|
return ($this->record) ? $this->record->getEntity() : null;
|
||||||
return ($this->record) ? $this->record->getTitle() : null;
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* @return ArrayList
|
||||||
* @return string
|
*/
|
||||||
*/
|
public function getVersions()
|
||||||
public function AbsoluteLink($action) {
|
{
|
||||||
return Controller::join_links(
|
return $this->getManifest()->getVersions($this->getEntity());
|
||||||
Director::absoluteBaseUrl(),
|
}
|
||||||
$this->Link($action)
|
|
||||||
);
|
/**
|
||||||
}
|
* Generate a string for the title tag in the URL.
|
||||||
|
*
|
||||||
/**
|
* @return string
|
||||||
* Return the base link to this documentation location.
|
*/
|
||||||
*
|
public function getTitle()
|
||||||
* @return string
|
{
|
||||||
*/
|
return ($this->record) ? $this->record->getTitle() : null;
|
||||||
public function Link($action = '') {
|
}
|
||||||
$link = Controller::join_links(
|
|
||||||
Config::inst()->get('DocumentationViewer', 'link_base'),
|
/**
|
||||||
$this->getLanguage(),
|
* @return string
|
||||||
$action,
|
*/
|
||||||
'/'
|
public function AbsoluteLink($action)
|
||||||
);
|
{
|
||||||
|
return Controller::join_links(
|
||||||
return $link;
|
Director::absoluteBaseUrl(),
|
||||||
}
|
$this->Link($action)
|
||||||
|
);
|
||||||
/**
|
}
|
||||||
* Generate a list of all the pages in the documentation grouped by the
|
|
||||||
* first letter of the page.
|
/**
|
||||||
*
|
* Return the base link to this documentation location.
|
||||||
* @return GroupedList
|
*
|
||||||
*/
|
* @return string
|
||||||
public function AllPages() {
|
*/
|
||||||
$pages = $this->getManifest()->getPages();
|
public function Link($action = '')
|
||||||
$output = new ArrayList();
|
{
|
||||||
|
$link = Controller::join_links(
|
||||||
foreach($pages as $url => $page) {
|
Config::inst()->get('DocumentationViewer', 'link_base'),
|
||||||
$first = strtoupper(trim(substr($page['title'], 0, 1)));
|
$this->getLanguage(),
|
||||||
|
$action,
|
||||||
if($first) {
|
'/'
|
||||||
$output->push(new ArrayData(array(
|
);
|
||||||
'Link' => $url,
|
|
||||||
'Title' => $page['title'],
|
return $link;
|
||||||
'FirstLetter' => $first
|
}
|
||||||
)));
|
|
||||||
}
|
/**
|
||||||
}
|
* Generate a list of all the pages in the documentation grouped by the
|
||||||
|
* first letter of the page.
|
||||||
return GroupedList::create($output->sort('Title', 'ASC'));
|
*
|
||||||
}
|
* @return GroupedList
|
||||||
|
*/
|
||||||
/**
|
public function AllPages()
|
||||||
* Documentation Search Form. Allows filtering of the results by many entities
|
{
|
||||||
* and multiple versions.
|
$pages = $this->getManifest()->getPages();
|
||||||
*
|
$output = new ArrayList();
|
||||||
* @return Form
|
|
||||||
*/
|
foreach ($pages as $url => $page) {
|
||||||
public function DocumentationSearchForm() {
|
$first = strtoupper(trim(substr($page['title'], 0, 1)));
|
||||||
if(!Config::inst()->get('DocumentationSearch','enabled')) {
|
|
||||||
return false;
|
if ($first) {
|
||||||
}
|
$output->push(new ArrayData(array(
|
||||||
|
'Link' => $url,
|
||||||
return new DocumentationSearchForm($this);
|
'Title' => $page['title'],
|
||||||
}
|
'FirstLetter' => $first
|
||||||
|
)));
|
||||||
/**
|
}
|
||||||
* Sets the mapping between a entity name and the link for the end user
|
}
|
||||||
* to jump into editing the documentation.
|
|
||||||
*
|
return GroupedList::create($output->sort('Title', 'ASC'));
|
||||||
* Some variables are replaced:
|
}
|
||||||
* - %version%
|
|
||||||
* - %entity%
|
/**
|
||||||
* - %path%
|
* Documentation Search Form. Allows filtering of the results by many entities
|
||||||
* - %lang%
|
* and multiple versions.
|
||||||
*
|
*
|
||||||
* For example to provide an edit link to the framework module in github:
|
* @return Form
|
||||||
*
|
*/
|
||||||
* <code>
|
public function DocumentationSearchForm()
|
||||||
* DocumentationViewer::set_edit_link(
|
{
|
||||||
* 'framework',
|
if (!Config::inst()->get('DocumentationSearch', 'enabled')) {
|
||||||
* 'https://github.com/silverstripe/%entity%/edit/%version%/docs/%lang%/%path%',
|
return false;
|
||||||
* $opts
|
}
|
||||||
* ));
|
|
||||||
* </code>
|
return new DocumentationSearchForm($this);
|
||||||
*
|
}
|
||||||
* @param string module name
|
|
||||||
* @param string link
|
/**
|
||||||
* @param array options ('rewritetrunktomaster')
|
* Sets the mapping between a entity name and the link for the end user
|
||||||
*/
|
* to jump into editing the documentation.
|
||||||
public static function set_edit_link($module, $link, $options = array()) {
|
*
|
||||||
self::$edit_links[$module] = array(
|
* Some variables are replaced:
|
||||||
'url' => $link,
|
* - %version%
|
||||||
'options' => $options
|
* - %entity%
|
||||||
);
|
* - %path%
|
||||||
}
|
* - %lang%
|
||||||
|
*
|
||||||
/**
|
* For example to provide an edit link to the framework module in github:
|
||||||
* Returns an edit link to the current page (optional).
|
*
|
||||||
*
|
* <code>
|
||||||
* @return string
|
* DocumentationViewer::set_edit_link(
|
||||||
*/
|
* 'framework',
|
||||||
public function getEditLink() {
|
* 'https://github.com/silverstripe/%entity%/edit/%version%/docs/%lang%/%path%',
|
||||||
|
* $opts
|
||||||
$page = $this->getPage();
|
* ));
|
||||||
|
* </code>
|
||||||
if($page) {
|
*
|
||||||
|
* @param string module name
|
||||||
$entity = $page->getEntity();
|
* @param string link
|
||||||
|
* @param array options ('rewritetrunktomaster')
|
||||||
|
*/
|
||||||
|
public static function set_edit_link($module, $link, $options = array())
|
||||||
if($entity && isset(self::$edit_links[strtolower($entity->title)])) {
|
{
|
||||||
|
self::$edit_links[$module] = array(
|
||||||
// build the edit link, using the version defined
|
'url' => $link,
|
||||||
$url = self::$edit_links[strtolower($entity->title)];
|
'options' => $options
|
||||||
$version = $entity->getVersion();
|
);
|
||||||
|
}
|
||||||
if($entity->getBranch()){
|
|
||||||
$version = $entity->getBranch();
|
/**
|
||||||
}
|
* Returns an edit link to the current page (optional).
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
if($version == "trunk" && (isset($url['options']['rewritetrunktomaster']))) {
|
*/
|
||||||
if($url['options']['rewritetrunktomaster']) {
|
public function getEditLink()
|
||||||
$version = "master";
|
{
|
||||||
}
|
$page = $this->getPage();
|
||||||
}
|
|
||||||
|
if ($page) {
|
||||||
return str_replace(
|
$entity = $page->getEntity();
|
||||||
array('%entity%', '%lang%', '%version%', '%path%'),
|
|
||||||
array(
|
|
||||||
$entity->title,
|
|
||||||
$this->getLanguage(),
|
if ($entity && isset(self::$edit_links[strtolower($entity->title)])) {
|
||||||
$version,
|
|
||||||
ltrim($page->getRelativePath(), '/')
|
// build the edit link, using the version defined
|
||||||
),
|
$url = self::$edit_links[strtolower($entity->title)];
|
||||||
|
$version = $entity->getVersion();
|
||||||
$url['url']
|
|
||||||
);
|
if ($entity->getBranch()) {
|
||||||
}
|
$version = $entity->getBranch();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
if ($version == "trunk" && (isset($url['options']['rewritetrunktomaster']))) {
|
||||||
|
if ($url['options']['rewritetrunktomaster']) {
|
||||||
|
$version = "master";
|
||||||
|
}
|
||||||
/**
|
}
|
||||||
* Returns the next page. Either retrieves the sibling of the current page
|
|
||||||
* or return the next sibling of the parent page.
|
return str_replace(
|
||||||
*
|
array('%entity%', '%lang%', '%version%', '%path%'),
|
||||||
* @return DocumentationPage
|
array(
|
||||||
*/
|
$entity->title,
|
||||||
public function getNextPage() {
|
$this->getLanguage(),
|
||||||
return ($this->record)
|
$version,
|
||||||
? $this->getManifest()->getNextPage(
|
ltrim($page->getRelativePath(), '/')
|
||||||
$this->record->getPath(), $this->getEntity()->getPath())
|
),
|
||||||
: null;
|
|
||||||
}
|
$url['url']
|
||||||
|
);
|
||||||
/**
|
}
|
||||||
* Returns the previous page. Either returns the previous sibling or the
|
}
|
||||||
* parent of this page
|
|
||||||
*
|
return false;
|
||||||
* @return DocumentationPage
|
}
|
||||||
*/
|
|
||||||
public function getPreviousPage() {
|
|
||||||
return ($this->record)
|
|
||||||
? $this->getManifest()->getPreviousPage(
|
/**
|
||||||
$this->record->getPath(), $this->getEntity()->getPath())
|
* Returns the next page. Either retrieves the sibling of the current page
|
||||||
: null;
|
* or return the next sibling of the parent page.
|
||||||
}
|
*
|
||||||
|
* @return DocumentationPage
|
||||||
/**
|
*/
|
||||||
* @return string
|
public function getNextPage()
|
||||||
*/
|
{
|
||||||
public function getGoogleAnalyticsCode() {
|
return ($this->record)
|
||||||
$code = $this->config()->get('google_analytics_code');
|
? $this->getManifest()->getNextPage(
|
||||||
|
$this->record->getPath(), $this->getEntity()->getPath())
|
||||||
if($code) {
|
: null;
|
||||||
return $code;
|
}
|
||||||
}
|
|
||||||
}
|
/**
|
||||||
|
* Returns the previous page. Either returns the previous sibling or the
|
||||||
/**
|
* parent of this page
|
||||||
* @return string
|
*
|
||||||
*/
|
* @return DocumentationPage
|
||||||
public function getDocumentationTitle() {
|
*/
|
||||||
return $this->config()->get('documentation_title');
|
public function getPreviousPage()
|
||||||
}
|
{
|
||||||
|
return ($this->record)
|
||||||
public function getDocumentationBaseHref() {
|
? $this->getManifest()->getPreviousPage(
|
||||||
return Config::inst()->get('DocumentationViewer', 'link_base');
|
$this->record->getPath(), $this->getEntity()->getPath())
|
||||||
}
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getGoogleAnalyticsCode()
|
||||||
|
{
|
||||||
|
$code = $this->config()->get('google_analytics_code');
|
||||||
|
|
||||||
|
if ($code) {
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDocumentationTitle()
|
||||||
|
{
|
||||||
|
return $this->config()->get('documentation_title');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDocumentationBaseHref()
|
||||||
|
{
|
||||||
|
return Config::inst()->get('DocumentationViewer', 'link_base');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,93 +1,96 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class DocumentationSearchExtension extends Extension {
|
class DocumentationSearchExtension extends Extension
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Return an array of folders and titles
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getSearchedEntities()
|
||||||
|
{
|
||||||
|
$entities = array();
|
||||||
|
|
||||||
/**
|
if (!empty($_REQUEST['Entities'])) {
|
||||||
* Return an array of folders and titles
|
if (is_array($_REQUEST['Entities'])) {
|
||||||
*
|
$entities = Convert::raw2att($_REQUEST['Entities']);
|
||||||
* @return array
|
} else {
|
||||||
*/
|
$entities = explode(',', Convert::raw2att($_REQUEST['Entities']));
|
||||||
public function getSearchedEntities() {
|
$entities = array_combine($entities, $entities);
|
||||||
$entities = array();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!empty($_REQUEST['Entities'])) {
|
return $entities;
|
||||||
if(is_array($_REQUEST['Entities'])) {
|
}
|
||||||
$entities = Convert::raw2att($_REQUEST['Entities']);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$entities = explode(',', Convert::raw2att($_REQUEST['Entities']));
|
|
||||||
$entities = array_combine($entities, $entities);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $entities;
|
/**
|
||||||
}
|
* Return an array of versions that we're allowed to return
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getSearchedVersions()
|
||||||
|
{
|
||||||
|
$versions = array();
|
||||||
|
|
||||||
/**
|
if (!empty($_REQUEST['Versions'])) {
|
||||||
* Return an array of versions that we're allowed to return
|
if (is_array($_REQUEST['Versions'])) {
|
||||||
*
|
$versions = Convert::raw2att($_REQUEST['Versions']);
|
||||||
* @return array
|
$versions = array_combine($versions, $versions);
|
||||||
*/
|
} else {
|
||||||
public function getSearchedVersions() {
|
$version = Convert::raw2att($_REQUEST['Versions']);
|
||||||
$versions = array();
|
$versions[$version] = $version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!empty($_REQUEST['Versions'])) {
|
return $versions;
|
||||||
if(is_array($_REQUEST['Versions'])) {
|
}
|
||||||
$versions = Convert::raw2att($_REQUEST['Versions']);
|
|
||||||
$versions = array_combine($versions, $versions);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$version = Convert::raw2att($_REQUEST['Versions']);
|
|
||||||
$versions[$version] = $version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $versions;
|
/**
|
||||||
}
|
* Return the current search query.
|
||||||
|
*
|
||||||
|
* @return HTMLText|null
|
||||||
|
*/
|
||||||
|
public function getSearchQuery()
|
||||||
|
{
|
||||||
|
if (isset($_REQUEST['Search'])) {
|
||||||
|
return DBField::create_field('HTMLText', $_REQUEST['Search']);
|
||||||
|
} elseif (isset($_REQUEST['q'])) {
|
||||||
|
return DBField::create_field('HTMLText', $_REQUEST['q']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the current search query.
|
* Past straight to results, display and encode the query.
|
||||||
*
|
*/
|
||||||
* @return HTMLText|null
|
public function getSearchResults()
|
||||||
*/
|
{
|
||||||
public function getSearchQuery() {
|
$query = $this->getSearchQuery();
|
||||||
if(isset($_REQUEST['Search'])) {
|
|
||||||
return DBField::create_field('HTMLText', $_REQUEST['Search']);
|
|
||||||
} else if(isset($_REQUEST['q'])) {
|
|
||||||
return DBField::create_field('HTMLText', $_REQUEST['q']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
$search = new DocumentationSearch();
|
||||||
* Past straight to results, display and encode the query.
|
$search->setQuery($query);
|
||||||
*/
|
$search->setVersions($this->getSearchedVersions());
|
||||||
public function getSearchResults() {
|
$search->setModules($this->getSearchedEntities());
|
||||||
$query = $this->getSearchQuery();
|
$search->setOutputController($this->owner);
|
||||||
|
|
||||||
$search = new DocumentationSearch();
|
return $search->renderResults();
|
||||||
$search->setQuery($query);
|
}
|
||||||
$search->setVersions($this->getSearchedVersions());
|
|
||||||
$search->setModules($this->getSearchedEntities());
|
|
||||||
$search->setOutputController($this->owner);
|
|
||||||
|
|
||||||
return $search->renderResults();
|
/**
|
||||||
}
|
* Returns an search form which allows people to express more complex rules
|
||||||
|
* and options than the plain search form.
|
||||||
/**
|
*
|
||||||
* Returns an search form which allows people to express more complex rules
|
* @return Form
|
||||||
* and options than the plain search form.
|
*/
|
||||||
*
|
public function AdvancedSearchForm()
|
||||||
* @return Form
|
{
|
||||||
*/
|
return new DocumentationAdvancedSearchForm($this->owner);
|
||||||
public function AdvancedSearchForm() {
|
}
|
||||||
return new DocumentationAdvancedSearchForm($this->owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function getAdvancedSearchEnabled() {
|
|
||||||
return Config::inst()->get("DocumentationSearch", 'advanced_search_enabled');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getAdvancedSearchEnabled()
|
||||||
|
{
|
||||||
|
return Config::inst()->get("DocumentationSearch", 'advanced_search_enabled');
|
||||||
|
}
|
||||||
}
|
}
|
@ -25,13 +25,14 @@
|
|||||||
*
|
*
|
||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
*/
|
*/
|
||||||
class DocumentationStaticPublisherExtension extends Extension {
|
class DocumentationStaticPublisherExtension extends Extension
|
||||||
|
{
|
||||||
|
public function alterExportUrls(&$urls)
|
||||||
|
{
|
||||||
|
$manifest = new DocumentationManifest(true);
|
||||||
|
|
||||||
public function alterExportUrls(&$urls) {
|
foreach ($manifest->getPages() as $url => $page) {
|
||||||
$manifest = new DocumentationManifest(true);
|
$urls[$url] = $url;
|
||||||
|
}
|
||||||
foreach($manifest->getPages() as $url => $page) {
|
}
|
||||||
$urls[$url] = $url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -7,43 +7,43 @@
|
|||||||
* @return false|ArrayData
|
* @return false|ArrayData
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DocumentationViewerVersionWarning extends Extension {
|
class DocumentationViewerVersionWarning extends Extension
|
||||||
|
{
|
||||||
|
public function VersionWarning()
|
||||||
|
{
|
||||||
|
$page = $this->owner->getPage();
|
||||||
|
|
||||||
public function VersionWarning() {
|
if (!$page) {
|
||||||
$page = $this->owner->getPage();
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!$page) {
|
$entity = $page->getEntity();
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$entity = $page->getEntity();
|
if (!$entity) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(!$entity) {
|
$versions = $this->owner->getManifest()->getAllVersionsOfEntity($entity);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$versions = $this->owner->getManifest()->getAllVersionsOfEntity($entity);
|
if ($entity->getIsStable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if($entity->getIsStable()) {
|
$stable = $this->owner->getManifest()->getStableVersion($entity);
|
||||||
return false;
|
$compare = $entity->compare($stable);
|
||||||
}
|
|
||||||
|
|
||||||
$stable = $this->owner->getManifest()->getStableVersion($entity);
|
if ($entity->getVersion() == "master" || $compare > 0) {
|
||||||
$compare = $entity->compare($stable);
|
return $this->owner->customise(new ArrayData(array(
|
||||||
|
'FutureRelease' => true,
|
||||||
|
'StableVersion' => DBField::create_field('HTMLText', $stable->getVersion())
|
||||||
|
)));
|
||||||
|
} else {
|
||||||
|
return $this->owner->customise(new ArrayData(array(
|
||||||
|
'OutdatedRelease' => true,
|
||||||
|
'StableVersion' => DBField::create_field('HTMLText', $stable->getVersion())
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
if($entity->getVersion() == "master" || $compare > 0) {
|
return false;
|
||||||
return $this->owner->customise(new ArrayData(array(
|
}
|
||||||
'FutureRelease' => true,
|
|
||||||
'StableVersion' => DBField::create_field('HTMLText', $stable->getVersion())
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return $this->owner->customise(new ArrayData(array(
|
|
||||||
'OutdatedRelease' => true,
|
|
||||||
'StableVersion' => DBField::create_field('HTMLText', $stable->getVersion())
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -3,56 +3,57 @@
|
|||||||
/**
|
/**
|
||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
*/
|
*/
|
||||||
class DocumentationAdvancedSearchForm extends Form {
|
class DocumentationAdvancedSearchForm extends Form
|
||||||
|
{
|
||||||
|
public function __construct($controller)
|
||||||
|
{
|
||||||
|
$versions = $controller->getManifest()->getAllVersions();
|
||||||
|
$entities = $controller->getManifest()->getEntities();
|
||||||
|
|
||||||
public function __construct($controller) {
|
$q = ($q = $controller->getSearchQuery()) ? $q->NoHTML() : "";
|
||||||
$versions = $controller->getManifest()->getAllVersions();
|
|
||||||
$entities = $controller->getManifest()->getEntities();
|
|
||||||
|
|
||||||
$q = ($q = $controller->getSearchQuery()) ? $q->NoHTML() : "";
|
// klude to take an array of objects down to a simple map
|
||||||
|
$entities = $entities->map('Key', 'Title');
|
||||||
|
|
||||||
// klude to take an array of objects down to a simple map
|
// if we haven't gone any search limit then we're searching everything
|
||||||
$entities = $entities->map('Key', 'Title');
|
$searchedEntities = $controller->getSearchedEntities();
|
||||||
|
|
||||||
// if we haven't gone any search limit then we're searching everything
|
if (count($searchedEntities) < 1) {
|
||||||
$searchedEntities = $controller->getSearchedEntities();
|
$searchedEntities = $entities;
|
||||||
|
}
|
||||||
|
|
||||||
if(count($searchedEntities) < 1) {
|
$searchedVersions = $controller->getSearchedVersions();
|
||||||
$searchedEntities = $entities;
|
|
||||||
}
|
|
||||||
|
|
||||||
$searchedVersions = $controller->getSearchedVersions();
|
if (count($searchedVersions) < 1) {
|
||||||
|
$searchedVersions = $versions;
|
||||||
|
}
|
||||||
|
|
||||||
if(count($searchedVersions) < 1) {
|
$fields = FieldList::create(
|
||||||
$searchedVersions = $versions;
|
TextField::create('q', _t('DocumentationViewer.KEYWORDS', 'Keywords'), $q),
|
||||||
}
|
//CheckboxSetField::create('Entities', _t('DocumentationViewer.MODULES', 'Modules'), $entities, $searchedEntities),
|
||||||
|
CheckboxSetField::create(
|
||||||
|
'Versions',
|
||||||
|
_t('DocumentationViewer.VERSIONS', 'Versions'),
|
||||||
|
$versions, $searchedVersions
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
$fields = FieldList::create(
|
$actions = FieldList::create(
|
||||||
TextField::create('q', _t('DocumentationViewer.KEYWORDS', 'Keywords'), $q),
|
FormAction::create('results', _t('DocumentationViewer.SEARCH', 'Search'))
|
||||||
//CheckboxSetField::create('Entities', _t('DocumentationViewer.MODULES', 'Modules'), $entities, $searchedEntities),
|
);
|
||||||
CheckboxSetField::create(
|
|
||||||
'Versions',
|
|
||||||
_t('DocumentationViewer.VERSIONS', 'Versions'),
|
|
||||||
$versions, $searchedVersions
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$actions = FieldList::create(
|
$required = RequiredFields::create(array('Search'));
|
||||||
FormAction::create('results', _t('DocumentationViewer.SEARCH', 'Search'))
|
|
||||||
);
|
|
||||||
|
|
||||||
$required = RequiredFields::create(array('Search'));
|
parent::__construct(
|
||||||
|
$controller,
|
||||||
|
'AdvancedSearchForm',
|
||||||
|
$fields,
|
||||||
|
$actions,
|
||||||
|
$required
|
||||||
|
);
|
||||||
|
|
||||||
parent::__construct(
|
$this->disableSecurityToken();
|
||||||
$controller,
|
$this->setFormMethod('GET');
|
||||||
'AdvancedSearchForm',
|
$this->setFormAction($controller->Link('results'));
|
||||||
$fields,
|
}
|
||||||
$actions,
|
|
||||||
$required
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->disableSecurityToken();
|
|
||||||
$this->setFormMethod('GET');
|
|
||||||
$this->setFormAction($controller->Link('results'));
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,37 +1,36 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class DocumentationSearchForm extends Form {
|
class DocumentationSearchForm extends Form
|
||||||
|
{
|
||||||
|
public function __construct($controller)
|
||||||
|
{
|
||||||
|
$fields = new FieldList(
|
||||||
|
TextField::create('q', _t('DocumentationViewer.SEARCH', 'Search'), '')
|
||||||
|
->setAttribute('placeholder', _t('DocumentationViewer.SEARCH', 'Search'))
|
||||||
|
);
|
||||||
|
|
||||||
public function __construct($controller) {
|
$page = $controller->getPage();
|
||||||
|
|
||||||
|
if ($page) {
|
||||||
|
$versions = HiddenField::create(
|
||||||
|
'Versions',
|
||||||
|
_t('DocumentationViewer.VERSIONS', 'Versions'),
|
||||||
|
$page->getEntity()->getVersion()
|
||||||
|
);
|
||||||
|
|
||||||
$fields = new FieldList(
|
$fields->push($versions);
|
||||||
TextField::create('q', _t('DocumentationViewer.SEARCH', 'Search'), '')
|
}
|
||||||
->setAttribute('placeholder', _t('DocumentationViewer.SEARCH', 'Search'))
|
|
||||||
);
|
|
||||||
|
|
||||||
$page = $controller->getPage();
|
$actions = new FieldList(
|
||||||
|
new FormAction('results', _t('DocumentationViewer.SEARCH', 'Search'))
|
||||||
|
);
|
||||||
|
|
||||||
if($page){
|
parent::__construct($controller, 'DocumentationSearchForm', $fields, $actions);
|
||||||
$versions = HiddenField::create(
|
|
||||||
'Versions',
|
|
||||||
_t('DocumentationViewer.VERSIONS', 'Versions'),
|
|
||||||
$page->getEntity()->getVersion()
|
|
||||||
);
|
|
||||||
|
|
||||||
$fields->push($versions);
|
$this->disableSecurityToken();
|
||||||
}
|
$this->setFormMethod('GET');
|
||||||
|
$this->setFormAction($controller->Link('results'));
|
||||||
|
|
||||||
$actions = new FieldList(
|
$this->addExtraClass('search');
|
||||||
new FormAction('results', _t('DocumentationViewer.SEARCH', 'Search'))
|
}
|
||||||
);
|
|
||||||
|
|
||||||
parent::__construct($controller, 'DocumentationSearchForm', $fields, $actions);
|
|
||||||
|
|
||||||
$this->disableSecurityToken();
|
|
||||||
$this->setFormMethod('GET');
|
|
||||||
$this->setFormAction($controller->Link('results'));
|
|
||||||
|
|
||||||
$this->addExtraClass('search');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,287 +16,308 @@
|
|||||||
* @subpackage models
|
* @subpackage models
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DocumentationEntity extends ViewableData {
|
class DocumentationEntity extends ViewableData
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The key to match entities with that is not localized. For instance, you
|
||||||
|
* may have three entities (en, de, fr) that you want to display a nice
|
||||||
|
* title for, but matching needs to occur on a specific key.
|
||||||
|
*
|
||||||
|
* @var string $key
|
||||||
|
*/
|
||||||
|
protected $key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The key to match entities with that is not localized. For instance, you
|
* The human readable title of this entity. Set when the module is
|
||||||
* may have three entities (en, de, fr) that you want to display a nice
|
* registered.
|
||||||
* title for, but matching needs to occur on a specific key.
|
*
|
||||||
*
|
* @var string $title
|
||||||
* @var string $key
|
*/
|
||||||
*/
|
protected $title;
|
||||||
protected $key;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The human readable title of this entity. Set when the module is
|
* If the system is setup to only document one entity then you may only
|
||||||
* registered.
|
* want to show a single entity in the URL and the sidebar. Set this when
|
||||||
*
|
* you register the entity with the key `DefaultEntity` and the URL will
|
||||||
* @var string $title
|
* not include any version or language information.
|
||||||
*/
|
*
|
||||||
protected $title;
|
* @var boolean $default_entity
|
||||||
|
*/
|
||||||
|
protected $defaultEntity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the system is setup to only document one entity then you may only
|
* @var mixed
|
||||||
* want to show a single entity in the URL and the sidebar. Set this when
|
*/
|
||||||
* you register the entity with the key `DefaultEntity` and the URL will
|
protected $path;
|
||||||
* not include any version or language information.
|
|
||||||
*
|
|
||||||
* @var boolean $default_entity
|
|
||||||
*/
|
|
||||||
protected $defaultEntity;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var mixed
|
* @see {@link http://php.net/manual/en/function.version-compare.php}
|
||||||
*/
|
* @var float $version
|
||||||
protected $path;
|
*/
|
||||||
|
protected $version;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see {@link http://php.net/manual/en/function.version-compare.php}
|
* The repository branch name (allows for $version to be an alias on development branches).
|
||||||
* @var float $version
|
*
|
||||||
*/
|
* @var string $branch
|
||||||
protected $version;
|
*/
|
||||||
|
protected $branch;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The repository branch name (allows for $version to be an alias on development branches).
|
* If this entity is a stable release or not. If it is not stable (i.e it
|
||||||
*
|
* could be a past or future release) then a warning message will be shown.
|
||||||
* @var string $branch
|
*
|
||||||
*/
|
* @var boolean $stable
|
||||||
protected $branch;
|
*/
|
||||||
|
protected $stable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this entity is a stable release or not. If it is not stable (i.e it
|
* @var string
|
||||||
* could be a past or future release) then a warning message will be shown.
|
*/
|
||||||
*
|
protected $language;
|
||||||
* @var boolean $stable
|
|
||||||
*/
|
|
||||||
protected $stable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
*
|
||||||
*/
|
*/
|
||||||
protected $language;
|
public function __construct($key)
|
||||||
|
{
|
||||||
/**
|
$this->key = DocumentationHelper::clean_page_url($key);
|
||||||
*
|
}
|
||||||
*/
|
|
||||||
public function __construct($key) {
|
|
||||||
$this->key = DocumentationHelper::clean_page_url($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the title of this module.
|
* Get the title of this module.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getTitle() {
|
public function getTitle()
|
||||||
if(!$this->title) {
|
{
|
||||||
$this->title = DocumentationHelper::clean_page_name($this->key);
|
if (!$this->title) {
|
||||||
}
|
$this->title = DocumentationHelper::clean_page_name($this->key);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->title;
|
return $this->title;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $title
|
* @param string $title
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public function setTitle($title) {
|
public function setTitle($title)
|
||||||
$this->title = $title;
|
{
|
||||||
|
$this->title = $title;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the web accessible link to this entity.
|
* Returns the web accessible link to this entity.
|
||||||
*
|
*
|
||||||
* Includes the version information
|
* Includes the version information
|
||||||
*
|
*
|
||||||
* @param boolean $short If true, will attempt to return a short version of the url
|
* @param boolean $short If true, will attempt to return a short version of the url
|
||||||
* This might omit the version number if this is the default version.
|
* This might omit the version number if this is the default version.
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function Link($short = false) {
|
public function Link($short = false)
|
||||||
if($this->getIsDefaultEntity()) {
|
{
|
||||||
$base = Controller::join_links(
|
if ($this->getIsDefaultEntity()) {
|
||||||
Config::inst()->get('DocumentationViewer', 'link_base'),
|
$base = Controller::join_links(
|
||||||
$this->getLanguage(),
|
Config::inst()->get('DocumentationViewer', 'link_base'),
|
||||||
'/'
|
$this->getLanguage(),
|
||||||
);
|
'/'
|
||||||
} else {
|
);
|
||||||
$base = Controller::join_links(
|
} else {
|
||||||
Config::inst()->get('DocumentationViewer', 'link_base'),
|
$base = Controller::join_links(
|
||||||
$this->getLanguage(),
|
Config::inst()->get('DocumentationViewer', 'link_base'),
|
||||||
$this->getKey(),
|
$this->getLanguage(),
|
||||||
'/'
|
$this->getKey(),
|
||||||
);
|
'/'
|
||||||
}
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$base = ltrim(str_replace('//', '/', $base), '/');
|
$base = ltrim(str_replace('//', '/', $base), '/');
|
||||||
|
|
||||||
if($short && $this->stable) {
|
if ($short && $this->stable) {
|
||||||
return $base;
|
return $base;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Controller::join_links(
|
return Controller::join_links(
|
||||||
$base,
|
$base,
|
||||||
$this->getVersion(),
|
$this->getVersion(),
|
||||||
'/'
|
'/'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function __toString() {
|
public function __toString()
|
||||||
return sprintf('DocumentationEntity: %s)', $this->getPath());
|
{
|
||||||
}
|
return sprintf('DocumentationEntity: %s)', $this->getPath());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param DocumentationPage $page
|
* @param DocumentationPage $page
|
||||||
*
|
*
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function hasRecord($page) {
|
public function hasRecord($page)
|
||||||
if(!$page) {
|
{
|
||||||
return false;
|
if (!$page) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return strstr($page->getPath(), $this->getPath()) !== false;
|
return strstr($page->getPath(), $this->getPath()) !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param boolean $bool
|
* @param boolean $bool
|
||||||
*/
|
*/
|
||||||
public function setIsDefaultEntity($bool) {
|
public function setIsDefaultEntity($bool)
|
||||||
$this->defaultEntity = $bool;
|
{
|
||||||
|
$this->defaultEntity = $bool;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function getIsDefaultEntity() {
|
public function getIsDefaultEntity()
|
||||||
return $this->defaultEntity;
|
{
|
||||||
}
|
return $this->defaultEntity;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getKey() {
|
public function getKey()
|
||||||
return $this->key;
|
{
|
||||||
}
|
return $this->key;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getLanguage() {
|
public function getLanguage()
|
||||||
return $this->language;
|
{
|
||||||
}
|
return $this->language;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string
|
* @param string
|
||||||
*
|
*
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public function setLanguage($language) {
|
public function setLanguage($language)
|
||||||
$this->language = $language;
|
{
|
||||||
|
$this->language = $language;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string
|
* @param string
|
||||||
*/
|
*/
|
||||||
public function setVersion($version) {
|
public function setVersion($version)
|
||||||
$this->version = $version;
|
{
|
||||||
|
$this->version = $version;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function getVersion() {
|
public function getVersion()
|
||||||
return $this->version;
|
{
|
||||||
}
|
return $this->version;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string
|
* @param string
|
||||||
*/
|
*/
|
||||||
public function setBranch($branch) {
|
public function setBranch($branch)
|
||||||
$this->branch = $branch;
|
{
|
||||||
|
$this->branch = $branch;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return float
|
* @return float
|
||||||
*/
|
*/
|
||||||
public function getBranch() {
|
public function getBranch()
|
||||||
return $this->branch;
|
{
|
||||||
}
|
return $this->branch;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getPath() {
|
public function getPath()
|
||||||
return $this->path;
|
{
|
||||||
}
|
return $this->path;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $path
|
* @param string $path
|
||||||
*
|
*
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
public function setPath($path) {
|
public function setPath($path)
|
||||||
$this->path = $path;
|
{
|
||||||
|
$this->path = $path;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param boolean
|
* @param boolean
|
||||||
*/
|
*/
|
||||||
public function setIsStable($stable) {
|
public function setIsStable($stable)
|
||||||
$this->stable = $stable;
|
{
|
||||||
|
$this->stable = $stable;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
public function getIsStable() {
|
public function getIsStable()
|
||||||
return $this->stable;
|
{
|
||||||
}
|
return $this->stable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an integer value based on if a given version is the latest
|
* Returns an integer value based on if a given version is the latest
|
||||||
* version. Will return -1 for if the version is older, 0 if versions are
|
* version. Will return -1 for if the version is older, 0 if versions are
|
||||||
* the same and 1 if the version is greater than.
|
* the same and 1 if the version is greater than.
|
||||||
*
|
*
|
||||||
* @param string $version
|
* @param string $version
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function compare(DocumentationEntity $other) {
|
public function compare(DocumentationEntity $other)
|
||||||
return version_compare($this->getVersion(), $other->getVersion());
|
{
|
||||||
}
|
return version_compare($this->getVersion(), $other->getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function toMap() {
|
public function toMap()
|
||||||
return array(
|
{
|
||||||
'Key' => $this->key,
|
return array(
|
||||||
'Path' => $this->getPath(),
|
'Key' => $this->key,
|
||||||
'Version' => $this->getVersion(),
|
'Path' => $this->getPath(),
|
||||||
'Branch' => $this->getBranch(),
|
'Version' => $this->getVersion(),
|
||||||
'IsStable' => $this->getIsStable(),
|
'Branch' => $this->getBranch(),
|
||||||
'Language' => $this->getLanguage()
|
'IsStable' => $this->getIsStable(),
|
||||||
);
|
'Language' => $this->getLanguage()
|
||||||
}
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,13 @@
|
|||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
* @subpackage model
|
* @subpackage model
|
||||||
*/
|
*/
|
||||||
class DocumentationFolder extends DocumentationPage {
|
class DocumentationFolder extends DocumentationPage
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getTitle() {
|
public function getTitle()
|
||||||
return $this->getTitleFromFolder();
|
{
|
||||||
}
|
return $this->getTitleFromFolder();
|
||||||
|
}
|
||||||
}
|
}
|
@ -10,280 +10,295 @@
|
|||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
* @subpackage model
|
* @subpackage model
|
||||||
*/
|
*/
|
||||||
class DocumentationPage extends ViewableData {
|
class DocumentationPage extends ViewableData
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $title, $summary, $introduction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var DocumentationEntity
|
||||||
*/
|
*/
|
||||||
protected $title, $summary, $introduction;
|
protected $entity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var DocumentationEntity
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $entity;
|
protected $path;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* Filename
|
||||||
*/
|
*
|
||||||
protected $path;
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $filename;
|
||||||
|
|
||||||
/**
|
protected $read = false;
|
||||||
* Filename
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
protected $filename;
|
|
||||||
|
|
||||||
protected $read = false;
|
/**
|
||||||
|
* @param DocumentationEntity $entity
|
||||||
|
* @param string $filename
|
||||||
|
* @param string $path
|
||||||
|
*/
|
||||||
|
public function __construct(DocumentationEntity $entity, $filename, $path)
|
||||||
|
{
|
||||||
|
$this->filename = $filename;
|
||||||
|
$this->path = $path;
|
||||||
|
$this->entity = $entity;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param DocumentationEntity $entity
|
* @return string
|
||||||
* @param string $filename
|
*/
|
||||||
* @param string $path
|
public function getExtension()
|
||||||
*/
|
{
|
||||||
public function __construct(DocumentationEntity $entity, $filename, $path) {
|
return DocumentationHelper::get_extension($this->filename);
|
||||||
$this->filename = $filename;
|
}
|
||||||
$this->path = $path;
|
|
||||||
$this->entity = $entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @param string - has to be plain text for open search compatibility.
|
||||||
*/
|
*
|
||||||
public function getExtension() {
|
* @return string
|
||||||
return DocumentationHelper::get_extension($this->filename);
|
*/
|
||||||
}
|
public function getBreadcrumbTitle($divider = ' - ')
|
||||||
|
{
|
||||||
|
$pathParts = explode('/', trim($this->getRelativePath(), '/'));
|
||||||
|
|
||||||
/**
|
// from the page from this
|
||||||
* @param string - has to be plain text for open search compatibility.
|
array_pop($pathParts);
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getBreadcrumbTitle($divider = ' - ') {
|
|
||||||
$pathParts = explode('/', trim($this->getRelativePath(), '/'));
|
|
||||||
|
|
||||||
// from the page from this
|
// add the module to the breadcrumb trail.
|
||||||
array_pop($pathParts);
|
$pathParts[] = $this->entity->getTitle();
|
||||||
|
|
||||||
// add the module to the breadcrumb trail.
|
$titleParts = array_map(array(
|
||||||
$pathParts[] = $this->entity->getTitle();
|
'DocumentationHelper', 'clean_page_name'
|
||||||
|
), $pathParts);
|
||||||
|
|
||||||
$titleParts = array_map(array(
|
$titleParts = array_filter($titleParts, function ($val) {
|
||||||
'DocumentationHelper', 'clean_page_name'
|
if ($val) {
|
||||||
), $pathParts);
|
return $val;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$titleParts = array_filter($titleParts, function($val) {
|
if ($this->getTitle()) {
|
||||||
if($val) {
|
array_unshift($titleParts, $this->getTitle());
|
||||||
return $val;
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if($this->getTitle()) {
|
return implode($divider, $titleParts);
|
||||||
array_unshift($titleParts, $this->getTitle());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return implode($divider, $titleParts);
|
/**
|
||||||
}
|
* @return DocumentationEntity
|
||||||
|
*/
|
||||||
|
public function getEntity()
|
||||||
|
{
|
||||||
|
return $this->entity;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return DocumentationEntity
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getEntity() {
|
public function getTitle()
|
||||||
return $this->entity;
|
{
|
||||||
}
|
if ($this->title) {
|
||||||
|
return $this->title;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
$page = DocumentationHelper::clean_page_name($this->filename);
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getTitle() {
|
|
||||||
if($this->title) {
|
|
||||||
return $this->title;
|
|
||||||
}
|
|
||||||
|
|
||||||
$page = DocumentationHelper::clean_page_name($this->filename);
|
if ($page == "Index") {
|
||||||
|
return $this->getTitleFromFolder();
|
||||||
|
}
|
||||||
|
|
||||||
if($page == "Index") {
|
return $page;
|
||||||
return $this->getTitleFromFolder();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return $page;
|
public function getTitleFromFolder()
|
||||||
}
|
{
|
||||||
|
$folder = $this->getPath();
|
||||||
|
$entity = $this->getEntity()->getPath();
|
||||||
|
|
||||||
public function getTitleFromFolder() {
|
$folder = str_replace('index.md', '', $folder);
|
||||||
$folder = $this->getPath();
|
|
||||||
$entity = $this->getEntity()->getPath();
|
|
||||||
|
|
||||||
$folder = str_replace('index.md', '', $folder);
|
// if it's the root of the entity then we want to use the entity name
|
||||||
|
// otherwise we'll get 'En' for the entity folder
|
||||||
|
if ($folder == $entity) {
|
||||||
|
return $this->getEntity()->getTitle();
|
||||||
|
} else {
|
||||||
|
$path = explode(DIRECTORY_SEPARATOR, trim($folder, DIRECTORY_SEPARATOR));
|
||||||
|
$folderName = array_pop($path);
|
||||||
|
}
|
||||||
|
|
||||||
// if it's the root of the entity then we want to use the entity name
|
return DocumentationHelper::clean_page_name($folderName);
|
||||||
// otherwise we'll get 'En' for the entity folder
|
}
|
||||||
if($folder == $entity) {
|
|
||||||
return $this->getEntity()->getTitle();
|
|
||||||
} else {
|
|
||||||
$path = explode(DIRECTORY_SEPARATOR, trim($folder, DIRECTORY_SEPARATOR));
|
|
||||||
$folderName = array_pop($path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return DocumentationHelper::clean_page_name($folderName);
|
/**
|
||||||
}
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSummary()
|
||||||
|
{
|
||||||
|
return $this->summary;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* Return the raw markdown for a given documentation page.
|
||||||
*/
|
*
|
||||||
public function getSummary() {
|
* @param boolean $removeMetaData
|
||||||
return $this->summary;
|
*
|
||||||
}
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMarkdown($removeMetaData = false)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ($md = file_get_contents($this->getPath())) {
|
||||||
|
$this->populateMetaDataFromText($md, $removeMetaData);
|
||||||
|
|
||||||
/**
|
return $md;
|
||||||
* Return the raw markdown for a given documentation page.
|
}
|
||||||
*
|
|
||||||
* @param boolean $removeMetaData
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getMarkdown($removeMetaData = false) {
|
|
||||||
try {
|
|
||||||
if ($md = file_get_contents($this->getPath())) {
|
|
||||||
$this->populateMetaDataFromText($md, $removeMetaData);
|
|
||||||
|
|
||||||
return $md;
|
$this->read = true;
|
||||||
}
|
} catch (InvalidArgumentException $e) {
|
||||||
|
}
|
||||||
|
|
||||||
$this->read = true;
|
return false;
|
||||||
}
|
}
|
||||||
catch(InvalidArgumentException $e) {
|
|
||||||
|
|
||||||
}
|
public function setMetaData($key, $value)
|
||||||
|
{
|
||||||
|
$key = strtolower($key);
|
||||||
|
|
||||||
return false;
|
$this->$key = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setMetaData($key, $value) {
|
public function getIntroduction()
|
||||||
$key = strtolower($key);
|
{
|
||||||
|
if (!$this->read) {
|
||||||
|
$this->getMarkdown();
|
||||||
|
}
|
||||||
|
|
||||||
$this->$key = $value;
|
return $this->introduction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getIntroduction() {
|
/**
|
||||||
if(!$this->read) {
|
* Parse a file and return the parsed HTML version.
|
||||||
$this->getMarkdown();
|
*
|
||||||
}
|
* @param string $baselink
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getHTML()
|
||||||
|
{
|
||||||
|
$html = DocumentationParser::parse(
|
||||||
|
$this,
|
||||||
|
$this->entity->Link()
|
||||||
|
);
|
||||||
|
|
||||||
return $this->introduction;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a file and return the parsed HTML version.
|
* This should return the link from the entity root to the page. The link
|
||||||
*
|
* value has the cleaned version of the folder names. See
|
||||||
* @param string $baselink
|
* {@link getRelativePath()} for the actual file path.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getHTML() {
|
public function getRelativeLink()
|
||||||
$html = DocumentationParser::parse(
|
{
|
||||||
$this,
|
$path = $this->getRelativePath();
|
||||||
$this->entity->Link()
|
$url = explode('/', $path);
|
||||||
);
|
$url = implode('/', array_map(function ($a) {
|
||||||
|
return DocumentationHelper::clean_page_url($a);
|
||||||
|
}, $url));
|
||||||
|
|
||||||
return $html;
|
$url = trim($url, '/') . '/';
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return $url;
|
||||||
* This should return the link from the entity root to the page. The link
|
}
|
||||||
* value has the cleaned version of the folder names. See
|
|
||||||
* {@link getRelativePath()} for the actual file path.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getRelativeLink() {
|
|
||||||
$path = $this->getRelativePath();
|
|
||||||
$url = explode('/', $path);
|
|
||||||
$url = implode('/', array_map(function($a) {
|
|
||||||
return DocumentationHelper::clean_page_url($a);
|
|
||||||
}, $url));
|
|
||||||
|
|
||||||
$url = trim($url, '/') . '/';
|
/**
|
||||||
|
* This should return the link from the entity root to the page. For the url
|
||||||
|
* polished version, see {@link getRelativeLink()}.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getRelativePath()
|
||||||
|
{
|
||||||
|
return str_replace($this->entity->getPath(), '', $this->getPath());
|
||||||
|
}
|
||||||
|
|
||||||
return $url;
|
/**
|
||||||
}
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getPath()
|
||||||
|
{
|
||||||
|
return $this->path;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This should return the link from the entity root to the page. For the url
|
* Returns the URL that will be required for the user to hit to view the
|
||||||
* polished version, see {@link getRelativeLink()}.
|
* given document base name.
|
||||||
*
|
*
|
||||||
* @return string
|
* @param boolean $short If true, will attempt to return a short version of the url
|
||||||
*/
|
* This might omit the version number if this is the default version.
|
||||||
public function getRelativePath() {
|
* @return string
|
||||||
return str_replace($this->entity->getPath(), '', $this->getPath());
|
*/
|
||||||
|
public function Link($short = false)
|
||||||
|
{
|
||||||
|
return ltrim(Controller::join_links(
|
||||||
|
$this->entity->Link($short),
|
||||||
|
$this->getRelativeLink()
|
||||||
|
), '/');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Return metadata from the first html block in the page, then remove the
|
||||||
|
* block on request
|
||||||
|
*
|
||||||
|
* @param DocumentationPage $md
|
||||||
|
* @param bool $remove
|
||||||
|
*/
|
||||||
|
public function populateMetaDataFromText(&$md, $removeMetaData = false)
|
||||||
|
{
|
||||||
|
if ($md) {
|
||||||
|
// get the text up to the first whiteline
|
||||||
|
$extPattern = "/^(.+)\n(\r)*\n/Uis";
|
||||||
|
$matches = preg_match($extPattern, $md, $block);
|
||||||
|
|
||||||
/**
|
if ($matches && $block[1]) {
|
||||||
* @return string
|
$metaDataFound = false;
|
||||||
*/
|
|
||||||
public function getPath() {
|
|
||||||
return $this->path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// find the key/value pairs
|
||||||
* Returns the URL that will be required for the user to hit to view the
|
$intPattern = '/(?<key>[A-Za-z][A-Za-z0-9_-]+)[\t]*:[\t]*(?<value>[^:\n\r\/]+)/x';
|
||||||
* given document base name.
|
$matches = preg_match_all($intPattern, $block[1], $meta);
|
||||||
*
|
|
||||||
* @param boolean $short If true, will attempt to return a short version of the url
|
|
||||||
* This might omit the version number if this is the default version.
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function Link($short = false) {
|
|
||||||
return ltrim(Controller::join_links(
|
|
||||||
$this->entity->Link($short),
|
|
||||||
$this->getRelativeLink()
|
|
||||||
), '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
foreach ($meta['key'] as $index => $key) {
|
||||||
* Return metadata from the first html block in the page, then remove the
|
if (isset($meta['value'][$index])) {
|
||||||
* block on request
|
// check if a property exists for this key
|
||||||
*
|
if (property_exists(get_class(), $key)) {
|
||||||
* @param DocumentationPage $md
|
$this->$key = $meta['value'][$index];
|
||||||
* @param bool $remove
|
$metaDataFound = true;
|
||||||
*/
|
}
|
||||||
public function populateMetaDataFromText(&$md, $removeMetaData = false) {
|
}
|
||||||
if($md) {
|
}
|
||||||
// get the text up to the first whiteline
|
|
||||||
$extPattern = "/^(.+)\n(\r)*\n/Uis";
|
|
||||||
$matches = preg_match($extPattern, $md, $block);
|
|
||||||
|
|
||||||
if($matches && $block[1]) {
|
// optionally remove the metadata block (only on the page that
|
||||||
$metaDataFound = false;
|
// is displayed)
|
||||||
|
if ($metaDataFound && $removeMetaData) {
|
||||||
|
$md = preg_replace($extPattern, '', $md);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// find the key/value pairs
|
public function getVersion()
|
||||||
$intPattern = '/(?<key>[A-Za-z][A-Za-z0-9_-]+)[\t]*:[\t]*(?<value>[^:\n\r\/]+)/x';
|
{
|
||||||
$matches = preg_match_all($intPattern, $block[1], $meta);
|
return $this->entity->getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
foreach($meta['key'] as $index => $key) {
|
public function __toString()
|
||||||
if(isset($meta['value'][$index])) {
|
{
|
||||||
// check if a property exists for this key
|
return sprintf(get_class($this) .': %s)', $this->getPath());
|
||||||
if (property_exists(get_class(), $key)) {
|
}
|
||||||
$this->$key = $meta['value'][$index];
|
|
||||||
$metaDataFound = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// optionally remove the metadata block (only on the page that
|
|
||||||
// is displayed)
|
|
||||||
if ($metaDataFound && $removeMetaData) {
|
|
||||||
$md = preg_replace($extPattern, '', $md);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getVersion() {
|
|
||||||
return $this->entity->getVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __toString() {
|
|
||||||
return sprintf(get_class($this) .': %s)', $this->getPath());
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,14 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class DocumentationBuild extends BuildTask {
|
class DocumentationBuild extends BuildTask
|
||||||
|
{
|
||||||
public function run($request) {
|
public function run($request)
|
||||||
$manifest = new DocumentationManifest(true);
|
{
|
||||||
echo "<pre>";
|
$manifest = new DocumentationManifest(true);
|
||||||
print_r($manifest->getPages());
|
echo "<pre>";
|
||||||
echo "</pre>";
|
print_r($manifest->getPages());
|
||||||
die();;
|
echo "</pre>";
|
||||||
|
die();
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,124 +9,127 @@
|
|||||||
* @subpackage tasks
|
* @subpackage tasks
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class RebuildLuceneDocsIndex extends BuildTask {
|
class RebuildLuceneDocsIndex extends BuildTask
|
||||||
|
{
|
||||||
|
protected $title = "Rebuild Documentation Search Indexes";
|
||||||
|
|
||||||
protected $title = "Rebuild Documentation Search Indexes";
|
protected $description = "
|
||||||
|
|
||||||
protected $description = "
|
|
||||||
Rebuilds the indexes used for the search engine in the docsviewer.";
|
Rebuilds the indexes used for the search engine in the docsviewer.";
|
||||||
|
|
||||||
public function run($request) {
|
public function run($request)
|
||||||
$this->rebuildIndexes();
|
{
|
||||||
}
|
$this->rebuildIndexes();
|
||||||
|
}
|
||||||
|
|
||||||
public function rebuildIndexes($quiet = false) {
|
public function rebuildIndexes($quiet = false)
|
||||||
require_once 'Zend/Search/Lucene.php';
|
{
|
||||||
|
require_once 'Zend/Search/Lucene.php';
|
||||||
|
|
||||||
ini_set("memory_limit", -1);
|
ini_set("memory_limit", -1);
|
||||||
ini_set('max_execution_time', 0);
|
ini_set('max_execution_time', 0);
|
||||||
|
|
||||||
Filesystem::makeFolder(DocumentationSearch::get_index_location());
|
Filesystem::makeFolder(DocumentationSearch::get_index_location());
|
||||||
|
|
||||||
// only rebuild the index if we have to. Check for either flush or the time write.lock.file
|
// only rebuild the index if we have to. Check for either flush or the time write.lock.file
|
||||||
// was last altered
|
// was last altered
|
||||||
$lock = DocumentationSearch::get_index_location() .'/write.lock.file';
|
$lock = DocumentationSearch::get_index_location() .'/write.lock.file';
|
||||||
$lockFileFresh = (file_exists($lock) && filemtime($lock) > (time() - (60 * 60 * 24)));
|
$lockFileFresh = (file_exists($lock) && filemtime($lock) > (time() - (60 * 60 * 24)));
|
||||||
|
|
||||||
echo "Building index in ". DocumentationSearch::get_index_location() . PHP_EOL;
|
echo "Building index in ". DocumentationSearch::get_index_location() . PHP_EOL;
|
||||||
|
|
||||||
if($lockFileFresh && !isset($_REQUEST['flush'])) {
|
if ($lockFileFresh && !isset($_REQUEST['flush'])) {
|
||||||
if(!$quiet) {
|
if (!$quiet) {
|
||||||
echo "Index recently rebuilt. If you want to force reindex use ?flush=1";
|
echo "Index recently rebuilt. If you want to force reindex use ?flush=1";
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$index = Zend_Search_Lucene::open(DocumentationSearch::get_index_location());
|
$index = Zend_Search_Lucene::open(DocumentationSearch::get_index_location());
|
||||||
$index->removeReference();
|
$index->removeReference();
|
||||||
}
|
} catch (Zend_Search_Lucene_Exception $e) {
|
||||||
catch (Zend_Search_Lucene_Exception $e) {
|
user_error($e);
|
||||||
user_error($e);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$index = Zend_Search_Lucene::create(DocumentationSearch::get_index_location());
|
$index = Zend_Search_Lucene::create(DocumentationSearch::get_index_location());
|
||||||
}
|
} catch (Zend_Search_Lucene_Exception $c) {
|
||||||
catch(Zend_Search_Lucene_Exception $c) {
|
user_error($c);
|
||||||
user_error($c);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// includes registration
|
// includes registration
|
||||||
$manifest = new DocumentationManifest(true);
|
$manifest = new DocumentationManifest(true);
|
||||||
$pages = $manifest->getPages();
|
$pages = $manifest->getPages();
|
||||||
|
|
||||||
if($pages) {
|
if ($pages) {
|
||||||
$count = 0;
|
$count = 0;
|
||||||
|
|
||||||
// iconv complains about all the markdown formatting
|
// iconv complains about all the markdown formatting
|
||||||
// turn off notices while we parse
|
// turn off notices while we parse
|
||||||
|
|
||||||
if(!Director::is_cli()) {
|
if (!Director::is_cli()) {
|
||||||
echo "<ul>";
|
echo "<ul>";
|
||||||
}
|
}
|
||||||
foreach($pages as $url => $record) {
|
foreach ($pages as $url => $record) {
|
||||||
$count++;
|
$count++;
|
||||||
$page = $manifest->getPage($url);
|
$page = $manifest->getPage($url);
|
||||||
|
|
||||||
$doc = new Zend_Search_Lucene_Document();
|
$doc = new Zend_Search_Lucene_Document();
|
||||||
$error = error_reporting();
|
$error = error_reporting();
|
||||||
error_reporting(E_ALL ^ E_NOTICE);
|
error_reporting(E_ALL ^ E_NOTICE);
|
||||||
$content = $page->getHTML();
|
$content = $page->getHTML();
|
||||||
error_reporting($error);
|
error_reporting($error);
|
||||||
|
|
||||||
$doc->addField(Zend_Search_Lucene_Field::Text('content', $content));
|
$doc->addField(Zend_Search_Lucene_Field::Text('content', $content));
|
||||||
$doc->addField($titleField = Zend_Search_Lucene_Field::Text('Title', $page->getTitle()));
|
$doc->addField($titleField = Zend_Search_Lucene_Field::Text('Title', $page->getTitle()));
|
||||||
$doc->addField($breadcrumbField = Zend_Search_Lucene_Field::Text('BreadcrumbTitle', $page->getBreadcrumbTitle()));
|
$doc->addField($breadcrumbField = Zend_Search_Lucene_Field::Text('BreadcrumbTitle', $page->getBreadcrumbTitle()));
|
||||||
|
|
||||||
$doc->addField(Zend_Search_Lucene_Field::Keyword(
|
$doc->addField(Zend_Search_Lucene_Field::Keyword(
|
||||||
'Version', $page->getEntity()->getVersion()
|
'Version', $page->getEntity()->getVersion()
|
||||||
));
|
));
|
||||||
|
|
||||||
$doc->addField(Zend_Search_Lucene_Field::Keyword(
|
$doc->addField(Zend_Search_Lucene_Field::Keyword(
|
||||||
'Language', $page->getEntity()->getLanguage()
|
'Language', $page->getEntity()->getLanguage()
|
||||||
));
|
));
|
||||||
|
|
||||||
$doc->addField(Zend_Search_Lucene_Field::Keyword(
|
$doc->addField(Zend_Search_Lucene_Field::Keyword(
|
||||||
'Entity', $page->getEntity()
|
'Entity', $page->getEntity()
|
||||||
));
|
));
|
||||||
|
|
||||||
$doc->addField(Zend_Search_Lucene_Field::Keyword(
|
$doc->addField(Zend_Search_Lucene_Field::Keyword(
|
||||||
'Link', $page->Link()
|
'Link', $page->Link()
|
||||||
));
|
));
|
||||||
|
|
||||||
// custom boosts
|
// custom boosts
|
||||||
$titleField->boost = 3;
|
$titleField->boost = 3;
|
||||||
$breadcrumbField->boost = 1.5;
|
$breadcrumbField->boost = 1.5;
|
||||||
|
|
||||||
$boost = Config::inst()->get('DocumentationSearch', 'boost_by_path');
|
$boost = Config::inst()->get('DocumentationSearch', 'boost_by_path');
|
||||||
|
|
||||||
foreach($boost as $pathExpr => $boost) {
|
foreach ($boost as $pathExpr => $boost) {
|
||||||
if(preg_match($pathExpr, $page->getRelativePath())) {
|
if (preg_match($pathExpr, $page->getRelativePath())) {
|
||||||
$doc->boost = $boost;
|
$doc->boost = $boost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error_reporting(E_ALL ^ E_NOTICE);
|
error_reporting(E_ALL ^ E_NOTICE);
|
||||||
$index->addDocument($doc);
|
$index->addDocument($doc);
|
||||||
|
|
||||||
if(!$quiet) {
|
if (!$quiet) {
|
||||||
if(Director::is_cli()) echo " * adding ". $page->getPath() ."\n";
|
if (Director::is_cli()) {
|
||||||
else echo "<li>adding ". $page->getPath() ."</li>\n";
|
echo " * adding ". $page->getPath() ."\n";
|
||||||
}
|
} else {
|
||||||
}
|
echo "<li>adding ". $page->getPath() ."</li>\n";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$index->commit();
|
$index->commit();
|
||||||
|
|
||||||
if(!$quiet) {
|
if (!$quiet) {
|
||||||
echo "complete.";
|
echo "complete.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,67 +4,72 @@
|
|||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
class DocumentationHelperTests extends SapphireTest {
|
class DocumentationHelperTests extends SapphireTest
|
||||||
|
{
|
||||||
|
public function testCleanName()
|
||||||
|
{
|
||||||
|
$this->assertEquals("File path", DocumentationHelper::clean_page_name(
|
||||||
|
'00_file-path.md'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
public function testCleanName() {
|
public function testCleanUrl()
|
||||||
$this->assertEquals("File path", DocumentationHelper::clean_page_name(
|
{
|
||||||
'00_file-path.md'
|
$this->assertEquals("some_path", DocumentationHelper::clean_page_url(
|
||||||
));
|
'Some Path'
|
||||||
}
|
));
|
||||||
|
|
||||||
public function testCleanUrl() {
|
$this->assertEquals("somefilepath", DocumentationHelper::clean_page_url(
|
||||||
$this->assertEquals("some_path", DocumentationHelper::clean_page_url(
|
'00_SomeFilePath.md'
|
||||||
'Some Path'
|
));
|
||||||
));
|
}
|
||||||
|
|
||||||
$this->assertEquals("somefilepath", DocumentationHelper::clean_page_url(
|
public function testTrimSortNumber()
|
||||||
'00_SomeFilePath.md'
|
{
|
||||||
));
|
$this->assertEquals('file', DocumentationHelper::trim_sort_number(
|
||||||
}
|
'0_file'
|
||||||
|
));
|
||||||
|
|
||||||
public function testTrimSortNumber() {
|
$this->assertEquals('2.1', DocumentationHelper::trim_sort_number(
|
||||||
$this->assertEquals('file', DocumentationHelper::trim_sort_number(
|
'2.1'
|
||||||
'0_file'
|
));
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertEquals('2.1', DocumentationHelper::trim_sort_number(
|
$this->assertEquals('dev/tasks/2.1', DocumentationHelper::trim_sort_number(
|
||||||
'2.1'
|
'dev/tasks/2.1'
|
||||||
));
|
));
|
||||||
|
}
|
||||||
|
|
||||||
$this->assertEquals('dev/tasks/2.1', DocumentationHelper::trim_sort_number(
|
public function testTrimExtension()
|
||||||
'dev/tasks/2.1'
|
{
|
||||||
));
|
$this->assertEquals('file', DocumentationHelper::trim_extension_off(
|
||||||
}
|
'file.md'
|
||||||
|
));
|
||||||
|
|
||||||
public function testTrimExtension() {
|
$this->assertEquals('dev/path/file', DocumentationHelper::trim_extension_off(
|
||||||
$this->assertEquals('file', DocumentationHelper::trim_extension_off(
|
'dev/path/file.md'
|
||||||
'file.md'
|
));
|
||||||
));
|
}
|
||||||
|
|
||||||
$this->assertEquals('dev/path/file', DocumentationHelper::trim_extension_off(
|
public function testGetExtension()
|
||||||
'dev/path/file.md'
|
{
|
||||||
));
|
$this->assertEquals('md', DocumentationHelper::get_extension(
|
||||||
}
|
'file.md'
|
||||||
|
));
|
||||||
|
|
||||||
public function testGetExtension() {
|
$this->assertEquals('md', DocumentationHelper::get_extension(
|
||||||
$this->assertEquals('md', DocumentationHelper::get_extension(
|
'dev/tasks/file.md'
|
||||||
'file.md'
|
));
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertEquals('md', DocumentationHelper::get_extension(
|
$this->assertEquals('txt', DocumentationHelper::get_extension(
|
||||||
'dev/tasks/file.md'
|
'dev/tasks/file.txt'
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->assertEquals('txt', DocumentationHelper::get_extension(
|
$this->assertNull(DocumentationHelper::get_extension(
|
||||||
'dev/tasks/file.txt'
|
'doc_test/2.3'
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->assertNull(DocumentationHelper::get_extension(
|
$this->assertNull(DocumentationHelper::get_extension(
|
||||||
'doc_test/2.3'
|
'dev/docs/en/doc_test/2.3/subfolder'
|
||||||
));
|
));
|
||||||
|
}
|
||||||
$this->assertNull(DocumentationHelper::get_extension(
|
|
||||||
'dev/docs/en/doc_test/2.3/subfolder'
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,208 +4,219 @@
|
|||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
class DocumentationManifestTests extends SapphireTest {
|
class DocumentationManifestTests extends SapphireTest
|
||||||
|
{
|
||||||
|
private $manifest;
|
||||||
|
|
||||||
private $manifest;
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
public function setUp() {
|
Config::nest();
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
Config::nest();
|
// explicitly use dev/docs. Custom paths should be tested separately
|
||||||
|
Config::inst()->update(
|
||||||
|
'DocumentationViewer', 'link_base', 'dev/docs'
|
||||||
|
);
|
||||||
|
|
||||||
// explicitly use dev/docs. Custom paths should be tested separately
|
// disable automatic module registration so modules don't interfere.
|
||||||
Config::inst()->update(
|
Config::inst()->update(
|
||||||
'DocumentationViewer', 'link_base', 'dev/docs'
|
'DocumentationManifest', 'automatic_registration', false
|
||||||
);
|
);
|
||||||
|
|
||||||
// disable automatic module registration so modules don't interfere.
|
Config::inst()->remove('DocumentationManifest', 'register_entities');
|
||||||
Config::inst()->update(
|
|
||||||
'DocumentationManifest', 'automatic_registration', false
|
|
||||||
);
|
|
||||||
|
|
||||||
Config::inst()->remove('DocumentationManifest', 'register_entities');
|
Config::inst()->update(
|
||||||
|
'DocumentationManifest', 'register_entities', array(
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs/",
|
||||||
|
'Title' => 'Doc Test',
|
||||||
|
'Key' => 'testdocs',
|
||||||
|
'Version' => '2.3'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs-v2.4/",
|
||||||
|
'Title' => 'Doc Test',
|
||||||
|
'Version' => '2.4',
|
||||||
|
'Key' => 'testdocs',
|
||||||
|
'Stable' => true
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs-v3.0/",
|
||||||
|
'Title' => 'Doc Test',
|
||||||
|
'Key' => 'testdocs',
|
||||||
|
'Version' => '3.0'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs-manifest/",
|
||||||
|
'Title' => 'Manifest',
|
||||||
|
'Key' => 'manifest'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
Config::inst()->update(
|
$this->manifest = new DocumentationManifest(true);
|
||||||
'DocumentationManifest', 'register_entities', array(
|
}
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs/",
|
|
||||||
'Title' => 'Doc Test',
|
|
||||||
'Key' => 'testdocs',
|
|
||||||
'Version' => '2.3'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs-v2.4/",
|
|
||||||
'Title' => 'Doc Test',
|
|
||||||
'Version' => '2.4',
|
|
||||||
'Key' => 'testdocs',
|
|
||||||
'Stable' => true
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs-v3.0/",
|
|
||||||
'Title' => 'Doc Test',
|
|
||||||
'Key' => 'testdocs',
|
|
||||||
'Version' => '3.0'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs-manifest/",
|
|
||||||
'Title' => 'Manifest',
|
|
||||||
'Key' => 'manifest'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->manifest = new DocumentationManifest(true);
|
public function tearDown()
|
||||||
}
|
{
|
||||||
|
parent::tearDown();
|
||||||
|
|
||||||
public function tearDown() {
|
Config::unnest();
|
||||||
parent::tearDown();
|
}
|
||||||
|
|
||||||
Config::unnest();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that the manifest matches what we'd expect.
|
* Check that the manifest matches what we'd expect.
|
||||||
*/
|
*/
|
||||||
public function testRegenerate() {
|
public function testRegenerate()
|
||||||
$match = array(
|
{
|
||||||
'de/testdocs/2.3/',
|
$match = array(
|
||||||
'de/testdocs/2.3/german/',
|
'de/testdocs/2.3/',
|
||||||
'de/testdocs/2.3/test/',
|
'de/testdocs/2.3/german/',
|
||||||
'en/testdocs/2.3/',
|
'de/testdocs/2.3/test/',
|
||||||
'en/testdocs/2.3/sort/',
|
'en/testdocs/2.3/',
|
||||||
'en/testdocs/2.3/sort/basic/',
|
'en/testdocs/2.3/sort/',
|
||||||
'en/testdocs/2.3/sort/intermediate/',
|
'en/testdocs/2.3/sort/basic/',
|
||||||
'en/testdocs/2.3/sort/advanced/',
|
'en/testdocs/2.3/sort/intermediate/',
|
||||||
'en/testdocs/2.3/sort/some-page/',
|
'en/testdocs/2.3/sort/advanced/',
|
||||||
'en/testdocs/2.3/sort/another-page/',
|
'en/testdocs/2.3/sort/some-page/',
|
||||||
'en/testdocs/2.3/subfolder/',
|
'en/testdocs/2.3/sort/another-page/',
|
||||||
'en/testdocs/2.3/subfolder/subpage/',
|
'en/testdocs/2.3/subfolder/',
|
||||||
'en/testdocs/2.3/subfolder/subsubfolder/',
|
'en/testdocs/2.3/subfolder/subpage/',
|
||||||
'en/testdocs/2.3/subfolder/subsubfolder/subsubpage/',
|
'en/testdocs/2.3/subfolder/subsubfolder/',
|
||||||
'en/testdocs/2.3/test/',
|
'en/testdocs/2.3/subfolder/subsubfolder/subsubpage/',
|
||||||
'en/testdocs/2.4/',
|
'en/testdocs/2.3/test/',
|
||||||
'en/testdocs/2.4/test/',
|
'en/testdocs/2.4/',
|
||||||
'en/testdocs/3.0/',
|
'en/testdocs/2.4/test/',
|
||||||
'en/testdocs/3.0/changelog/',
|
'en/testdocs/3.0/',
|
||||||
'en/testdocs/3.0/tutorials/',
|
'en/testdocs/3.0/changelog/',
|
||||||
'en/testdocs/3.0/empty/',
|
'en/testdocs/3.0/tutorials/',
|
||||||
'en/manifest/',
|
'en/testdocs/3.0/empty/',
|
||||||
'en/manifest/guide/',
|
'en/manifest/',
|
||||||
'en/manifest/guide/test/',
|
'en/manifest/guide/',
|
||||||
'en/manifest/second-guide/',
|
'en/manifest/guide/test/',
|
||||||
'en/manifest/second-guide/afile/'
|
'en/manifest/second-guide/',
|
||||||
);
|
'en/manifest/second-guide/afile/'
|
||||||
|
);
|
||||||
|
|
||||||
$this->assertEquals($match, array_keys($this->manifest->getPages()));
|
$this->assertEquals($match, array_keys($this->manifest->getPages()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetNextPage() {
|
public function testGetNextPage()
|
||||||
// get next page at the end of one subfolder goes back up to the top
|
{
|
||||||
// most directory
|
// get next page at the end of one subfolder goes back up to the top
|
||||||
$this->assertStringEndsWith('2.3/test/', $this->manifest->getNextPage(
|
// most directory
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/subfolder/subsubfolder/subsubpage.md',
|
$this->assertStringEndsWith('2.3/test/', $this->manifest->getNextPage(
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/'
|
DOCSVIEWER_PATH . '/tests/docs/en/subfolder/subsubfolder/subsubpage.md',
|
||||||
)->Link);
|
DOCSVIEWER_PATH . '/tests/docs/en/'
|
||||||
|
)->Link);
|
||||||
|
|
||||||
// after sorting, 2 is shown.
|
// after sorting, 2 is shown.
|
||||||
$this->assertContains('/intermediate/', $this->manifest->getNextPage(
|
$this->assertContains('/intermediate/', $this->manifest->getNextPage(
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/sort/01-basic.md',
|
DOCSVIEWER_PATH . '/tests/docs/en/sort/01-basic.md',
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/'
|
DOCSVIEWER_PATH . '/tests/docs/en/'
|
||||||
)->Link);
|
)->Link);
|
||||||
|
|
||||||
|
|
||||||
// next gets the following URL
|
// next gets the following URL
|
||||||
$this->assertContains('/test/', $this->manifest->getNextPage(
|
$this->assertContains('/test/', $this->manifest->getNextPage(
|
||||||
DOCSVIEWER_PATH . '/tests/docs-v2.4/en/index.md',
|
DOCSVIEWER_PATH . '/tests/docs-v2.4/en/index.md',
|
||||||
DOCSVIEWER_PATH . '/tests/docs-v2.4/en/'
|
DOCSVIEWER_PATH . '/tests/docs-v2.4/en/'
|
||||||
)->Link);
|
)->Link);
|
||||||
|
|
||||||
|
|
||||||
// last folder in a entity does not leak
|
// last folder in a entity does not leak
|
||||||
$this->assertNull($this->manifest->getNextPage(
|
$this->assertNull($this->manifest->getNextPage(
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/test.md',
|
DOCSVIEWER_PATH . '/tests/docs/en/test.md',
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/'
|
DOCSVIEWER_PATH . '/tests/docs/en/'
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetPreviousPage() {
|
public function testGetPreviousPage()
|
||||||
// goes right into subfolders
|
{
|
||||||
$this->assertContains('subfolder/subsubfolder/subsubpage', $this->manifest->getPreviousPage(
|
// goes right into subfolders
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/test.md',
|
$this->assertContains('subfolder/subsubfolder/subsubpage', $this->manifest->getPreviousPage(
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/'
|
DOCSVIEWER_PATH . '/tests/docs/en/test.md',
|
||||||
)->Link);
|
DOCSVIEWER_PATH . '/tests/docs/en/'
|
||||||
|
)->Link);
|
||||||
|
|
||||||
// does not leak between entities
|
// does not leak between entities
|
||||||
$this->assertNull($this->manifest->getPreviousPage(
|
$this->assertNull($this->manifest->getPreviousPage(
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/index.md',
|
DOCSVIEWER_PATH . '/tests/docs/en/index.md',
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/'
|
DOCSVIEWER_PATH . '/tests/docs/en/'
|
||||||
));
|
));
|
||||||
|
|
||||||
// does not leak between entities
|
// does not leak between entities
|
||||||
$this->assertNull($this->manifest->getPreviousPage(
|
$this->assertNull($this->manifest->getPreviousPage(
|
||||||
DOCSVIEWER_PATH . ' /tests/docs/en/index.md',
|
DOCSVIEWER_PATH . ' /tests/docs/en/index.md',
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/'
|
DOCSVIEWER_PATH . '/tests/docs/en/'
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetPage() {
|
public function testGetPage()
|
||||||
$this->markTestIncomplete();
|
{
|
||||||
}
|
$this->markTestIncomplete();
|
||||||
|
}
|
||||||
|
|
||||||
public function testGenerateBreadcrumbs() {
|
public function testGenerateBreadcrumbs()
|
||||||
$this->markTestIncomplete();
|
{
|
||||||
}
|
$this->markTestIncomplete();
|
||||||
|
}
|
||||||
|
|
||||||
public function testGetChildrenFor() {
|
public function testGetChildrenFor()
|
||||||
$expected = array(
|
{
|
||||||
array('Title' => 'Test', 'LinkingMode' => 'link')
|
$expected = array(
|
||||||
);
|
array('Title' => 'Test', 'LinkingMode' => 'link')
|
||||||
|
);
|
||||||
|
|
||||||
$this->assertDOSContains($expected, $this->manifest->getChildrenFor(
|
$this->assertDOSContains($expected, $this->manifest->getChildrenFor(
|
||||||
DOCSVIEWER_PATH . "/tests/docs/en/"
|
DOCSVIEWER_PATH . "/tests/docs/en/"
|
||||||
));
|
));
|
||||||
|
|
||||||
$expected = array(
|
$expected = array(
|
||||||
array('Title' => 'ChangeLog', 'LinkingMode' => 'current'),
|
array('Title' => 'ChangeLog', 'LinkingMode' => 'current'),
|
||||||
array('Title' => 'Tutorials'),
|
array('Title' => 'Tutorials'),
|
||||||
array('Title' => 'Empty')
|
array('Title' => 'Empty')
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertDOSContains($expected, $this->manifest->getChildrenFor(
|
$this->assertDOSContains($expected, $this->manifest->getChildrenFor(
|
||||||
DOCSVIEWER_PATH . '/tests/docs-v3.0/en/',
|
DOCSVIEWER_PATH . '/tests/docs-v3.0/en/',
|
||||||
DOCSVIEWER_PATH . '/tests/docs-v3.0/en/ChangeLog.md'
|
DOCSVIEWER_PATH . '/tests/docs-v3.0/en/ChangeLog.md'
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetAllVersions() {
|
public function testGetAllVersions()
|
||||||
$expected = array(
|
{
|
||||||
'2.3' => '2.3',
|
$expected = array(
|
||||||
'2.4' => '2.4',
|
'2.3' => '2.3',
|
||||||
'3.0' => '3.0',
|
'2.4' => '2.4',
|
||||||
'0.0' => 'Master'
|
'3.0' => '3.0',
|
||||||
);
|
'0.0' => 'Master'
|
||||||
|
);
|
||||||
|
|
||||||
$this->assertEquals($expected, $this->manifest->getAllVersions());
|
$this->assertEquals($expected, $this->manifest->getAllVersions());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetAllEntityVersions() {
|
public function testGetAllEntityVersions()
|
||||||
$expected = array(
|
{
|
||||||
'Version' => '2.3',
|
$expected = array(
|
||||||
'Version' => '2.4',
|
'Version' => '2.3',
|
||||||
'Version' => '3.0'
|
'Version' => '2.4',
|
||||||
);
|
'Version' => '3.0'
|
||||||
|
);
|
||||||
|
|
||||||
$entity = $this->manifest->getEntities()->find('Language', 'en');
|
$entity = $this->manifest->getEntities()->find('Language', 'en');
|
||||||
|
|
||||||
$this->assertEquals(3, $this->manifest->getAllVersionsOfEntity($entity)->count());
|
$this->assertEquals(3, $this->manifest->getAllVersionsOfEntity($entity)->count());
|
||||||
|
|
||||||
$entity = $this->manifest->getEntities()->find('Language', 'de');
|
$entity = $this->manifest->getEntities()->find('Language', 'de');
|
||||||
|
|
||||||
$this->assertEquals(1, $this->manifest->getAllVersionsOfEntity($entity)->count());
|
$this->assertEquals(1, $this->manifest->getAllVersionsOfEntity($entity)->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetStableVersion() {
|
public function testGetStableVersion()
|
||||||
$this->markTestIncomplete();
|
{
|
||||||
}
|
$this->markTestIncomplete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,87 +4,90 @@
|
|||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
class DocumentationPageTest extends SapphireTest {
|
class DocumentationPageTest extends SapphireTest
|
||||||
|
{
|
||||||
|
protected $entity;
|
||||||
|
|
||||||
protected $entity;
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
public function setUp() {
|
$this->entity = new DocumentationEntity('doctest');
|
||||||
parent::setUp();
|
$this->entity->setPath(DOCSVIEWER_PATH . '/tests/docs/en/');
|
||||||
|
$this->entity->setVersion('2.4');
|
||||||
|
$this->entity->setLanguage('en');
|
||||||
|
|
||||||
$this->entity = new DocumentationEntity('doctest');
|
Config::nest();
|
||||||
$this->entity->setPath(DOCSVIEWER_PATH . '/tests/docs/en/');
|
|
||||||
$this->entity->setVersion('2.4');
|
|
||||||
$this->entity->setLanguage('en');
|
|
||||||
|
|
||||||
Config::nest();
|
// explicitly use dev/docs. Custom paths should be tested separately
|
||||||
|
Config::inst()->update(
|
||||||
|
'DocumentationViewer', 'link_base', 'dev/docs/'
|
||||||
|
);
|
||||||
|
|
||||||
// explicitly use dev/docs. Custom paths should be tested separately
|
$manifest = new DocumentationManifest(true);
|
||||||
Config::inst()->update(
|
}
|
||||||
'DocumentationViewer', 'link_base', 'dev/docs/'
|
|
||||||
);
|
|
||||||
|
|
||||||
$manifest = new DocumentationManifest(true);
|
public function tearDown()
|
||||||
}
|
{
|
||||||
|
parent::tearDown();
|
||||||
|
|
||||||
public function tearDown() {
|
Config::unnest();
|
||||||
parent::tearDown();
|
}
|
||||||
|
|
||||||
Config::unnest();
|
public function testGetLink()
|
||||||
}
|
{
|
||||||
|
$page = new DocumentationPage(
|
||||||
|
$this->entity,
|
||||||
|
'test.md',
|
||||||
|
DOCSVIEWER_PATH . '/tests/docs/en/test.md'
|
||||||
|
);
|
||||||
|
|
||||||
public function testGetLink() {
|
// single layer
|
||||||
$page = new DocumentationPage(
|
$this->assertEquals('dev/docs/en/doctest/2.4/test/', $page->Link(),
|
||||||
$this->entity,
|
'The page link should have no extension and have a language'
|
||||||
'test.md',
|
);
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/test.md'
|
|
||||||
);
|
|
||||||
|
|
||||||
// single layer
|
$page = new DocumentationFolder(
|
||||||
$this->assertEquals('dev/docs/en/doctest/2.4/test/', $page->Link(),
|
$this->entity,
|
||||||
'The page link should have no extension and have a language'
|
'sort',
|
||||||
);
|
DOCSVIEWER_PATH . '/tests/docs/en/sort/'
|
||||||
|
);
|
||||||
|
|
||||||
$page = new DocumentationFolder(
|
$this->assertEquals('dev/docs/en/doctest/2.4/sort/', $page->Link());
|
||||||
$this->entity,
|
|
||||||
'sort',
|
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/sort/'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->assertEquals('dev/docs/en/doctest/2.4/sort/', $page->Link());
|
$page = new DocumentationFolder(
|
||||||
|
$this->entity,
|
||||||
|
'1-basic.md',
|
||||||
|
DOCSVIEWER_PATH . '/tests/docs/en/sort/1-basic.md'
|
||||||
|
);
|
||||||
|
|
||||||
$page = new DocumentationFolder(
|
$this->assertEquals('dev/docs/en/doctest/2.4/sort/basic/', $page->Link());
|
||||||
$this->entity,
|
}
|
||||||
'1-basic.md',
|
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/sort/1-basic.md'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->assertEquals('dev/docs/en/doctest/2.4/sort/basic/', $page->Link());
|
public function testGetBreadcrumbTitle()
|
||||||
}
|
{
|
||||||
|
$page = new DocumentationPage(
|
||||||
|
$this->entity,
|
||||||
|
'test.md',
|
||||||
|
DOCSVIEWER_PATH . '/tests/docs/en/test.md'
|
||||||
|
);
|
||||||
|
|
||||||
public function testGetBreadcrumbTitle() {
|
$this->assertEquals("Test - Doctest", $page->getBreadcrumbTitle());
|
||||||
$page = new DocumentationPage(
|
|
||||||
$this->entity,
|
|
||||||
'test.md',
|
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/test.md'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->assertEquals("Test - Doctest", $page->getBreadcrumbTitle());
|
$page = new DocumentationFolder(
|
||||||
|
$this->entity,
|
||||||
|
'1-basic.md',
|
||||||
|
DOCSVIEWER_PATH . '/tests/docs/en/sort/1-basic.md'
|
||||||
|
);
|
||||||
|
|
||||||
$page = new DocumentationFolder(
|
$this->assertEquals('Basic - Sort - Doctest', $page->getBreadcrumbTitle());
|
||||||
$this->entity,
|
|
||||||
'1-basic.md',
|
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/sort/1-basic.md'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->assertEquals('Basic - Sort - Doctest', $page->getBreadcrumbTitle());
|
$page = new DocumentationFolder(
|
||||||
|
$this->entity,
|
||||||
|
'',
|
||||||
|
DOCSVIEWER_PATH . '/tests/docs/en/sort/'
|
||||||
|
);
|
||||||
|
|
||||||
$page = new DocumentationFolder(
|
$this->assertEquals('Sort - Doctest', $page->getBreadcrumbTitle());
|
||||||
$this->entity,
|
}
|
||||||
'',
|
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/sort/'
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->assertEquals('Sort - Doctest', $page->getBreadcrumbTitle());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -4,87 +4,90 @@
|
|||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
class DocumentationParserTest extends SapphireTest {
|
class DocumentationParserTest extends SapphireTest
|
||||||
|
{
|
||||||
|
protected $entity, $entityAlt, $page, $subPage, $subSubPage, $filePage, $metaDataPage, $indexPage;
|
||||||
|
|
||||||
protected $entity, $entityAlt, $page, $subPage, $subSubPage, $filePage, $metaDataPage, $indexPage;
|
public function tearDown()
|
||||||
|
{
|
||||||
|
parent::tearDown();
|
||||||
|
|
||||||
public function tearDown() {
|
Config::unnest();
|
||||||
parent::tearDown();
|
}
|
||||||
|
|
||||||
Config::unnest();
|
public function setUp()
|
||||||
}
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
public function setUp() {
|
Config::nest();
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
Config::nest();
|
// explicitly use dev/docs. Custom paths should be tested separately
|
||||||
|
Config::inst()->update(
|
||||||
|
'DocumentationViewer', 'link_base', 'dev/docs/'
|
||||||
|
);
|
||||||
|
|
||||||
// explicitly use dev/docs. Custom paths should be tested separately
|
$this->entity = new DocumentationEntity('DocumentationParserTest');
|
||||||
Config::inst()->update(
|
$this->entity->setPath(DOCSVIEWER_PATH . '/tests/docs/en/');
|
||||||
'DocumentationViewer', 'link_base', 'dev/docs/'
|
$this->entity->setVersion('2.4');
|
||||||
);
|
$this->entity->setLanguage('en');
|
||||||
|
|
||||||
$this->entity = new DocumentationEntity('DocumentationParserTest');
|
|
||||||
$this->entity->setPath(DOCSVIEWER_PATH . '/tests/docs/en/');
|
|
||||||
$this->entity->setVersion('2.4');
|
|
||||||
$this->entity->setLanguage('en');
|
|
||||||
|
|
||||||
|
|
||||||
$this->entityAlt = new DocumentationEntity('DocumentationParserParserTest');
|
$this->entityAlt = new DocumentationEntity('DocumentationParserParserTest');
|
||||||
$this->entityAlt->setPath(DOCSVIEWER_PATH . '/tests/docs-parser/en/');
|
$this->entityAlt->setPath(DOCSVIEWER_PATH . '/tests/docs-parser/en/');
|
||||||
$this->entityAlt->setVersion('2.4');
|
$this->entityAlt->setVersion('2.4');
|
||||||
$this->entityAlt->setLanguage('en');
|
$this->entityAlt->setLanguage('en');
|
||||||
|
|
||||||
$this->page = new DocumentationPage(
|
$this->page = new DocumentationPage(
|
||||||
$this->entity,
|
$this->entity,
|
||||||
'test.md',
|
'test.md',
|
||||||
DOCSVIEWER_PATH . '/tests/docs/en/test.md'
|
DOCSVIEWER_PATH . '/tests/docs/en/test.md'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->subPage = new DocumentationPage(
|
$this->subPage = new DocumentationPage(
|
||||||
$this->entity,
|
$this->entity,
|
||||||
'subpage.md',
|
'subpage.md',
|
||||||
DOCSVIEWER_PATH. '/tests/docs/en/subfolder/subpage.md'
|
DOCSVIEWER_PATH. '/tests/docs/en/subfolder/subpage.md'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->subSubPage = new DocumentationPage(
|
$this->subSubPage = new DocumentationPage(
|
||||||
$this->entity,
|
$this->entity,
|
||||||
'subsubpage.md',
|
'subsubpage.md',
|
||||||
DOCSVIEWER_PATH. '/tests/docs/en/subfolder/subsubfolder/subsubpage.md'
|
DOCSVIEWER_PATH. '/tests/docs/en/subfolder/subsubfolder/subsubpage.md'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->filePage = new DocumentationPage(
|
$this->filePage = new DocumentationPage(
|
||||||
$this->entityAlt,
|
$this->entityAlt,
|
||||||
'file-download.md',
|
'file-download.md',
|
||||||
DOCSVIEWER_PATH . '/tests/docs-parser/en/file-download.md'
|
DOCSVIEWER_PATH . '/tests/docs-parser/en/file-download.md'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->metaDataPage = new DocumentationPage(
|
$this->metaDataPage = new DocumentationPage(
|
||||||
$this->entityAlt,
|
$this->entityAlt,
|
||||||
'MetaDataTest.md',
|
'MetaDataTest.md',
|
||||||
DOCSVIEWER_PATH . '/tests/docs-parser/en/MetaDataTest.md'
|
DOCSVIEWER_PATH . '/tests/docs-parser/en/MetaDataTest.md'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->indexPage = new DocumentationPage(
|
$this->indexPage = new DocumentationPage(
|
||||||
$this->entity,
|
$this->entity,
|
||||||
'index.md',
|
'index.md',
|
||||||
DOCSVIEWER_PATH. '/tests/docs/en/index.md'
|
DOCSVIEWER_PATH. '/tests/docs/en/index.md'
|
||||||
);
|
);
|
||||||
|
|
||||||
$manifest = new DocumentationManifest(true);
|
$manifest = new DocumentationManifest(true);
|
||||||
}
|
}
|
||||||
public function testRewriteCodeBlocks() {
|
public function testRewriteCodeBlocks()
|
||||||
$codePage = new DocumentationPage(
|
{
|
||||||
$this->entityAlt,
|
$codePage = new DocumentationPage(
|
||||||
'CodeSnippets.md',
|
$this->entityAlt,
|
||||||
DOCSVIEWER_PATH . '/tests/docs-parser/en/CodeSnippets.md'
|
'CodeSnippets.md',
|
||||||
);
|
DOCSVIEWER_PATH . '/tests/docs-parser/en/CodeSnippets.md'
|
||||||
|
);
|
||||||
|
|
||||||
$result = DocumentationParser::rewrite_code_blocks(
|
$result = DocumentationParser::rewrite_code_blocks(
|
||||||
$codePage->getMarkdown()
|
$codePage->getMarkdown()
|
||||||
);
|
);
|
||||||
|
|
||||||
$expected = <<<HTML
|
$expected = <<<HTML
|
||||||
#### <% control Foo %>
|
#### <% control Foo %>
|
||||||
```
|
```
|
||||||
code block
|
code block
|
||||||
@ -112,13 +115,13 @@ baz: qux
|
|||||||
```
|
```
|
||||||
HTML;
|
HTML;
|
||||||
|
|
||||||
$this->assertEquals($expected, $result, 'Code blocks support line breaks');
|
$this->assertEquals($expected, $result, 'Code blocks support line breaks');
|
||||||
|
|
||||||
$result = DocumentationParser::rewrite_code_blocks(
|
$result = DocumentationParser::rewrite_code_blocks(
|
||||||
$this->page->getMarkdown()
|
$this->page->getMarkdown()
|
||||||
);
|
);
|
||||||
|
|
||||||
$expected = <<<HTML
|
$expected = <<<HTML
|
||||||
```php
|
```php
|
||||||
code block
|
code block
|
||||||
with multiple
|
with multiple
|
||||||
@ -130,24 +133,24 @@ lines
|
|||||||
Normal text after code block
|
Normal text after code block
|
||||||
HTML;
|
HTML;
|
||||||
|
|
||||||
$this->assertContains($expected, $result, 'Custom code blocks with ::: prefix');
|
$this->assertContains($expected, $result, 'Custom code blocks with ::: prefix');
|
||||||
|
|
||||||
$expected = <<<HTML
|
$expected = <<<HTML
|
||||||
```
|
```
|
||||||
code block
|
code block
|
||||||
without formatting prefix
|
without formatting prefix
|
||||||
```
|
```
|
||||||
HTML;
|
HTML;
|
||||||
$this->assertContains($expected, $result, 'Traditional markdown code blocks');
|
$this->assertContains($expected, $result, 'Traditional markdown code blocks');
|
||||||
|
|
||||||
$expected = <<<HTML
|
$expected = <<<HTML
|
||||||
```
|
```
|
||||||
Fenced code block
|
Fenced code block
|
||||||
```
|
```
|
||||||
HTML;
|
HTML;
|
||||||
$this->assertContains($expected, $result, 'Backtick code blocks');
|
$this->assertContains($expected, $result, 'Backtick code blocks');
|
||||||
|
|
||||||
$expected = <<<HTML
|
$expected = <<<HTML
|
||||||
```php
|
```php
|
||||||
Fenced box with
|
Fenced box with
|
||||||
|
|
||||||
@ -158,227 +161,232 @@ between
|
|||||||
content
|
content
|
||||||
```
|
```
|
||||||
HTML;
|
HTML;
|
||||||
$this->assertContains($expected, $result, 'Backtick with newlines');
|
$this->assertContains($expected, $result, 'Backtick with newlines');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRelativeLinks() {
|
public function testRelativeLinks()
|
||||||
// index.md
|
{
|
||||||
$result = DocumentationParser::rewrite_relative_links(
|
// index.md
|
||||||
$this->indexPage->getMarkdown(),
|
$result = DocumentationParser::rewrite_relative_links(
|
||||||
$this->indexPage
|
$this->indexPage->getMarkdown(),
|
||||||
);
|
$this->indexPage
|
||||||
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: subfolder index](dev/docs/en/documentationparsertest/2.4/subfolder/)',
|
'[link: subfolder index](dev/docs/en/documentationparsertest/2.4/subfolder/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
|
|
||||||
// test.md
|
// test.md
|
||||||
|
|
||||||
$result = DocumentationParser::rewrite_relative_links(
|
$result = DocumentationParser::rewrite_relative_links(
|
||||||
$this->page->getMarkdown(),
|
$this->page->getMarkdown(),
|
||||||
$this->page
|
$this->page
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: subfolder index](dev/docs/en/documentationparsertest/2.4/subfolder/)',
|
'[link: subfolder index](dev/docs/en/documentationparsertest/2.4/subfolder/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: subfolder page](dev/docs/en/documentationparsertest/2.4/subfolder/subpage/)',
|
'[link: subfolder page](dev/docs/en/documentationparsertest/2.4/subfolder/subpage/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: http](http://silverstripe.org)',
|
'[link: http](http://silverstripe.org)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: api](api:DataObject)',
|
'[link: api](api:DataObject)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
$result = DocumentationParser::rewrite_relative_links(
|
$result = DocumentationParser::rewrite_relative_links(
|
||||||
$this->subPage->getMarkdown(),
|
$this->subPage->getMarkdown(),
|
||||||
$this->subPage
|
$this->subPage
|
||||||
);
|
);
|
||||||
|
|
||||||
# @todo this should redirect to /subpage/
|
# @todo this should redirect to /subpage/
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: relative](dev/docs/en/documentationparsertest/2.4/subfolder/subpage.md/)',
|
'[link: relative](dev/docs/en/documentationparsertest/2.4/subfolder/subpage.md/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: absolute index](dev/docs/en/documentationparsertest/2.4/)',
|
'[link: absolute index](dev/docs/en/documentationparsertest/2.4/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
|
|
||||||
# @todo this should redirect to /
|
# @todo this should redirect to /
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: absolute index with name](dev/docs/en/documentationparsertest/2.4/index/)',
|
'[link: absolute index with name](dev/docs/en/documentationparsertest/2.4/index/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: relative index](dev/docs/en/documentationparsertest/2.4/)',
|
'[link: relative index](dev/docs/en/documentationparsertest/2.4/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: relative parent page](dev/docs/en/documentationparsertest/2.4/test/)',
|
'[link: relative parent page](dev/docs/en/documentationparsertest/2.4/test/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: absolute parent page](dev/docs/en/documentationparsertest/2.4/test/)',
|
'[link: absolute parent page](dev/docs/en/documentationparsertest/2.4/test/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
|
|
||||||
$result = DocumentationParser::rewrite_relative_links(
|
$result = DocumentationParser::rewrite_relative_links(
|
||||||
$this->subSubPage->getMarkdown(),
|
$this->subSubPage->getMarkdown(),
|
||||||
$this->subSubPage
|
$this->subSubPage
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: absolute index](dev/docs/en/documentationparsertest/2.4/)',
|
'[link: absolute index](dev/docs/en/documentationparsertest/2.4/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: relative index](dev/docs/en/documentationparsertest/2.4/subfolder/)',
|
'[link: relative index](dev/docs/en/documentationparsertest/2.4/subfolder/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: relative parent page](dev/docs/en/documentationparsertest/2.4/subfolder/subpage/)',
|
'[link: relative parent page](dev/docs/en/documentationparsertest/2.4/subfolder/subpage/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: relative grandparent page](dev/docs/en/documentationparsertest/2.4/test/)',
|
'[link: relative grandparent page](dev/docs/en/documentationparsertest/2.4/test/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
'[link: absolute page](dev/docs/en/documentationparsertest/2.4/test/)',
|
'[link: absolute page](dev/docs/en/documentationparsertest/2.4/test/)',
|
||||||
$result
|
$result
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGenerateHtmlId() {
|
public function testGenerateHtmlId()
|
||||||
$this->assertEquals('title-one', DocumentationParser::generate_html_id('title one'));
|
{
|
||||||
$this->assertEquals('title-one', DocumentationParser::generate_html_id('Title one'));
|
$this->assertEquals('title-one', DocumentationParser::generate_html_id('title one'));
|
||||||
$this->assertEquals('title-and-one', DocumentationParser::generate_html_id('Title & One'));
|
$this->assertEquals('title-one', DocumentationParser::generate_html_id('Title one'));
|
||||||
$this->assertEquals('title-and-one', DocumentationParser::generate_html_id('Title & One'));
|
$this->assertEquals('title-and-one', DocumentationParser::generate_html_id('Title & One'));
|
||||||
$this->assertEquals('title-one', DocumentationParser::generate_html_id(' Title one '));
|
$this->assertEquals('title-and-one', DocumentationParser::generate_html_id('Title & One'));
|
||||||
$this->assertEquals('title-one', DocumentationParser::generate_html_id('Title--one'));
|
$this->assertEquals('title-one', DocumentationParser::generate_html_id(' Title one '));
|
||||||
}
|
$this->assertEquals('title-one', DocumentationParser::generate_html_id('Title--one'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function testImageRewrites() {
|
public function testImageRewrites()
|
||||||
|
{
|
||||||
|
$result = DocumentationParser::rewrite_image_links(
|
||||||
|
$this->subPage->getMarkdown(),
|
||||||
|
$this->subPage
|
||||||
|
);
|
||||||
|
|
||||||
$result = DocumentationParser::rewrite_image_links(
|
$expected = Controller::join_links(
|
||||||
$this->subPage->getMarkdown(),
|
Director::absoluteBaseURL(), DOCSVIEWER_DIR, '/tests/docs/en/subfolder/_images/image.png'
|
||||||
$this->subPage
|
);
|
||||||
);
|
|
||||||
|
|
||||||
$expected = Controller::join_links(
|
$this->assertContains(
|
||||||
Director::absoluteBaseURL(), DOCSVIEWER_DIR, '/tests/docs/en/subfolder/_images/image.png'
|
sprintf('[relative image link](%s)', $expected),
|
||||||
);
|
$result
|
||||||
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
sprintf('[relative image link](%s)', $expected),
|
sprintf('[parent image link](%s)', Controller::join_links(
|
||||||
$result
|
Director::absoluteBaseURL(), DOCSVIEWER_DIR, '/tests/docs/en/_images/image.png'
|
||||||
);
|
)),
|
||||||
|
$result
|
||||||
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$expected = Controller::join_links(
|
||||||
sprintf('[parent image link](%s)', Controller::join_links(
|
Director::absoluteBaseURL(), DOCSVIEWER_DIR, '/tests/docs/en/_images/image.png'
|
||||||
Director::absoluteBaseURL(), DOCSVIEWER_DIR, '/tests/docs/en/_images/image.png'
|
);
|
||||||
)),
|
|
||||||
$result
|
|
||||||
);
|
|
||||||
|
|
||||||
$expected = Controller::join_links(
|
$this->assertContains(
|
||||||
Director::absoluteBaseURL(), DOCSVIEWER_DIR, '/tests/docs/en/_images/image.png'
|
sprintf('[absolute image link](%s)', $expected),
|
||||||
);
|
$result
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$this->assertContains(
|
public function testApiLinks()
|
||||||
sprintf('[absolute image link](%s)', $expected),
|
{
|
||||||
$result
|
$result = DocumentationParser::rewrite_api_links(
|
||||||
);
|
$this->page->getMarkdown(),
|
||||||
}
|
$this->page
|
||||||
|
);
|
||||||
|
|
||||||
public function testApiLinks() {
|
$this->assertContains(
|
||||||
$result = DocumentationParser::rewrite_api_links(
|
'[link: api](http://api.silverstripe.org/search/lookup/?q=DataObject&version=2.4&module=documentationparsertest)',
|
||||||
$this->page->getMarkdown(),
|
$result
|
||||||
$this->page
|
);
|
||||||
);
|
$this->assertContains(
|
||||||
|
'[DataObject::$has_one](http://api.silverstripe.org/search/lookup/?q=DataObject::$has_one&version=2.4&module=documentationparsertest)',
|
||||||
|
$result
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$this->assertContains(
|
public function testHeadlineAnchors()
|
||||||
'[link: api](http://api.silverstripe.org/search/lookup/?q=DataObject&version=2.4&module=documentationparsertest)',
|
{
|
||||||
$result
|
$result = DocumentationParser::rewrite_heading_anchors(
|
||||||
);
|
$this->page->getMarkdown(),
|
||||||
$this->assertContains(
|
$this->page
|
||||||
'[DataObject::$has_one](http://api.silverstripe.org/search/lookup/?q=DataObject::$has_one&version=2.4&module=documentationparsertest)',
|
);
|
||||||
$result
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testHeadlineAnchors() {
|
/*
|
||||||
$result = DocumentationParser::rewrite_heading_anchors(
|
# Heading one {#Heading-one}
|
||||||
$this->page->getMarkdown(),
|
|
||||||
$this->page
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
# Heading with custom anchor {#custom-anchor} {#Heading-with-custom-anchor-custom-anchor}
|
||||||
# Heading one {#Heading-one}
|
|
||||||
|
|
||||||
# Heading with custom anchor {#custom-anchor} {#Heading-with-custom-anchor-custom-anchor}
|
## Heading two {#Heading-two}
|
||||||
|
|
||||||
## Heading two {#Heading-two}
|
### Heading three {#Heading-three}
|
||||||
|
|
||||||
### Heading three {#Heading-three}
|
## Heading duplicate {#Heading-duplicate}
|
||||||
|
|
||||||
## Heading duplicate {#Heading-duplicate}
|
## Heading duplicate {#Heading-duplicate-2}
|
||||||
|
|
||||||
## Heading duplicate {#Heading-duplicate-2}
|
## Heading duplicate {#Heading-duplicate-3}
|
||||||
|
|
||||||
## Heading duplicate {#Heading-duplicate-3}
|
*/
|
||||||
|
|
||||||
*/
|
$this->assertContains('# Heading one {#heading-one}', $result);
|
||||||
|
$this->assertContains('# Heading with custom anchor {#custom-anchor}', $result);
|
||||||
$this->assertContains('# Heading one {#heading-one}', $result);
|
$this->assertNotContains('# Heading with custom anchor {#custom-anchor} {#heading', $result);
|
||||||
$this->assertContains('# Heading with custom anchor {#custom-anchor}', $result);
|
$this->assertContains('# Heading two {#heading-two}', $result);
|
||||||
$this->assertNotContains('# Heading with custom anchor {#custom-anchor} {#heading', $result);
|
$this->assertContains('# Heading three {#heading-three}', $result);
|
||||||
$this->assertContains('# Heading two {#heading-two}', $result);
|
$this->assertContains('## Heading duplicate {#heading-duplicate}', $result);
|
||||||
$this->assertContains('# Heading three {#heading-three}', $result);
|
$this->assertContains('## Heading duplicate {#heading-duplicate-2}', $result);
|
||||||
$this->assertContains('## Heading duplicate {#heading-duplicate}', $result);
|
$this->assertContains('## Heading duplicate {#heading-duplicate-3}', $result);
|
||||||
$this->assertContains('## Heading duplicate {#heading-duplicate-2}', $result);
|
}
|
||||||
$this->assertContains('## Heading duplicate {#heading-duplicate-3}', $result);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function testRetrieveMetaData() {
|
public function testRetrieveMetaData()
|
||||||
DocumentationParser::retrieve_meta_data($this->metaDataPage);
|
{
|
||||||
|
DocumentationParser::retrieve_meta_data($this->metaDataPage);
|
||||||
|
|
||||||
$this->assertEquals('Dr. Foo Bar.', $this->metaDataPage->author);
|
$this->assertEquals('Dr. Foo Bar.', $this->metaDataPage->author);
|
||||||
$this->assertEquals("Foo Bar's Test page.", $this->metaDataPage->getTitle());
|
$this->assertEquals("Foo Bar's Test page.", $this->metaDataPage->getTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRewritingRelativeLinksToFiles() {
|
public function testRewritingRelativeLinksToFiles()
|
||||||
$parsed = DocumentationParser::parse($this->filePage);
|
{
|
||||||
|
$parsed = DocumentationParser::parse($this->filePage);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
DOCSVIEWER_DIR .'/tests/docs-parser/en/_images/external_link.png',
|
DOCSVIEWER_DIR .'/tests/docs-parser/en/_images/external_link.png',
|
||||||
$parsed
|
$parsed
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertContains(
|
$this->assertContains(
|
||||||
DOCSVIEWER_DIR .'/tests/docs-parser/en/_images/test.tar.gz',
|
DOCSVIEWER_DIR .'/tests/docs-parser/en/_images/test.tar.gz',
|
||||||
$parsed
|
$parsed
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,40 +4,42 @@
|
|||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
class DocumentationPermalinksTest extends FunctionalTest {
|
class DocumentationPermalinksTest extends FunctionalTest
|
||||||
|
{
|
||||||
|
public function testSavingAndAccessingMapping()
|
||||||
|
{
|
||||||
|
// basic test
|
||||||
|
DocumentationPermalinks::add(array(
|
||||||
|
'foo' => 'en/framework/subfolder/foo',
|
||||||
|
'bar' => 'en/cms/bar'
|
||||||
|
));
|
||||||
|
|
||||||
public function testSavingAndAccessingMapping() {
|
$this->assertEquals('en/framework/subfolder/foo',
|
||||||
// basic test
|
DocumentationPermalinks::map('foo')
|
||||||
DocumentationPermalinks::add(array(
|
);
|
||||||
'foo' => 'en/framework/subfolder/foo',
|
|
||||||
'bar' => 'en/cms/bar'
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->assertEquals('en/framework/subfolder/foo',
|
$this->assertEquals('en/cms/bar',
|
||||||
DocumentationPermalinks::map('foo')
|
DocumentationPermalinks::map('bar')
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$this->assertEquals('en/cms/bar',
|
/**
|
||||||
DocumentationPermalinks::map('bar')
|
* Tests to make sure short codes get translated to full paths.
|
||||||
);
|
*
|
||||||
}
|
*/
|
||||||
|
public function testRedirectingMapping()
|
||||||
|
{
|
||||||
|
DocumentationPermalinks::add(array(
|
||||||
|
'foo' => 'en/framework/subfolder/foo',
|
||||||
|
'bar' => 'en/cms/bar'
|
||||||
|
));
|
||||||
|
|
||||||
/**
|
$this->autoFollowRedirection = false;
|
||||||
* Tests to make sure short codes get translated to full paths.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function testRedirectingMapping() {
|
|
||||||
DocumentationPermalinks::add(array(
|
|
||||||
'foo' => 'en/framework/subfolder/foo',
|
|
||||||
'bar' => 'en/cms/bar'
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->autoFollowRedirection = false;
|
$v = new DocumentationViewer();
|
||||||
|
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'foo'), DataModel::inst());
|
||||||
|
|
||||||
$v = new DocumentationViewer();
|
$this->assertEquals('301', $response->getStatusCode());
|
||||||
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'foo'), DataModel::inst());
|
$this->assertContains('en/framework/subfolder/foo', $response->getHeader('Location'));
|
||||||
|
}
|
||||||
$this->assertEquals('301', $response->getStatusCode());
|
|
||||||
$this->assertContains('en/framework/subfolder/foo', $response->getHeader('Location'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -5,62 +5,65 @@
|
|||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DocumentationSearchTest extends FunctionalTest {
|
class DocumentationSearchTest extends FunctionalTest
|
||||||
|
{
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
public function setUp() {
|
Config::nest();
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
Config::nest();
|
// explicitly use dev/docs. Custom paths should be tested separately
|
||||||
|
Config::inst()->update(
|
||||||
|
'DocumentationViewer', 'link_base', 'dev/docs'
|
||||||
|
);
|
||||||
|
|
||||||
// explicitly use dev/docs. Custom paths should be tested separately
|
// disable automatic module registration so modules don't interfere.
|
||||||
Config::inst()->update(
|
Config::inst()->update(
|
||||||
'DocumentationViewer', 'link_base', 'dev/docs'
|
'DocumentationManifest', 'automatic_registration', false
|
||||||
);
|
);
|
||||||
|
|
||||||
// disable automatic module registration so modules don't interfere.
|
Config::inst()->remove('DocumentationManifest', 'register_entities');
|
||||||
Config::inst()->update(
|
Config::inst()->update('DocumentationSearch', 'enabled', true);
|
||||||
'DocumentationManifest', 'automatic_registration', false
|
Config::inst()->update(
|
||||||
);
|
'DocumentationManifest', 'register_entities', array(
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs-search/",
|
||||||
|
'Title' => 'Docs Search Test', )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
Config::inst()->remove('DocumentationManifest', 'register_entities');
|
$this->manifest = new DocumentationManifest(true);
|
||||||
Config::inst()->update('DocumentationSearch', 'enabled', true);
|
}
|
||||||
Config::inst()->update(
|
|
||||||
'DocumentationManifest', 'register_entities', array(
|
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs-search/",
|
|
||||||
'Title' => 'Docs Search Test', )
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->manifest = new DocumentationManifest(true);
|
public function tearDown()
|
||||||
}
|
{
|
||||||
|
parent::tearDown();
|
||||||
|
|
||||||
public function tearDown() {
|
Config::unnest();
|
||||||
parent::tearDown();
|
}
|
||||||
|
|
||||||
Config::unnest();
|
public function testOpenSearchControllerAccessible()
|
||||||
}
|
{
|
||||||
|
$c = new DocumentationOpenSearchController();
|
||||||
|
$response = $c->handleRequest(new SS_HTTPRequest('GET', ''), DataModel::inst());
|
||||||
|
$this->assertEquals(404, $response->getStatusCode());
|
||||||
|
|
||||||
public function testOpenSearchControllerAccessible() {
|
Config::inst()->update('DocumentationSearch', 'enabled', false);
|
||||||
$c = new DocumentationOpenSearchController();
|
|
||||||
$response = $c->handleRequest(new SS_HTTPRequest('GET', ''), DataModel::inst());
|
|
||||||
$this->assertEquals(404, $response->getStatusCode());
|
|
||||||
|
|
||||||
Config::inst()->update('DocumentationSearch', 'enabled', false);
|
$response = $c->handleRequest(new SS_HTTPRequest('GET', 'description/'), DataModel::inst());
|
||||||
|
$this->assertEquals(404, $response->getStatusCode());
|
||||||
|
|
||||||
$response = $c->handleRequest(new SS_HTTPRequest('GET', 'description/'), DataModel::inst());
|
// test we get a response to the description. The meta data test will
|
||||||
$this->assertEquals(404, $response->getStatusCode());
|
// check that the individual fields are valid but we should check urls
|
||||||
|
// are there
|
||||||
|
|
||||||
// test we get a response to the description. The meta data test will
|
Config::inst()->update('DocumentationSearch', 'enabled', true);
|
||||||
// check that the individual fields are valid but we should check urls
|
|
||||||
// are there
|
|
||||||
|
|
||||||
Config::inst()->update('DocumentationSearch', 'enabled', true);
|
$response = $c->handleRequest(new SS_HTTPRequest('GET', 'description'), DataModel::inst());
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
|
||||||
$response = $c->handleRequest(new SS_HTTPRequest('GET', 'description'), DataModel::inst());
|
$desc = new SimpleXMLElement($response->getBody());
|
||||||
$this->assertEquals(200, $response->getStatusCode());
|
$this->assertEquals(2, count($desc->Url));
|
||||||
|
}
|
||||||
$desc = new SimpleXMLElement($response->getBody());
|
|
||||||
$this->assertEquals(2, count($desc->Url));
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -8,208 +8,213 @@
|
|||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DocumentationViewerTest extends FunctionalTest {
|
class DocumentationViewerTest extends FunctionalTest
|
||||||
|
{
|
||||||
|
protected $autoFollowRedirection = false;
|
||||||
|
|
||||||
protected $autoFollowRedirection = false;
|
protected $manifest;
|
||||||
|
|
||||||
protected $manifest;
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
public function setUp() {
|
Config::nest();
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
Config::nest();
|
// explicitly use dev/docs. Custom paths should be tested separately
|
||||||
|
Config::inst()->update(
|
||||||
|
'DocumentationViewer', 'link_base', 'dev/docs/'
|
||||||
|
);
|
||||||
|
|
||||||
// explicitly use dev/docs. Custom paths should be tested separately
|
// disable automatic module registration so modules don't interfere.
|
||||||
Config::inst()->update(
|
Config::inst()->update(
|
||||||
'DocumentationViewer', 'link_base', 'dev/docs/'
|
'DocumentationManifest', 'automatic_registration', false
|
||||||
);
|
);
|
||||||
|
|
||||||
// disable automatic module registration so modules don't interfere.
|
Config::inst()->remove('DocumentationManifest', 'register_entities');
|
||||||
Config::inst()->update(
|
|
||||||
'DocumentationManifest', 'automatic_registration', false
|
|
||||||
);
|
|
||||||
|
|
||||||
Config::inst()->remove('DocumentationManifest', 'register_entities');
|
Config::inst()->update(
|
||||||
|
'DocumentationManifest', 'register_entities', array(
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs/",
|
||||||
|
'Title' => 'Doc Test',
|
||||||
|
'Version' => '2.3'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs-v2.4/",
|
||||||
|
'Title' => 'Doc Test',
|
||||||
|
'Version' => '2.4',
|
||||||
|
'Stable' => true
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs-v3.0/",
|
||||||
|
'Title' => 'Doc Test',
|
||||||
|
'Version' => '3.0'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs-parser/",
|
||||||
|
'Title' => 'DocumentationViewerAltModule1'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs-search/",
|
||||||
|
'Title' => 'DocumentationViewerAltModule2'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
Config::inst()->update(
|
Config::inst()->update('SSViewer', 'theme_enabled', false);
|
||||||
'DocumentationManifest', 'register_entities', array(
|
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs/",
|
|
||||||
'Title' => 'Doc Test',
|
|
||||||
'Version' => '2.3'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs-v2.4/",
|
|
||||||
'Title' => 'Doc Test',
|
|
||||||
'Version' => '2.4',
|
|
||||||
'Stable' => true
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs-v3.0/",
|
|
||||||
'Title' => 'Doc Test',
|
|
||||||
'Version' => '3.0'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs-parser/",
|
|
||||||
'Title' => 'DocumentationViewerAltModule1'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs-search/",
|
|
||||||
'Title' => 'DocumentationViewerAltModule2'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
Config::inst()->update('SSViewer', 'theme_enabled', false);
|
$this->manifest = new DocumentationManifest(true);
|
||||||
|
}
|
||||||
|
|
||||||
$this->manifest = new DocumentationManifest(true);
|
public function tearDown()
|
||||||
}
|
{
|
||||||
|
parent::tearDown();
|
||||||
|
|
||||||
public function tearDown() {
|
Config::unnest();
|
||||||
parent::tearDown();
|
}
|
||||||
|
|
||||||
Config::unnest();
|
/**
|
||||||
}
|
* This tests that all the locations will exist if we access it via the urls.
|
||||||
|
*/
|
||||||
|
public function testLocationsExists()
|
||||||
|
{
|
||||||
|
$this->autoFollowRedirection = false;
|
||||||
|
|
||||||
/**
|
$response = $this->get('dev/docs/en/doc_test/2.3/subfolder/');
|
||||||
* This tests that all the locations will exist if we access it via the urls.
|
$this->assertEquals($response->getStatusCode(), 200, 'Existing base folder');
|
||||||
*/
|
|
||||||
public function testLocationsExists() {
|
|
||||||
$this->autoFollowRedirection = false;
|
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/2.3/subfolder/');
|
$response = $this->get('dev/docs/en/doc_test/2.3/subfolder/subsubfolder/');
|
||||||
$this->assertEquals($response->getStatusCode(), 200, 'Existing base folder');
|
$this->assertEquals($response->getStatusCode(), 200, 'Existing base folder');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/2.3/subfolder/subsubfolder/');
|
$response = $this->get('dev/docs/en/doc_test/2.3/subfolder/subsubfolder/subsubpage/');
|
||||||
$this->assertEquals($response->getStatusCode(), 200, 'Existing base folder');
|
$this->assertEquals($response->getStatusCode(), 200, 'Existing base folder');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/2.3/subfolder/subsubfolder/subsubpage/');
|
$response = $this->get('dev/docs/en/');
|
||||||
$this->assertEquals($response->getStatusCode(), 200, 'Existing base folder');
|
$this->assertEquals($response->getStatusCode(), 200, 'Lists the home index');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/');
|
$response = $this->get('dev/docs/');
|
||||||
$this->assertEquals($response->getStatusCode(), 200, 'Lists the home index');
|
$this->assertEquals($response->getStatusCode(), 302, 'Go to english view');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/');
|
|
||||||
$this->assertEquals($response->getStatusCode(), 302, 'Go to english view');
|
|
||||||
|
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/3.0/empty.md');
|
$response = $this->get('dev/docs/en/doc_test/3.0/empty.md');
|
||||||
$this->assertEquals(301, $response->getStatusCode(), 'Direct markdown links also work. They should redirect to /empty/');
|
$this->assertEquals(301, $response->getStatusCode(), 'Direct markdown links also work. They should redirect to /empty/');
|
||||||
|
|
||||||
|
|
||||||
// 2.4 is the stable release. Not in the URL
|
// 2.4 is the stable release. Not in the URL
|
||||||
$response = $this->get('dev/docs/en/doc_test/2.4');
|
$response = $this->get('dev/docs/en/doc_test/2.4');
|
||||||
$this->assertEquals($response->getStatusCode(), 200, 'Existing base folder');
|
$this->assertEquals($response->getStatusCode(), 200, 'Existing base folder');
|
||||||
$this->assertContains('english test', $response->getBody(), 'Toplevel content page');
|
$this->assertContains('english test', $response->getBody(), 'Toplevel content page');
|
||||||
|
|
||||||
// accessing base redirects to the version with the version number.
|
// accessing base redirects to the version with the version number.
|
||||||
$response = $this->get('dev/docs/en/doc_test/');
|
$response = $this->get('dev/docs/en/doc_test/');
|
||||||
$this->assertEquals($response->getStatusCode(), 301, 'Existing base folder redirects to with version');
|
$this->assertEquals($response->getStatusCode(), 301, 'Existing base folder redirects to with version');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/3.0/');
|
$response = $this->get('dev/docs/en/doc_test/3.0/');
|
||||||
$this->assertEquals($response->getStatusCode(), 200, 'Existing base folder');
|
$this->assertEquals($response->getStatusCode(), 200, 'Existing base folder');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/2.3/nonexistant-subfolder');
|
$response = $this->get('dev/docs/en/doc_test/2.3/nonexistant-subfolder');
|
||||||
$this->assertEquals($response->getStatusCode(), 404, 'Nonexistant subfolder');
|
$this->assertEquals($response->getStatusCode(), 404, 'Nonexistant subfolder');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/2.3/nonexistant-file.txt');
|
$response = $this->get('dev/docs/en/doc_test/2.3/nonexistant-file.txt');
|
||||||
$this->assertEquals($response->getStatusCode(), 301, 'Nonexistant file');
|
$this->assertEquals($response->getStatusCode(), 301, 'Nonexistant file');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/2.3/nonexistant-file/');
|
$response = $this->get('dev/docs/en/doc_test/2.3/nonexistant-file/');
|
||||||
$this->assertEquals($response->getStatusCode(), 404, 'Nonexistant file');
|
$this->assertEquals($response->getStatusCode(), 404, 'Nonexistant file');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/2.3/test');
|
$response = $this->get('dev/docs/en/doc_test/2.3/test');
|
||||||
$this->assertEquals($response->getStatusCode(), 200, 'Existing file');
|
$this->assertEquals($response->getStatusCode(), 200, 'Existing file');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/3.0/empty?foo');
|
$response = $this->get('dev/docs/en/doc_test/3.0/empty?foo');
|
||||||
$this->assertEquals(200, $response->getStatusCode(), 'Existing page');
|
$this->assertEquals(200, $response->getStatusCode(), 'Existing page');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/3.0/empty/');
|
$response = $this->get('dev/docs/en/doc_test/3.0/empty/');
|
||||||
$this->assertEquals($response->getStatusCode(), 200, 'Existing page');
|
$this->assertEquals($response->getStatusCode(), 200, 'Existing page');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/3.0/test');
|
$response = $this->get('dev/docs/en/doc_test/3.0/test');
|
||||||
$this->assertEquals($response->getStatusCode(), 404, 'Missing page');
|
$this->assertEquals($response->getStatusCode(), 404, 'Missing page');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/3.0/test.md');
|
$response = $this->get('dev/docs/en/doc_test/3.0/test.md');
|
||||||
$this->assertEquals($response->getStatusCode(), 301, 'Missing page');
|
$this->assertEquals($response->getStatusCode(), 301, 'Missing page');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/en/doc_test/3.0/test/');
|
$response = $this->get('dev/docs/en/doc_test/3.0/test/');
|
||||||
$this->assertEquals($response->getStatusCode(), 404, 'Missing page');
|
$this->assertEquals($response->getStatusCode(), 404, 'Missing page');
|
||||||
|
|
||||||
$response = $this->get('dev/docs/dk/');
|
$response = $this->get('dev/docs/dk/');
|
||||||
$this->assertEquals($response->getStatusCode(), 404, 'Access a language that doesn\'t exist');
|
$this->assertEquals($response->getStatusCode(), 404, 'Access a language that doesn\'t exist');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testGetMenu() {
|
public function testGetMenu()
|
||||||
$v = new DocumentationViewer();
|
{
|
||||||
// check with children
|
$v = new DocumentationViewer();
|
||||||
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/doc_test/2.3/'), DataModel::inst());
|
// check with children
|
||||||
|
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/doc_test/2.3/'), DataModel::inst());
|
||||||
|
|
||||||
$expected = array(
|
$expected = array(
|
||||||
'dev/docs/en/doc_test/2.3/sort/' => 'Sort',
|
'dev/docs/en/doc_test/2.3/sort/' => 'Sort',
|
||||||
'dev/docs/en/doc_test/2.3/subfolder/' => 'Subfolder',
|
'dev/docs/en/doc_test/2.3/subfolder/' => 'Subfolder',
|
||||||
'dev/docs/en/doc_test/2.3/test/' => 'Test'
|
'dev/docs/en/doc_test/2.3/test/' => 'Test'
|
||||||
);
|
);
|
||||||
|
|
||||||
$actual = $v->getMenu()->first()->Children->map('Link', 'Title');
|
$actual = $v->getMenu()->first()->Children->map('Link', 'Title');
|
||||||
$this->assertEquals($expected, $actual);
|
$this->assertEquals($expected, $actual);
|
||||||
|
|
||||||
|
|
||||||
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/doc_test/2.4/'), DataModel::inst());
|
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/doc_test/2.4/'), DataModel::inst());
|
||||||
$this->assertEquals('current', $v->getMenu()->first()->LinkingMode);
|
$this->assertEquals('current', $v->getMenu()->first()->LinkingMode);
|
||||||
|
|
||||||
// 2.4 stable release has 1 child page (not including index)
|
// 2.4 stable release has 1 child page (not including index)
|
||||||
$this->assertEquals(1, $v->getMenu()->first()->Children->count());
|
$this->assertEquals(1, $v->getMenu()->first()->Children->count());
|
||||||
|
|
||||||
// menu should contain all the english entities
|
// menu should contain all the english entities
|
||||||
$expected = array(
|
$expected = array(
|
||||||
'dev/docs/en/doc_test/2.4/' => 'Doc Test',
|
'dev/docs/en/doc_test/2.4/' => 'Doc Test',
|
||||||
'dev/docs/en/documentationvieweraltmodule1/' => 'DocumentationViewerAltModule1',
|
'dev/docs/en/documentationvieweraltmodule1/' => 'DocumentationViewerAltModule1',
|
||||||
'dev/docs/en/documentationvieweraltmodule2/' => 'DocumentationViewerAltModule2'
|
'dev/docs/en/documentationvieweraltmodule2/' => 'DocumentationViewerAltModule2'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertEquals($expected, $v->getMenu()->map('Link', 'Title'));
|
$this->assertEquals($expected, $v->getMenu()->map('Link', 'Title'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function testGetLanguage() {
|
public function testGetLanguage()
|
||||||
$v = new DocumentationViewer();
|
{
|
||||||
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/doc_test/2.3/'), DataModel::inst());
|
$v = new DocumentationViewer();
|
||||||
|
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/doc_test/2.3/'), DataModel::inst());
|
||||||
|
|
||||||
$this->assertEquals('en', $v->getLanguage());
|
$this->assertEquals('en', $v->getLanguage());
|
||||||
|
|
||||||
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/doc_test/2.3/subfolder/subsubfolder/subsubpage/'), DataModel::inst());
|
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/doc_test/2.3/subfolder/subsubfolder/subsubpage/'), DataModel::inst());
|
||||||
$this->assertEquals('en', $v->getLanguage());
|
$this->assertEquals('en', $v->getLanguage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function testAccessingAll() {
|
public function testAccessingAll()
|
||||||
$response = $this->get('dev/docs/en/all/');
|
{
|
||||||
|
$response = $this->get('dev/docs/en/all/');
|
||||||
|
|
||||||
// should response with the documentation index
|
// should response with the documentation index
|
||||||
$this->assertEquals(200, $response->getStatusCode());
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
|
||||||
$items = $this->cssParser()->getBySelector('#documentation_index');
|
$items = $this->cssParser()->getBySelector('#documentation_index');
|
||||||
$this->assertNotEmpty($items);
|
$this->assertNotEmpty($items);
|
||||||
|
|
||||||
// should also have a DE version of the page
|
// should also have a DE version of the page
|
||||||
$response = $this->get('dev/docs/de/all/');
|
$response = $this->get('dev/docs/de/all/');
|
||||||
|
|
||||||
// should response with the documentation index
|
// should response with the documentation index
|
||||||
$this->assertEquals(200, $response->getStatusCode());
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
|
||||||
$items = $this->cssParser()->getBySelector('#documentation_index');
|
$items = $this->cssParser()->getBySelector('#documentation_index');
|
||||||
$this->assertNotEmpty($items);
|
$this->assertNotEmpty($items);
|
||||||
|
|
||||||
// accessing a language that doesn't exist should throw a 404
|
// accessing a language that doesn't exist should throw a 404
|
||||||
$response = $this->get('dev/docs/fu/all/');
|
$response = $this->get('dev/docs/fu/all/');
|
||||||
$this->assertEquals(404, $response->getStatusCode());
|
$this->assertEquals(404, $response->getStatusCode());
|
||||||
|
|
||||||
// accessing all without a language should fail
|
// accessing all without a language should fail
|
||||||
$response = $this->get('dev/docs/all/');
|
$response = $this->get('dev/docs/all/');
|
||||||
$this->assertEquals(404, $response->getStatusCode());
|
$this->assertEquals(404, $response->getStatusCode());
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
@ -4,83 +4,85 @@
|
|||||||
* @package docsviewer
|
* @package docsviewer
|
||||||
* @subpackage tests
|
* @subpackage tests
|
||||||
*/
|
*/
|
||||||
class DocumentationViewerVersionWarningTest extends SapphireTest {
|
class DocumentationViewerVersionWarningTest extends SapphireTest
|
||||||
|
{
|
||||||
|
protected $autoFollowRedirection = false;
|
||||||
|
|
||||||
protected $autoFollowRedirection = false;
|
private $manifest;
|
||||||
|
|
||||||
private $manifest;
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
public function setUp() {
|
Config::nest();
|
||||||
parent::setUp();
|
|
||||||
|
|
||||||
Config::nest();
|
// explicitly use dev/docs. Custom paths should be tested separately
|
||||||
|
Config::inst()->update(
|
||||||
|
'DocumentationViewer', 'link_base', 'dev/docs'
|
||||||
|
);
|
||||||
|
|
||||||
// explicitly use dev/docs. Custom paths should be tested separately
|
// disable automatic module registration so modules don't interfere.
|
||||||
Config::inst()->update(
|
Config::inst()->update(
|
||||||
'DocumentationViewer', 'link_base', 'dev/docs'
|
'DocumentationManifest', 'automatic_registration', false
|
||||||
);
|
);
|
||||||
|
|
||||||
// disable automatic module registration so modules don't interfere.
|
Config::inst()->remove('DocumentationManifest', 'register_entities');
|
||||||
Config::inst()->update(
|
|
||||||
'DocumentationManifest', 'automatic_registration', false
|
|
||||||
);
|
|
||||||
|
|
||||||
Config::inst()->remove('DocumentationManifest', 'register_entities');
|
Config::inst()->update(
|
||||||
|
'DocumentationManifest', 'register_entities', array(
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs/",
|
||||||
|
'Title' => 'Doc Test',
|
||||||
|
'Key' => 'testdocs',
|
||||||
|
'Version' => '2.3'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs-v2.4/",
|
||||||
|
'Title' => 'Doc Test',
|
||||||
|
'Version' => '2.4',
|
||||||
|
'Key' => 'testdocs',
|
||||||
|
'Stable' => true
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'Path' => DOCSVIEWER_PATH . "/tests/docs-v3.0/",
|
||||||
|
'Title' => 'Doc Test',
|
||||||
|
'Key' => 'testdocs',
|
||||||
|
'Version' => '3.0'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
Config::inst()->update(
|
$this->manifest = new DocumentationManifest(true);
|
||||||
'DocumentationManifest', 'register_entities', array(
|
}
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs/",
|
|
||||||
'Title' => 'Doc Test',
|
|
||||||
'Key' => 'testdocs',
|
|
||||||
'Version' => '2.3'
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs-v2.4/",
|
|
||||||
'Title' => 'Doc Test',
|
|
||||||
'Version' => '2.4',
|
|
||||||
'Key' => 'testdocs',
|
|
||||||
'Stable' => true
|
|
||||||
),
|
|
||||||
array(
|
|
||||||
'Path' => DOCSVIEWER_PATH . "/tests/docs-v3.0/",
|
|
||||||
'Title' => 'Doc Test',
|
|
||||||
'Key' => 'testdocs',
|
|
||||||
'Version' => '3.0'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->manifest = new DocumentationManifest(true);
|
public function tearDown()
|
||||||
}
|
{
|
||||||
|
parent::tearDown();
|
||||||
|
|
||||||
public function tearDown() {
|
Config::unnest();
|
||||||
parent::tearDown();
|
}
|
||||||
|
|
||||||
Config::unnest();
|
public function testVersionWarning()
|
||||||
|
{
|
||||||
|
$v = new DocumentationViewer();
|
||||||
|
|
||||||
}
|
// the current version is set to 2.4, no notice should be shown on that page
|
||||||
|
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/testdocs/'), DataModel::inst());
|
||||||
public function testVersionWarning() {
|
$this->assertFalse($v->VersionWarning());
|
||||||
$v = new DocumentationViewer();
|
|
||||||
|
|
||||||
// the current version is set to 2.4, no notice should be shown on that page
|
|
||||||
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/testdocs/'), DataModel::inst());
|
|
||||||
$this->assertFalse($v->VersionWarning());
|
|
||||||
|
|
||||||
|
|
||||||
// 2.3 is an older release, hitting that should return us an outdated flag
|
// 2.3 is an older release, hitting that should return us an outdated flag
|
||||||
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/testdocs/2.3/'), DataModel::inst());
|
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/testdocs/2.3/'), DataModel::inst());
|
||||||
$warn = $v->VersionWarning();
|
$warn = $v->VersionWarning();
|
||||||
|
|
||||||
$this->assertTrue($warn->OutdatedRelease);
|
$this->assertTrue($warn->OutdatedRelease);
|
||||||
$this->assertNull($warn->FutureRelease);
|
$this->assertNull($warn->FutureRelease);
|
||||||
|
|
||||||
// 3.0 is a future release
|
// 3.0 is a future release
|
||||||
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/testdocs/3.0/'), DataModel::inst());
|
$response = $v->handleRequest(new SS_HTTPRequest('GET', 'en/testdocs/3.0/'), DataModel::inst());
|
||||||
$warn = $v->VersionWarning();
|
$warn = $v->VersionWarning();
|
||||||
|
|
||||||
$this->assertNull($warn->OutdatedRelease);
|
$this->assertNull($warn->OutdatedRelease);
|
||||||
$this->assertTrue($warn->FutureRelease);
|
$this->assertTrue($warn->FutureRelease);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user