1<?php
2/**
3 * Squiz_Sniffs_Scope_StaticThisUsageSniff.
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-2014 Squiz Pty Ltd (ABN 77 084 670 600)
12 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
13 * @link      http://pear.php.net/package/PHP_CodeSniffer
14 */
15
16if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
17    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found');
18}
19
20/**
21 * Squiz_Sniffs_Scope_StaticThisUsageSniff.
22 *
23 * Checks for usage of "$this" in static methods, which will cause
24 * runtime errors.
25 *
26 * @category  PHP
27 * @package   PHP_CodeSniffer
28 * @author    Greg Sherwood <gsherwood@squiz.net>
29 * @author    Marc McIntyre <mmcintyre@squiz.net>
30 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
31 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
32 * @version   Release: @package_version@
33 * @link      http://pear.php.net/package/PHP_CodeSniffer
34 */
35class Squiz_Sniffs_Scope_StaticThisUsageSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
36{
37
38
39    /**
40     * Constructs the test with the tokens it wishes to listen for.
41     */
42    public function __construct()
43    {
44        parent::__construct(array(T_CLASS), array(T_FUNCTION));
45
46    }//end __construct()
47
48
49    /**
50     * Processes this test, when one of its tokens is encountered.
51     *
52     * @param PHP_CodeSniffer_File $phpcsFile The current file being scanned.
53     * @param int                  $stackPtr  The position of the current token in the
54     *                                        stack passed in $tokens.
55     * @param int                  $currScope A pointer to the start of the scope.
56     *
57     * @return void
58     */
59    public function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
60    {
61        $tokens   = $phpcsFile->getTokens();
62        $function = $tokens[($stackPtr + 2)];
63
64        if ($function['code'] !== T_STRING) {
65            return;
66        }
67
68        $functionName = $function['content'];
69        $classOpener  = $tokens[$currScope]['scope_condition'];
70        $className    = $tokens[($classOpener + 2)]['content'];
71
72        $methodProps = $phpcsFile->getMethodProperties($stackPtr);
73
74        if ($methodProps['is_static'] === true) {
75            if (isset($tokens[$stackPtr]['scope_closer']) === false) {
76                // There is no scope opener or closer, so the function
77                // must be abstract.
78                return;
79            }
80
81            $thisUsage = $stackPtr;
82            while (($thisUsage = $phpcsFile->findNext(array(T_VARIABLE), ($thisUsage + 1), $tokens[$stackPtr]['scope_closer'], false, '$this')) !== false) {
83                if ($thisUsage === false) {
84                    return;
85                }
86
87                $error = 'Usage of "$this" in static methods will cause runtime errors';
88                $phpcsFile->addError($error, $thisUsage, 'Found');
89            }
90        }//end if
91
92    }//end processTokenWithinScope()
93
94
95}//end class
96