Completed
Push — master ( a32632...c637b7 )
by Juliette
9s
created

process()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 53
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 53
rs 7.5251
c 0
b 0
f 0
cc 7
eloc 36
nc 9
nop 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * PHPCompatibility_Sniffs_PHP_ValidIntegersSniff.
4
 *
5
 * @category  PHP
6
 * @package   PHPCompatibility
7
 * @author    Juliette Reinders Folmer <[email protected]>
8
 */
9
10
/**
11
 * PHPCompatibility_Sniffs_PHP_ValidIntegersSniff.
12
 *
13
 * @category  PHP
14
 * @package   PHPCompatibility
15
 * @author    Juliette Reinders Folmer <[email protected]>
16
 */
17
class PHPCompatibility_Sniffs_PHP_ValidIntegersSniff extends PHPCompatibility_Sniff
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
18
{
19
    protected $isLowPHPVersion = false;
20
21
    /**
22
     * Returns an array of tokens this test wants to listen for.
23
     *
24
     * @return array
25
     */
26
    public function register()
27
    {
28
        $this->isLowPHPVersion = version_compare(phpversion(), '5.4', '<');
29
30
        return array(
31
                T_LNUMBER, // Binary, octal integers.
32
                T_CONSTANT_ENCAPSED_STRING, // Hex numeric string.
33
               );
34
35
    }//end register()
36
37
38
    /**
39
     * Processes this test, when one of its tokens is encountered.
40
     *
41
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
42
     * @param int                  $stackPtr  The position of the current token in
43
     *                                        the stack.
44
     *
45
     * @return void
46
     */
47
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
48
    {
49
        $tokens = $phpcsFile->getTokens();
50
        $token  = $tokens[$stackPtr];
51
52
        if ($this->couldBeBinaryInteger($tokens, $stackPtr) === true) {
53
            if ($this->supportsBelow('5.3')) {
54
                $error = 'Binary integer literals were not present in PHP version 5.3 or earlier. Found: %s';
55
                if ($this->isLowPHPVersion === false) {
56
                    $data = array($token['content']);
57
                }
58
                else {
59
                    $data = array($this->getBinaryInteger($phpcsFile, $tokens, $stackPtr));
60
                }
61
                $phpcsFile->addError($error, $stackPtr, 'BinaryIntegerFound', $data);
62
            }
63
64
            if ($this->isInvalidBinaryInteger($tokens, $stackPtr) === true) {
65
                $error = 'Invalid binary integer detected. Found: %s';
66
                $data  = array($this->getBinaryInteger($phpcsFile, $tokens, $stackPtr));
67
                $phpcsFile->addWarning($error, $stackPtr, 'InvalidBinaryIntegerFound', $data);
68
            }
69
            return;
70
        }
71
72
        $isError = $this->supportsAbove('7.0');
73
        $data    = array( $token['content'] );
74
75
        if ($this->isInvalidOctalInteger($tokens, $stackPtr) === true) {
76
            $this->addMessage(
77
                $phpcsFile,
78
                'Invalid octal integer detected. Prior to PHP 7 this would lead to a truncated number. From PHP 7 onwards this causes a parse error. Found: %s',
79
                $stackPtr,
80
                $isError,
81
                'InvalidOctalIntegerFound',
82
                $data
83
            );
84
            return;
85
        }
86
87
        if ($this->isHexidecimalNumericString($tokens, $stackPtr) === true) {
88
            $this->addMessage(
89
                $phpcsFile,
90
                'The behaviour of hexadecimal numeric strings was inconsistent prior to PHP 7 and support has been removed in PHP 7. Found: %s',
91
                $stackPtr,
92
                $isError,
93
                'HexNumericStringFound',
94
                $data
95
            );
96
            return;
97
        }
98
99
    }//end process()
100
101
102
    /**
103
     * Could the current token an potentially be a binary integer ?
104
     *
105
     * @param array $tokens   Token stack.
106
     * @param int   $stackPtr The current position in the token stack.
107
     *
108
     * @return bool
109
     */
110
    private function couldBeBinaryInteger($tokens, $stackPtr) {
111
        $token = $tokens[$stackPtr];
112
113
        if ($token['code'] !== T_LNUMBER) {
114
            return false;
115
        }
116
117
        if ($this->isLowPHPVersion === false) {
118
            return (preg_match('`^0b[0-1]+$`D', $token['content']) === 1);
119
        }
120
        // Pre-5.4, binary strings are tokenized as T_LNUMBER (0) + T_STRING ("b01010101").
121
        // At this point, we don't yet care whether it's a valid binary int, that's a separate check.
122
        else {
123
            return($token['content'] === '0' && $tokens[$stackPtr+1]['code'] === T_STRING && preg_match('`^b[0-9]+$`D', $tokens[$stackPtr+1]['content']) === 1);
124
        }
125
    }
126
127
    /**
128
     * Is the current token an invalid binary integer ?
129
     *
130
     * @param array $tokens   Token stack.
131
     * @param int   $stackPtr The current position in the token stack.
132
     *
133
     * @return bool
134
     */
135
    private function isInvalidBinaryInteger($tokens, $stackPtr) {
136
        if ($this->couldBeBinaryInteger($tokens, $stackPtr) === false) {
137
            return false;
138
        }
139
140
        if ($this->isLowPHPVersion === false) {
141
            // If it's an invalid binary int, the token will be split into two T_LNUMBER tokens.
142
            return ($tokens[$stackPtr+1]['code'] === T_LNUMBER);
143
        }
144
        else {
145
            return (preg_match('`^b[0-1]+$`D', $tokens[$stackPtr+1]['content']) === 0);
146
        }
147
    }
148
149
    /**
150
     * Retrieve the content of the tokens which together look like a binary integer.
151
     *
152
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
153
     * @param array                $tokens    Token stack.
154
     * @param int                  $stackPtr  The position of the current token in
155
     *                                        the stack.
156
     *
157
     * @return string
158
     */
159
    private function getBinaryInteger(PHP_CodeSniffer_File $phpcsFile, $tokens, $stackPtr) {
160
        $length = 2; // PHP < 5.4 T_LNUMBER + T_STRING
161
162
        if ($this->isLowPHPVersion === false) {
163
            $i = $stackPtr;
164
            while ($tokens[$i]['code'] === T_LNUMBER) {
165
                $i++;
166
            }
167
            $length = ($i - $stackPtr);
168
        }
169
170
        return $phpcsFile->getTokensAsString($stackPtr, $length);
171
    }
172
173
    /**
174
     * Is the current token an invalid octal integer ?
175
     *
176
     * @param array $tokens   Token stack.
177
     * @param int   $stackPtr The current position in the token stack.
178
     *
179
     * @return bool
180
     */
181 View Code Duplication
    private function isInvalidOctalInteger($tokens, $stackPtr) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
182
        $token = $tokens[$stackPtr];
183
184
        if ($token['code'] === T_LNUMBER && preg_match('`^0[0-7]*[8-9]+[0-9]*$`D', $token['content']) === 1) {
185
            return true;
186
        }
187
188
        return false;
189
    }
190
191
    /**
192
     * Is the current token a hexidecimal numeric string ?
193
     *
194
     * @param array $tokens   Token stack.
195
     * @param int   $stackPtr The current position in the token stack.
196
     *
197
     * @return bool
198
     */
199 View Code Duplication
    private function isHexidecimalNumericString($tokens, $stackPtr) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
200
        $token = $tokens[$stackPtr];
201
202
        if ($token['code'] === T_CONSTANT_ENCAPSED_STRING && preg_match('`^0x[a-f0-9]+$`iD', $this->stripQuotes($token['content'])) === 1) {
203
            return true;
204
        }
205
206
        return false;
207
    }
208
209
}//end class
210