Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.91% covered (success)
90.91%
70 / 77
75.00% covered (warning)
75.00%
9 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
Less_Tree
90.91% covered (success)
90.91%
70 / 77
75.00% covered (warning)
75.00%
9 / 12
48.66
0.00% covered (danger)
0.00%
0 / 1
 toCSS
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 genCSS
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 compile
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 _operate
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
 fround
83.33% covered (warning)
83.33%
5 / 6
0.00% covered (danger)
0.00%
0 / 1
3.04
 outputRuleset
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
4
 accept
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 nodeCompare
95.83% covered (success)
95.83%
23 / 24
0.00% covered (danger)
0.00%
0 / 1
21
 numericCompare
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 ReferencedArray
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 __set_state
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 isVisible
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3/**
4 * Tree
5 */
6class Less_Tree {
7
8    /** @var bool */
9    public $parensInOp = false;
10    /** @var true|null */
11    public $extendOnEveryPath;
12    /** @var Less_Tree_Extend[] */
13    public $allExtends;
14    /**
15     * This is set to true to ensure visibility
16     * for all except Less_Tree_Anonymous where we decide
17     * if the the node should be visible or not
18     *
19     * @var bool
20     */
21    public $nodeVisible = true;
22
23    /**
24     * @var Less_Parser
25     * @see less-3.13.1.js#Node.prototype.parse
26     */
27    public static $parse;
28
29    /**
30     * @see less-2.5.3.js#Node.prototype.toCSS
31     */
32    public function toCSS() {
33        $output = new Less_Output();
34        $this->genCSS( $output );
35        return $output->toString();
36    }
37
38    /**
39     * Generate CSS by adding it to the output object
40     *
41     * @param Less_Output $output The output
42     * @return void
43     */
44    public function genCSS( $output ) {
45    }
46
47    public function compile( $env ) {
48        return $this;
49    }
50
51    /**
52     * @param string $op
53     * @param float $a
54     * @param float $b
55     * @see less-2.5.3.js#Node.prototype._operate
56     */
57    protected function _operate( $op, $a, $b ) {
58        switch ( $op ) {
59            case '+':
60                return $a + $b;
61            case '-':
62                return $a - $b;
63            case '*':
64                return $a * $b;
65            case '/':
66                return $a / $b;
67        }
68    }
69
70    /**
71     * @see less-2.5.3.js#Node.prototype.fround
72     */
73    protected function fround( $value ) {
74        if ( $value === 0 ) {
75            return $value;
76        }
77
78        // TODO: Migrate to passing $env.
79        if ( Less_Parser::$options['numPrecision'] ) {
80            $p = pow( 10, Less_Parser::$options['numPrecision'] );
81            return round( $value * $p ) / $p;
82        }
83        return $value;
84    }
85
86    /**
87     * @param Less_Output $output
88     * @param Less_Tree_Ruleset[] $rules
89     */
90    public static function outputRuleset( $output, $rules ) {
91        $ruleCnt = count( $rules );
92        Less_Environment::$tabLevel++;
93
94        // Compressed
95        if ( Less_Parser::$options['compress'] ) {
96            $output->add( '{' );
97            for ( $i = 0; $i < $ruleCnt; $i++ ) {
98                $rules[$i]->genCSS( $output );
99            }
100
101            $output->add( '}' );
102            Less_Environment::$tabLevel--;
103            return;
104        }
105
106        // Non-compressed
107        $tabSetStr = "\n" . str_repeat( Less_Parser::$options['indentation'], Less_Environment::$tabLevel - 1 );
108        $tabRuleStr = $tabSetStr . Less_Parser::$options['indentation'];
109
110        $output->add( " {" );
111        for ( $i = 0; $i < $ruleCnt; $i++ ) {
112            $output->add( $tabRuleStr );
113            $rules[$i]->genCSS( $output );
114        }
115        Less_Environment::$tabLevel--;
116        $output->add( $tabSetStr . '}' );
117    }
118
119    public function accept( $visitor ) {
120    }
121
122    /**
123     * @param Less_Tree $a
124     * @param Less_Tree $b
125     * @return int|null
126     * @see less-2.5.3.js#Node.compare
127     */
128    public static function nodeCompare( $a, $b ) {
129        // Less_Tree subclasses that implement compare() are:
130        // Anonymous, Color, Dimension, Quoted, Unit
131        $aHasCompare = ( $a instanceof Less_Tree_Anonymous || $a instanceof Less_Tree_Color
132            || $a instanceof Less_Tree_Dimension || $a instanceof Less_Tree_Quoted || $a instanceof Less_Tree_Unit
133        );
134        $bHasCompare = ( $b instanceof Less_Tree_Anonymous || $b instanceof Less_Tree_Color
135            || $b instanceof Less_Tree_Dimension || $b instanceof Less_Tree_Quoted || $b instanceof Less_Tree_Unit
136        );
137
138        if ( $aHasCompare &&
139            !( $b instanceof Less_Tree_Quoted || $b instanceof Less_Tree_Anonymous )
140        ) {
141            // for "symmetric results" force toCSS-based comparison via b.compare()
142            // of Quoted or Anonymous if either value is one of those
143            // @phan-suppress-next-line PhanUndeclaredMethod
144            return $a->compare( $b );
145        } elseif ( $bHasCompare ) {
146            $res = $b->compare( $a );
147            // In JS, `-undefined` produces NAN, which, just like undefined
148            // will enter the the default/false branch of Less_Tree_Condition#compile.
149            // In PHP, `-null` is 0. To ensure parity, preserve the null.
150            return $res !== null ? -$res : null;
151        } elseif ( get_class( $a ) !== get_class( $b ) ) {
152            return null;
153        }
154
155        // Less_Tree subclasses that have an array value: Less_Tree_Expression, Less_Tree_Value
156        // @phan-suppress-next-line PhanUndeclaredProperty
157        $aval = $a->value ?? [];
158        $bval = $b->value ?? [];
159        if ( !( $a instanceof Less_Tree_Expression || $a instanceof Less_Tree_Value ) ) {
160            return $aval === $bval ? 0 : null;
161        }
162        '@phan-var Less_Tree[] $aval';
163        '@phan-var Less_Tree[] $bval';
164        if ( count( $aval ) !== count( $bval ) ) {
165            return null;
166        }
167        foreach ( $aval as $i => $item ) {
168            if ( self::nodeCompare( $item, $bval[$i] ) !== 0 ) {
169                return null;
170            }
171        }
172        return 0;
173    }
174
175    /**
176     * @param string|float|int $a
177     * @param string|float|int $b
178     * @return int|null
179     * @see less-2.5.3.js#Node.numericCompare
180     */
181    public static function numericCompare( $a, $b ) {
182        return $a < $b ? -1
183            : ( $a === $b ? 0
184                : ( $a > $b ? 1
185                    // NAN is not greater, less, or equal
186                    : null
187                )
188            );
189    }
190
191    public static function ReferencedArray( $rules ) {
192        foreach ( $rules as $rule ) {
193            if ( method_exists( $rule, 'markReferenced' ) ) {
194                // @phan-suppress-next-line PhanUndeclaredMethod False positive
195                $rule->markReferenced();
196            }
197        }
198    }
199
200    /**
201     * Requires php 5.3+
202     */
203    public static function __set_state( $args ) {
204        $class = get_called_class();
205        $obj = new $class( null, null, null, null );
206        foreach ( $args as $key => $val ) {
207            $obj->$key = $val;
208        }
209        return $obj;
210    }
211
212    /**
213     * @see less-3.13.1.js#Node.prototype.isVisible
214     */
215    public function isVisible() {
216        return $this->nodeVisible;
217    }
218
219}