annotate vendor/drupal/coder/coder_sniffer/Drupal/Sniffs/Semantics/FunctionTSniff.php @ 2:92f882872392

Trusted hosts, + remove migration modules
author Chris Cannam
date Tue, 05 Dec 2017 09:26:43 +0000
parents 4c8ae668cc8c
children 129ea1e6d783
rev   line source
Chris@0 1 <?php
Chris@0 2 /**
Chris@0 3 * Drupal_Sniffs_Semantics_FunctionTSniff
Chris@0 4 *
Chris@0 5 * @category PHP
Chris@0 6 * @package PHP_CodeSniffer
Chris@0 7 * @link http://pear.php.net/package/PHP_CodeSniffer
Chris@0 8 */
Chris@0 9
Chris@0 10 /**
Chris@0 11 * Check the usage of the t() function to not escape translateable strings with back
Chris@0 12 * slashes. Also checks that the first argument does not use string concatenation.
Chris@0 13 *
Chris@0 14 * @category PHP
Chris@0 15 * @package PHP_CodeSniffer
Chris@0 16 * @link http://pear.php.net/package/PHP_CodeSniffer
Chris@0 17 */
Chris@0 18 class Drupal_Sniffs_Semantics_FunctionTSniff extends Drupal_Sniffs_Semantics_FunctionCall
Chris@0 19 {
Chris@0 20
Chris@0 21 /**
Chris@0 22 * We also want to catch $this->t() calls in Drupal 8.
Chris@0 23 *
Chris@0 24 * @var bool
Chris@0 25 */
Chris@0 26 protected $includeMethodCalls = true;
Chris@0 27
Chris@0 28
Chris@0 29 /**
Chris@0 30 * Returns an array of function names this test wants to listen for.
Chris@0 31 *
Chris@0 32 * @return array
Chris@0 33 */
Chris@0 34 public function registerFunctionNames()
Chris@0 35 {
Chris@0 36 return array(
Chris@0 37 't',
Chris@0 38 'TranslatableMarkup',
Chris@0 39 'TranslationWrapper',
Chris@0 40 );
Chris@0 41
Chris@0 42 }//end registerFunctionNames()
Chris@0 43
Chris@0 44
Chris@0 45 /**
Chris@0 46 * Processes this function call.
Chris@0 47 *
Chris@0 48 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
Chris@0 49 * @param int $stackPtr The position of the function call in
Chris@0 50 * the stack.
Chris@0 51 * @param int $openBracket The position of the opening
Chris@0 52 * parenthesis in the stack.
Chris@0 53 * @param int $closeBracket The position of the closing
Chris@0 54 * parenthesis in the stack.
Chris@0 55 *
Chris@0 56 * @return void
Chris@0 57 */
Chris@0 58 public function processFunctionCall(
Chris@0 59 PHP_CodeSniffer_File $phpcsFile,
Chris@0 60 $stackPtr,
Chris@0 61 $openBracket,
Chris@0 62 $closeBracket
Chris@0 63 ) {
Chris@0 64 $tokens = $phpcsFile->getTokens();
Chris@0 65 $argument = $this->getArgument(1);
Chris@0 66
Chris@0 67 if ($argument === false) {
Chris@0 68 $error = 'Empty calls to t() are not allowed';
Chris@0 69 $phpcsFile->addError($error, $stackPtr, 'EmptyT');
Chris@0 70 return;
Chris@0 71 }
Chris@0 72
Chris@0 73 if ($tokens[$argument['start']]['code'] !== T_CONSTANT_ENCAPSED_STRING) {
Chris@0 74 // Not a translatable string literal.
Chris@0 75 $warning = 'Only string literals should be passed to t() where possible';
Chris@0 76 $phpcsFile->addWarning($warning, $argument['start'], 'NotLiteralString');
Chris@0 77 return;
Chris@0 78 }
Chris@0 79
Chris@0 80 $string = $tokens[$argument['start']]['content'];
Chris@0 81 if ($string === '""' || $string === "''") {
Chris@0 82 $warning = 'Do not pass empty strings to t()';
Chris@0 83 $phpcsFile->addWarning($warning, $argument['start'], 'EmptyString');
Chris@0 84 return;
Chris@0 85 }
Chris@0 86
Chris@0 87 $concatAfter = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($closeBracket + 1), null, true, null, true);
Chris@0 88 if ($concatAfter !== false && $tokens[$concatAfter]['code'] === T_STRING_CONCAT) {
Chris@0 89 $stringAfter = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($concatAfter + 1), null, true, null, true);
Chris@0 90 if ($stringAfter !== false
Chris@0 91 && $tokens[$stringAfter]['code'] === T_CONSTANT_ENCAPSED_STRING
Chris@0 92 && $this->checkConcatString($tokens[$stringAfter]['content']) === false
Chris@0 93 ) {
Chris@0 94 $warning = 'Do not concatenate strings to translatable strings, they should be part of the t() argument and you should use placeholders';
Chris@0 95 $phpcsFile->addWarning($warning, $stringAfter, 'ConcatString');
Chris@0 96 }
Chris@0 97 }
Chris@0 98
Chris@0 99 $lastChar = substr($string, -1);
Chris@0 100 if ($lastChar === '"' || $lastChar === "'") {
Chris@0 101 $message = substr($string, 1, -1);
Chris@0 102 if ($message !== trim($message)) {
Chris@0 103 $warning = 'Translatable strings must not begin or end with white spaces, use placeholders with t() for variables';
Chris@0 104 $phpcsFile->addWarning($warning, $argument['start'], 'WhiteSpace');
Chris@0 105 }
Chris@0 106 }
Chris@0 107
Chris@0 108 $concatFound = $phpcsFile->findNext(T_STRING_CONCAT, $argument['start'], $argument['end']);
Chris@0 109 if ($concatFound !== false) {
Chris@0 110 $error = 'Concatenating translatable strings is not allowed, use placeholders instead and only one string literal';
Chris@0 111 $phpcsFile->addError($error, $concatFound, 'Concat');
Chris@0 112 }
Chris@0 113
Chris@0 114 // Check if there is a backslash escaped single quote in the string and
Chris@0 115 // if the string makes use of double quotes.
Chris@0 116 if ($string{0} === "'" && strpos($string, "\'") !== false
Chris@0 117 && strpos($string, '"') === false
Chris@0 118 ) {
Chris@0 119 $warn = 'Avoid backslash escaping in translatable strings when possible, use "" quotes instead';
Chris@0 120 $phpcsFile->addWarning($warn, $argument['start'], 'BackslashSingleQuote');
Chris@0 121 return;
Chris@0 122 }
Chris@0 123
Chris@0 124 if ($string{0} === '"' && strpos($string, '\"') !== false
Chris@0 125 && strpos($string, "'") === false
Chris@0 126 ) {
Chris@0 127 $warn = "Avoid backslash escaping in translatable strings when possible, use '' quotes instead";
Chris@0 128 $phpcsFile->addWarning($warn, $argument['start'], 'BackslashDoubleQuote');
Chris@0 129 }
Chris@0 130
Chris@0 131 }//end processFunctionCall()
Chris@0 132
Chris@0 133
Chris@0 134 /**
Chris@0 135 * Checks if a string can be concatenated with a translatable string.
Chris@0 136 *
Chris@0 137 * @param string $string The string that is concatenated to a t() call.
Chris@0 138 *
Chris@0 139 * @return bool
Chris@0 140 * TRUE if the string is allowed to be concatenated with a translatable
Chris@0 141 * string, FALSE if not.
Chris@0 142 */
Chris@0 143 protected function checkConcatString($string)
Chris@0 144 {
Chris@0 145 // Remove outer quotes, spaces and HTML tags from the original string.
Chris@0 146 $string = trim($string, '"\'');
Chris@0 147 $string = trim(strip_tags($string));
Chris@0 148
Chris@0 149 if ($string === '') {
Chris@0 150 return true;
Chris@0 151 }
Chris@0 152
Chris@0 153 if (in_array($string, ['(', ')', '[', ']', '-', '<', '>', '«', '»', '\n'], true)) {
Chris@0 154 return true;
Chris@0 155 }
Chris@0 156
Chris@0 157 return false;
Chris@0 158
Chris@0 159 }//end checkConcatString()
Chris@0 160
Chris@0 161
Chris@0 162 }//end class