FinalPrivateSniff   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 139
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 14
eloc 36
c 3
b 0
f 0
dl 0
loc 139
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A handleProtectedMethodToken() 0 5 1
A register() 0 3 1
A handleProtectedVariableToken() 0 5 1
A process() 0 13 2
A handleErrors() 0 8 3
A handleToken() 0 18 4
A handleFoundProtectedElement() 0 10 2
1
<?php declare(strict_types = 1);
2
3
namespace Codor\Sniffs\Classes;
4
5
use PHP_CodeSniffer\Sniffs\Sniff as PHP_CodeSniffer_Sniff;
6
use PHP_CodeSniffer\Files\File as PHP_CodeSniffer_File;
7
8
/**
9
 * @SuppressWarnings(PHPMD.LongVariable)
10
 */
11
class FinalPrivateSniff implements PHP_CodeSniffer_Sniff
12
{
13
    /**
14
     * Returns the token types that this sniff is interested in.
15
     * @return array
16
     */
17
    public function register(): array
18
    {
19
        return [T_CLASS];
20
    }
21
22
    /**
23
     * Is the class marked as final?
24
     * @var boolean
25
     */
26
    protected $classIsMarkedFinal = false;
27
28
    /**
29
     * List of protected methods found.
30
     * @var array
31
     */
32
    protected $protectedMethodTokens = [];
33
34
    /**
35
     * List of protected variables found.
36
     * @var array
37
     */
38
    protected $protectedVariableTokens = [];
39
40
    /**
41
     * Processes the tokens that this sniff is interested in.
42
     *
43
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
44
     * @param int                  $stackPtr  The position in the stack where
45
     *                                        the token was found.
46
     * @return void
47
     * @SuppressWarnings(PHPMD.UnusedLocalVariable,)
48
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
49
     */
50
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
51
    {
52
        $this->classIsMarkedFinal = false;
53
        $this->protectedMethodTokens = [];
54
        $this->protectedVariableTokens = [];
55
56
        $tokens = $phpcsFile->getTokens();
57
58
        foreach ($tokens as $index => $token) {
59
            $this->handleToken($tokens, $index);
60
        }
61
62
        $this->handleErrors($phpcsFile);
63
    }
64
65
    /**
66
     * Handle the incoming token.
67
     * @param  array   $tokens List of tokens.
68
     * @param  integer $index  Current token index.
69
     * @return void
70
     */
71
    protected function handleToken($tokens, $index)
72
    {
73
        $tokenType = $tokens[$index]['type'];
74
75
        if ($tokenType === 'T_FINAL') {
76
            $this->classIsMarkedFinal = true;
77
            return;
78
        }
79
80
        if (! $this->classIsMarkedFinal) {
81
            return;
82
        }
83
84
        if ($tokenType !== 'T_PROTECTED') {
85
            return;
86
        }
87
        
88
        $this->handleFoundProtectedElement($tokens, $index);
89
    }
90
91
    /**
92
     * Handles found protected method or variable within
93
     * a final class.
94
     * @param  array   $tokens List of tokens.
95
     * @param  integer $index  Current token index.
96
     * @return void
97
     */
98
    protected function handleFoundProtectedElement($tokens, $index)
99
    {
100
        $type = $tokens[$index+2]['type'];
101
102
        if ($type === 'T_VARIABLE') {
103
            $this->protectedVariableTokens[] = $tokens[$index+2];
104
            return;
105
        }
106
107
        $this->protectedMethodTokens[] = $tokens[$index+4];
108
    }
109
110
    /**
111
     * Handle any errors.
112
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
113
     * @return void
114
     */
115
    protected function handleErrors($phpcsFile)
116
    {
117
        foreach ($this->protectedMethodTokens as $protectedMethodToken) {
118
            $this->handleProtectedMethodToken($protectedMethodToken, $phpcsFile);
119
        }
120
121
        foreach ($this->protectedVariableTokens as $protectedVariableToken) {
122
            $this->handleProtectedVariableToken($protectedVariableToken, $phpcsFile);
123
        }
124
    }
125
126
    /**
127
     * Add a protected method found error.
128
     * @param  array                $token     Token data.
129
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
130
     * @return void
131
     */
132
    protected function handleProtectedMethodToken($token, $phpcsFile)
133
    {
134
        $methodName = $token['content'];
135
        $line = $token['line'];
136
        $phpcsFile->addError("Final Class contains a protected method {$methodName} - should be private.", $line, __CLASS__);
137
    }
138
139
    /**
140
     * Add a protected variable found error.
141
     * @param  array                $token     Token data.
142
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
143
     * @return void
144
     */
145
    protected function handleProtectedVariableToken($token, $phpcsFile)
146
    {
147
        $variableName = $token['content'];
148
        $line = $token['line'];
149
        $phpcsFile->addError("Final Class contains a protected variable {$variableName} - should be private.", $line, __CLASS__);
150
    }
151
}
152