GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

CoverFishHelper   B
last analyzed

Complexity

Total Complexity 49

Size/Duplication

Total Lines 323
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
wmc 49
lcom 1
cbo 0
dl 0
loc 323
rs 8.5454
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
A checkFileExist() 0 4 2
A checkParamNotEmpty() 0 4 2
A getClassNameFromClassFQN() 0 4 1
A getFileNameFromPath() 0 4 1
A getPathFromFileNameAndPath() 0 4 1
A getLastItemInFQNBlock() 0 8 2
A getClassFromUse() 0 15 4
A getUsedClassesInClass() 0 11 3
A getLocOfTestMethod() 0 8 3
A checkPath() 0 6 3
A checkFileOrPath() 0 8 2
A getFileContent() 0 8 2
A getCoversDefaultClassUsable() 0 8 2
A getAnnotationByKey() 0 10 2
A getAttributeByKey() 0 8 2
A getRegexPath() 0 4 1
A parseCoverAnnotationDocBlock() 0 20 4
A isValidTestMethod() 0 11 4
B isValidTestClass() 0 24 6
A checkClassHasFQN() 0 6 1
A stringToBool() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like CoverFishHelper often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use CoverFishHelper, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace DF\PHPCoverFish\Common;
4
5
/**
6
 * Class CoverFishHelper, coverFish toolbox
7
 *
8
 * @package   DF\PHPCoverFish
9
 * @author    Patrick Paechnatz <[email protected]>
10
 * @copyright 2015 Patrick Paechnatz <[email protected]>
11
 * @license   http://www.opensource.org/licenses/MIT
12
 * @link      http://github.com/dunkelfrosch/phpcoverfish/tree
13
 * @since     class available since Release 0.9.0
14
 * @version   1.0.0
15
 */
16
class CoverFishHelper
17
{
18
    const PHPUNIT_ID_INTERFACE = 'PHPUnit_Framework_Test',
19
          PHPUNIT_ID_CLASS = 'PHPUnit_Framework_TestCase';
20
21
    /**
22
     * @param string $file
23
     *
24
     * @return bool
25
     */
26
    public function checkFileExist($file)
27
    {
28
        return (true === $this->checkParamNotEmpty($file) && true === file_exists($file));
29
    }
30
31
    /**
32
     * @param $param
33
     *
34
     * @return bool
35
     */
36
    public function checkParamNotEmpty($param)
37
    {
38
        return ((null !== $param) && ('' !== $param));
39
    }
40
41
    /**
42
     * @param string $namespace
43
     *
44
     * @return string
45
     */
46
    public function getClassNameFromClassFQN($namespace)
47
    {
48
        return $this->getLastItemInFQNBlock($namespace, '\\');
49
    }
50
51
    /**
52
     * @param string $fileNameAndPath
53
     *
54
     * @return string
55
     */
56
    public function getFileNameFromPath($fileNameAndPath)
57
    {
58
        return $this->getLastItemInFQNBlock($fileNameAndPath, '/');
59
    }
60
61
    /**
62
     * @param string $namespace
63
     *
64
     * @return string
65
     */
66
    public function getPathFromFileNameAndPath($namespace)
67
    {
68
        return (string) str_replace($this->getFileNameFromPath($namespace), null, $namespace);
69
    }
70
71
    /**
72
     * @param string $fqn
73
     * @param string $delimiter
74
     *
75
     * @return string
76
     */
77
    public function getLastItemInFQNBlock($fqn, $delimiter)
78
    {
79
        if (false === $fqnBlock = explode($delimiter, $fqn)) {
80
            return $fqnBlock;
81
        }
82
83
        return (string) $fqnBlock[count($fqnBlock) - 1];
84
    }
85
86
    /**
87
     * check for className in use statements, return className on missing use statement
88
     *
89
     * @param string     $coverClassName
90
     * @param array|null $usedClasses
91
     *
92
     * @return string
93
     */
94
    public function getClassFromUse($coverClassName, $usedClasses)
95
    {
96
        if (false === is_array($usedClasses)) {
97
            return $coverClassName;
98
        }
99
100
        foreach ($usedClasses as $use) {
101
            $this->getClassNameFromClassFQN($use);
102
            if ($coverClassName === $this->getClassNameFromClassFQN($use)) {
103
                return $use;
104
            }
105
        }
106
107
        return $coverClassName;
108
    }
109
110
    /**
111
     * return all in file use statement defined classes
112
     *
113
     * @param string $classFile absolute path of readable class file
114
     *
115
     * @return array
116
     */
117
    public function getUsedClassesInClass($classFile)
118
    {
119
        $useResult = array();
120
        $content = $this->getFileContent($classFile);
121
        if (preg_match_all('/(use\s+)(.*)(;)/', $content, $useResult) && 4 === count($useResult)) {
122
            // @todo: use keyName based result check instead of index!
123
            return ($useResult[2]);
124
        }
125
126
        return null;
127
    }
128
129
    /**
130
     * return loc of given test method
131
     *
132
     * @param array $methodData
133
     *
134
     * @return int
135
     */
136
    public function getLocOfTestMethod(array $methodData)
137
    {
138
        if (array_key_exists('endLine', $methodData) && array_key_exists('startLine', $methodData)) {
139
            return $methodData['endLine'] - $methodData['startLine'];
140
        }
141
142
        return 0;
143
    }
144
145
    /**
146
     * @param string $path
147
     *
148
     * @return string|false
149
     */
150
    public function checkPath($path)
151
    {
152
        $path = realpath($path);
153
154
        return ($path !== false && is_dir($path)) ? $path : false;
155
    }
156
157
    /**
158
     * @param string $fileOrPath
159
     *
160
     * @return bool
161
     */
162
    public function checkFileOrPath($fileOrPath)
163
    {
164
        if (false === $this->checkPath($fileOrPath)) {
165
            return file_exists($fileOrPath);
166
        }
167
168
        return true;
169
    }
170
171
    /**
172
     * @param string $file absolute path of readable class file
173
     *
174
     * @return null|string
175
     */
176
    public function getFileContent($file)
177
    {
178
        if (!is_readable($file)) {
179
            return null;
180
        }
181
182
        return file_get_contents($file);
183
    }
184
185
    /**
186
     * in case of (wrong) multiple annotation, get the last defined coversDefaultClass from class docBlock
187
     *
188
     * @param array $coversDefaultClass
189
     *
190
     * @return string
191
     */
192
    public function getCoversDefaultClassUsable(array $coversDefaultClass)
193
    {
194
        if (true === empty($coversDefaultClass)) {
195
            return null;
196
        }
197
198
        return $coversDefaultClass[count($coversDefaultClass) - 1];
199
    }
200
201
    /**
202
     * fetch annotation key value(s) as array from corresponding class docBlock directly
203
     *
204
     * @param string $docBlock
205
     * @param string $key
206
     *
207
     * @return array
208
     */
209
    public function getAnnotationByKey($docBlock, $key)
210
    {
211
        /** @var array $classAnnotations */
212
        $classAnnotations = $this->parseCoverAnnotationDocBlock($docBlock);
213
        if (false === array_key_exists($key, $classAnnotations)) {
214
            return array();
215
        }
216
217
        return $classAnnotations[$key];
218
    }
219
220
    /**
221
     * @param string $key
222
     * @param array  $classData
223
     *
224
     * @return string
225
     */
226
    public function getAttributeByKey($key, array $classData)
227
    {
228
        if (false === array_key_exists($key, $classData)) {
229
            return '';
230
        }
231
232
        return (string) $classData[$key];
233
    }
234
235
    /**
236
     * @param string $inputPath
237
     *
238
     * @return string
239
     */
240
    public function getRegexPath($inputPath)
241
    {
242
        return sprintf('/%s/', str_replace('/', '\/', $inputPath));
243
    }
244
245
    /**
246
     * @param string $docBlock
247
     *
248
     * @return array
249
     */
250
    public function parseCoverAnnotationDocBlock($docBlock)
251
    {
252
        $annotations = array('covers' => array(), 'uses' => array());
253
        $docBlock = substr($docBlock, 3, -2);
254
        if (preg_match_all('/@(?P<name>[A-Za-z_-]+)(?:[ \t]+(?P<value>.*?))?[ \t]*\r?$/m', $docBlock, $matches)) {
255
            $numMatches = count($matches[0]);
256
            for ($i = 0; $i < $numMatches; ++$i) {
257
                $annotations[$matches['name'][$i]][] = $matches['value'][$i];
258
            }
259
        }
260
        array_walk_recursive(
261
            $annotations,
262
            function(&$element) {
263
                if (substr($element, 0, 1) === '\\') {
264
                    $element = substr($element, 1);
265
                }
266
            }
267
        );
268
        return $annotations;
269
    }
270
271
    public function isValidTestMethod($methodSignature)
272
    {
273
        $result = array();
274
275
        if (preg_match_all('/(?P<prefix>^test)/', $methodSignature, $result)
276
            && (array_key_exists('prefix', $result) && false === empty($result['prefix']))) {
277
            return true;
278
        }
279
280
        return false;
281
    }
282
283
    /**
284
     * Check if a class extends or implements a specific class/interface
285
     *
286
     * @param string $classFQN The class name of the object to compare to
287
     *
288
     * @return bool
289
     */
290
    public function isValidTestClass($classFQN)
291
    {
292
        try {
293
            $testClass = new \ReflectionClass($classFQN);
294
            do {
295
                if( self::PHPUNIT_ID_CLASS === $testClass->getName() ) {
296
                    return true;
297
                }
298
299
                $interfaces = $testClass->getInterfaceNames();
300
                if (is_array( $interfaces) && in_array(self::PHPUNIT_ID_INTERFACE, $interfaces)) {
301
                    return true;
302
                }
303
304
                $testClass = $testClass->getParentClass();
305
306
            } while (false !== $testClass);
307
308
        } catch (\Exception $e) {
309
            return false;
310
        }
311
312
        return false;
313
    }
314
315
    /**
316
     * check if class got fully qualified name
317
     *
318
     * @param string $class
319
     *
320
     * @return bool
321
     */
322
    public function checkClassHasFQN($class)
323
    {
324
        preg_match_all('/(\\\\+)/', $class, $result, PREG_SET_ORDER);
325
326
        return count($result) > 0;
327
    }
328
329
    /**
330
     * @param $string
331
     *
332
     * @return bool
333
     */
334
    public function stringToBool($string)
335
    {
336
        return filter_var($string, FILTER_VALIDATE_BOOLEAN);
337
    }
338
}