surroundVariableWithBraces()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 2
b 0
f 0
nc 1
nop 3
dl 0
loc 6
rs 10
1
<?php
2
3
/**
4
 * This file is part of the mo4-coding-standard (phpcs standard)
5
 *
6
 * @author  Xaver Loppenstedt <[email protected]>
7
 *
8
 * @license http://spdx.org/licenses/MIT MIT License
9
 *
10
 * @link    https://github.com/mayflower/mo4-coding-standard
11
 */
12
13
declare(strict_types=1);
14
15
namespace MO4\Sniffs\Strings;
16
17
use PHP_CodeSniffer\Files\File;
18
use PHP_CodeSniffer\Sniffs\Sniff;
19
20
/**
21
 * Variable in Double Quoted String sniff.
22
 *
23
 * Variables in double quoted strings must be surrounded by { }
24
 *
25
 * @author    Xaver Loppenstedt <[email protected]>
26
 *
27
 * @copyright 2013 Xaver Loppenstedt, some rights reserved.
28
 *
29
 * @license   http://spdx.org/licenses/MIT MIT License
30
 *
31
 * @link      https://github.com/mayflower/mo4-coding-standard
32
 */
33
class VariableInDoubleQuotedStringSniff implements Sniff
34
{
35
    /**
36
     * Registers the tokens that this sniff wants to listen for.
37
     *
38
     * @return array<int, string>
39
     *
40
     * @see Tokens.php
41
     */
42
    public function register(): array
43
    {
44
        return [T_DOUBLE_QUOTED_STRING];
45
    }
46
47
    /**
48
     * Called when one of the token types that this sniff is listening for
49
     * is found.
50
     *
51
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint
52
     *
53
     * @param File $phpcsFile The PHP_CodeSniffer file where the
54
     *                        token was found.
55
     * @param int  $stackPtr  The position in the PHP_CodeSniffer
56
     *                        file's token stack where the token
57
     *                        was found.
58
     *
59
     * @return void
60
     */
61
    public function process(File $phpcsFile, $stackPtr): void
62
    {
63
        $varRegExp = '/\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/';
64
65
        $tokens  = $phpcsFile->getTokens();
66
        $content = $tokens[$stackPtr]['content'];
67
68
        $matches = [];
69
70
        \preg_match_all($varRegExp, $content, $matches, PREG_OFFSET_CAPTURE);
71
72
        foreach ($matches as $match) {
73
            foreach ($match as [$var, $pos]) {
74
                if (1 !== $pos && '{' === $content[($pos - 1)]) {
75
                    continue;
76
                }
77
78
                if (\strpos(\substr($content, 0, $pos), '{') > 0
79
                    && false === \strpos(\substr($content, 0, $pos), '}')
80
                ) {
81
                    continue;
82
                }
83
84
                $lastOpeningBrace = \strrpos(\substr($content, 0, $pos), '{');
85
86
                if (false !== $lastOpeningBrace
87
                    && '$' === $content[($lastOpeningBrace + 1)]
88
                ) {
89
                    $lastClosingBrace = \strrpos(\substr($content, 0, $pos), '}');
90
91
                    if (false !== $lastClosingBrace
92
                        && $lastClosingBrace < $lastOpeningBrace
93
                    ) {
94
                        continue;
95
                    }
96
                }
97
98
                $fix = $phpcsFile->addFixableError(
99
                    \sprintf(
100
                        'must surround variable %s with { }',
101
                        $var
102
                    ),
103
                    $stackPtr,
104
                    'NotSurroundedWithBraces'
105
                );
106
107
                if (true !== $fix) {
108
                    continue;
109
                }
110
111
                $correctVariable = $this->surroundVariableWithBraces(
112
                    $content,
113
                    $pos,
114
                    $var
115
                );
116
117
                $this->fixPhpCsFile($stackPtr, $correctVariable, $phpcsFile);
118
            }
119
        }
120
    }
121
122
    /**
123
     * Surrounds a variable with curly brackets
124
     *
125
     * @param string $content content
126
     * @param int    $pos     position
127
     * @param string $var     variable
128
     *
129
     * @return string
130
     */
131
    private function surroundVariableWithBraces(string $content, int $pos, string $var): string
132
    {
133
        $before = \substr($content, 0, $pos);
134
        $after  = \substr($content, ($pos + \strlen($var)));
135
136
        return $before.'{'.$var.'}'.$after;
137
    }
138
139
    /**
140
     * Fixes the file
141
     *
142
     * @param int    $stackPtr        stack pointer
143
     * @param string $correctVariable correct variable
144
     * @param File   $phpCsFile       PHP_CodeSniffer File object
145
     *
146
     * @return void
147
     */
148
    private function fixPhpCsFile(int $stackPtr, string $correctVariable, File $phpCsFile): void
149
    {
150
        $phpCsFile->fixer->beginChangeset();
151
        $phpCsFile->fixer->replaceToken($stackPtr, $correctVariable);
152
        $phpCsFile->fixer->endChangeset();
153
    }
154
}
155