You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
259 lines
5.2 KiB
259 lines
5.2 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Engine;
|
|
|
|
/**
|
|
* Main class responsible for controlling the compilation process.
|
|
*
|
|
* @author Adam Pippin <hello@adampippin.ca>
|
|
*/
|
|
class Engine
|
|
{
|
|
/**
|
|
* Compiler for processing documents.
|
|
*
|
|
* @var \App\Engine\ICompile
|
|
*/
|
|
protected $compile;
|
|
|
|
/**
|
|
* Serializer to convert documents back to whatever line/disk format we
|
|
* want.
|
|
*
|
|
* @var \App\Serialize\ISerialize
|
|
*/
|
|
protected $serialize;
|
|
|
|
/**
|
|
* Unserializer to convert line/disk format documents into documents.
|
|
*
|
|
* @var \App\Serialize\IUnserialize
|
|
*/
|
|
protected $unserialize;
|
|
|
|
/**
|
|
* Represents the current document state after any operations called.
|
|
*
|
|
* @var \App\Dom\Document
|
|
*/
|
|
protected $document;
|
|
|
|
/**
|
|
* Process a domdocument, applying some higher level operations such as
|
|
* stacking documents.
|
|
*
|
|
* @todo break all this stuff out
|
|
* @param string $input_file
|
|
* @param IOptions $options
|
|
* @return string
|
|
*/
|
|
public function process(string $input_file, IOptions $options): string
|
|
{
|
|
$file_helper = new File([dirname(realpath($input_file))]);
|
|
|
|
$documents = [];
|
|
|
|
// First, figure out which files to process and load all files.
|
|
$files = [basename($input_file)];
|
|
|
|
for ($i = 0; $i < sizeof($files); $i++)
|
|
{
|
|
if (!isset($documents[$files[$i]]))
|
|
{
|
|
$documents[$files[$i]] = $document = $this->unserialize->unserialize(file_get_contents($file_helper->resolve($files[$i])));
|
|
$includes = [];
|
|
try
|
|
{
|
|
$includes = $document->getMeta('stack');
|
|
}
|
|
catch (\Exception $ex)
|
|
{
|
|
}
|
|
if (sizeof($includes))
|
|
{
|
|
array_splice($files, $i, 0, $includes);
|
|
--$i;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Go through and load all the variables and parameters
|
|
$variables = [];
|
|
$parameters = [];
|
|
for ($i = 0; $i < sizeof($files); $i++)
|
|
{
|
|
$file_variables = [];
|
|
try
|
|
{
|
|
$file_variables = $documents[$files[$i]]->getMeta('variables');
|
|
}
|
|
catch (\Exception $ex)
|
|
{
|
|
}
|
|
|
|
foreach ($file_variables as $k => $v)
|
|
{
|
|
$variables[$k] = $v;
|
|
}
|
|
|
|
$file_parameters = [];
|
|
try
|
|
{
|
|
$file_parameters = $documents[$files[$i]]->getMeta('parameters');
|
|
}
|
|
catch (\Exception $ex)
|
|
{
|
|
}
|
|
|
|
foreach ($file_parameters as $k => $v)
|
|
{
|
|
$parameters[$k] = $v;
|
|
}
|
|
}
|
|
|
|
foreach ($variables as $k => $v)
|
|
{
|
|
if (!$options->hasVariable($k))
|
|
{
|
|
$options->setVariable($k, $v);
|
|
}
|
|
}
|
|
|
|
foreach ($parameters as $k => $v)
|
|
{
|
|
if (!$options->hasParameter($k))
|
|
{
|
|
$options->setParameter($k, $v);
|
|
}
|
|
}
|
|
|
|
// Now actually process all the documents
|
|
for ($i = 0; $i < sizeof($files); $i++)
|
|
{
|
|
$this->compileDocument($documents[$files[$i]]);
|
|
}
|
|
|
|
// Set metadata in output
|
|
$document = $this->getOutputDocument();
|
|
|
|
$document->addChildUnderPath('Metadata', new \App\Dom\NodeValue(null, 'Stack', implode(', ', $files)));
|
|
$cfnpp = $document->getChildByName('cfnpp');
|
|
if (isset($cfnpp))
|
|
{
|
|
$cfnpp->remove();
|
|
}
|
|
|
|
return $this->serialize->serialize($document);
|
|
}
|
|
|
|
/**
|
|
* Set the compiler to use.
|
|
*
|
|
* @param ICompile $compiler
|
|
* @return Engine
|
|
*/
|
|
public function setCompiler(ICompile $compiler): Engine
|
|
{
|
|
$this->compile = $compiler;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set the serializer to use.
|
|
*
|
|
* @param \App\Serialize\ISerialize $serializer
|
|
* @return Engine
|
|
*/
|
|
public function setSerializer(\App\Serialize\ISerialize $serializer): Engine
|
|
{
|
|
$this->serialize = $serializer;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set the unserializer to use.
|
|
*
|
|
* @param \App\Serialize\IUnserialize $unserializer
|
|
* @return Engine
|
|
*/
|
|
public function setUnserializer(\App\Serialize\IUnserialize $unserializer): Engine
|
|
{
|
|
$this->unserialize = $unserializer;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set the initial compiler state.
|
|
*
|
|
* @param \App\Dom\Document $document
|
|
* @return Engine
|
|
*/
|
|
public function setInputDocument(\App\Dom\Document $document): Engine
|
|
{
|
|
$this->document = $document;
|
|
$this->compile->setDocument($document);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Set the initial compiler state from a serialized string.
|
|
*
|
|
* @param string $document_string
|
|
* @return Engine
|
|
*/
|
|
public function setInput(string $document_string): Engine
|
|
{
|
|
$document = $this->unserialize->unserialize($document_string);
|
|
$this->setInputDocument($document);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Compile a new document, mutating current state.
|
|
*
|
|
* @param string $document_string
|
|
* @return Engine
|
|
*/
|
|
public function compile(string $document_string): Engine
|
|
{
|
|
$document = $this->unserialize->unserialize($document_string);
|
|
$this->compileDocument($document);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Compile a new document, mutating current state.
|
|
*
|
|
* @param \App\Dom\Document $document
|
|
* @return Engine
|
|
*/
|
|
public function compileDocument(\App\Dom\Document $document): Engine
|
|
{
|
|
$this->compile->compile($document);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get the document state after all applied compile() calls.
|
|
*
|
|
* @return \App\Dom\Document
|
|
*/
|
|
public function getOutputDocument(): \App\Dom\Document
|
|
{
|
|
return $this->compile->getDocument();
|
|
}
|
|
|
|
/**
|
|
* Get the document state after all applied compile() calls and serialize
|
|
* it, returning line/disk format.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getOutput(): string
|
|
{
|
|
$document = $this->getOutputDocument();
|
|
return $this->serialize->serialize($document);
|
|
}
|
|
}
|
|
|