Completed
Pull Request — master (#174)
by Juliette
02:35
created

NonStaticMagicMethodsSniff::process()   C

Complexity

Conditions 11
Paths 17

Size

Total Lines 68
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 68
rs 5.8371
cc 11
eloc 35
nc 17
nop 2

How to fix   Long Method    Complexity   

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_NonStaticMagicMethodsSniff.
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  PHP
8
 * @package   PHPCompatibility
9
 * @author    Wim Godden <[email protected]>
10
 * @copyright 2012 Cu.be Solutions bvba
11
 */
12
13
/**
14
 * PHPCompatibility_Sniffs_PHP_NonStaticMagicMethodsSniff.
15
 *
16
 * Verifies the use of the correct visibility and static properties of magic methods.
17
 *
18
 * @category  PHP
19
 * @package   PHPCompatibility
20
 * @author    Wim Godden <[email protected]>
21
 * @copyright 2012 Cu.be Solutions bvba
22
 */
23
class PHPCompatibility_Sniffs_PHP_NonStaticMagicMethodsSniff 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...
24
{
25
26
    /**
27
     * A list of PHP magic methods and their visibility and static requirements.
28
     *
29
     * Method names in the array should be all *lowercase*.
30
     * Visibility can be either 'public', 'protected' or 'private'.
31
     * Static can be either 'true' - *must* be static, or 'false' - *must* be non-static.
32
     * When a method does not have a specific requirement for either visibility or static,
33
     * do *not* add the key.
34
     *
35
     * @var array(string)
36
     */
37
    protected $magicMethods = array(
38
        '__get' => array(
39
            'visibility' => 'public',
40
            'static'     => false,
41
        ),
42
        '__set' => array(
43
            'visibility' => 'public',
44
            'static'     => false,
45
        ),
46
        '__isset' => array(
47
            'visibility' => 'public',
48
            'static'     => false,
49
        ),
50
        '__unset' => array(
51
            'visibility' => 'public',
52
            'static'     => false,
53
        ),
54
        '__call' => array(
55
            'visibility' => 'public',
56
            'static'     => false,
57
        ),
58
        '__callstatic' => array(
59
            'visibility' => 'public',
60
            'static'     => true,
61
        ),
62
        '__sleep' => array(
63
            'visibility' => 'public',
64
        ),
65
        '__tostring' => array(
66
            'visibility' => 'public',
67
        ),
68
        '__set_state' => array(
69
            'static'     => true,
70
        ),
71
72
        /*
73
         * SoapClient specific magic methods.
74
         * @link http://php.net/manual/en/class.soapclient.php
75
         */
76
        '__dorequest' => array(
77
            'visibility' => 'public',
78
        ),
79
        '__getfunctions' => array(
80
            'visibility' => 'public',
81
        ),
82
        '__getlastrequest' => array(
83
            'visibility' => 'public',
84
        ),
85
        '__getlastrequestheaders' => array(
86
            'visibility' => 'public',
87
        ),
88
        '__getlastresponse' => array(
89
            'visibility' => 'public',
90
        ),
91
        '__getlastresponseheaders' => array(
92
            'visibility' => 'public',
93
        ),
94
        '__gettypes' => array(
95
            'visibility' => 'public',
96
        ),
97
        '__setcookie' => array(
98
            'visibility' => 'public',
99
        ),
100
        '__setlocation' => array(
101
            'visibility' => 'public',
102
        ),
103
        '__setsoapheaders' => array(
104
            'visibility' => 'public',
105
        ),
106
        '__soapcall' => array(
107
            'visibility' => 'public',
108
        ),
109
    );
110
111
112
    /**
113
     * Returns an array of tokens this test wants to listen for.
114
     *
115
     * @return array
116
     */
117
    public function register()
118
    {
119
        return array(T_CLASS, T_INTERFACE, T_TRAIT);
120
121
    }//end register()
122
123
124
    /**
125
     * Processes this test, when one of its tokens is encountered.
126
     *
127
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
128
     * @param int                  $stackPtr  The position of the current token in the
129
     *                                        stack passed in $tokens.
130
     *
131
     * @return void
132
     */
133
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
134
    {
135
        // Should be removed, the requirement was previously also there, 5.3 just started throwing a warning about it.
136
        if ($this->supportsAbove('5.3') === false) {
137
            return;
138
        }
139
140
        $tokens = $phpcsFile->getTokens();
141
142
        if (isset($tokens[$stackPtr]['scope_closer']) === false) {
143
            return;
144
        }
145
146
        $classScopeCloser = $tokens[$stackPtr]['scope_closer'];
147
        $functionPtr      = $stackPtr;
148
149
        // Find all the functions in this class or interface.
150
        while ($functionToken = $phpcsFile->findNext(T_FUNCTION, $functionPtr, $classScopeCloser)) {
151
            /*
152
             * Get the scope closer for this function in order to know how
153
             * to advance to the next function.
154
             * If no body of function (e.g. for interfaces), there is
155
             * no closing curly brace; advance the pointer differently.
156
             */
157
            $scopeCloser = isset($tokens[$functionToken]['scope_closer'])
158
                ? $tokens[$functionToken]['scope_closer']
159
                : $functionToken + 1;
160
161
162
            $methodName   = $phpcsFile->getDeclarationName($functionToken);
163
            $methodNameLc = strtolower($methodName);
164
            if (isset($this->magicMethods[$methodNameLc]) === false) {
165
                $functionPtr = $scopeCloser;
166
                continue;
167
            }
168
169
            $methodProperties = $phpcsFile->getMethodProperties($functionToken);
170
171
            if (isset($this->magicMethods[$methodNameLc]['visibility']) && $this->magicMethods[$methodNameLc]['visibility'] !== $methodProperties['scope']) {
172
                $error = 'Visibility for magic method %s must be %s. Found: %s';
173
                $data  = array(
174
                    $methodName,
175
                    $this->magicMethods[$methodNameLc]['visibility'],
176
                    $methodProperties['scope'],
177
                );
178
179
                $phpcsFile->addError($error, $functionToken, 'MethodVisibility', $data);
180
            }
181
182
            if (isset($this->magicMethods[$methodNameLc]['static']) && $this->magicMethods[$methodNameLc]['static'] !== $methodProperties['is_static']) {
183
                $error     = 'Magic method %s cannot be defined as static.';
184
                $errorCode = 'MethodStatic';
185
                if ( $this->magicMethods[$methodNameLc]['static'] === true ) {
186
                    $error     = 'Magic method %s must be defined as static.';
187
                    $errorCode = 'MethodNonStatic';
188
                }
189
                $data = array(
190
                    $methodName,
191
                );
192
193
                $phpcsFile->addError($error, $functionToken, $errorCode, $data);
194
            }
195
196
            // Advance to next function.
197
            $functionPtr = $scopeCloser;
198
        }
199
200
    }//end process()
201
202
203
}//end class
204