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