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.
Completed
Pull Request — master (#48)
by joseph
07:07 queued 04:31
created

CheckAnnotations::checkMedium()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\PHPQA\PHPUnit;
4
5
/**
6
 * Class CheckForLargeAndMediumAnnotations
7
 *
8
 * This class checks a test directory structure and if it is using the Edmonds Commerce recommended style of a
9
 * `Large`,`Medium` and `Large` sub directory structure, then we will also ensure that the large and medium tests are
10
 * correctly annotated
11
 *
12
 * @package EdmondsCommerce\PHPQA\PHPUnit
13
 */
14
class CheckAnnotations
15
{
16
    /**
17
     * @var string
18
     */
19
    private $largePath;
20
    /**
21
     * @var string
22
     */
23
    private $mediumPath;
24
25
    /**
26
     * @var string
27
     */
28
    private $smallPath;
29
30
    /**
31
     * @var array
32
     */
33
    private $errors = [];
34
35
    /**
36
     * Check the Large and Medium directories, if they exist, and then assert that all tests have the correct annotation
37
     *
38
     * @param string $pathToTestsDirectory
39
     *
40
     * @return array of errors
41
     */
42 6
    public function main(string $pathToTestsDirectory): array
43
    {
44 6
        if (!is_dir($pathToTestsDirectory)) {
45 1
            throw new \InvalidArgumentException(
46 1
                '$pathToTestsDirectory "'.$pathToTestsDirectory.'" does not exist"'
47
            );
48
        }
49 5
        $this->largePath  = $pathToTestsDirectory.'/Large';
50 5
        $this->mediumPath = $pathToTestsDirectory.'/Medium';
51 5
        $this->smallPath  = $pathToTestsDirectory.'/Small';
52 5
        $this->checkLarge();
53 5
        $this->checkMedium();
54 5
        $this->checkSmall();
55
56 5
        return $this->errors;
57
    }
58
59 5
    private function checkLarge(): void
60
    {
61 5
        if (!is_dir($this->largePath)) {
62 3
            return;
63
        }
64 2
        $this->checkDirectory($this->largePath, 'large');
65 2
    }
66
67 5
    private function checkMedium(): void
68
    {
69 5
        if (!is_dir($this->mediumPath)) {
70 1
            return;
71
        }
72 4
        $this->checkDirectory($this->mediumPath, 'medium');
73 4
    }
74
75 5
    private function checkSmall(): void
76
    {
77 5
        if (!is_dir($this->smallPath)) {
78 2
            return;
79
        }
80 3
        $this->checkDirectory($this->smallPath, 'small');
81 3
    }
82
83 4
    private function checkDirectory(string $path, string $annotation): void
84
    {
85 4
        foreach ($this->yieldTestFilesInPath($path) as $fileInfo) {
86 4
            if (false === strpos($fileInfo->getFilename(), 'Test.php')) {
87 4
                continue;
88
            }
89 4
            $this->checkFile($fileInfo, $annotation);
90
        }
91 4
    }
92
93
    /**
94
     * @param \SplFileInfo $fileInfo
95
     * @param string       $annotation
96
     *
97
     */
98 4
    private function checkFile(\SplFileInfo $fileInfo, string $annotation): void
99
    {
100 4
        $contents = (string)file_get_contents($fileInfo->getPathname());
101 4
        if($this->isAnnotationInClassDocBlock($contents, $annotation) === true) {
102 1
            return;
103
        }
104
105 4
        $matches  = [];
106 4
        preg_match_all(
107
            <<<REGEXP
108
%(?<docblock>/\*(?:[^*]|\n|(?:\*(?:[^/]|\n)))*\*/|\n)\s+?public\s+?function\s+?(?<method>.+?)\(%
109
REGEXP
110 4
            .'si',
111 4
            $contents,
112 4
            $matches
113
        );
114 4
        if ('' === $matches[0]) {
115
            $this->errors[$fileInfo->getFilename()][] = 'Failed finding any doc blocks';
116
117
            return;
118
        }
119 4
        foreach ($matches['method'] as $key => $method) {
120 4
            $docblock = $matches['docblock'][$key];
121
            /* Found the annotation - continue */
122 4
            if (false !== \strpos($docblock, '@'.$annotation)) {
123 4
                continue;
124
            }
125
            /* No @test annotation found & method not beginning test =  not a test, so continue */
126 4
            if (false === \strpos($docblock, '@test') && false === \strpos($method, 'test')) {
127 1
                continue;
128
            }
129 3
            $this->errors[$fileInfo->getFilename()][] =
130 3
                'Failed finding @'.$annotation.' for method: '.$method;
131
        }
132 4
    }
133
134
    /**
135
     * It is possible to put the annotation in the class doc, and have it apply to all tests in the file. This checks
136
     * the class docblock and if the annotation is found there returns true. If not it returns false and the rest of the
137
     * self::checkFile method runs looking for it in the method docblocks
138
     *
139
     * @param string $fileContent
140
     * @param string $annotation
141
     *
142
     * @return bool
143
     */
144 4
    private function isAnnotationInClassDocBlock(string $fileContent, string $annotation):bool
145
    {
146 4
        $matches = [];
147 4
        preg_match_all(
148
            <<<REGEXP
149
%(?<docblock>/\*(?:[^*]|\n|(?:\*(?:[^/]|\n)))*\*/)\s+?class\s+?(?<classname>.+?)\s+?extends%
150
REGEXP
151 4
            . 'si',
152 4
            $fileContent,
153 4
            $matches
154
        );
155 4
        if (count($matches['docblock']) !== 1) {
156 4
            return false;
157
        }
158 1
        $docBlock = array_shift($matches['docblock']);
159 1
        return strpos($docBlock, '@'. $annotation) !== false;
160
    }
161
162
163
    /**
164
     * @param string $path
165
     *
166
     * @return \Generator|\SplFileInfo[]
167
     */
168 4
    private function yieldTestFilesInPath(string $path): \Generator
169
    {
170 4
        $recursiveDirectoryIterator = new \RecursiveDirectoryIterator($path);
171 4
        $iterator                   = new \RecursiveIteratorIterator($recursiveDirectoryIterator);
172 4
        foreach ($iterator as $fileInfo) {
173 4
            yield $fileInfo;
174
        }
175 4
    }
176
}
177