Css2Less::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 1
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 16
    public function __construct($cssContent)
55
    {
56 16
        $this->cssContent = $cssContent;
57 16
        $this->parser = new \CssParser($this->cssContent);
58 16
    }
59
60
    /**
61
     * Iterates through all tokens and extracts the values into variables
62
     */
63 2
    protected function extractVariables()
64
    {
65 2
        $properties = ['color', 'font-family', 'background-color', 'border-color', 'border-top-color', 'border-right-color', 'border-bottom-color', 'border-left-color', 'outline-color'];
66 2
        foreach ($properties as $property) {
67 2
            $propertyName = str_replace('-', '_', $property);
68 2
            $this->variables[$propertyName] = [];
69 2
        }
70
71 2
        foreach ($this->tokens as $token) {
72 2
            if ($token instanceof \CssRulesetDeclarationToken && in_array($token->Property, $properties)) {
73 2
                $propertyName = str_replace('-', '_', $token->Property);
74 2
                if (!array_key_exists($token->Value, $this->variables[$propertyName])) {
75 2
                    $this->variables[$propertyName][$token->Value] = $propertyName . '_' . (count($this->variables[$propertyName]) + 1);
76
77 2
                }
78 2
                $token->Value = '@' . $this->variables[$propertyName][$token->Value];
79 2
            }
80 2
        }
81 2
    }
82
83
    /**
84
     * Returns a string containing all variables to be printed in the output
85
     *
86
     * @return string
87
     */
88 2
    protected function getVariables()
89
    {
90 2
        $return = '';
91 2
        foreach ($this->variables as $properties) {
92 2
            foreach ($properties as $variable => $property) {
93 2
                $return .= "@{$property}: {$variable};\n";
94 2
            }
95 2
        }
96 2
        $return .= "\n";
97 2
        return $return;
98
    }
99
100
    /**
101
     * Returns a string containing the LESS content matching the CSS input
102
     * @return string
103
     */
104 16
    public function getLess($extractVariables = false)
105
    {
106
107 16
        $this->tokens = $this->parser->getTokens();
108
109
        // extract variables
110 16
        if ($extractVariables) {
111 2
            $this->extractVariables();
112 2
        }
113
114 16
        $this->buildNestedTree();
115
116 16
        $return = '';
117
118
        // print variables
119 16
        if ($extractVariables) {
120 2
            $return .= $this->getVariables();
121 2
        }
122
123 16
        foreach ($this->lessTree as $node) {
124
            // @TODO this format method shouldn't be in this class..
125 1
            $return .= $this->ruleSetList->formatTokenAsLess($node) . "\n";
126 16
        }
127
128 16
        $return .= $this->ruleSetList->lessify();
129
130 16
        return $return;
131
    }
132
133
    /**
134
     * Build a nested tree based on the flat CSS tokens
135
     */
136 16
    protected function buildNestedTree()
137
    {
138
        // this variable is true, if we're within a ruleset, e.g. p { .. here .. }
139
        // we have to normalize them
140 16
        $withinRulset = false;
141 16
        $ruleSet = null;
142 16
        $this->ruleSetList = new LessRuleList();
143
144 16
        foreach ($this->tokens as $token) {
145
            // we have to skip some tokens, their information is redundant
146 16
            if ($token instanceof \CssAtMediaStartToken ||
147
                $token instanceof \CssAtMediaEndToken
148 16
            ) {
149 1
                continue;
150
            }
151
152
            // we have to build a hierarchy with CssRulesetStartToken, CssRulesetEndToken
153 16
            if ($token instanceof \CssRulesetStartToken) {
154 16
                $withinRulset = true;
155 16
                $ruleSet = new LessRule($token->Selectors);
156 16
            } elseif ($token instanceof \CssRulesetEndToken) {
157 16
                $withinRulset = false;
158 16
                if ($ruleSet) {
159 16
                    $this->ruleSetList->addRule($ruleSet);
160 16
                }
161 16
                $ruleSet = null;
162 16
            } else {
163
                // as long as we're in a ruleset, we're adding all token to a custom array
164
                // this will be lessified once we've found CssRulesetEndToken and then added
165
                // to the actual $lessTree variable
166 16
                if ($withinRulset) {
167 16
                    $ruleSet->addToken($token);
168 16
                } else {
169 1
                    $this->lessTree[] = $token;
170
                }
171
            }
172 16
        }
173 16
    }
174
}
175