comparison vendor/drupal/coder/coder_sniffer/Drupal/Sniffs/Semantics/FunctionTSniff.php @ 0:4c8ae668cc8c

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