Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * Squiz_Sniffs_PHP_EmbeddedPhpSniff.
4
 *
5
 * PHP version 5
6
 *
7
 * @category  PHP
8
 * @package   PHP_CodeSniffer
9
 * @author    Greg Sherwood <gsherwood@squiz.net>
10
 * @author    Marc McIntyre <mmcintyre@squiz.net>
11
 * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
12
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
13
 * @version   CVS: $Id: EmbeddedPhpSniff.php 246277 2007-11-16 03:09:20Z squiz $
14
 * @link      http://pear.php.net/package/PHP_CodeSniffer
15
 */
16
 
17
/**
18
 * Squiz_Sniffs_PHP_EmbeddedPhpSniff.
19
 *
20
 * Checks the indentation of embedded PHP code segments.
21
 *
22
 * @category  PHP
23
 * @package   PHP_CodeSniffer
24
 * @author    Greg Sherwood <gsherwood@squiz.net>
25
 * @author    Marc McIntyre <mmcintyre@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.1
29
 * @link      http://pear.php.net/package/PHP_CodeSniffer
30
 */
31
class Squiz_Sniffs_PHP_EmbeddedPhpSniff implements PHP_CodeSniffer_Sniff
32
{
33
 
34
 
35
    /**
36
     * Returns an array of tokens this test wants to listen for.
37
     *
38
     * @return array
39
     */
40
    public function register()
41
    {
42
        return array(T_OPEN_TAG);
43
 
44
    }//end register()
45
 
46
 
47
    /**
48
     * Processes this test, when one of its tokens is encountered.
49
     *
50
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
51
     * @param int                  $stackPtr  The position of the current token in the
52
     *                                        stack passed in $tokens.
53
     *
54
     * @return void
55
     */
56
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
57
    {
58
        $tokens = $phpcsFile->getTokens();
59
 
60
        // If the close php tag is on the same line as the opening
61
        // then we have an inline embedded PHP block.
62
        $closeTag = $phpcsFile->findNext(array(T_CLOSE_TAG), $stackPtr);
63
        if ($tokens[$stackPtr]['line'] !== $tokens[$closeTag]['line']) {
64
            $this->_validateMultilineEmbeddedPhp($phpcsFile, $stackPtr);
65
        } else {
66
            $this->_validateInlineEmbeddedPhp($phpcsFile, $stackPtr);
67
        }
68
 
69
    }//end process()
70
 
71
 
72
    /**
73
     * Validates embedded PHP that exists on multiple lines.
74
     *
75
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
76
     * @param int                  $stackPtr  The position of the current token in the
77
     *                                        stack passed in $tokens.
78
     *
79
     * @return void
80
     */
81
    private function _validateMultilineEmbeddedPhp(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
82
    {
83
        $tokens = $phpcsFile->getTokens();
84
 
85
        $prevTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1));
86
        if ($prevTag === false) {
87
            // This is the first open tag.
88
            return;
89
        }
90
 
91
        // This isn't the first opening tag.
92
        $closingTag = $phpcsFile->findNext(T_CLOSE_TAG, $stackPtr);
93
        if ($closingTag === false) {
94
            // No closing tag? Problem.
95
            return;
96
        }
97
 
98
        $nextContent = $phpcsFile->findNext(T_WHITESPACE, ($closingTag + 1), $phpcsFile->numTokens, true);
99
        if ($nextContent === false) {
100
            // Final closing tag. It will be handled elsewhere.
101
            return;
102
        }
103
 
104
        // Make sure the lines are opening and closing on different lines.
105
        if ($tokens[$stackPtr]['line'] === $tokens[$closingTag]['line']) {
106
            return;
107
        }
108
 
109
        // We have an opening and a closing tag, that lie within other content.
110
        // They are also on different lines.
111
        $firstContent = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), $closingTag, true);
112
        if ($firstContent === false) {
113
            $error = 'Empty embedded PHP tag found';
114
            $phpcsFile->addError($error, $stackPtr);
115
            return;
116
        }
117
 
118
        // Check for a blank line at the top.
119
        if ($tokens[$firstContent]['line'] > ($tokens[$stackPtr]['line'] + 1)) {
120
            // Find a token on the blank line to throw the error on.
121
            $i = $stackPtr;
122
            do {
123
                $i++;
124
            } while ($tokens[$i]['line'] !== ($tokens[$stackPtr]['line'] + 1));
125
 
126
            $error = 'Blank line found at start of embedded PHP content';
127
            $phpcsFile->addError($error, $i);
128
        } else if ($tokens[$firstContent]['line'] === $tokens[$stackPtr]['line']) {
129
            $error = 'Opening PHP tag must be on a line by itself';
130
            $phpcsFile->addError($error, $stackPtr);
131
        }
132
 
133
        // Check the indent of the first line.
134
        $startColumn   = $tokens[$stackPtr]['column'];
135
        $contentColumn = $tokens[$firstContent]['column'];
136
        if ($contentColumn !== $startColumn) {
137
            $error = "First line of embedded PHP code must be indented $startColumn spaces; $contentColumn found";
138
            $phpcsFile->addError($error, $firstContent);
139
        }
140
 
141
        // Check for a blank line at the bottom.
142
        $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($closingTag - 1), ($stackPtr + 1), true);
143
        if ($tokens[$lastContent]['line'] < ($tokens[$closingTag]['line'] - 1)) {
144
            // Find a token on the blank line to throw the error on.
145
            $i = $closingTag;
146
            do {
147
                $i--;
148
            } while ($tokens[$i]['line'] !== ($tokens[$closingTag]['line'] - 1));
149
 
150
            $error = 'Blank line found at end of embedded PHP content';
151
            $phpcsFile->addError($error, $i);
152
        } else if ($tokens[$lastContent]['line'] === $tokens[$closingTag]['line']) {
153
            $error = 'Closing PHP tag must be on a line by itself';
154
            $phpcsFile->addError($error, $closingTag);
155
        }
156
 
157
    }//end _validateMultilineEmbeddedPhp()
158
 
159
 
160
    /**
161
     * Validates embedded PHP that exists on one line.
162
     *
163
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
164
     * @param int                  $stackPtr  The position of the current token in the
165
     *                                        stack passed in $tokens.
166
     *
167
     * @return void
168
     */
169
    private function _validateInlineEmbeddedPhp(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
170
    {
171
        $tokens = $phpcsFile->getTokens();
172
 
173
        // We only want one line PHP sections, so return if the closing tag is
174
        // on the next line.
175
        $closeTag = $phpcsFile->findNext(array(T_CLOSE_TAG), $stackPtr, null, false);
176
        if ($tokens[$stackPtr]['line'] !== $tokens[$closeTag]['line']) {
177
            return;
178
        }
179
 
180
        // Check that there is one, and only one space at the start of the statement.
181
        $firstContent = $phpcsFile->findNext(array(T_WHITESPACE), ($stackPtr + 1), null, true);
182
 
183
        if ($firstContent === false || $tokens[$firstContent]['code'] === T_CLOSE_TAG) {
184
            $error = 'Empty embedded PHP tag found';
185
            $phpcsFile->addError($error, $stackPtr);
186
            return;
187
        }
188
 
189
        $leadingSpace = '';
190
        for ($i = ($stackPtr + 1); $i < $firstContent; $i++) {
191
            $leadingSpace .= $tokens[$i]['content'];
192
        }
193
 
194
        if (strlen($leadingSpace) >= 1) {
195
            $error = 'Expected 1 space after openning PHP tag; '.(strlen($leadingSpace) + 1).' found';
196
            $phpcsFile->addError($error, $stackPtr);
197
        }
198
 
199
        $semiColonCount = 0;
200
        $semiColon      = $stackPtr;
201
        $lastSemiColon  = $semiColon;
202
 
203
        while (($semiColon = $phpcsFile->findNext(array(T_SEMICOLON), ($semiColon + 1), $closeTag)) !== false) {
204
            $lastSemiColon = $semiColon;
205
            $semiColonCount++;
206
        }
207
 
208
        $semiColon = $lastSemiColon;
209
        $error     = '';
210
 
211
        // Make sure there is atleast 1 semicolon.
212
        if ($semiColonCount === 0) {
213
            $error = 'Inline PHP statement must end with a semicolon';
214
            $phpcsFile->addError($error, $stackPtr);
215
            return;
216
        }
217
 
218
        // Make sure that there aren't more semicolons than are allowed.
219
        if ($semiColonCount > 1) {
220
            $error = "Inline PHP statement must contain one statement per line; $semiColonCount found";
221
            $phpcsFile->addError($error, $stackPtr);
222
        }
223
 
224
        // The statement contains only 1 semicolon, now it must be spaced properly.
225
        $whitespace = '';
226
        for ($i = ($semiColon + 1); $i < $closeTag; $i++) {
227
            if ($tokens[$i]['code'] !== T_WHITESPACE) {
228
                $error = 'Expected 1 space before closing PHP tag; 0 found';
229
                $phpcsFile->addError($error, $stackPtr);
230
                return;
231
            }
232
 
233
            $whitespace .= $tokens[$i]['content'];
234
        }
235
 
236
        if (strlen($whitespace) === 1) {
237
            return;
238
        }
239
 
240
        if (strlen($whitespace) === 0) {
241
            $error = 'Expected 1 space before closing PHP tag; 0 found';
242
            $phpcsFile->addError($error, $stackPtr);
243
        } else {
244
            $error = 'Expected 1 space before closing PHP tag; '.strlen($whitespace).' found';
245
            $phpcsFile->addError($error, $stackPtr);
246
        }
247
 
248
    }//end _validateInlineEmbeddedPhp()
249
 
250
 
251
}//end class
252
 
253
?>