• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PHPCSStandards / PHP_CodeSniffer / 11820195198

13 Nov 2024 03:15PM UTC coverage: 76.142% (+0.03%) from 76.11%
11820195198

Pull #663

github

web-flow
Merge 755f0bc35 into 7f5d178f4
Pull Request #663: Tests: Add unit tests for Common::prepareForOutput()

23649 of 31059 relevant lines covered (76.14%)

64.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.89
/src/Standards/Generic/Sniffs/PHP/DisallowShortOpenTagSniff.php
1
<?php
2
/**
3
 * Makes sure that shorthand PHP open tags are not used.
4
 *
5
 * @author    Greg Sherwood <gsherwood@squiz.net>
6
 * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
 * @license   https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
 */
9

10
namespace PHP_CodeSniffer\Standards\Generic\Sniffs\PHP;
11

12
use PHP_CodeSniffer\Files\File;
13
use PHP_CodeSniffer\Sniffs\Sniff;
14
use PHP_CodeSniffer\Util\Tokens;
15

16
class DisallowShortOpenTagSniff implements Sniff
17
{
18

19

20
    /**
21
     * Returns an array of tokens this test wants to listen for.
22
     *
23
     * @return array<int|string>
24
     */
25
    public function register()
3✔
26
    {
27
        $targets = [
1✔
28
            T_OPEN_TAG,
3✔
29
            T_OPEN_TAG_WITH_ECHO,
3✔
30
        ];
2✔
31

32
        $shortOpenTags = (bool) ini_get('short_open_tag');
3✔
33
        if ($shortOpenTags === false) {
3✔
34
            $targets[] = T_INLINE_HTML;
3✔
35
        }
1✔
36

37
        return $targets;
3✔
38

39
    }//end register()
40

41

42
    /**
43
     * Processes this test, when one of its tokens is encountered.
44
     *
45
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
46
     * @param int                         $stackPtr  The position of the current token
47
     *                                               in the stack passed in $tokens.
48
     *
49
     * @return void|int
50
     */
51
    public function process(File $phpcsFile, $stackPtr)
3✔
52
    {
53
        $tokens = $phpcsFile->getTokens();
3✔
54
        $token  = $tokens[$stackPtr];
3✔
55

56
        if ($token['code'] === T_OPEN_TAG && $token['content'] === '<?') {
3✔
57
            $error = 'Short PHP opening tag used; expected "<?php" but found "%s"';
×
58
            $data  = [$token['content']];
×
59
            $fix   = $phpcsFile->addFixableError($error, $stackPtr, 'Found', $data);
×
60
            if ($fix === true) {
×
61
                $correctOpening = '<?php';
×
62
                if (isset($tokens[($stackPtr + 1)]) === true && $tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {
×
63
                    // Avoid creation of invalid open tags like <?phpecho if the original was <?echo .
64
                    $correctOpening .= ' ';
×
65
                }
66

67
                $phpcsFile->fixer->replaceToken($stackPtr, $correctOpening);
×
68
            }
69

70
            $phpcsFile->recordMetric($stackPtr, 'PHP short open tag used', 'yes');
×
71
        } else {
72
            $phpcsFile->recordMetric($stackPtr, 'PHP short open tag used', 'no');
3✔
73
        }
74

75
        if ($token['code'] === T_OPEN_TAG_WITH_ECHO) {
3✔
76
            $nextVar = $tokens[$phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true)];
3✔
77
            $error   = 'Short PHP opening tag used with echo; expected "<?php echo %s ..." but found "%s %s ..."';
3✔
78
            $data    = [
1✔
79
                $nextVar['content'],
3✔
80
                $token['content'],
3✔
81
                $nextVar['content'],
3✔
82
            ];
2✔
83
            $fix     = $phpcsFile->addFixableError($error, $stackPtr, 'EchoFound', $data);
3✔
84
            if ($fix === true) {
3✔
85
                if ($tokens[($stackPtr + 1)]['code'] !== T_WHITESPACE) {
3✔
86
                    $phpcsFile->fixer->replaceToken($stackPtr, '<?php echo ');
3✔
87
                } else {
1✔
88
                    $phpcsFile->fixer->replaceToken($stackPtr, '<?php echo');
3✔
89
                }
90
            }
1✔
91
        }
1✔
92

93
        if ($token['code'] === T_INLINE_HTML) {
3✔
94
            $content     = $token['content'];
3✔
95
            $openerFound = strpos($content, '<?');
3✔
96

97
            if ($openerFound === false) {
3✔
98
                return;
3✔
99
            }
100

101
            $closerFound = false;
3✔
102

103
            // Inspect current token and subsequent inline HTML token to find a close tag.
104
            for ($i = $stackPtr; $i < $phpcsFile->numTokens; $i++) {
3✔
105
                if ($tokens[$i]['code'] !== T_INLINE_HTML) {
3✔
106
                    break;
3✔
107
                }
108

109
                $closerFound = strrpos($tokens[$i]['content'], '?>');
3✔
110
                if ($closerFound !== false) {
3✔
111
                    if ($i !== $stackPtr) {
3✔
112
                        break;
3✔
113
                    } else if ($closerFound > $openerFound) {
3✔
114
                        break;
3✔
115
                    } else {
116
                        $closerFound = false;
3✔
117
                    }
118
                }
1✔
119
            }
1✔
120

121
            if ($closerFound !== false) {
3✔
122
                $error   = 'Possible use of short open tags detected; found: %s';
3✔
123
                $snippet = $this->getSnippet($content, '<?');
3✔
124
                $data    = ['<?'.$snippet];
3✔
125

126
                $phpcsFile->addWarning($error, $stackPtr, 'PossibleFound', $data);
3✔
127

128
                // Skip forward to the token containing the closer.
129
                if (($i - 1) > $stackPtr) {
3✔
130
                    return $i;
3✔
131
                }
132
            }
1✔
133
        }//end if
1✔
134

135
    }//end process()
2✔
136

137

138
    /**
139
     * Get a snippet from a HTML token.
140
     *
141
     * @param string $content The content of the HTML token.
142
     * @param string $start   Partial string to use as a starting point for the snippet.
143
     * @param int    $length  The target length of the snippet to get. Defaults to 40.
144
     *
145
     * @return string
146
     */
147
    protected function getSnippet($content, $start='', $length=40)
3✔
148
    {
149
        $startPos = 0;
3✔
150

151
        if ($start !== '') {
3✔
152
            $startPos = strpos($content, $start);
3✔
153
            if ($startPos !== false) {
3✔
154
                $startPos += strlen($start);
3✔
155
            }
1✔
156
        }
1✔
157

158
        $snippet = substr($content, $startPos, $length);
3✔
159
        if ((strlen($content) - $startPos) > $length) {
3✔
160
            $snippet .= '...';
3✔
161
        }
1✔
162

163
        return $snippet;
3✔
164

165
    }//end getSnippet()
166

167

168
}//end class
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc