Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
76 / 76
100.00% covered (success)
100.00%
11 / 11
CRAP
100.00% covered (success)
100.00%
1 / 1
Less_Tree_Selector
100.00% covered (success)
100.00%
76 / 76
100.00% covered (success)
100.00%
11 / 11
42
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
3
 accept
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 createDerived
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
3
 match
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 CacheElements
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
10
 isJustParentSelector
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
5
 compile
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
4
 genCSS
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
4
 markReferenced
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getIsReferenced
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
3
 getIsOutput
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * @private
4 */
5class Less_Tree_Selector extends Less_Tree {
6
7    /** @var Less_Tree_Element[] */
8    public $elements;
9    /** @var Less_Tree_Condition|null */
10    public $condition;
11    /** @var Less_Tree_Extend[] */
12    public $extendList = [];
13    /** @var int|null */
14    public $index;
15    /** @var bool */
16    public $evaldCondition = false;
17    /** @var array|null */
18    public $currentFileInfo = [];
19    /** @var null|bool */
20    public $isReferenced;
21    /** @var null|bool */
22    public $mediaEmpty;
23
24    /** @var int */
25    public $elements_len = 0;
26
27    /** @var string[] */
28    public $_oelements;
29    /** @var array<string,true> */
30    public $_oelements_assoc;
31    /** @var int */
32    public $_oelements_len;
33    /** @var bool */
34    public $cacheable = true;
35
36    /**
37     * @param Less_Tree_Element[] $elements
38     * @param Less_Tree_Element[] $extendList
39     * @param Less_Tree_Condition|null $condition
40     * @param int|null $index
41     * @param array|null $currentFileInfo
42     * @param bool|null $isReferenced
43     */
44    public function __construct( $elements, $extendList = [], $condition = null, $index = null, $currentFileInfo = null, $isReferenced = null ) {
45        $this->elements = $elements;
46        $this->elements_len = count( $elements );
47        $this->extendList = $extendList;
48        $this->condition = $condition;
49        if ( $currentFileInfo ) {
50            $this->currentFileInfo = $currentFileInfo;
51        }
52        $this->isReferenced = $isReferenced;
53        if ( !$condition ) {
54            $this->evaldCondition = true;
55        }
56
57        $this->CacheElements();
58    }
59
60    public function accept( $visitor ) {
61        $this->elements = $visitor->visitArray( $this->elements );
62        $this->extendList = $visitor->visitArray( $this->extendList );
63        if ( $this->condition ) {
64            $this->condition = $visitor->visitObj( $this->condition );
65        }
66
67        if ( $visitor instanceof Less_Visitor_extendFinder ) {
68            $this->CacheElements();
69        }
70    }
71
72    public function createDerived( $elements, $extendList = null, $evaldCondition = null ) {
73        $newSelector = new self(
74            $elements,
75            ( $extendList ?: $this->extendList ),
76            null,
77            $this->index,
78            $this->currentFileInfo,
79            $this->isReferenced
80        );
81        $newSelector->evaldCondition = $evaldCondition ?: $this->evaldCondition;
82        $newSelector->mediaEmpty = $this->mediaEmpty;
83        return $newSelector;
84    }
85
86    public function match( $other ) {
87        if ( !$other->_oelements || ( $this->elements_len < $other->_oelements_len ) ) {
88            return 0;
89        }
90
91        for ( $i = 0; $i < $other->_oelements_len; $i++ ) {
92            if ( $this->elements[$i]->value !== $other->_oelements[$i] ) {
93                return 0;
94            }
95        }
96
97        return $other->_oelements_len; // return number of matched elements
98    }
99
100    /**
101     * @see less-2.5.3.js#Selector.prototype.CacheElements
102     */
103    public function CacheElements() {
104        $this->_oelements = [];
105        $this->_oelements_assoc = [];
106
107        $css = '';
108
109        foreach ( $this->elements as $v ) {
110
111            $css .= $v->combinator;
112            if ( !( $v->value instanceof Less_Tree ) ) {
113                $css .= $v->value;
114                continue;
115            }
116
117            // @phan-suppress-next-line PhanUndeclaredProperty
118            if ( isset( $v->value->value ) && is_scalar( $v->value->value ) ) {
119                // @phan-suppress-next-line PhanUndeclaredProperty
120                $css .= $v->value->value;
121                continue;
122            }
123
124            if ( ( $v->value instanceof Less_Tree_Selector || $v->value instanceof Less_Tree_Variable )
125                // @phan-suppress-next-line PhanUndeclaredProperty
126                || !is_string( $v->value->value ) ) {
127                $this->cacheable = false;
128                return;
129            }
130        }
131
132        $this->_oelements_len = preg_match_all( '/[,&#\*\.\w-](?:[\w-]|(?:\\\\.))*/', $css, $matches );
133        if ( $this->_oelements_len ) {
134            $this->_oelements = $matches[0];
135
136            if ( $this->_oelements[0] === '&' ) {
137                array_shift( $this->_oelements );
138                $this->_oelements_len--;
139            }
140
141            $this->_oelements_assoc = array_fill_keys( $this->_oelements, true );
142        }
143    }
144
145    public function isJustParentSelector() {
146        return !$this->mediaEmpty &&
147            count( $this->elements ) === 1 &&
148            $this->elements[0]->value === '&' &&
149            ( $this->elements[0]->combinator === ' ' || $this->elements[0]->combinator === '' );
150    }
151
152    public function compile( $env ) {
153        $elements = [];
154        foreach ( $this->elements as $el ) {
155            $elements[] = $el->compile( $env );
156        }
157
158        $extendList = [];
159        foreach ( $this->extendList as $el ) {
160            $extendList[] = $el->compile( $env );
161        }
162
163        $evaldCondition = false;
164        if ( $this->condition ) {
165            $evaldCondition = $this->condition->compile( $env );
166        }
167
168        return $this->createDerived( $elements, $extendList, $evaldCondition );
169    }
170
171    /**
172     * @see Less_Tree::genCSS
173     */
174    public function genCSS( $output, $firstSelector = true ) {
175        if ( !$firstSelector && $this->elements[0]->combinator === "" ) {
176            $output->add( ' ', $this->currentFileInfo, $this->index );
177        }
178
179        foreach ( $this->elements as $element ) {
180            $element->genCSS( $output );
181        }
182    }
183
184    public function markReferenced() {
185        $this->isReferenced = true;
186    }
187
188    public function getIsReferenced() {
189        return !isset( $this->currentFileInfo['reference'] ) || !$this->currentFileInfo['reference'] || $this->isReferenced;
190    }
191
192    public function getIsOutput() {
193        return $this->evaldCondition;
194    }
195
196}