summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Less/DeferredColorProp.php
diff options
context:
space:
mode:
Diffstat (limited to 'library/Icinga/Less/DeferredColorProp.php')
-rw-r--r--library/Icinga/Less/DeferredColorProp.php136
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);
+ }
+}