mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-22 21:34:28 +02:00
doc: Support loading images beneath doc/ directories
This commit is contained in:
parent
dc4bcdabb6
commit
38892a971f
@ -3,6 +3,8 @@
|
||||
|
||||
namespace Icinga\Module\Doc\Controllers;
|
||||
|
||||
use finfo;
|
||||
use SplFileInfo;
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Module\Doc\DocController;
|
||||
use Icinga\Module\Doc\Exception\DocException;
|
||||
@ -120,6 +122,7 @@ class ModuleController extends DocController
|
||||
$this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc')),
|
||||
$chapter,
|
||||
'doc/module/chapter',
|
||||
'doc/module/img',
|
||||
array('moduleName' => $module)
|
||||
);
|
||||
} catch (DocException $e) {
|
||||
@ -127,6 +130,60 @@ class ModuleController extends DocController
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deliver images
|
||||
*/
|
||||
public function imageAction()
|
||||
{
|
||||
$module = $this->params->getRequired('moduleName');
|
||||
$image = $this->params->getRequired('image');
|
||||
$docPath = $this->getPath($module, Icinga::app()->getModuleManager()->getModuleDir($module, '/doc'));
|
||||
$imagePath = realpath($docPath . '/' . $image);
|
||||
if ($imagePath === false) {
|
||||
$this->httpNotFound('%s does not exist', $image);
|
||||
}
|
||||
|
||||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
$this->_helper->layout()->disableLayout();
|
||||
|
||||
$imageInfo = new SplFileInfo($imagePath);
|
||||
|
||||
$ETag = md5($imageInfo->getMTime() . $imagePath);
|
||||
$lastModified = gmdate('D, d M Y H:i:s T', $imageInfo->getMTime());
|
||||
$match = false;
|
||||
|
||||
if (isset($_SERER['HTTP_IF_NONE_MATCH'])) {
|
||||
$ifNoneMatch = explode(', ', stripslashes($_SERVER['HTTP_IF_NONE_MATCH']));
|
||||
foreach ($ifNoneMatch as $tag) {
|
||||
if ($tag === $ETag) {
|
||||
$match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} elseif (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
|
||||
$lastModifiedSince = stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']);
|
||||
if ($lastModifiedSince === $lastModified) {
|
||||
$match = true;
|
||||
}
|
||||
}
|
||||
|
||||
header('ETag: "' . $ETag . '"');
|
||||
header('Cache-Control: no-transform,public,max-age=3600');
|
||||
header('Last-Modified: ' . $lastModified);
|
||||
// Set additional headers for compatibility reasons (Cache-Control should have precedence) in case
|
||||
// session.cache_limiter is set to no cache
|
||||
header('Pragma: cache');
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s T', time() + 3600));
|
||||
|
||||
if ($match) {
|
||||
header('HTTP/1.1 304 Not Modified');
|
||||
} else {
|
||||
$finfo = new finfo();
|
||||
header('Content-Type: ' . $finfo->file($imagePath, FILEINFO_MIME_TYPE));
|
||||
readfile($imagePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View a module's documentation as PDF
|
||||
*
|
||||
|
@ -1,6 +1,6 @@
|
||||
# <a id="module-documentation"></a> Writing Module Documentation
|
||||
|
||||

|
||||

|
||||
|
||||
Icinga Web 2 is capable of viewing your module's documentation, if the documentation is written in
|
||||
[Markdown](http://en.wikipedia.org/wiki/Markdown). Please refer to
|
||||
@ -50,13 +50,15 @@ This syntax is also supported in Icinga Web 2.
|
||||
|
||||
## <a id="images"></a> Including Images
|
||||
|
||||
Images must placed in the `img` directory beneath your module's `public` directory, e.g.:
|
||||
Images must placed in the `doc` directory beneath your module's root directory, e.g.:
|
||||
|
||||
example-module/public/img/doc
|
||||
/path/to/icingaweb2/modules/example-module/doc/img/example.png
|
||||
|
||||
Note that the `img` sub directory is not mandatory but good for organizing your directory structure.
|
||||
|
||||
Module images can be accessed using the following URL:
|
||||
|
||||
{baseURL}/img/{moduleName}/{file} e.g. icingaweb/img/example-module/doc/example.png
|
||||
{baseURL}/doc/module/{moduleName}/image/{image} e.g. icingaweb2/doc/module/example-module/image/img/example.png
|
||||
|
||||
Markdown's image syntax is very similar to Markdown's link syntax, but prefixed with an exclamation mark, e.g.:
|
||||
|
||||
@ -64,4 +66,4 @@ Markdown's image syntax is very similar to Markdown's link syntax, but prefixed
|
||||
|
||||
URLs to images inside your Markdown documentation files must be specified without the base URL, e.g.:
|
||||
|
||||

|
||||

|
||||
|
@ -20,6 +20,9 @@ class DocController extends Controller
|
||||
if ($this->hasParam('chapter')) {
|
||||
$this->params->set('chapter', $this->getParam('chapter'));
|
||||
}
|
||||
if ($this->hasParam('image')) {
|
||||
$this->params->set('image', $this->getParam('image'));
|
||||
}
|
||||
if ($this->hasParam('moduleName')) {
|
||||
$this->params->set('moduleName', $this->getParam('moduleName'));
|
||||
}
|
||||
@ -31,16 +34,18 @@ class DocController extends Controller
|
||||
* @param string $path Path to the documentation
|
||||
* @param string $chapter ID of the chapter
|
||||
* @param string $url URL to replace links with
|
||||
* @param string $imageUrl URL to images
|
||||
* @param array $urlParams Additional URL parameters
|
||||
*/
|
||||
protected function renderChapter($path, $chapter, $url, array $urlParams = array())
|
||||
protected function renderChapter($path, $chapter, $url, $imageUrl = null, array $urlParams = array())
|
||||
{
|
||||
$parser = new DocParser($path);
|
||||
$section = new DocSectionRenderer($parser->getDocTree(), DocSectionRenderer::decodeUrlParam($chapter));
|
||||
$this->view->section = $section
|
||||
->setHighlightSearch($this->params->get('highlight-search'))
|
||||
->setImageUrl($imageUrl)
|
||||
->setUrl($url)
|
||||
->setUrlParams($urlParams)
|
||||
->setHighlightSearch($this->params->get('highlight-search'));
|
||||
->setUrlParams($urlParams);
|
||||
$this->view->title = $chapter;
|
||||
$this->getTabs()->add('toc', array(
|
||||
'active' => true,
|
||||
|
@ -13,6 +13,13 @@ use Icinga\Web\View;
|
||||
*/
|
||||
abstract class DocRenderer extends RecursiveIteratorIterator
|
||||
{
|
||||
/**
|
||||
* URL to images
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $imageUrl;
|
||||
|
||||
/**
|
||||
* URL to replace links with
|
||||
*
|
||||
@ -34,6 +41,38 @@ abstract class DocRenderer extends RecursiveIteratorIterator
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* Get the URL to images
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getImageUrl()
|
||||
{
|
||||
return $this->imageUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the URL to images
|
||||
*
|
||||
* @param string $imageUrl
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setImageUrl($imageUrl)
|
||||
{
|
||||
$this->imageUrl = (string) $imageUrl;
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Get the URL to replace links with
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl()
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the URL to replace links with
|
||||
*
|
||||
@ -48,13 +87,13 @@ abstract class DocRenderer extends RecursiveIteratorIterator
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL to replace links with
|
||||
* Get additional URL parameters
|
||||
*
|
||||
* @return string
|
||||
* @return array
|
||||
*/
|
||||
public function getUrl()
|
||||
public function getUrlParams()
|
||||
{
|
||||
return $this->url;
|
||||
return $this->urlParams;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,13 +110,16 @@ abstract class DocRenderer extends RecursiveIteratorIterator
|
||||
}
|
||||
|
||||
/**
|
||||
* Get additional URL parameters
|
||||
* Get the view
|
||||
*
|
||||
* @return array
|
||||
* @return View
|
||||
*/
|
||||
public function getUrlParams()
|
||||
public function getView()
|
||||
{
|
||||
return $this->urlParams;
|
||||
if ($this->view === null) {
|
||||
$this->view = Icinga::app()->getViewRenderer()->view;
|
||||
}
|
||||
return $this->view;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,19 +135,6 @@ abstract class DocRenderer extends RecursiveIteratorIterator
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function getView()
|
||||
{
|
||||
if ($this->view === null) {
|
||||
$this->view = Icinga::app()->getViewRenderer()->view;
|
||||
}
|
||||
return $this->view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an anchor identifier
|
||||
*
|
||||
|
@ -190,7 +190,20 @@ class DocSectionRenderer extends DocRenderer
|
||||
$xpath = new DOMXPath($doc);
|
||||
$img = $xpath->query('//img[1]')->item(0);
|
||||
/** @var \DOMElement $img */
|
||||
$img->setAttribute('src', Url::fromPath($img->getAttribute('src'))->getAbsoluteUrl());
|
||||
$path = $this->getView()->getHelper('Url')->url(
|
||||
array_merge(
|
||||
array(
|
||||
'image' => $img->getAttribute('src')
|
||||
),
|
||||
$this->urlParams
|
||||
),
|
||||
$this->imageUrl,
|
||||
false,
|
||||
false
|
||||
);
|
||||
$url = $this->getView()->url($path);
|
||||
/** @var \Icinga\Web\Url $url */
|
||||
$img->setAttribute('src', $url->getAbsoluteUrl());
|
||||
return substr_replace($doc->saveXML($img), '', -2, 1); // Replace '/>' with '>'
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,22 @@ $docModulePdf = new Zend_Controller_Router_Route(
|
||||
)
|
||||
);
|
||||
|
||||
$docModuleImg = new Zend_Controller_Router_Route_Regex(
|
||||
'doc/module/([^/]+)/image/(.+)',
|
||||
array(
|
||||
'controller' => 'module',
|
||||
'action' => 'image',
|
||||
'module' => 'doc'
|
||||
),
|
||||
array(
|
||||
'moduleName' => 1,
|
||||
'image' => 2
|
||||
),
|
||||
'doc/module/%s/image/%s'
|
||||
);
|
||||
|
||||
$this->addRoute('doc/module/chapter', $docModuleChapter);
|
||||
$this->addRoute('doc/icingaweb/chapter', $docIcingaWebChapter);
|
||||
$this->addRoute('doc/module/toc', $docModuleToc);
|
||||
$this->addRoute('doc/module/pdf', $docModulePdf);
|
||||
$this->addRoute('doc/module/img', $docModuleImg);
|
||||
|
Loading…
x
Reference in New Issue
Block a user