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

PHPCSStandards / PHP_CodeSniffer / 15253296250

26 May 2025 11:55AM UTC coverage: 78.632% (+0.3%) from 78.375%
15253296250

Pull #1105

github

web-flow
Merge d9441d98f into caf806050
Pull Request #1105: Skip tests when 'git' command is not available

19665 of 25009 relevant lines covered (78.63%)

88.67 hits per line

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

98.36
/src/Standards/Squiz/Sniffs/PHP/LowercasePHPFunctionsSniff.php
1
<?php
2
/**
3
 * Ensures all calls to inbuilt PHP functions are lowercase.
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\Squiz\Sniffs\PHP;
11

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

16
class LowercasePHPFunctionsSniff implements Sniff
17
{
18

19
    /**
20
     * String -> int hash map of all php built in function names
21
     *
22
     * @var array
23
     */
24
    private $builtInFunctions;
25

26

27
    /**
28
     * Construct the LowercasePHPFunctionSniff
29
     */
30
    public function __construct()
3✔
31
    {
32

33
        $allFunctions           = get_defined_functions();
3✔
34
        $this->builtInFunctions = array_flip($allFunctions['internal']);
3✔
35

36
    }//end __construct()
1✔
37

38

39
    /**
40
     * Returns an array of tokens this test wants to listen for.
41
     *
42
     * @return array<int|string>
43
     */
44
    public function register()
3✔
45
    {
46
        return [
2✔
47
            T_STRING,
3✔
48
            T_NAME_FULLY_QUALIFIED,
3✔
49
        ];
2✔
50

51
    }//end register()
52

53

54
    /**
55
     * Processes this test, when one of its tokens is encountered.
56
     *
57
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
58
     * @param int                         $stackPtr  The position of the current token in
59
     *                                               the stack passed in $tokens.
60
     *
61
     * @return void
62
     */
63
    public function process(File $phpcsFile, $stackPtr)
3✔
64
    {
65
        $tokens = $phpcsFile->getTokens();
3✔
66

67
        $content = $tokens[$stackPtr]['content'];
3✔
68
        if ($tokens[$stackPtr]['code'] === T_NAME_FULLY_QUALIFIED) {
3✔
69
            $content = ltrim($content, '\\');
3✔
70
        }
71

72
        $contentLc = strtolower($content);
3✔
73
        if ($content === $contentLc) {
3✔
74
            return;
3✔
75
        }
76

77
        // Make sure it is an inbuilt PHP function.
78
        // PHP_CodeSniffer can possibly include user defined functions
79
        // through the use of vendor/autoload.php.
80
        if (isset($this->builtInFunctions[$contentLc]) === false) {
3✔
81
            return;
3✔
82
        }
83

84
        // Make sure this is a function call or a use statement.
85
        if (empty($tokens[$stackPtr]['nested_attributes']) === false) {
3✔
86
            // Class instantiation in attribute, not function call.
87
            return;
3✔
88
        }
89

90
        $next = $phpcsFile->findNext(Tokens::EMPTY_TOKENS, ($stackPtr + 1), null, true);
3✔
91
        if ($next === false) {
3✔
92
            // Not a function call.
93
            return;
×
94
        }
95

96
        $ignore   = Tokens::EMPTY_TOKENS;
3✔
97
        $ignore[] = T_BITWISE_AND;
3✔
98
        $prev     = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true);
3✔
99
        $prevPrev = $phpcsFile->findPrevious(Tokens::EMPTY_TOKENS, ($prev - 1), null, true);
3✔
100

101
        if ($tokens[$next]['code'] !== T_OPEN_PARENTHESIS) {
3✔
102
            // Is this a use statement importing a PHP native function ?
103
            if ($tokens[$stackPtr]['code'] === T_STRING
3✔
104
                && $tokens[$prev]['code'] === T_STRING
3✔
105
                && $tokens[$prev]['content'] === 'function'
3✔
106
                && $prevPrev !== false
3✔
107
                && $tokens[$prevPrev]['code'] === T_USE
3✔
108
            ) {
109
                $error = 'Use statements for PHP native functions must be lowercase; expected "%s" but found "%s"';
3✔
110
                $data  = [
2✔
111
                    $contentLc,
3✔
112
                    $content,
3✔
113
                ];
2✔
114

115
                $fix = $phpcsFile->addFixableError($error, $stackPtr, 'UseStatementUppercase', $data);
3✔
116
                if ($fix === true) {
3✔
117
                    $phpcsFile->fixer->replaceToken($stackPtr, $contentLc);
3✔
118
                }
119
            }
120

121
            // No open parenthesis; not a "use function" statement nor a function call.
122
            return;
3✔
123
        }//end if
124

125
        if ($tokens[$prev]['code'] === T_FUNCTION) {
3✔
126
            // Function declaration, not a function call.
127
            return;
3✔
128
        }
129

130
        if ($tokens[$prev]['code'] === T_NEW) {
3✔
131
            // Object creation, not an inbuilt function.
132
            return;
3✔
133
        }
134

135
        if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR
3✔
136
            || $tokens[$prev]['code'] === T_NULLSAFE_OBJECT_OPERATOR
3✔
137
        ) {
138
            // Not an inbuilt function.
139
            return;
3✔
140
        }
141

142
        if ($tokens[$prev]['code'] === T_DOUBLE_COLON) {
3✔
143
            // Not an inbuilt function.
144
            return;
3✔
145
        }
146

147
        $error = 'Calls to PHP native functions must be lowercase; expected "%s" but found "%s"';
3✔
148
        $data  = [
2✔
149
            $contentLc,
3✔
150
            $content,
3✔
151
        ];
2✔
152

153
        $fix = $phpcsFile->addFixableError($error, $stackPtr, 'CallUppercase', $data);
3✔
154
        if ($fix === true) {
3✔
155
            $phpcsFile->fixer->replaceToken($stackPtr, strtolower($tokens[$stackPtr]['content']));
3✔
156
        }
157

158
    }//end process()
1✔
159

160

161
}//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

© 2025 Coveralls, Inc