diff options
Diffstat (limited to 'library/Icinga/Less/DeferredColorProp.php')
-rw-r--r-- | library/Icinga/Less/DeferredColorProp.php | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/library/Icinga/Less/DeferredColorProp.php b/library/Icinga/Less/DeferredColorProp.php new file mode 100644 index 0000000..c9c39ad --- /dev/null +++ b/library/Icinga/Less/DeferredColorProp.php @@ -0,0 +1,136 @@ +<?php + +/* Icinga Web 2 | (c) 2022 Icinga GmbH | GPLv2+ */ + +namespace Icinga\Less; + +use Less_Exception_Compiler; +use Less_Tree_Call; +use Less_Tree_Color; +use Less_Tree_Keyword; +use Less_Tree_Value; +use Less_Tree_Variable; + +class DeferredColorProp extends Less_Tree_Variable +{ + /** @var DeferredColorProp|ColorProp */ + protected $reference; + + protected $resolved = false; + + public function __construct($name, $variable, $index = null, $currentFileInfo = null) + { + parent::__construct($name, $index, $currentFileInfo); + + if ($variable instanceof Less_Tree_Variable) { + $this->reference = self::fromVariable($variable); + } + } + + public function isResolved() + { + return $this->resolved; + } + + public function getName() + { + $name = $this->name; + if ($this->name[0] === '@') { + $name = substr($this->name, 1); + } + + return $name; + } + + public function hasReference() + { + return $this->reference !== null; + } + + public function getRef() + { + return $this->reference; + } + + public function setReference($ref) + { + $this->reference = $ref; + + return $this; + } + + public static function fromVariable(Less_Tree_Variable $variable) + { + $static = new static($variable->name, $variable->index, $variable->currentFileInfo); + $static->evaluating = $variable->evaluating; + $static->type = $variable->type; + + return $static; + } + + public function compile($env) + { + if (! $this->hasReference()) { + // This is never supposed to happen, however, we might have a deferred color prop + // without a reference. In this case we can simply use the parent method. + return parent::compile($env); + } + + if ($this->isResolved()) { + // The dependencies are already resolved, no need to traverse the frame stack over again! + return $this; + } + + if ($this->evaluating) { // Just like the parent method + throw new Less_Exception_Compiler( + "Recursive variable definition for " . $this->name, + null, + $this->index, + $this->currentFileInfo + ); + } + + $this->evaluating = true; + + foreach ($env->frames as $frame) { + if (($v = $frame->variable($this->getRef()->name))) { + $rv = $v->value; + if ($rv instanceof Less_Tree_Value) { + $rv = $rv->compile($env); + } + + // As we are at it anyway, let's cast the tree color to our color prop as well! + if ($rv instanceof Less_Tree_Color) { + $rv = ColorProp::fromColor($rv); + $rv->setName($this->getRef()->getName()); + } + + $this->evaluating = false; + $this->resolved = true; + $this->setReference($rv); + + break; + } + } + + return $this; + } + + public function genCSS($output) + { + if (! $this->hasReference()) { + return; // Nothing to generate + } + + $css = (new Less_Tree_Call( + 'var', + [ + new Less_Tree_Keyword('--' . $this->getName()), + $this->getRef() // Each of the references will be generated recursively + ], + $this->index + ))->toCSS(); + + $output->add($css); + } +} |