Completed
Pull Request — master (#165)
by Juliette
10:56 queued 08:22
created

RequiredOptionalFunctionParametersSniff   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 12
c 1
b 0
f 1
lcom 1
cbo 3
dl 0
loc 110
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 4 1
C process() 0 58 11
1
<?php
2
/**
3
 * PHPCompatibility_Sniffs_PHP_RequiredOptionalFunctionParametersSniff.
4
 *
5
 * @category  PHP
6
 * @package   PHPCompatibility
7
 * @author    Wim Godden <[email protected]>
8
 */
9
10
/**
11
 * PHPCompatibility_Sniffs_PHP_RequiredOptionalFunctionParametersSniff.
12
 *
13
 * @category  PHP
14
 * @package   PHPCompatibility
15
 * @author    Wim Godden <[email protected]>
16
 */
17
class PHPCompatibility_Sniffs_PHP_RequiredOptionalFunctionParametersSniff 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
20
    /**
21
     * A list of function parameters, which were required in older versions and became optional later on.
22
     *
23
     * The array lists : version number with true (required) and false (optional).
24
     *
25
     * The index is the location of the parameter in the parameter list, starting at 0 !
26
     * If's sufficient to list the last version in which the parameter was still required.
27
     *
28
     * @var array
29
     */
30
    protected $functionParameters = array(
31
                                     'preg_match_all' => array(
32
                                         2 => array(
33
                                             'name' => 'matches',
34
                                             '5.3' => true,
35
                                             '5.4' => false,
36
                                         ),
37
                                     ),
38
                                     'stream_socket_enable_crypto' => array(
39
                                         2 => array(
40
                                             'name' => 'crypto_type',
41
                                             '5.5' => true,
42
                                             '5.6' => false,
43
                                         ),
44
                                     ),
45
                                    );
46
47
48
    /**
49
     * Returns an array of tokens this test wants to listen for.
50
     *
51
     * @return array
52
     */
53
    public function register()
54
    {
55
        return array(T_STRING);
56
    }//end register()
57
58
    /**
59
     * Processes this test, when one of its tokens is encountered.
60
     *
61
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
62
     * @param int                  $stackPtr  The position of the current token in
63
     *                                        the stack passed in $tokens.
64
     *
65
     * @return void
66
     */
67
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
68
    {
69
        $tokens = $phpcsFile->getTokens();
70
71
        $ignore = array(
72
                T_DOUBLE_COLON,
73
                T_OBJECT_OPERATOR,
74
                T_FUNCTION,
75
                T_CONST,
76
        );
77
78
        $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
79
        if (in_array($tokens[$prevToken]['code'], $ignore) === true) {
80
            // Not a call to a PHP function.
81
            return;
82
        }
83
84
        $function = strtolower($tokens[$stackPtr]['content']);
85
86
        if (isset($this->functionParameters[$function]) === false) {
87
            return;
88
        }
89
90
        $parameterCount = $this->getFunctionCallParameterCount($phpcsFile, $stackPtr);
91
        if ($parameterCount === 0) {
92
            return;
93
        }
94
95
        // If the parameter count returned > 0, we know there will be valid open parenthesis.
96
        $openParenthesis      = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $stackPtr + 1, null, true, null, true);
97
        $parameterOffsetFound = $parameterCount - 1;
98
        $requiredVersion      = null;
99
        $parameterName        = null;
100
101
        foreach($this->functionParameters[$function] as $offset => $parameterDetails) {
102
            if ($offset > $parameterOffsetFound) {
103
                foreach ($parameterDetails as $version => $present) {
104
                    if ($version !== 'name' && $present === true && $this->supportsBelow($version)) {
105
						$requiredVersion = $version;
106
						$parameterName   = $parameterDetails['name'];
107
                    }
108
                }
109
            }
110
        }
111
        
112
        if (isset($requiredVersion, $parameterName)) {
113
114
            $error     = 'The "%s" parameter for function %s is missing, but was required for PHP version %s and lower';
115
            $errorCode = 'MissingRequiredParameter';
116
            $data      = array(
117
                          $parameterName,
118
                          $function,
119
                          $requiredVersion,
120
                         );
121
            $phpcsFile->addError($error, $openParenthesis, $errorCode, $data);
0 ignored issues
show
Security Bug introduced by
It seems like $openParenthesis defined by $phpcsFile->findNext(\PH...null, true, null, true) on line 96 can also be of type false; however, PHP_CodeSniffer_File::addError() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
122
		}
123
124
    }//end process()
125
126
}//end class
127