Failed Conditions
Push — master ( c35fd9...2f93af )
by Alexander
02:57
created

ValidFunctionNameSniff   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 217
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 96.97%

Importance

Changes 0
Metric Value
dl 0
loc 217
ccs 64
cts 66
cp 0.9697
rs 9.76
c 0
b 0
f 0
wmc 33
lcom 1
cbo 3

4 Methods

Rating   Name   Duplication   Size   Complexity  
F processTokenWithinScope() 0 102 21
A isExclusion() 0 10 5
A isEventHandlerExclusion() 0 9 4
A isTagProcessorExclusion() 0 9 3
1
<?php
2
/**
3
 * CodingStandard_Sniffs_NamingConventions_ValidFunctionNameSniff.
4
 *
5
 * PHP version 5
6
 *
7
 * @category PHP
8
 * @package  PHP_CodeSniffer
9
 * @author   Greg Sherwood <[email protected]>
10
 * @author   Marc McIntyre <[email protected]>
11
 * @author   Alexander Obuhovich <[email protected]>
12
 * @license  https://github.com/aik099/CodingStandard/blob/master/LICENSE BSD 3-Clause
13
 * @link     https://github.com/aik099/CodingStandard
14
 */
15
16
namespace CodingStandard\Sniffs\NamingConventions;
17
18
use PHP_CodeSniffer\Files\File;
19
use PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff as PEAR_ValidFunctionNameSniff;
20
use PHP_CodeSniffer\Util\Common;
21
22
/**
23
 * CodingStandard_Sniffs_NamingConventions_ValidFunctionNameSniff.
24
 *
25
 * Ensures method names are correct depending on whether they are public
26
 * or private, and that functions are named correctly.
27
 *
28
 * @category PHP
29
 * @package  PHP_CodeSniffer
30
 * @author   Greg Sherwood <[email protected]>
31
 * @author   Marc McIntyre <[email protected]>
32
 * @author   Alexander Obuhovich <[email protected]>
33
 * @license  https://github.com/aik099/CodingStandard/blob/master/LICENSE BSD 3-Clause
34
 * @link     https://github.com/aik099/CodingStandard
35
 */
36
class ValidFunctionNameSniff extends PEAR_ValidFunctionNameSniff
37
{
38
39
    protected $exclusions = array(
40
        // Don't match to the end of class name to allow "SomeEventHandlerFeature" format.
41
        '/EventHandler/' => array(
42
            'SetCustomQuery',
43
            'CheckPermission',
44
            'BaseQuery',
45
            'ListPrepareQuery',
46
            'ItemPrepareQuery',
47
            'SetPagination',
48
            'SetSorting',
49
        ),
50
        // Don't match to the end of class name to allow "SomeTagProcessorFeature" format.
51
        '/TagProcessor/' => array(
52
            'PrepareListElementParams',
53
        ),
54
        '/Formatter$/' => array(
55
            'Format',
56
            'Parse',
57
            'PrepareOptions',
58
        ),
59
        '/Validator$/' => array(
60
            'GetErrorMsg',
61
            'CustomValidation',
62
            'SetError',
63
        ),
64
        '/ShippingQuoteEngine$/' => array(
65
            'GetShippingQuotes',
66
            'GetAvailableTypes',
67
            'GetEngineFields',
68
            'MakeOrder',
69
        ),
70
        '/Helper$/' => array(
71
            'Init',
72
            'InitHelper',
73
        ),
74
        '/Item$/' => array('*'),
75
        '/List$/' => array('*'),
76
        '/DBConnection/' => array('*'),
77
        '/DBLoadBalancer$/' => array('*'),
78
        '/Application$/' => array('*'),
79
    );
80
81
    /**
82
     * Processes the tokens within the scope.
83
     *
84
     * @param File $phpcsFile The file being processed.
85
     * @param int  $stackPtr  The position where this token was
86
     *                        found.
87
     * @param int  $currScope The position of the current scope.
88
     *
89
     * @return void
90
     */
91 1
    protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope)
92
    {
93 1
        $methodName = $phpcsFile->getDeclarationName($stackPtr);
94 1
        if ($methodName === null) {
95
            // Ignore closures.
96
            return;
97
        }
98
99 1
        $className = $phpcsFile->getDeclarationName($currScope);
100 1
        $errorData = array($className.'::'.$methodName);
101
102
        // Is this a magic method. i.e., is prefixed with "__" ?
103 1
        if (strpos($methodName, '__') === 0) {
104 1
            $magicPart = strtolower(substr($methodName, 2));
105
106 1
            if (isset($this->magicMethods[$magicPart]) === false) {
107 1
                $error = 'Method name "%s" is invalid; only PHP magic methods should be prefixed with a double underscore';
108 1
                $phpcsFile->addError($error, $stackPtr, 'MethodDoubleUnderscore', $errorData);
109
            }
110
111 1
            return;
112
        }
113
114
        // PHP4 constructors are allowed to break our rules.
115 1
        if ($methodName === $className) {
116 1
            return;
117
        }
118
119
        // PHP4 destructors are allowed to break our rules.
120 1
        if ($methodName === '_'.$className) {
121 1
            return;
122
        }
123
124 1
        $methodProps    = $phpcsFile->getMethodProperties($stackPtr);
125 1
        $isPublic       = ($methodProps['scope'] === 'private') ? false : true;
126 1
        $scope          = $methodProps['scope'];
127 1
        $scopeSpecified = $methodProps['scope_specified'];
128
129
        // If it's a private method, it must have an underscore on the front.
130 1
        if ($isPublic === false) {
131 1
            if ($methodName{0} !== '_') {
132 1
                $error = 'Private method name "%s" must be prefixed with an underscore';
133 1
                $phpcsFile->addError($error, $stackPtr, 'PrivateNoUnderscore', $errorData);
134
135 1
                if (isset($phpcsFile->fixer) === true) {
136 1
                    $phpcsFile->recordMetric($stackPtr, 'Private method prefixed with underscore', 'no');
137
                }
138
139 1
                return;
140
            } else {
141 1
                if (isset($phpcsFile->fixer) === true) {
142 1
                    $phpcsFile->recordMetric($stackPtr, 'Private method prefixed with underscore', 'yes');
143
                }
144
            }
145
        }
146
147
        // If it's not a private method, it must not have an underscore on the front.
148 1
        if ($isPublic === true && $scopeSpecified === true && $methodName{0} === '_') {
149 1
            $error = '%s method name "%s" must not be prefixed with an underscore';
150
            $data  = array(
151 1
                      ucfirst($scope),
152 1
                      $errorData[0],
153
                     );
154 1
            $phpcsFile->addError($error, $stackPtr, 'PublicUnderscore', $data);
155 1
            return;
156
        }
157
158
        // If the scope was specified on the method, then the method must be
159
        // camel caps and an underscore should be checked for. If it wasn't
160
        // specified, treat it like a public method and remove the underscore
161
        // prefix if there is one because we cant determine if it is private or
162
        // public.
163 1
        $testMethodName = $methodName;
164 1
        if ($scopeSpecified === false && $methodName{0} === '_') {
165 1
            $testMethodName = substr($methodName, 1);
166
        }
167
168 1
        $methodParams = $phpcsFile->getMethodParameters($stackPtr);
169
170 1
        if ($this->isExclusion($className, $methodName, $isPublic) === true
171 1
            || $this->isEventHandlerExclusion($className, $methodName, $methodParams) === true
172 1
            || $this->isTagProcessorExclusion($className, $methodName, $methodParams) === true
173
        ) {
174 1
            return;
175
        }
176
177 1
        if (Common::isCamelCaps($testMethodName, false, $isPublic, false) === false) {
178 1
            if ($scopeSpecified === true) {
179 1
                $error = '%s method name "%s" is not in camel caps format';
180
                $data  = array(
181 1
                          ucfirst($scope),
182 1
                          $errorData[0],
183
                         );
184 1
                $phpcsFile->addError($error, $stackPtr, 'ScopeNotCamelCaps', $data);
185
            } else {
186 1
                $error = 'Method name "%s" is not in camel caps format';
187 1
                $phpcsFile->addError($error, $stackPtr, 'NotCamelCaps', $errorData);
188
            }
189
190 1
            return;
191
        }
192 1
    }//end processTokenWithinScope()
193
194
    /**
195
     * Determines if a method name shouldn't be checked for camelCaps format.
196
     *
197
     * @param string $className  Class name.
198
     * @param string $methodName Method name.
199
     * @param bool   $isPublic   Public.
200
     *
201
     * @return bool
202
     */
203 1
    protected function isExclusion($className, $methodName, $isPublic)
204
    {
205 1
        foreach ($this->exclusions as $classRegExp => $excludedMethods) {
206 1
            if (preg_match($classRegExp, $className)) {
207 1
                return ($excludedMethods[0] == '*' && $isPublic) || in_array($methodName, $excludedMethods);
208
            }
209
        }
210
211 1
        return false;
212
    }//end isExclusion()
213
214
    /**
215
     * Determines if a method is an event in the event handler class.
216
     *
217
     * @param string $className    Class name.
218
     * @param string $methodName   Method name.
219
     * @param array  $methodParams Method parameters.
220
     *
221
     * @return bool
222
     */
223 1
    protected function isEventHandlerExclusion($className, $methodName, array $methodParams)
224
    {
225 1
        if (strpos($className, 'EventHandler') === false) {
226
            // Not EventHandler class.
227 1
            return false;
228
        }
229
230 1
        return substr($methodName, 0, 2) == 'On' && count($methodParams) === 1 && $methodParams[0]['name'] === '$event';
231
    }//end isEventHandlerExclusion()
232
233
234
    /**
235
     * Determines if a method is an tag in the tag processor class.
236
     *
237
     * @param string $className    Class name.
238
     * @param string $methodName   Method name.
239
     * @param array  $methodParams Method parameters.
240
     *
241
     * @return bool
242
     */
243 1
    protected function isTagProcessorExclusion($className, $methodName, array $methodParams)
0 ignored issues
show
Unused Code introduced by
The parameter $methodName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
244
    {
245 1
        if (strpos($className, 'TagProcessor') === false) {
246
            // Not TagProcessor class.
247 1
            return false;
248
        }
249
250
        return count($methodParams) === 1 && $methodParams[0]['name'] === '$params';
251
    }//end isTagProcessorExclusion()
252
}//end class
253