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

Breadcrumb

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

class UnusedVariableSniff

Hierarchy

  • class \SlevomatCodingStandard\Sniffs\Variables\UnusedVariableSniff implements \PHP_CodeSniffer\Sniffs\Sniff

Expanded class hierarchy of UnusedVariableSniff

File

vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Variables/UnusedVariableSniff.php, line 70

Namespace

SlevomatCodingStandard\Sniffs\Variables
View source
class UnusedVariableSniff implements Sniff {
    public const CODE_UNUSED_VARIABLE = 'UnusedVariable';
    
    /** @var bool */
    public $ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach = false;
    
    /**
     * @return array<int, (int|string)>
     */
    public function register() : array {
        return [
            T_VARIABLE,
        ];
    }
    
    /**
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
     * @param int $variablePointer
     */
    public function process(File $phpcsFile, $variablePointer) : void {
        if (!$this->isAssignment($phpcsFile, $variablePointer)) {
            return;
        }
        $tokens = $phpcsFile->getTokens();
        $variableName = $tokens[$variablePointer]['content'];
        if (in_array($variableName, [
            '$this',
            '$GLOBALS',
            '$_SERVER',
            '$_GET',
            '$_POST',
            '$_FILES',
            '$_COOKIE',
            '$_SESSION',
            '$_REQUEST',
            '$_ENV',
        ], true)) {
            return;
        }
        $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1);
        if (in_array($tokens[$previousPointer]['code'], [
            T_OBJECT_OPERATOR,
            T_DOUBLE_COLON,
        ], true)) {
            // Property
            return;
        }
        if (in_array($tokens[$previousPointer]['code'], Tokens::$castTokens, true)) {
            $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1);
        }
        if (in_array($tokens[$previousPointer]['code'], [
            T_EQUAL,
            T_PLUS_EQUAL,
            T_MINUS_EQUAL,
            T_MUL_EQUAL,
            T_DIV_EQUAL,
            T_POW_EQUAL,
            T_MOD_EQUAL,
            T_AND_EQUAL,
            T_OR_EQUAL,
            T_XOR_EQUAL,
            T_SL_EQUAL,
            T_SR_EQUAL,
            T_CONCAT_EQUAL,
            T_YIELD,
        ], true)) {
            return;
        }
        if ($this->isUsedAsParameter($phpcsFile, $variablePointer)) {
            return;
        }
        if ($this->isUsedInForLoopCondition($phpcsFile, $variablePointer, $variableName)) {
            return;
        }
        if ($this->isDefinedInDoConditionAndUsedInLoop($phpcsFile, $variablePointer, $variableName)) {
            return;
        }
        if ($this->isUsedInLoopCycle($phpcsFile, $variablePointer, $variableName)) {
            return;
        }
        if ($this->isUsedAsKeyOrValueInArray($phpcsFile, $variablePointer)) {
            return;
        }
        if ($this->isValueInForeachAndErrorIsIgnored($phpcsFile, $variablePointer)) {
            return;
        }
        $scopeOwnerPointer = ScopeHelper::getRootPointer($phpcsFile, $variablePointer - 1);
        foreach (array_reverse($tokens[$variablePointer]['conditions'], true) as $conditionPointer => $conditionTokenCode) {
            if (in_array($conditionTokenCode, TokenHelper::$functionTokenCodes, true)) {
                $scopeOwnerPointer = $conditionPointer;
                break;
            }
        }
        if (in_array($tokens[$scopeOwnerPointer]['code'], TokenHelper::$functionTokenCodes, true)) {
            if ($this->isStaticOrGlobalVariable($phpcsFile, $scopeOwnerPointer, $variableName)) {
                return;
            }
            if ($this->isParameterPassedByReference($phpcsFile, $scopeOwnerPointer, $variableName)) {
                return;
            }
            if ($tokens[$scopeOwnerPointer]['code'] === T_CLOSURE && $this->isInheritedVariablePassedByReference($phpcsFile, $scopeOwnerPointer, $variableName)) {
                return;
            }
        }
        if ($this->isReference($phpcsFile, $scopeOwnerPointer, $variablePointer)) {
            return;
        }
        if (VariableHelper::isUsedInScopeAfterPointer($phpcsFile, $scopeOwnerPointer, $variablePointer, $variablePointer + 1)) {
            return;
        }
        if ($this->isPartOfStatementAndWithIncrementOrDecrementOperator($phpcsFile, $variablePointer)) {
            return;
        }
        $phpcsFile->addError(sprintf('Unused variable %s.', $variableName), $variablePointer, self::CODE_UNUSED_VARIABLE);
    }
    private function isAssignment(File $phpcsFile, int $variablePointer) : bool {
        $tokens = $phpcsFile->getTokens();
        $nextPointer = TokenHelper::findNextEffective($phpcsFile, $variablePointer + 1);
        if (in_array($tokens[$nextPointer]['code'], [
            T_EQUAL,
            T_PLUS_EQUAL,
            T_MINUS_EQUAL,
            T_MUL_EQUAL,
            T_DIV_EQUAL,
            T_POW_EQUAL,
            T_MOD_EQUAL,
            T_AND_EQUAL,
            T_OR_EQUAL,
            T_XOR_EQUAL,
            T_SL_EQUAL,
            T_SR_EQUAL,
            T_CONCAT_EQUAL,
        ], true)) {
            if ($tokens[$nextPointer]['code'] === T_EQUAL) {
                if (PropertyHelper::isProperty($phpcsFile, $variablePointer)) {
                    return false;
                }
                if (ParameterHelper::isParameter($phpcsFile, $variablePointer)) {
                    return false;
                }
            }
            return true;
        }
        $actualPointer = $variablePointer;
        do {
            $parenthesisOpenerPointer = $this->findOpenerOfNestedParentheses($phpcsFile, $actualPointer);
            $parenthesisOwnerPointer = $this->findOwnerOfNestedParentheses($phpcsFile, $actualPointer);
            $actualPointer = $parenthesisOpenerPointer;
        } while ($parenthesisOwnerPointer === null && isset($tokens[$actualPointer]['nested_parenthesis']));
        $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1);
        if (in_array($tokens[$nextPointer]['code'], [
            T_INC,
            T_DEC,
        ], true) || in_array($tokens[$previousPointer]['code'], [
            T_INC,
            T_DEC,
        ], true)) {
            if ($parenthesisOwnerPointer === null) {
                return true;
            }
            return !in_array($tokens[$parenthesisOwnerPointer]['code'], [
                T_FOR,
                T_WHILE,
                T_IF,
                T_ELSEIF,
            ], true);
        }
        if ($parenthesisOwnerPointer !== null && $tokens[$parenthesisOwnerPointer]['code'] === T_FOREACH) {
            $pointerBeforeVariable = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1);
            return in_array($tokens[$pointerBeforeVariable]['code'], [
                T_AS,
                T_DOUBLE_ARROW,
            ], true);
        }
        if ($parenthesisOpenerPointer !== null) {
            $pointerBeforeParenthesisOpener = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1);
            if ($tokens[$pointerBeforeParenthesisOpener]['code'] === T_LIST) {
                return true;
            }
        }
        $possibleShortListCloserPointer = TokenHelper::findNextExcluding($phpcsFile, array_merge(TokenHelper::$ineffectiveTokenCodes, [
            T_VARIABLE,
            T_COMMA,
        ]), $variablePointer + 1);
        if ($tokens[$possibleShortListCloserPointer]['code'] === T_CLOSE_SHORT_ARRAY) {
            return $tokens[TokenHelper::findNextEffective($phpcsFile, $possibleShortListCloserPointer + 1)]['code'] === T_EQUAL;
        }
        return false;
    }
    private function isUsedAsParameter(File $phpcsFile, int $variablePointer) : bool {
        $parenthesisOpenerPointer = $this->findOpenerOfNestedParentheses($phpcsFile, $variablePointer);
        if ($parenthesisOpenerPointer === null) {
            return false;
        }
        if (!ScopeHelper::isInSameScope($phpcsFile, $parenthesisOpenerPointer, $variablePointer)) {
            return false;
        }
        return $phpcsFile->getTokens()[TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpenerPointer - 1)]['code'] === T_STRING;
    }
    private function isUsedInForLoopCondition(File $phpcsFile, int $variablePointer, string $variableName) : bool {
        $tokens = $phpcsFile->getTokens();
        $parenthesisOpenerPointer = $this->findOpenerOfNestedParentheses($phpcsFile, $variablePointer);
        if ($parenthesisOpenerPointer === null) {
            return false;
        }
        $parenthesisOwnerPointer = $this->findOwnerOfNestedParentheses($phpcsFile, $variablePointer);
        if ($parenthesisOwnerPointer === null) {
            return false;
        }
        if ($tokens[$parenthesisOwnerPointer]['code'] !== T_FOR) {
            return false;
        }
        for ($i = $parenthesisOpenerPointer + 1; $i < $tokens[$parenthesisOwnerPointer]['parenthesis_closer']; $i++) {
            if ($i === $variablePointer) {
                continue;
            }
            if ($tokens[$i]['code'] !== T_VARIABLE) {
                continue;
            }
            if ($tokens[$i]['content'] !== $variableName) {
                continue;
            }
            return true;
        }
        return false;
    }
    private function isDefinedInDoConditionAndUsedInLoop(File $phpcsFile, int $variablePointer, string $variableName) : bool {
        $tokens = $phpcsFile->getTokens();
        $parenthesisOpener = TokenHelper::findPrevious($phpcsFile, T_OPEN_PARENTHESIS, $variablePointer - 1);
        if ($parenthesisOpener === null || $tokens[$parenthesisOpener]['parenthesis_closer'] < $variablePointer) {
            return false;
        }
        $whilePointer = TokenHelper::findPreviousEffective($phpcsFile, $parenthesisOpener - 1);
        if ($tokens[$whilePointer]['code'] !== T_WHILE) {
            return false;
        }
        $loopCloserPointer = TokenHelper::findPreviousEffective($phpcsFile, $whilePointer - 1);
        if ($tokens[$loopCloserPointer]['code'] !== T_CLOSE_CURLY_BRACKET) {
            return false;
        }
        $doPointer = TokenHelper::findPreviousEffective($phpcsFile, $tokens[$loopCloserPointer]['bracket_opener'] - 1);
        if ($tokens[$doPointer]['code'] !== T_DO) {
            return false;
        }
        return TokenHelper::findNextContent($phpcsFile, T_VARIABLE, $variableName, $tokens[$loopCloserPointer]['bracket_opener'] + 1, $loopCloserPointer) !== null;
    }
    private function isUsedInLoopCycle(File $phpcsFile, int $variablePointer, string $variableName) : bool {
        $tokens = $phpcsFile->getTokens();
        $loopPointer = null;
        foreach (array_reverse($tokens[$variablePointer]['conditions'], true) as $conditionPointer => $conditionTokenCode) {
            if (in_array($conditionTokenCode, TokenHelper::$functionTokenCodes, true)) {
                break;
            }
            if (!in_array($conditionTokenCode, [
                T_FOREACH,
                T_FOR,
                T_DO,
                T_WHILE,
            ], true)) {
                continue;
            }
            $loopPointer = $conditionPointer;
            $loopConditionPointer = $conditionTokenCode === T_DO ? TokenHelper::findNextEffective($phpcsFile, $tokens[$loopPointer]['scope_closer'] + 1) : $loopPointer;
            $variableUsedInLoopConditionPointer = TokenHelper::findNextContent($phpcsFile, T_VARIABLE, $variableName, $tokens[$loopConditionPointer]['parenthesis_opener'] + 1, $tokens[$loopConditionPointer]['parenthesis_closer']);
            if ($variableUsedInLoopConditionPointer === null || $variableUsedInLoopConditionPointer === $variablePointer) {
                continue;
            }
            if ($conditionTokenCode !== T_FOREACH) {
                return true;
            }
            $pointerBeforeVariableUsedInLoopCondition = TokenHelper::findPreviousEffective($phpcsFile, $variableUsedInLoopConditionPointer - 1);
            if ($tokens[$pointerBeforeVariableUsedInLoopCondition]['code'] === T_BITWISE_AND) {
                return true;
            }
        }
        if ($loopPointer === null) {
            return false;
        }
        for ($i = $tokens[$loopPointer]['scope_opener'] + 1; $i < $tokens[$loopPointer]['scope_closer']; $i++) {
            if (in_array($tokens[$i]['code'], [
                T_DOUBLE_QUOTED_STRING,
                T_HEREDOC,
            ], true) && VariableHelper::isUsedInScopeInString($phpcsFile, $variableName, $i)) {
                return true;
            }
            if ($tokens[$i]['code'] !== T_VARIABLE) {
                continue;
            }
            if ($tokens[$i]['content'] !== $variableName) {
                continue;
            }
            if (!$this->isAssignment($phpcsFile, $i)) {
                return true;
            }
            $nextPointer = TokenHelper::findNextEffective($phpcsFile, $i + 1);
            if (!in_array($tokens[$nextPointer]['code'], [
                T_INC,
                T_DEC,
                T_PLUS_EQUAL,
                T_MINUS_EQUAL,
                T_MUL_EQUAL,
                T_DIV_EQUAL,
                T_POW_EQUAL,
                T_MOD_EQUAL,
                T_AND_EQUAL,
                T_OR_EQUAL,
                T_XOR_EQUAL,
                T_SL_EQUAL,
                T_SR_EQUAL,
                T_CONCAT_EQUAL,
            ], true)) {
                continue;
            }
            $parenthesisOwnerPointer = $this->findNestedParenthesisWithOwner($phpcsFile, $i);
            if ($parenthesisOwnerPointer !== null && in_array($tokens[$parenthesisOwnerPointer]['code'], [
                T_IF,
                T_ELSEIF,
            ], true)) {
                return true;
            }
        }
        return false;
    }
    private function isUsedAsKeyOrValueInArray(File $phpcsFile, int $variablePointer) : bool {
        $tokens = $phpcsFile->getTokens();
        $squareBracketOpenerPointer = TokenHelper::findPrevious($phpcsFile, T_OPEN_SQUARE_BRACKET, $variablePointer - 1);
        if ($squareBracketOpenerPointer !== null && $tokens[$squareBracketOpenerPointer]['bracket_closer'] > $variablePointer) {
            return true;
        }
        $arrayOpenerPointer = TokenHelper::findPrevious($phpcsFile, T_OPEN_SHORT_ARRAY, $variablePointer - 1);
        if ($arrayOpenerPointer === null) {
            return false;
        }
        $arrayCloserPointer = $tokens[$arrayOpenerPointer]['bracket_closer'];
        if ($arrayCloserPointer < $variablePointer) {
            return false;
        }
        $pointerAfterArrayCloser = TokenHelper::findNextEffective($phpcsFile, $arrayCloserPointer + 1);
        if ($tokens[$pointerAfterArrayCloser]['code'] === T_EQUAL) {
            return false;
        }
        $pointerBeforeVariable = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1);
        if (in_array($tokens[$pointerBeforeVariable]['code'], [
            T_INC,
            T_DEC,
        ], true)) {
            $pointerBeforeVariable = TokenHelper::findPreviousEffective($phpcsFile, $pointerBeforeVariable - 1);
        }
        return in_array($tokens[$pointerBeforeVariable]['code'], [
            T_OPEN_SHORT_ARRAY,
            T_COMMA,
            T_DOUBLE_ARROW,
        ], true);
    }
    private function isValueInForeachAndErrorIsIgnored(File $phpcsFile, int $variablePointer) : bool {
        $tokens = $phpcsFile->getTokens();
        $parenthesisOwnerPointer = $this->findNestedParenthesisWithOwner($phpcsFile, $variablePointer);
        $isInForeach = $parenthesisOwnerPointer !== null && $tokens[$parenthesisOwnerPointer]['code'] === T_FOREACH;
        if (!$isInForeach) {
            return false;
        }
        $pointerAfterVariable = TokenHelper::findNextEffective($phpcsFile, $variablePointer + 1);
        if ($pointerAfterVariable !== null && $tokens[$pointerAfterVariable]['code'] === T_DOUBLE_ARROW) {
            return false;
        }
        return $this->ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach;
    }
    private function isStaticOrGlobalVariable(File $phpcsFile, int $functionPointer, string $variableName) : bool {
        $tokens = $phpcsFile->getTokens();
        for ($i = $tokens[$functionPointer]['scope_opener'] + 1; $i < $tokens[$functionPointer]['scope_closer']; $i++) {
            if ($tokens[$i]['code'] !== T_VARIABLE) {
                continue;
            }
            if ($tokens[$i]['content'] !== $variableName) {
                continue;
            }
            $pointerBeforeParameter = TokenHelper::findPreviousEffective($phpcsFile, $i - 1);
            if (in_array($tokens[$pointerBeforeParameter]['code'], [
                T_STATIC,
                T_GLOBAL,
            ], true)) {
                return true;
            }
        }
        return false;
    }
    private function isParameterPassedByReference(File $phpcsFile, int $functionPointer, string $variableName) : bool {
        $tokens = $phpcsFile->getTokens();
        for ($i = $tokens[$functionPointer]['parenthesis_opener'] + 1; $i < $tokens[$functionPointer]['parenthesis_closer']; $i++) {
            if ($tokens[$i]['code'] !== T_VARIABLE) {
                continue;
            }
            if ($tokens[$i]['content'] !== $variableName) {
                continue;
            }
            $pointerBeforeParameter = TokenHelper::findPreviousEffective($phpcsFile, $i - 1);
            if ($tokens[$pointerBeforeParameter]['code'] === T_BITWISE_AND) {
                return true;
            }
        }
        return false;
    }
    private function isInheritedVariablePassedByReference(File $phpcsFile, int $functionPointer, string $variableName) : bool {
        $tokens = $phpcsFile->getTokens();
        $usePointer = TokenHelper::findNextEffective($phpcsFile, $tokens[$functionPointer]['parenthesis_closer'] + 1);
        if ($tokens[$usePointer]['code'] !== T_USE) {
            return false;
        }
        $useParenthesisOpener = TokenHelper::findNextEffective($phpcsFile, $usePointer + 1);
        for ($i = $useParenthesisOpener + 1; $i < $tokens[$useParenthesisOpener]['parenthesis_closer']; $i++) {
            if ($tokens[$i]['code'] !== T_VARIABLE) {
                continue;
            }
            if ($tokens[$i]['content'] !== $variableName) {
                continue;
            }
            $pointerBeforeInheritedVariable = TokenHelper::findPreviousEffective($phpcsFile, $i - 1);
            if ($tokens[$pointerBeforeInheritedVariable]['code'] === T_BITWISE_AND) {
                return true;
            }
        }
        return false;
    }
    private function isReference(File $phpcsFile, int $scopeOwnerPointer, int $variablePointer) : bool {
        $tokens = $phpcsFile->getTokens();
        $scopeOpenerPointer = $tokens[$scopeOwnerPointer]['code'] === T_OPEN_TAG ? $scopeOwnerPointer : $tokens[$scopeOwnerPointer]['scope_opener'];
        for ($i = $scopeOpenerPointer + 1; $i < $variablePointer; $i++) {
            if ($tokens[$i]['code'] !== T_VARIABLE) {
                continue;
            }
            if ($tokens[$i]['content'] !== $tokens[$variablePointer]['content']) {
                continue;
            }
            $assignmentPointer = TokenHelper::findNextEffective($phpcsFile, $i + 1);
            if ($tokens[$assignmentPointer]['code'] !== T_EQUAL) {
                continue;
            }
            $referencePointer = TokenHelper::findNextEffective($phpcsFile, $assignmentPointer + 1);
            if ($tokens[$referencePointer]['code'] === T_BITWISE_AND) {
                return true;
            }
        }
        return false;
    }
    private function isPartOfStatementAndWithIncrementOrDecrementOperator(File $phpcsFile, int $variablePointer) : bool {
        $tokens = $phpcsFile->getTokens();
        $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $variablePointer - 1);
        $nextPointer = TokenHelper::findNextEffective($phpcsFile, $variablePointer + 1);
        if (in_array($tokens[$previousPointer]['code'], [
            T_DEC,
            T_INC,
        ], true)) {
            $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1);
        }
        elseif ($nextPointer !== null && in_array($tokens[$nextPointer]['code'], [
            T_DEC,
            T_INC,
        ], true)) {
            // Nothing
        }
        else {
            return false;
        }
        if ($tokens[$previousPointer]['code'] === T_OPEN_PARENTHESIS) {
            $previousPointer = TokenHelper::findPreviousEffective($phpcsFile, $previousPointer - 1);
        }
        return in_array($tokens[$previousPointer]['code'], array_merge([
            T_STRING_CONCAT,
            T_ECHO,
            T_RETURN,
            T_EXIT,
            T_PRINT,
            T_COMMA,
            T_EMPTY,
            T_EVAL,
            T_YIELD,
        ], Tokens::$operators, Tokens::$assignmentTokens, Tokens::$booleanOperators, Tokens::$castTokens), true);
    }
    private function findNestedParenthesisWithOwner(File $phpcsFile, int $pointer) : ?int {
        $tokens = $phpcsFile->getTokens();
        if (!array_key_exists('nested_parenthesis', $tokens[$pointer])) {
            return null;
        }
        foreach (array_reverse(array_keys($tokens[$pointer]['nested_parenthesis'])) as $nestedParenthesisOpener) {
            if (array_key_exists('parenthesis_owner', $tokens[$nestedParenthesisOpener])) {
                return $tokens[$nestedParenthesisOpener]['parenthesis_owner'];
            }
        }
        return null;
    }
    private function findOpenerOfNestedParentheses(File $phpcsFile, int $pointer) : ?int {
        $tokens = $phpcsFile->getTokens();
        if (!array_key_exists('nested_parenthesis', $tokens[$pointer])) {
            return null;
        }
        return array_reverse(array_keys($tokens[$pointer]['nested_parenthesis']))[0];
    }
    private function findOwnerOfNestedParentheses(File $phpcsFile, int $pointer) : ?int {
        $tokens = $phpcsFile->getTokens();
        $parenthesisOpenerPointer = $this->findOpenerOfNestedParentheses($phpcsFile, $pointer);
        if ($parenthesisOpenerPointer === null) {
            return null;
        }
        return array_key_exists('parenthesis_owner', $tokens[$parenthesisOpenerPointer]) ? $tokens[$parenthesisOpenerPointer]['parenthesis_owner'] : null;
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
UnusedVariableSniff::$ignoreUnusedValuesWhenOnlyKeysAreUsedInForeach public property @var bool
UnusedVariableSniff::CODE_UNUSED_VARIABLE public constant
UnusedVariableSniff::findNestedParenthesisWithOwner private function
UnusedVariableSniff::findOpenerOfNestedParentheses private function
UnusedVariableSniff::findOwnerOfNestedParentheses private function
UnusedVariableSniff::isAssignment private function
UnusedVariableSniff::isDefinedInDoConditionAndUsedInLoop private function
UnusedVariableSniff::isInheritedVariablePassedByReference private function
UnusedVariableSniff::isParameterPassedByReference private function
UnusedVariableSniff::isPartOfStatementAndWithIncrementOrDecrementOperator private function
UnusedVariableSniff::isReference private function
UnusedVariableSniff::isStaticOrGlobalVariable private function
UnusedVariableSniff::isUsedAsKeyOrValueInArray private function
UnusedVariableSniff::isUsedAsParameter private function
UnusedVariableSniff::isUsedInForLoopCondition private function
UnusedVariableSniff::isUsedInLoopCycle private function
UnusedVariableSniff::isValueInForeachAndErrorIsIgnored private function
UnusedVariableSniff::process public function * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
*
Overrides Sniff::process
UnusedVariableSniff::register public function * Overrides Sniff::register
RSS feed
Powered by Drupal