Completed
Push — master ( 799388...1db2c8 )
by Remo
05:41 queued 03:48
created

Css2Less::buildNestedTree()   C

Complexity

Conditions 8
Paths 7

Size

Total Lines 38
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 38
ccs 24
cts 24
cp 1
rs 5.3846
cc 8
eloc 21
nc 7
nop 0
crap 8
1
<?php
2
3
namespace Ortic\Css2Less;
4
5
use Ortic\Css2Less\tokens\LessRuleList;
6
use Ortic\Css2Less\tokens\LessRule;
7
8
class Css2Less
9
{
10
    /**
11
     * @var string $cssContent
12
     */
13
    protected $cssContent;
14
15
    /**
16
     * @var \CssParser $parser
17
     */
18
    protected $parser;
19
20
    /**
21
     * Tokens.
22
     *
23
     * @var array
24
     */
25
    protected $tokens = [];
26
27
    /**
28
     * Nested CSS tree
29
     *
30
     * @var array
31
     */
32
    protected $lessTree = [];
33
34
    /**
35
     * List of CSS rules
36
     *
37
     * @var LessRuleList
38
     */
39
    protected $ruleSetList;
40
41
    /**
42
     * Variables.
43
     *
44
     * @var array
45
     */
46
    protected $variables = [];
47
48
    /**
49
     * Create a new parser object, use parameter to specify CSS you
50
     * wish to convert into a LESS file
51
     *
52
     * @param string $cssContent
53
     */
54 10
    public function __construct($cssContent)
55
    {
56 10
        $this->cssContent = $cssContent;
57 10
        $this->parser = new \CssParser($this->cssContent);
58 10
    }
59
60
    /**
61
     * Iterates through all tokens and extracts the values into variables
62
     */
63 1
    protected function extractVariables()
64
    {
65 1
        $properties = ['color', 'font-family'];
66 1
        foreach ($properties as $property) {
67 1
            $this->variables[$property] = [];
68 1
        }
69
70 1
        foreach ($this->tokens as $token) {
71 1
            if ($token instanceof \CssRulesetDeclarationToken && in_array($token->Property, $properties)) {
72 1
                if (!array_key_exists($token->Value, $this->variables[$token->Property])) {
73 1
                    $this->variables[$token->Property][$token->Value] = $token->Property . '_' . (count($this->variables[$token->Property]) + 1);
74
75 1
                }
76 1
                $token->Value = '@' . $this->variables[$token->Property][$token->Value];
77 1
            }
78 1
        }
79 1
    }
80
81
    /**
82
     * Returns a string containing all variables to be printed in the output
83
     *
84
     * @return string
85
     */
86 1
    protected function getVariables()
87
    {
88 1
        $return = '';
89 1
        foreach ($this->variables as $properties) {
90 1
            foreach ($properties as $variable => $property) {
91 1
                $return .= "@{$property}: {$variable};\n";
92 1
            }
93 1
        }
94 1
        $return .= "\n";
95 1
        return $return;
96
    }
97
98
    /**
99
     * Returns a string containing the LESS content matching the CSS input
100
     * @return string
101
     */
102 10
    public function getLess($extractVariables = false)
103
    {
104
105 10
        $this->tokens = $this->parser->getTokens();
106
107
        // extract variables
108 10
        if ($extractVariables) {
109 1
            $this->extractVariables();
110 1
        }
111
112 10
        $this->buildNestedTree();
113
114 10
        $return = '';
115
116
        // print variables
117 10
        if ($extractVariables) {
118 1
            $return .= $this->getVariables();
119 1
        }
120
121 10
        foreach ($this->lessTree as $node) {
122
            // @TODO this format method shouldn't be in this class..
123 1
            $return .= $this->ruleSetList->formatTokenAsLess($node) . "\n";
124 10
        }
125
126 10
        $return .= $this->ruleSetList->lessify();
127
128 10
        return $return;
129
    }
130
131
    /**
132
     * Build a nested tree based on the flat CSS tokens
133
     */
134 10
    protected function buildNestedTree()
135
    {
136
        // this variable is true, if we're within a ruleset, e.g. p { .. here .. }
137
        // we have to normalize them
138 10
        $withinRulset = false;
139 10
        $ruleSet = null;
140 10
        $this->ruleSetList = new LessRuleList();
141
142 10
        foreach ($this->tokens as $token) {
143
            // we have to skip some tokens, their information is redundant
144 10
            if ($token instanceof \CssAtMediaStartToken ||
145
                $token instanceof \CssAtMediaEndToken
146 10
            ) {
147 1
                continue;
148
            }
149
150
            // we have to build a hierarchy with CssRulesetStartToken, CssRulesetEndToken
151 10
            if ($token instanceof \CssRulesetStartToken) {
152 10
                $withinRulset = true;
153 10
                $ruleSet = new LessRule($token->Selectors);
154 10
            } elseif ($token instanceof \CssRulesetEndToken) {
155 10
                $withinRulset = false;
156 10
                if ($ruleSet) {
157 10
                    $this->ruleSetList->addRule($ruleSet);
158 10
                }
159 10
                $ruleSet = null;
160 10
            } else {
161
                // as long as we're in a ruleset, we're adding all token to a custom array
162
                // this will be lessified once we've found CssRulesetEndToken and then added
163
                // to the actual $lessTree variable
164 10
                if ($withinRulset) {
165 10
                    $ruleSet->addToken($token);
166 10
                } else {
167 1
                    $this->lessTree[] = $token;
168
                }
169
            }
170 10
        }
171 10
    }
172
}
173