/** * Processes this function call. * * @param PHP_CodeSniffer_File $phpcsFile * The file being scanned. * @param int $stackPtr * The position of the function call in the stack. * @param int $openBracket * The position of the opening parenthesis in the stack. * @param int $closeBracket * The position of the closing parenthesis in the stack. * @param Drupal_Sniffs_Semantics_FunctionCallSniff $sniff * Can be used to retreive the function's arguments with the getArgument() * method. * * @return void */ public function processFunctionCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $closeBracket, Drupal_Sniffs_Semantics_FunctionCallSniff $sniff) { $tokens = $phpcsFile->getTokens(); // We assume that the sequence '#default_value' => variable_get(...) // indicates a variable that the module owns. $arrow = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr - 1, null, true); if ($arrow === false || $tokens[$arrow]['code'] !== T_DOUBLE_ARROW) { return; } $arrayKey = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, $arrow - 1, null, true); if ($arrayKey === false || $tokens[$arrayKey]['code'] !== T_CONSTANT_ENCAPSED_STRING || substr($tokens[$arrayKey]['content'], 1, -1) !== '#default_value') { return; } $argument = $sniff->getArgument(1); // Variable name is not a literal string, so we return early. if ($argument === false || $tokens[$argument['start']]['code'] !== T_CONSTANT_ENCAPSED_STRING) { return; } $moduleName = DrupalPractice_Project::getName($phpcsFile); if ($moduleName === false) { return; } $variableName = substr($tokens[$argument['start']]['content'], 1, -1); if (strpos($variableName, $moduleName) !== 0) { $warning = 'All variables defined by your module must be prefixed with your module\'s name to avoid name collisions with others. Expected start with "%s" but found "%s"'; $data = array($moduleName, $variableName); $phpcsFile->addWarning($warning, $argument['start'], 'VariableName', $data); } }
/** * Process this function definition. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the function name in the stack. * name in the stack. * @param int $functionPtr The position of the function keyword in the stack. * keyword in the stack. * * @return void */ public function processFunction(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $functionPtr) { $fileExtension = strtolower(substr($phpcsFile->getFilename(), -7)); // Only check in *.install files. if ($fileExtension !== 'install') { return; } $fileName = substr(basename($phpcsFile->getFilename()), 0, -8); $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr]['content'] !== $fileName . '_install' && $tokens[$stackPtr]['content'] !== $fileName . '_requirements') { return; } // This check only applies to Drupal 7, not Drupal 8. if (DrupalPractice_Project::getCoreVersion($phpcsFile) !== '7.x') { return; } // Search in the function body for t() calls. $string = $phpcsFile->findNext(T_STRING, $tokens[$functionPtr]['scope_opener'], $tokens[$functionPtr]['scope_closer']); while ($string !== false) { if ($tokens[$string]['content'] === 't' || $tokens[$string]['content'] === 'st') { $opener = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $string + 1, null, true); if ($opener !== false && $tokens[$opener]['code'] === T_OPEN_PARENTHESIS) { $error = 'Do not use t() or st() in installation phase hooks, use $t = get_t() to retrieve the appropriate localization function name'; $phpcsFile->addError($error, $string, 'TranslationFound'); } } $string = $phpcsFile->findNext(T_STRING, $string + 1, $tokens[$functionPtr]['scope_closer']); } //end while }
/** * Processes this test, when one of its tokens is encountered. * * @param PHP_CodeSniffer_File $phpcsFile The current file being processed. * @param int $stackPtr The position of the current token * in the stack passed in $tokens. * * @return void */ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) { // If there is a PHP 5.3 namespace declaration in the file we return // immediately as classes can be named arbitrary within a namespace. $namespace = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr - 1); if ($namespace !== false) { return; } $moduleName = DrupalPractice_Project::getName($phpcsFile); if ($moduleName === false) { return; } $tokens = $phpcsFile->getTokens(); $className = $phpcsFile->findNext(T_STRING, $stackPtr); $name = trim($tokens[$className]['content']); // Underscores are omitted in class names. Also convert all characters // to lower case to compare them later. $classPrefix = strtolower(str_replace('_', '', $moduleName)); // Views classes might have underscores in the name, which is also fine. $viewsPrefix = strtolower($moduleName); $name = strtolower($name); if (strpos($name, $classPrefix) !== 0 && strpos($name, $viewsPrefix) !== 0) { $warning = '%s name must be prefixed with the project name "%s"'; $nameParts = explode('_', $moduleName); $camelName = ''; foreach ($nameParts as &$part) { $camelName .= ucfirst($part); } $errorData = array(ucfirst($tokens[$stackPtr]['content']), $camelName); $phpcsFile->addWarning($warning, $className, 'ClassPrefix', $errorData); } }
/** * Process this function definition. * * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. * @param int $stackPtr The position of the function name in the stack. * name in the stack. * @param int $functionPtr The position of the function keyword in the stack. * keyword in the stack. * * @return void */ public function processFunction(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $functionPtr) { $fileExtension = strtolower(substr($phpcsFile->getFilename(), -6)); // Only check in *.module files. if ($fileExtension !== 'module') { return; } // This check only applies to Drupal 7, not Drupal 6. if (DrupalPractice_Project::getCoreVersion($phpcsFile) !== '7.x') { return; } $fileName = substr(basename($phpcsFile->getFilename()), 0, -7); $tokens = $phpcsFile->getTokens(); if ($tokens[$stackPtr]['content'] !== $fileName . '_init' && $tokens[$stackPtr]['content'] !== $fileName . '_page_build') { return; } // Search in the function body for drupal_add_css() calls. $string = $phpcsFile->findNext(T_STRING, $tokens[$functionPtr]['scope_opener'], $tokens[$functionPtr]['scope_closer']); while ($string !== false) { if ($tokens[$string]['content'] === 'drupal_add_css' || $tokens[$string]['content'] === 'drupal_add_js') { $opener = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $string + 1, null, true); if ($opener !== false && $tokens[$opener]['code'] === T_OPEN_PARENTHESIS) { if ($tokens[$stackPtr]['content'] === $fileName . '_init') { $warning = 'Do not use %s() in hook_init(), move it to your page/form callback or use hook_page_build() instead'; $phpcsFile->addWarning($warning, $string, 'AddFunctionFound', array($tokens[$string]['content'])); } else { $warning = 'Do not use %s() in hook_page_build(), use #attached on the $page render array instead'; $phpcsFile->addWarning($warning, $string, 'AddFunctionFoundPageBuild', array($tokens[$string]['content'])); } } } $string = $phpcsFile->findNext(T_STRING, $string + 1, $tokens[$functionPtr]['scope_closer']); } //end while }
/** * Processes this function call. * * @param PHP_CodeSniffer_File $phpcsFile * The file being scanned. * @param int $stackPtr * The position of the function call in the stack. * @param int $openBracket * The position of the opening parenthesis in the stack. * @param int $closeBracket * The position of the closing parenthesis in the stack. * * @return void */ public function processFunctionCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $closeBracket) { // This check only applies to Drupal 7, not Drupal 6. if (DrupalPractice_Project::getCoreVersion($phpcsFile) !== '7.x') { return; } $tokens = $phpcsFile->getTokens(); $argument = $this->getArgument(1); $query_start = ''; for ($start = $argument['start']; $tokens[$start]['code'] === T_CONSTANT_ENCAPSED_STRING && empty($query_start) === true; $start++) { // Remove quote and white space from the beginning. $query_start = trim(substr($tokens[$start]['content'], 1)); // Just look at the first word. $parts = explode(' ', $query_start); $query_start = $parts[0]; if (in_array(strtoupper($query_start), array('INSERT', 'UPDATE', 'DELETE', 'TRUNCATE')) === true) { $warning = 'Do not use %s queries with db_query(), use %s instead'; $phpcsFile->addWarning($warning, $start, 'DbQuery', array($query_start, 'db_' . strtolower($query_start) . '()')); } } }
/** * Tests the extending classes Sniff class. * * @dataProvider coreVersionProvider */ public function testCoreVersion($filename, $core_version) { $this->phpcsFile->expects($this->any())->method('getFilename')->will($this->returnValue($filename)); $this->assertEquals(DrupalPractice_Project::getCoreVersion($this->phpcsFile), $core_version); }