Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * Ensures that systems, asset types and libs are included before they are used.
4
 *
5
 * PHP version 5
6
 *
7
 * @category  PHP
8
 * @package   PHP_CodeSniffer_MySource
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
12
 * @version   CVS: $Id: IncludeSystemSniff.php 283091 2009-06-30 02:08:55Z squiz $
13
 * @link      http://pear.php.net/package/PHP_CodeSniffer
14
 */
15
 
16
if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
17
    $error = 'Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found';
18
    throw new PHP_CodeSniffer_Exception($error);
19
}
20
 
21
/**
22
 * Ensures that systems, asset types and libs are included before they are used.
23
 *
24
 * @category  PHP
25
 * @package   PHP_CodeSniffer_MySource
26
 * @author    Greg Sherwood <gsherwood@squiz.net>
27
 * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
28
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
29
 * @version   Release: 1.2.1
30
 * @link      http://pear.php.net/package/PHP_CodeSniffer
31
 */
32
class MySource_Sniffs_Channels_IncludeSystemSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
33
{
34
 
35
    /**
36
     * A list of classes that don't need to be included.
37
     *
38
     * @var array(string)
39
     */
40
    private $_ignore = array(
41
                        'self',
42
                        'parent',
43
                        'channels',
44
                        'basesystem',
45
                        'dal',
46
                        'init',
47
                        'pdo',
48
                        'util',
49
                        'ziparchive',
50
                        'phpunit_framework_assert',
51
                        'abstractmysourceunittest',
52
                        'abstractdatacleanunittest',
53
                       );
54
 
55
 
56
    /**
57
     * Constructs a Squiz_Sniffs_Scope_MethodScopeSniff.
58
     */
59
    public function __construct()
60
    {
61
        parent::__construct(array(T_FUNCTION), array(T_DOUBLE_COLON, T_EXTENDS), true);
62
 
63
    }//end __construct()
64
 
65
 
66
    /**
67
     * Processes the function tokens within the class.
68
     *
69
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
70
     * @param int                  $stackPtr  The position where the token was found.
71
     * @param int                  $currScope The current scope opener token.
72
     *
73
     * @return void
74
     */
75
    protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
76
    {
77
        $tokens = $phpcsFile->getTokens();
78
 
79
        // Determine the name of the class that the static function
80
        // is being called on.
81
        $classNameToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
82
        $className      = $tokens[$classNameToken]['content'];
83
        if (in_array(strtolower($className), $this->_ignore) === true) {
84
            return;
85
        }
86
 
87
        $includedClasses = array();
88
 
89
        $fileName = strtolower($phpcsFile->getFilename());
90
        $matches  = array();
91
        if (preg_match('|/systems/(.*)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0) {
92
            // This is an actions file, which means we don't
93
            // have to include the system in which it exists
94
            // We know the system from the path.
95
            $includedClasses[] = $matches[2];
96
        }
97
 
98
        // Go searching for includeSystem and includeAsset calls within this
99
        // function, or the inclusion of .inc files, which
100
        // would be library files.
101
        for ($i = ($currScope + 1); $i < $stackPtr; $i++) {
102
            $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
103
            if ($name !== false) {
104
                $includedClasses[] = $name;
105
            }
106
        }
107
 
108
        // Now go searching for includeSystem, includeAsset or require/include
109
        // calls outside our scope. If we are in a class, look outside the
110
        // class. If we are not, look outside the function.
111
        $condPtr = $currScope;
112
        if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true) {
113
            foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType) {
114
                if ($condType === T_CLASS) {
115
                    break;
116
                }
117
            }
118
        }
119
 
120
        for ($i = 0; $i < $condPtr; $i++) {
121
            // Skip other scopes.
122
            if (isset($tokens[$i]['scope_closer']) === true) {
123
                $i = $tokens[$i]['scope_closer'];
124
                continue;
125
            }
126
 
127
            $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
128
            if ($name !== false) {
129
                $includedClasses[] = $name;
130
            }
131
        }//end for
132
 
133
        // If we are in a testing class, we might have also included
134
        // some systems and classes in our setUp() method.
135
        $setupFunction = null;
136
        if ($phpcsFile->hasCondition($stackPtr, T_CLASS) === true) {
137
            foreach ($tokens[$stackPtr]['conditions'] as $condPtr => $condType) {
138
                if ($condType === T_CLASS) {
139
                    // Is this is a testing class?
140
                    $name = $phpcsFile->findNext(T_STRING, $condPtr);
141
                    $name = $tokens[$name]['content'];
142
                    if (substr($name, -8) === 'UnitTest') {
143
                        // Look for a method called setUp().
144
                        $end      = $tokens[$condPtr]['scope_closer'];
145
                        $function = $phpcsFile->findNext(T_FUNCTION, ($condPtr + 1), $end);
146
                        while ($function !== false) {
147
                            $name = $phpcsFile->findNext(T_STRING, $function);
148
                            if ($tokens[$name]['content'] === 'setUp') {
149
                                $setupFunction = $function;
150
                                break;
151
                            }
152
 
153
                            $function = $phpcsFile->findNext(T_FUNCTION, ($function + 1), $end);
154
                        }
155
                    }
156
                }
157
            }//end foreach
158
        }//end if
159
 
160
        if ($setupFunction !== null) {
161
            $start = ($tokens[$setupFunction]['scope_opener'] + 1);
162
            $end   = $tokens[$setupFunction]['scope_closer'];
163
            for ($i = $start; $i < $end; $i++) {
164
                $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
165
                if ($name !== false) {
166
                    $includedClasses[] = $name;
167
                }
168
            }
169
        }//end if
170
 
171
        if (in_array(strtolower($className), $includedClasses) === false) {
172
            $error = "Static method called on non-included class or system \"$className\"; include system with Channels::includeSystem() or include class with require_once";
173
            $phpcsFile->addError($error, $stackPtr);
174
        }
175
 
176
    }//end processTokenWithinScope()
177
 
178
 
179
    /**
180
     * Processes a token within the scope that this test is listening to.
181
     *
182
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
183
     * @param int                  $stackPtr  The position in the stack where
184
     *                                        this token was found.
185
     *
186
     * @return void
187
     */
188
    protected function processTokenOutsideScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
189
    {
190
        $tokens = $phpcsFile->getTokens();
191
 
192
        if ($tokens[$stackPtr]['code'] === T_EXTENDS) {
193
            // Find the class name.
194
            $classNameToken = $phpcsFile->findNext(T_STRING, ($stackPtr + 1));
195
            $className      = $tokens[$classNameToken]['content'];
196
        } else {
197
            // Determine the name of the class that the static function
198
            // is being called on.
199
            $classNameToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
200
            $className      = $tokens[$classNameToken]['content'];
201
        }
202
 
203
        // Some systems are always available.
204
        if (in_array(strtolower($className), $this->_ignore) === true) {
205
            return;
206
        }
207
 
208
        $includedClasses = array();
209
 
210
        $fileName = strtolower($phpcsFile->getFilename());
211
        $matches  = array();
212
        if (preg_match('|/systems/([^/]+)/([^/]+)?actions.inc$|', $fileName, $matches) !== 0) {
213
            // This is an actions file, which means we don't
214
            // have to include the system in which it exists
215
            // We know the system from the path.
216
            $includedClasses[] = $matches[1];
217
        }
218
 
219
        // Go searching for includeSystem, includeAsset or require/include
220
        // calls outside our scope.
221
        for ($i = 0; $i < $stackPtr; $i++) {
222
            // Skip other scopes.
223
            if (isset($tokens[$i]['scope_closer']) === true) {
224
                $i = $tokens[$i]['scope_closer'];
225
                continue;
226
            }
227
 
228
            $name = $this->getIncludedClassFromToken($phpcsFile, $tokens, $i);
229
            if ($name !== false) {
230
                $includedClasses[] = $name;
231
                // Special case for Widgets cause they are, well, special.
232
            } else if (strtolower($tokens[$i]['content']) === 'includewidget') {
233
                $typeName          = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($i + 1));
234
                $typeName          = trim($tokens[$typeName]['content'], " '");
235
                $includedClasses[] = strtolower($typeName).'widgettype';
236
            }
237
        }//end for
238
 
239
        if (in_array(strtolower($className), $includedClasses) === false) {
240
            if ($tokens[$stackPtr]['code'] === T_EXTENDS) {
241
                $error = "Class extends non-included class or system \"$className\"; include system with Channels::includeSystem() or include class with require_once";
242
            } else {
243
                $error = "Static method called on non-included class or system \"$className\"; include system with Channels::includeSystem() or include class with require_once";
244
            }
245
 
246
            $phpcsFile->addError($error, $stackPtr);
247
        }
248
 
249
    }//end processTokenOutsideScope()
250
 
251
 
252
    /**
253
     * Determines the included class name from given token.
254
     *
255
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
256
     * @param array                $tokens    The array of file tokens.
257
     * @param int                  $stackPtr  The position in the tokens array of the
258
     *                                        potentially included class.
259
     *
260
     * @return string
261
     */
262
    protected function getIncludedClassFromToken(PHP_CodeSniffer_File $phpcsFile, $tokens, $stackPtr)
263
    {
264
        if (strtolower($tokens[$stackPtr]['content']) === 'includesystem') {
265
            $systemName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1));
266
            $systemName = trim($tokens[$systemName]['content'], " '");
267
            return strtolower($systemName);
268
        } else if (strtolower($tokens[$stackPtr]['content']) === 'includeasset') {
269
            $typeName = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1));
270
            $typeName = trim($tokens[$typeName]['content'], " '");
271
            return strtolower($typeName).'assettype';
272
        } else if (in_array($tokens[$stackPtr]['code'], PHP_CodeSniffer_Tokens::$includeTokens) === true) {
273
            $filePath = $phpcsFile->findNext(T_CONSTANT_ENCAPSED_STRING, ($stackPtr + 1));
274
            $filePath = $tokens[$filePath]['content'];
275
            $filePath = trim($filePath, " '");
276
            $filePath = basename($filePath, '.inc');
277
            return strtolower($filePath);
278
        }
279
 
280
        return false;
281
 
282
    }//end getIncludedClassFromToken()
283
 
284
 
285
}//end class
286
 
287
?>