Failed Conditions
Branch test-scrutinizer-coverage (7e25b2)
by Wim
13:51 queued 10:07
created

NonStaticMagicMethodsSniff::process()   C

Complexity

Conditions 11
Paths 17

Size

Total Lines 69
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 11.0025

Importance

Changes 0
Metric Value
dl 0
loc 69
ccs 35
cts 36
cp 0.9722
rs 5.7847
c 0
b 0
f 0
cc 11
eloc 36
nc 17
nop 2
crap 11.0025

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
74
    /**
75
     * Returns an array of tokens this test wants to listen for.
76
     *
77
     * @return array
78
     */
79 145
    public function register()
80
    {
81
        $targets = array(
82 145
            T_CLASS,
83
            T_INTERFACE,
84
            T_TRAIT,
85
        );
86
87 145
        if (defined('T_ANON_CLASS')) {
88 145
            $targets[] = constant('T_ANON_CLASS');
89
        }
90
91 145
        return $targets;
92
93
    }//end register()
94
95
96
    /**
97
     * Processes this test, when one of its tokens is encountered.
98
     *
99
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
100
     * @param int                  $stackPtr  The position of the current token in the
101
     *                                        stack passed in $tokens.
102
     *
103
     * @return void
104
     */
105 3
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
106
    {
107
        // Should be removed, the requirement was previously also there, 5.3 just started throwing a warning about it.
108 3
        if ($this->supportsAbove('5.3') === false) {
109 1
            return;
110
        }
111
112 2
        $tokens = $phpcsFile->getTokens();
113
114 2
        if (isset($tokens[$stackPtr]['scope_closer']) === false) {
115
            return;
116
        }
117
118 2
        $classScopeCloser = $tokens[$stackPtr]['scope_closer'];
119 2
        $functionPtr      = $stackPtr;
120
121
        // Find all the functions in this class or interface.
122 2
        while ($functionToken = $phpcsFile->findNext(T_FUNCTION, $functionPtr, $classScopeCloser)) {
123
            /*
124
             * Get the scope closer for this function in order to know how
125
             * to advance to the next function.
126
             * If no body of function (e.g. for interfaces), there is
127
             * no closing curly brace; advance the pointer differently.
128
             */
129 2
            $scopeCloser = isset($tokens[$functionToken]['scope_closer'])
130 2
                ? $tokens[$functionToken]['scope_closer']
131 2
                : $functionToken + 1;
132
133
134 2
            $methodName   = $phpcsFile->getDeclarationName($functionToken);
135 2
            $methodNameLc = strtolower($methodName);
136 2
            if (isset($this->magicMethods[$methodNameLc]) === false) {
137 2
                $functionPtr = $scopeCloser;
138 2
                continue;
139
            }
140
141 2
            $methodProperties = $phpcsFile->getMethodProperties($functionToken);
142 2
            $errorCodeBase    = $this->stringToErrorCode($methodNameLc);
143
144 2
            if (isset($this->magicMethods[$methodNameLc]['visibility']) && $this->magicMethods[$methodNameLc]['visibility'] !== $methodProperties['scope']) {
145 2
                $error     = 'Visibility for magic method %s must be %s. Found: %s';
146 2
                $errorCode = $errorCodeBase.'MethodVisibility';
147
                $data      = array(
148 2
                    $methodName,
149 2
                    $this->magicMethods[$methodNameLc]['visibility'],
150 2
                    $methodProperties['scope'],
151
                );
152
153 2
                $phpcsFile->addError($error, $functionToken, $errorCode, $data);
154
            }
155
156 2
            if (isset($this->magicMethods[$methodNameLc]['static']) && $this->magicMethods[$methodNameLc]['static'] !== $methodProperties['is_static']) {
157 2
                $error     = 'Magic method %s cannot be defined as static.';
158 2
                $errorCode = $errorCodeBase.'MethodStatic';
159 2
                $data      = array($methodName);
160
161 2
                if ($this->magicMethods[$methodNameLc]['static'] === true) {
162 2
                    $error     = 'Magic method %s must be defined as static.';
163 2
                    $errorCode = $errorCodeBase.'MethodNonStatic';
164
                }
165
166 2
                $phpcsFile->addError($error, $functionToken, $errorCode, $data);
167
            }
168
169
            // Advance to next function.
170 2
            $functionPtr = $scopeCloser;
171
        }
172
173 2
    }//end process()
174
175
176
}//end class
177