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