1<?php
2/**
3 * Ensures that eval() is not used to create objects.
4 *
5 * PHP version 5
6 *
7 * @category  PHP
8 * @package   PHP_CodeSniffer_MySource
9 * @author    Greg Sherwood <gsherwood@squiz.net>
10 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
11 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
12 * @link      http://pear.php.net/package/PHP_CodeSniffer
13 */
14
15/**
16 * Ensures that eval() is not used to create objects.
17 *
18 * @category  PHP
19 * @package   PHP_CodeSniffer_MySource
20 * @author    Greg Sherwood <gsherwood@squiz.net>
21 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
22 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
23 * @version   Release: @package_version@
24 * @link      http://pear.php.net/package/PHP_CodeSniffer
25 */
26class MySource_Sniffs_PHP_EvalObjectFactorySniff implements PHP_CodeSniffer_Sniff
27{
28
29
30    /**
31     * Returns an array of tokens this test wants to listen for.
32     *
33     * @return array
34     */
35    public function register()
36    {
37        return array(T_EVAL);
38
39    }//end register()
40
41
42    /**
43     * Processes this sniff, when one of its tokens is encountered.
44     *
45     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
46     * @param int                  $stackPtr  The position of the current token in
47     *                                        the stack passed in $tokens.
48     *
49     * @return void
50     */
51    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
52    {
53        $tokens = $phpcsFile->getTokens();
54
55        /*
56            We need to find all strings that will be in the eval
57            to determine if the "new" keyword is being used.
58        */
59
60        $openBracket  = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($stackPtr + 1));
61        $closeBracket = $tokens[$openBracket]['parenthesis_closer'];
62
63        $strings = array();
64        $vars    = array();
65
66        for ($i = ($openBracket + 1); $i < $closeBracket; $i++) {
67            if (isset(PHP_CodeSniffer_Tokens::$stringTokens[$tokens[$i]['code']]) === true) {
68                $strings[$i] = $tokens[$i]['content'];
69            } else if ($tokens[$i]['code'] === T_VARIABLE) {
70                $vars[$i] = $tokens[$i]['content'];
71            }
72        }
73
74        /*
75            We now have some variables that we need to expand into
76            the strings that were assigned to them, if any.
77        */
78
79        foreach ($vars as $varPtr => $varName) {
80            while (($prev = $phpcsFile->findPrevious(T_VARIABLE, ($varPtr - 1))) !== false) {
81                // Make sure this is an assignment of the variable. That means
82                // it will be the first thing on the line.
83                $prevContent = $phpcsFile->findPrevious(T_WHITESPACE, ($prev - 1), null, true);
84                if ($tokens[$prevContent]['line'] === $tokens[$prev]['line']) {
85                    $varPtr = $prevContent;
86                    continue;
87                }
88
89                if ($tokens[$prev]['content'] !== $varName) {
90                    // This variable has a different name.
91                    $varPtr = $prevContent;
92                    continue;
93                }
94
95                // We found one.
96                break;
97            }//end while
98
99            if ($prev !== false) {
100                // Find all strings on the line.
101                $lineEnd = $phpcsFile->findNext(T_SEMICOLON, ($prev + 1));
102                for ($i = ($prev + 1); $i < $lineEnd; $i++) {
103                    if (isset(PHP_CodeSniffer_Tokens::$stringTokens[$tokens[$i]['code']]) === true) {
104                        $strings[$i] = $tokens[$i]['content'];
105                    }
106                }
107            }
108        }//end foreach
109
110        foreach ($strings as $string) {
111            // If the string has "new" in it, it is not allowed.
112            // We don't bother checking if the word "new" is echo'd
113            // because that is unlikely to happen. We assume the use
114            // of "new" is for object instantiation.
115            if (strstr($string, ' new ') !== false) {
116                $error = 'Do not use eval() to create objects dynamically; use reflection instead';
117                $phpcsFile->addWarning($error, $stackPtr, 'Found');
118            }
119        }
120
121    }//end process()
122
123
124}//end class
125