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.
156 lines
3.4 KiB
156 lines
3.4 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Engine\Cfnpp;
|
|
|
|
use App\Dom\Node;
|
|
use App\Dom\NodeValue;
|
|
use App\Dom\NodeFunction;
|
|
use App\Dom\NodeFunctionValue;
|
|
|
|
/**
|
|
* Functions available in a cfnpp document.
|
|
*
|
|
* @author Adam Pippin <hello@adampippin.ca>
|
|
*/
|
|
class Functions
|
|
{
|
|
/**
|
|
* cfnpp compiler.
|
|
* @var Compiler
|
|
*/
|
|
protected $compiler;
|
|
|
|
/**
|
|
* cfnpp compiler options, stores state.
|
|
* @var Options
|
|
*/
|
|
protected $options;
|
|
|
|
public function __construct(Compiler $compiler, Options $options)
|
|
{
|
|
$this->compiler = $compiler;
|
|
$this->options = $options;
|
|
}
|
|
|
|
/**
|
|
* Examines this class with reflection and registers all functions on a cfnpp
|
|
* compiler instance.
|
|
*
|
|
* @param Compiler $compiler
|
|
* @return void
|
|
*/
|
|
public function register(Compiler $compiler): void
|
|
{
|
|
$reflection = new \ReflectionClass(static::class);
|
|
$methods = $reflection->getMethods();
|
|
|
|
foreach ($methods as $method)
|
|
{
|
|
if (!stristr($method->name, '_'))
|
|
{
|
|
continue;
|
|
}
|
|
[$method_type, $method_name] = explode('_', $method->name, 2);
|
|
switch ($method_type)
|
|
{
|
|
case 'mf':
|
|
$compiler->registerMergeFunction($method_name, [$this, $method->name]);
|
|
break;
|
|
case 'f':
|
|
$compiler->registerFunction($method_name, [$this, $method->name]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Replace all children nodes in original with those from target, rather than
|
|
* merging them.
|
|
*
|
|
* @param Node $original
|
|
* @param Node $target
|
|
* @param NodeFunction $function
|
|
* @return ?Node
|
|
*/
|
|
public function mf_replace(Node $original, Node $target, NodeFunction $function): ?Node
|
|
{
|
|
// TODO: Deal with nodefunctionvalue
|
|
|
|
$replacement = new Node(null, $target->hasName() ? $target->getName() : null);
|
|
$replacement->setChildren($function->getChildren());
|
|
return $replacement;
|
|
}
|
|
|
|
/**
|
|
* Unset a node, completely removing it from the document.
|
|
*
|
|
* @param Node $node
|
|
* @param NodeFunction $function
|
|
* @return ?Node
|
|
*/
|
|
public function f_unset(Node $node, NodeFunction $function): ?Node
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get the value of a variable.
|
|
*
|
|
* @param Node $node
|
|
* @param NodeFunction $function
|
|
* @return ?Node
|
|
*/
|
|
public function f_var(Node $node, NodeFunction $function): ?Node
|
|
{
|
|
if (!($function instanceof NodeFunctionValue))
|
|
{
|
|
throw new \Exception('!var requires scalar argument');
|
|
}
|
|
$value = $this->options->getVariable($function->getValue());
|
|
return new NodeValue(null, $node->hasName() ? $node->getName() : null, $value);
|
|
}
|
|
|
|
/**
|
|
* Conditionally include part of the file.
|
|
*
|
|
* @param Node $node
|
|
* @param NodeFunction $function
|
|
* @return ?Node
|
|
*/
|
|
public function f_if(Node $node, NodeFunction $function): ?Node
|
|
{
|
|
if (!($function instanceof NodeFunction))
|
|
{
|
|
throw new \Exception('!if expects array of parameters');
|
|
}
|
|
|
|
$nodes = $function->getChildren();
|
|
|
|
$condition = $nodes[0];
|
|
|
|
if (!($condition instanceof NodeValue))
|
|
{
|
|
throw new \Exception('!if requires scalar condition');
|
|
}
|
|
$if_true = $nodes[1];
|
|
$if_false = sizeof($nodes) == 3 ? $nodes[2] : null;
|
|
|
|
$parser = new \App\Engine\Cfnpp\Expression\Parser();
|
|
$expression = $parser->parse($condition->getValue());
|
|
$result = $expression->evaluate($this->options->getVariables());
|
|
|
|
if ($result)
|
|
{
|
|
$if_true->setName($node->hasName() ? $node->getName() : null);
|
|
return $if_true;
|
|
}
|
|
|
|
if (isset($if_false))
|
|
{
|
|
$if_false->setName($node->hasName() ? $node->getName() : null);
|
|
}
|
|
return $if_false;
|
|
}
|
|
}
|
|
|