221 lines
5.4 KiB
PHP
221 lines
5.4 KiB
PHP
|
<?php
|
||
|
|
||
|
declare(strict_types=1);
|
||
|
|
||
|
namespace Doctrine\RST;
|
||
|
|
||
|
use Doctrine\RST\Directives\Directive;
|
||
|
use Doctrine\RST\NodeFactory\NodeFactory;
|
||
|
use Doctrine\RST\Nodes\DocumentNode;
|
||
|
use Doctrine\RST\Nodes\SpanNode;
|
||
|
use Doctrine\RST\Parser\DocumentParser;
|
||
|
use InvalidArgumentException;
|
||
|
use RuntimeException;
|
||
|
|
||
|
use function file_exists;
|
||
|
use function file_get_contents;
|
||
|
use function fwrite;
|
||
|
use function getenv;
|
||
|
use function sprintf;
|
||
|
|
||
|
use const PHP_SAPI;
|
||
|
use const STDERR;
|
||
|
|
||
|
class Parser
|
||
|
{
|
||
|
/** @var Configuration */
|
||
|
private $configuration;
|
||
|
|
||
|
/** @var Kernel */
|
||
|
private $kernel;
|
||
|
|
||
|
/** @var Environment */
|
||
|
private $environment;
|
||
|
|
||
|
/** @var Directive[] */
|
||
|
private $directives = [];
|
||
|
|
||
|
/** @var bool */
|
||
|
private $includeAllowed = true;
|
||
|
|
||
|
/** @var string */
|
||
|
private $includeRoot = '';
|
||
|
|
||
|
/** @var string|null */
|
||
|
private $filename = null;
|
||
|
|
||
|
/** @var DocumentParser|null */
|
||
|
private $documentParser;
|
||
|
|
||
|
public function __construct(
|
||
|
?Kernel $kernel = null,
|
||
|
?Environment $environment = null
|
||
|
) {
|
||
|
if ($kernel === null) {
|
||
|
$kernel = new Kernel();
|
||
|
}
|
||
|
|
||
|
$this->configuration = $kernel->getConfiguration();
|
||
|
$this->kernel = $kernel;
|
||
|
$this->environment = $environment ?? new Environment($this->configuration);
|
||
|
|
||
|
$this->initDirectives();
|
||
|
$this->initReferences();
|
||
|
}
|
||
|
|
||
|
public function getSubParser(): Parser
|
||
|
{
|
||
|
return new Parser($this->kernel, $this->environment);
|
||
|
}
|
||
|
|
||
|
public function getNodeFactory(): NodeFactory
|
||
|
{
|
||
|
return $this->configuration->getNodeFactory($this->environment);
|
||
|
}
|
||
|
|
||
|
/** @param mixed[] $parameters */
|
||
|
public function renderTemplate(string $template, array $parameters = []): string
|
||
|
{
|
||
|
return $this->configuration->getTemplateRenderer()->render($template, $parameters);
|
||
|
}
|
||
|
|
||
|
public function initDirectives(): void
|
||
|
{
|
||
|
$directives = $this->kernel->getDirectives();
|
||
|
|
||
|
foreach ($directives as $directive) {
|
||
|
$this->registerDirective($directive);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function initReferences(): void
|
||
|
{
|
||
|
$references = $this->kernel->getReferences();
|
||
|
|
||
|
foreach ($references as $reference) {
|
||
|
$this->environment->registerReference($reference);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function getEnvironment(): Environment
|
||
|
{
|
||
|
return $this->environment;
|
||
|
}
|
||
|
|
||
|
public function getKernel(): Kernel
|
||
|
{
|
||
|
return $this->kernel;
|
||
|
}
|
||
|
|
||
|
public function registerDirective(Directive $directive): void
|
||
|
{
|
||
|
$this->directives[$directive->getName()] = $directive;
|
||
|
}
|
||
|
|
||
|
public function getDocument(): DocumentNode
|
||
|
{
|
||
|
if ($this->documentParser === null) {
|
||
|
throw new RuntimeException('Nothing has been parsed yet.');
|
||
|
}
|
||
|
|
||
|
return $this->documentParser->getDocument();
|
||
|
}
|
||
|
|
||
|
public function getFilename(): string
|
||
|
{
|
||
|
return $this->filename ?? '(unknown)';
|
||
|
}
|
||
|
|
||
|
public function getIncludeAllowed(): bool
|
||
|
{
|
||
|
return $this->includeAllowed;
|
||
|
}
|
||
|
|
||
|
public function getIncludeRoot(): string
|
||
|
{
|
||
|
return $this->includeRoot;
|
||
|
}
|
||
|
|
||
|
public function setIncludePolicy(bool $includeAllowed, ?string $directory = null): self
|
||
|
{
|
||
|
$this->includeAllowed = $includeAllowed;
|
||
|
|
||
|
if ($directory !== null) {
|
||
|
$this->includeRoot = $directory;
|
||
|
}
|
||
|
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
/** @param string|string[]|SpanNode $span */
|
||
|
public function createSpanNode($span): SpanNode
|
||
|
{
|
||
|
return $this->getNodeFactory()->createSpanNode($this, $span);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Parses the given contents as a new file.
|
||
|
*/
|
||
|
public function parse(string $contents): DocumentNode
|
||
|
{
|
||
|
$this->getEnvironment()->reset();
|
||
|
|
||
|
return $this->parseLocal($contents);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Parses the given contents in a new document node.
|
||
|
*
|
||
|
* CAUTION: This modifies the state of the Parser, do not use this method
|
||
|
* on the main parser (use `Parser::getSubParser()->parseLocal(...)` instead).
|
||
|
*
|
||
|
* Use this method to parse contents of an other node. Nodes created by
|
||
|
* this new parser are not added to the main DocumentNode.
|
||
|
*/
|
||
|
public function parseLocal(string $contents): DocumentNode
|
||
|
{
|
||
|
$this->documentParser = $this->createDocumentParser();
|
||
|
|
||
|
return $this->documentParser->parse($contents);
|
||
|
}
|
||
|
|
||
|
public function parseFragment(string $contents): DocumentNode
|
||
|
{
|
||
|
return $this->createDocumentParser()->parse($contents);
|
||
|
}
|
||
|
|
||
|
public function parseFile(string $file): DocumentNode
|
||
|
{
|
||
|
if (getenv('SHELL_VERBOSITY') >= 2 && PHP_SAPI === 'cli') {
|
||
|
fwrite(STDERR, sprintf("Parsing file: %s\n", $file));
|
||
|
}
|
||
|
|
||
|
if (! file_exists($file)) {
|
||
|
throw new InvalidArgumentException(sprintf('File at path %s does not exist', $file));
|
||
|
}
|
||
|
|
||
|
$this->filename = $file;
|
||
|
|
||
|
$contents = file_get_contents($file);
|
||
|
|
||
|
if ($contents === false) {
|
||
|
throw new InvalidArgumentException(sprintf('Could not load file from path %s', $file));
|
||
|
}
|
||
|
|
||
|
return $this->parse($contents);
|
||
|
}
|
||
|
|
||
|
private function createDocumentParser(): DocumentParser
|
||
|
{
|
||
|
return new DocumentParser(
|
||
|
$this,
|
||
|
$this->environment,
|
||
|
$this->getNodeFactory(),
|
||
|
$this->configuration->getEventManager(),
|
||
|
$this->directives,
|
||
|
$this->includeAllowed,
|
||
|
$this->includeRoot
|
||
|
);
|
||
|
}
|
||
|
}
|