Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. FunctionTSniff.php

class FunctionTSniff

Check the usage of the t() function to not escape translatable strings with back slashes. Also checks that the first argument does not use string concatenation.

@category PHP @package PHP_CodeSniffer @link http://pear.php.net/package/PHP_CodeSniffer

Hierarchy

  • class \Drupal\Sniffs\Semantics\FunctionCall implements \PHP_CodeSniffer\Sniffs\Sniff
    • class \Drupal\Sniffs\Semantics\FunctionTSniff extends \Drupal\Sniffs\Semantics\FunctionCall

Expanded class hierarchy of FunctionTSniff

File

vendor/drupal/coder/coder_sniffer/Drupal/Sniffs/Semantics/FunctionTSniff.php, line 23

Namespace

Drupal\Sniffs\Semantics
View source
class FunctionTSniff extends FunctionCall {
    
    /**
     * We also want to catch $this->t() calls in Drupal 8.
     *
     * @var boolean
     */
    protected $includeMethodCalls = true;
    
    /**
     * Returns an array of function names this test wants to listen for.
     *
     * @return array<string>
     */
    public function registerFunctionNames() {
        return [
            't',
            'TranslatableMarkup',
            'TranslationWrapper',
        ];
    }
    
    //end registerFunctionNames()
    
    /**
     * Processes this function call.
     *
     * @param \PHP_CodeSniffer\Files\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(File $phpcsFile, $stackPtr, $openBracket, $closeBracket) {
        $tokens = $phpcsFile->getTokens();
        $argument = $this->getArgument(1);
        if ($argument === false) {
            $error = 'Empty calls to t() are not allowed';
            $phpcsFile->addError($error, $stackPtr, 'EmptyT');
            return;
        }
        if ($tokens[$argument['start']]['code'] !== T_CONSTANT_ENCAPSED_STRING) {
            // Not a translatable string literal.
            $warning = 'Only string literals should be passed to t() where possible';
            $phpcsFile->addWarning($warning, $argument['start'], 'NotLiteralString');
            return;
        }
        $string = $tokens[$argument['start']]['content'];
        if ($string === '""' || $string === "''") {
            $warning = 'Do not pass empty strings to t()';
            $phpcsFile->addWarning($warning, $argument['start'], 'EmptyString');
            return;
        }
        $concatAfter = $phpcsFile->findNext(Tokens::$emptyTokens, $closeBracket + 1, null, true, null, true);
        if ($concatAfter !== false && $tokens[$concatAfter]['code'] === T_STRING_CONCAT) {
            $stringAfter = $phpcsFile->findNext(Tokens::$emptyTokens, $concatAfter + 1, null, true, null, true);
            if ($stringAfter !== false && $tokens[$stringAfter]['code'] === T_CONSTANT_ENCAPSED_STRING && $this->checkConcatString($tokens[$stringAfter]['content']) === false) {
                $warning = 'Do not concatenate strings to translatable strings, they should be part of the t() argument and you should use placeholders';
                $phpcsFile->addWarning($warning, $stringAfter, 'ConcatString');
            }
        }
        $lastChar = substr($string, -1);
        if ($lastChar === '"' || $lastChar === "'") {
            $message = substr($string, 1, -1);
            if ($message !== trim($message)) {
                $warning = 'Translatable strings must not begin or end with white spaces, use placeholders with t() for variables';
                $phpcsFile->addWarning($warning, $argument['start'], 'WhiteSpace');
            }
        }
        $concatFound = $phpcsFile->findNext(T_STRING_CONCAT, $argument['start'], $argument['end']);
        if ($concatFound !== false) {
            $error = 'Concatenating translatable strings is not allowed, use placeholders instead and only one string literal';
            $phpcsFile->addError($error, $concatFound, 'Concat');
        }
        // Check if there is a backslash escaped single quote in the string and
        // if the string makes use of double quotes.
        if ($string[0] === "'" && strpos($string, "\\'") !== false && strpos($string, '"') === false) {
            $warn = 'Avoid backslash escaping in translatable strings when possible, use "" quotes instead';
            $phpcsFile->addWarning($warn, $argument['start'], 'BackslashSingleQuote');
            return;
        }
        if ($string[0] === '"' && strpos($string, '\\"') !== false && strpos($string, "'") === false) {
            $warn = "Avoid backslash escaping in translatable strings when possible, use '' quotes instead";
            $phpcsFile->addWarning($warn, $argument['start'], 'BackslashDoubleQuote');
        }
    }
    
    //end processFunctionCall()
    
    /**
     * Checks if a string can be concatenated with a translatable string.
     *
     * @param string $string The string that is concatenated to a t() call.
     *
     * @return bool
     *   TRUE if the string is allowed to be concatenated with a translatable
     *   string, FALSE if not.
     */
    protected function checkConcatString($string) {
        // Remove outer quotes, spaces and HTML tags from the original string.
        $string = trim($string, '"\'');
        $string = trim(strip_tags($string));
        if ($string === '') {
            return true;
        }
        $allowedItems = [
            '(',
            ')',
            '[',
            ']',
            '-',
            '<',
            '>',
            '«',
            '»',
            '\\n',
        ];
        foreach ($allowedItems as $item) {
            if ($item === $string) {
                return true;
            }
        }
        return false;
    }
    
    //end checkConcatString()

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
FunctionCall::$arguments protected property Internal cache to save the calculated arguments of the function call.
FunctionCall::$closeBracket protected property The token position of the closing bracket of the function call.
FunctionCall::$functionCall protected property The token position of the function call.
FunctionCall::$openBracket protected property The token position of the opening bracket of the function call.
FunctionCall::$phpcsFile protected property The currently processed file.
FunctionCall::getArgument public function Returns start and end token for a given argument number.
FunctionCall::isFunctionCall protected function Checks if this is a function call.
FunctionCall::process public function Processes this test, when one of its tokens is encountered. Overrides Sniff::process 2
FunctionCall::register public function Returns an array of tokens this test wants to listen for. Overrides Sniff::register
FunctionTSniff::$includeMethodCalls protected property We also want to catch $this-&gt;t() calls in Drupal 8. Overrides FunctionCall::$includeMethodCalls
FunctionTSniff::checkConcatString protected function Checks if a string can be concatenated with a translatable string.
FunctionTSniff::processFunctionCall public function Processes this function call.
FunctionTSniff::registerFunctionNames public function Returns an array of function names this test wants to listen for.

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal