Subversion Repositories Applications.framework

Rev

Rev 5 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 aurelien 1
<?php
2
/**
3
 * Tokenizes CSS code.
4
 *
5
 * PHP version 5
6
 *
7
 * @category  PHP
8
 * @package   PHP_CodeSniffer
9
 * @author    Greg Sherwood <gsherwood@squiz.net>
10
 * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
11
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
34 aurelien 12
 * @version   CVS: $Id: CSS.php 34 2009-04-09 07:34:39Z aurelien $
5 aurelien 13
 * @link      http://pear.php.net/package/PHP_CodeSniffer
14
 */
15
 
16
if (class_exists('PHP_CodeSniffer_Tokenizers_PHP', true) === false) {
17
    throw new Exception('Class PHP_CodeSniffer_Tokenizers_PHP not found');
18
}
19
 
20
/**
21
 * Tokenizes CSS code.
22
 *
23
 * @category  PHP
24
 * @package   PHP_CodeSniffer
25
 * @author    Greg Sherwood <gsherwood@squiz.net>
26
 * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
27
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
28
 * @version   Release: 1.2.0RC1
29
 * @link      http://pear.php.net/package/PHP_CodeSniffer
30
 */
31
class PHP_CodeSniffer_Tokenizers_CSS extends PHP_CodeSniffer_Tokenizers_PHP
32
{
33
 
34
 
35
    /**
36
     * Creates an array of tokens when given some CSS code.
37
     *
38
     * Uses the PHP tokenizer to do all the tricky work
39
     *
40
     * @param string $string  The string to tokenize.
41
     * @param string $eolChar The EOL character to use for splitting strings.
42
     *
43
     * @return array
44
     */
45
    public function tokenizeString($string, $eolChar='\n')
46
    {
47
        $tokens      = parent::tokenizeString('<?php '.$string.' ?>', $eolChar);
48
        $finalTokens = array();
49
 
50
        $newStackPtr = 0;
51
        $numTokens   = count($tokens);
52
        for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) {
53
            $token = $tokens[$stackPtr];
54
 
55
            // Styles like list-style are tokenized as T_LIST-T_STRING
56
            // so convert the T_LIST to a string.
57
            if ($token['code'] === T_LIST) {
58
                $token['code'] = T_STRING;
59
                $token['type'] = 'T_STRING';
60
            }
61
 
62
            if ($token['code'] === T_COMMENT
63
                && (substr($token['content'], 0, 2) === '//'
64
                || $token['content']{0} === '#')
65
            ) {
66
                $content = ltrim($token['content'], '#/');
67
                $commentTokens
68
                    = parent::tokenizeString('<?php '.$content.'?>', $eolChar);
69
 
70
                // The first and last tokens are the open/close tags.
71
                array_shift($commentTokens);
72
                array_pop($commentTokens);
73
 
74
                if ($token['content']{0} === '#') {
75
                    // The # character is not a comment in CSS files, so determine
76
                    // what it means in this context.
77
                    $firstContent = $commentTokens[0]['content'];
78
 
79
                    // If the first content is just a number, it is probably a
80
                    // colour like 8FB7DB, which PHP splits into 8 and FB7DB.
81
                    if ($commentTokens[0]['code'] === T_LNUMBER
82
                        && $commentTokens[1]['code'] === T_STRING
83
                    ) {
84
                        $firstContent .= $commentTokens[1]['content'];
85
                        array_shift($commentTokens);
86
                    }
87
 
88
                    // If the first content looks like a colour and not a class
89
                    // definition, join the tokens together.
90
                    if (preg_match('/^[ABCDEF0-9]+$/i', $firstContent) === 1) {
91
                        array_shift($commentTokens);
92
                        $finalTokens[$newStackPtr] = array(
93
                                                      'type'    => 'T_COLOUR',
94
                                                      'code'    => T_COLOUR,
95
                                                      'content' => '#'.$firstContent,
96
                                                     );
97
                    } else {
98
                        $finalTokens[$newStackPtr] = array(
99
                                                      'type'    => 'T_HASH',
100
                                                      'code'    => T_HASH,
101
                                                      'content' => '#',
102
                                                     );
103
                    }
104
                } else {
105
                    $finalTokens[$newStackPtr] = array(
106
                                                  'type'    => 'T_STRING',
107
                                                  'code'    => T_STRING,
108
                                                  'content' => '//',
109
                                                 );
110
                }//end if
111
 
112
                $newStackPtr++;
113
 
114
                foreach ($commentTokens as $tokenData) {
115
                    $finalTokens[$newStackPtr] = $tokenData;
116
                    $newStackPtr++;
117
                }
118
 
119
                continue;
120
            }//end if
121
 
122
            $finalTokens[$newStackPtr] = $token;
123
            $newStackPtr++;
124
        }//end for
125
 
126
        $numTokens = count($finalTokens);
127
        for ($stackPtr = 0; $stackPtr < $numTokens; $stackPtr++) {
128
            $token = $finalTokens[$stackPtr];
129
 
130
            switch ($token['code']) {
131
            case T_MINUS:
132
                // Minus signs are often used instead of spaces inside
133
                // class names, IDs and styles.
134
                if ($finalTokens[($stackPtr + 1)]['code'] === T_STRING) {
135
                    if ($finalTokens[($stackPtr - 1)]['code'] === T_STRING) {
136
                        $newContent = $finalTokens[($stackPtr - 1)]['content'].'-'.$finalTokens[($stackPtr + 1)]['content'];
137
 
138
                        $finalTokens[($stackPtr - 1)]['content'] = $newContent;
139
                        unset($finalTokens[$stackPtr]);
140
                        unset($finalTokens[($stackPtr + 1)]);
141
                        $stackPtr -= 2;
142
                    } else {
143
                        $newContent = '-'.$finalTokens[($stackPtr + 1)]['content'];
144
 
145
                        $finalTokens[($stackPtr + 1)]['content'] = $newContent;
146
                        unset($finalTokens[$stackPtr]);
147
                        $stackPtr--;
148
                    }
149
 
150
                    $finalTokens = array_values($finalTokens);
151
                    $numTokens   = count($finalTokens);
152
                } else if ($finalTokens[($stackPtr + 1)]['code'] === T_LNUMBER) {
153
                    // They can also be used to provide negative numbers.
154
                    $finalTokens[($stackPtr + 1)]['content']
155
                        = '-'.$finalTokens[($stackPtr + 1)]['content'];
156
                    unset($finalTokens[$stackPtr]);
157
 
158
                    $finalTokens = array_values($finalTokens);
159
                    $numTokens   = count($finalTokens);
160
                }
161
 
162
                break;
163
            case T_COLON:
164
                // Find the previous content.
165
                for ($x = ($stackPtr - 1); $x >= 0; $x--) {
166
                    if (in_array($finalTokens[$x]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
167
                        break;
168
                    }
169
                }
170
 
171
                $finalTokens[$x]['type'] = 'T_STYLE';
172
                $finalTokens[$x]['code'] = T_STYLE;
173
                break;
174
            case T_STRING:
175
                if (strtolower($token['content']) === 'url') {
176
                    // Find the next content.
177
                    for ($x = ($stackPtr + 1); $x < $numTokens; $x++) {
178
                        if (in_array($finalTokens[$x]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
179
                            break;
180
                        }
181
                    }
182
 
183
                    // Needs to be in the format url( for it to be a URL.
184
                    if ($finalTokens[$x]['code'] !== T_OPEN_PARENTHESIS) {
185
                        continue;
186
                    }
187
 
188
                    // Join all the content together inside the url() statement.
189
                    $newContent = '';
190
                    for ($i = ($x + 2); $i < $numTokens; $i++) {
191
                        if ($finalTokens[$i]['code'] === T_CLOSE_PARENTHESIS) {
192
                            break;
193
                        }
194
 
195
                        $newContent .= $finalTokens[$i]['content'];
196
                        unset($finalTokens[$i]);
197
                    }
198
 
199
                    $finalTokens[($x + 1)]['type']     = 'T_URL';
200
                    $finalTokens[($x + 1)]['code']     = T_URL;
201
                    $finalTokens[($x + 1)]['content'] .= $newContent;
202
 
203
                    $finalTokens = array_values($finalTokens);
204
                    $numTokens   = count($finalTokens);
205
                }//end if
206
 
207
                break;
208
            default:
209
                // Nothing special to be done with this token.
210
                break;
211
            }//end switch
212
        }//end for
213
 
214
        return $finalTokens;
215
 
216
    }//end tokenizeString()
217
 
218
 
219
}//end class
220
 
221
?>