236 lines
5.8 KiB
PHP
236 lines
5.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Doctrine\RST\Nodes;
|
|
|
|
use Doctrine\RST\Configuration;
|
|
use Doctrine\RST\Environment;
|
|
use Doctrine\RST\ErrorManager;
|
|
use Doctrine\RST\Renderers\FullDocumentNodeRenderer;
|
|
use Exception;
|
|
|
|
use function array_unshift;
|
|
use function assert;
|
|
use function count;
|
|
use function is_string;
|
|
use function sprintf;
|
|
|
|
class DocumentNode extends Node
|
|
{
|
|
/** @var Environment */
|
|
protected $environment;
|
|
|
|
/** @var Configuration */
|
|
private $configuration;
|
|
|
|
/** @var ErrorManager */
|
|
private $errorManager;
|
|
|
|
/** @var Node[] */
|
|
private $headerNodes = [];
|
|
|
|
/** @var Node[] */
|
|
private $nodes = [];
|
|
|
|
public function __construct(Environment $environment)
|
|
{
|
|
parent::__construct();
|
|
|
|
$this->environment = $environment;
|
|
$this->configuration = $environment->getConfiguration();
|
|
$this->errorManager = $environment->getErrorManager();
|
|
}
|
|
|
|
public function getEnvironment(): Environment
|
|
{
|
|
return $this->environment;
|
|
}
|
|
|
|
public function getConfiguration(): Configuration
|
|
{
|
|
return $this->configuration;
|
|
}
|
|
|
|
/** @return Node[] */
|
|
public function getHeaderNodes(): array
|
|
{
|
|
return $this->headerNodes;
|
|
}
|
|
|
|
public function renderDocument(): string
|
|
{
|
|
$renderedDocument = $this->doRenderDocument();
|
|
|
|
$this->postRenderValidate();
|
|
|
|
return $renderedDocument;
|
|
}
|
|
|
|
/** @return Node[] */
|
|
public function getNodes(?callable $function = null): array
|
|
{
|
|
$nodes = [];
|
|
|
|
if ($function === null) {
|
|
return $this->nodes;
|
|
}
|
|
|
|
foreach ($this->nodes as $node) {
|
|
if (! $function($node)) {
|
|
continue;
|
|
}
|
|
|
|
$nodes[] = $node;
|
|
}
|
|
|
|
return $nodes;
|
|
}
|
|
|
|
public function getTitle(): ?string
|
|
{
|
|
foreach ($this->nodes as $node) {
|
|
if ($node instanceof TitleNode && $node->getLevel() === 1) {
|
|
return $node->getValue()->render() . '';
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/** @return mixed[] */
|
|
public function getTocs(): array
|
|
{
|
|
$tocs = [];
|
|
|
|
$nodes = $this->getNodes(static function ($node): bool {
|
|
return $node instanceof TocNode;
|
|
});
|
|
|
|
foreach ($nodes as $toc) {
|
|
assert($toc instanceof TocNode);
|
|
$files = $toc->getFiles();
|
|
|
|
foreach ($files as &$file) {
|
|
$file = $this->environment->canonicalUrl($file);
|
|
}
|
|
|
|
$tocs[] = $files;
|
|
}
|
|
|
|
return $tocs;
|
|
}
|
|
|
|
/** @return string[][] */
|
|
public function getTitles(): array
|
|
{
|
|
$titles = [];
|
|
$levels = [&$titles];
|
|
|
|
foreach ($this->nodes as $node) {
|
|
if (! ($node instanceof TitleNode)) {
|
|
continue;
|
|
}
|
|
|
|
$level = $node->getLevel();
|
|
$text = $node->getValue()->getText();
|
|
$redirection = $node->getTarget();
|
|
$value = $redirection !== '' ? [$text, $redirection] : $text;
|
|
|
|
if (! isset($levels[$level - 1])) {
|
|
continue;
|
|
}
|
|
|
|
$parent = &$levels[$level - 1];
|
|
$element = [$value, []];
|
|
$parent[] = $element;
|
|
$levels[$level] = &$parent[count($parent) - 1][1];
|
|
}
|
|
|
|
return $titles;
|
|
}
|
|
|
|
/** @param string|Node $node */
|
|
public function addNode($node): void
|
|
{
|
|
if (is_string($node)) {
|
|
$node = new RawNode($node);
|
|
}
|
|
|
|
$this->nodes[] = $node;
|
|
}
|
|
|
|
public function prependNode(Node $node): void
|
|
{
|
|
array_unshift($this->nodes, $node);
|
|
}
|
|
|
|
public function addHeaderNode(Node $node): void
|
|
{
|
|
$this->headerNodes[] = $node;
|
|
}
|
|
|
|
public function addCss(string $css): void
|
|
{
|
|
$css = $this->environment->relativeUrl($css);
|
|
|
|
if ($css === null) {
|
|
throw new Exception(sprintf('Could not get relative url for css %s', $css));
|
|
}
|
|
|
|
$this->addHeaderNode($this->environment->getNodeFactory()->createRawNode(
|
|
$this->environment->getTemplateRenderer()->render('stylesheet-link.html.twig', ['css' => $css])
|
|
));
|
|
}
|
|
|
|
public function addJs(string $js): void
|
|
{
|
|
$js = $this->environment->relativeUrl($js);
|
|
|
|
if ($js === null) {
|
|
throw new Exception(sprintf('Could not get relative url for js %s', $js));
|
|
}
|
|
|
|
$this->addHeaderNode($this->environment->getNodeFactory()->createRawNode(
|
|
$this->environment->getTemplateRenderer()->render('javascript.html.twig', ['js' => $js])
|
|
));
|
|
}
|
|
|
|
public function addFavicon(string $url = '/favicon.ico'): void
|
|
{
|
|
$url = $this->environment->relativeUrl($url);
|
|
|
|
if ($url === null) {
|
|
throw new Exception(sprintf('Could not get relative url for favicon %s', $url));
|
|
}
|
|
|
|
$this->addHeaderNode($this->environment->getNodeFactory()->createRawNode(
|
|
$this->environment->getTemplateRenderer()->render('favicon.html.twig', ['url' => $url])
|
|
));
|
|
}
|
|
|
|
protected function doRenderDocument(): string
|
|
{
|
|
$renderer = $this->getRenderer();
|
|
assert($renderer instanceof FullDocumentNodeRenderer);
|
|
|
|
return $renderer->renderDocument();
|
|
}
|
|
|
|
private function postRenderValidate(): void
|
|
{
|
|
if ($this->configuration->getIgnoreInvalidReferences() !== false) {
|
|
return;
|
|
}
|
|
|
|
$currentFileName = $this->environment->getCurrentFileName();
|
|
|
|
foreach ($this->environment->getInvalidLinks() as $invalidLink) {
|
|
$this->errorManager->error(
|
|
sprintf('Found invalid reference "%s"', $invalidLink->getName()),
|
|
$currentFileName
|
|
);
|
|
}
|
|
}
|
|
}
|