diffBaseline()   C
last analyzed

Complexity

Conditions 15
Paths 160

Size

Total Lines 76
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
cc 15
eloc 52
c 6
b 0
f 0
nc 160
nop 2
dl 0
loc 76
rs 5.4166

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 // phpcs:ignore SR1.Files.SideEffects.FoundWithSymbols
2
3
$baselineFilePath = $argv[1] ?? null;
4
$targetFilePath = $argv[2] ?? null;
5
$exitCode = diffBaseline($baselineFilePath, $targetFilePath);
0 ignored issues
show
Bug introduced by
It seems like $baselineFilePath can also be of type null; however, parameter $baselineFilePath of diffBaseline() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

5
$exitCode = diffBaseline(/** @scrutinizer ignore-type */ $baselineFilePath, $targetFilePath);
Loading history...
Bug introduced by
It seems like $targetFilePath can also be of type null; however, parameter $targetFilePath of diffBaseline() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

5
$exitCode = diffBaseline($baselineFilePath, /** @scrutinizer ignore-type */ $targetFilePath);
Loading history...
6
7
exit($exitCode);
8
9
function diffBaseline(string $baselineFilePath, string $targetFilePath): int
10
{
11
    $realBaselineFilePath = getRealFilePath($baselineFilePath);
12
    $realTargetFilePath = getRealFilePath($targetFilePath);
13
14
    // Collect violationIds from baseline file, put them into a map for faster lookup
15
    // If violationId is not found, the use single filename + line + error hash. This works for simple errors e.g. PSR-12
16
    $errorFileLine = '';
17
    $violationIdMap = [];
18
    $lineHashMap = [];
19
    $baselineFile = fopen($realBaselineFilePath, 'r');
20
    while (!feof($baselineFile)) {
21
        $line = fgets($baselineFile);
22
        if (false !== strpos($line, '<file')) {
23
            $errorFileLine = $line;
24
            continue;
25
        }
26
27
        if (false === strpos($line, '<error')) {
28
            continue;
29
        }
30
31
        if ($violationId = findViolationId($line)) {
32
            $violationIdMap[$violationId] = null;
33
        } else {
34
            $lineHash = getLineHash($errorFileLine, $line);
35
            $lineHashMap[$lineHash] = null;
36
        }
37
    }
38
    fclose($baselineFile);
39
40
    // Iterate over report file, keep errors only if they are not in the ignored error maps.
41
    // If a file segment contains new errors, then keep file segment with those new errors.
42
    // In the end, write collected file (with errors) segments to the same file.
43
    $remainingWarningCount = 0;
44
    $removedWarningCount = 0;
45
    $newFileLines = [];
46
    $errorFileLine = '';
47
    $errorLines = [];
48
    $realTargetFile = fopen($realTargetFilePath, 'r');
49
    while (!feof($realTargetFile)) {
50
        $line = fgets($realTargetFile);
51
52
        if (false !== strpos($line, '<file')) {
53
            $errorFileLine = $line;
54
        } elseif (false !== strpos($line, '</file')) {
55
            if (!empty($errorLines)) {
56
                array_push($newFileLines, $errorFileLine, ...$errorLines);
57
                array_push($newFileLines, $line);
58
            }
59
            $errorFileLine = '';
60
            $errorLines = [];
61
        } elseif (false !== strpos($line, '<error')) {
62
            $violationId = findViolationId($line);
63
            if (null !== $violationId && key_exists($violationId, $violationIdMap)) {
64
                $removedWarningCount++;
65
            } elseif (key_exists(getLineHash($errorFileLine, $line), $lineHashMap)) {
66
                $removedWarningCount++;
67
            } else {
68
                $remainingWarningCount++;
69
                $errorLines[] = $line;
70
            }
71
        } else {
72
            $newFileLines[] = $line;
73
        }
74
    }
75
    fclose($realTargetFile);
76
77
    echo sprintf('Found %s warning(s) in %s.%s', count($violationIdMap) + count($lineHashMap), $baselineFilePath, PHP_EOL);
78
    echo sprintf('Removed %s warning(s) from %s, %s warning(s) remain.%s', $removedWarningCount, $targetFilePath, $remainingWarningCount, PHP_EOL);
79
80
    if ($removedWarningCount > 0) {
81
        file_put_contents($realTargetFilePath, implode('', $newFileLines));
82
    }
83
84
    return $remainingWarningCount > 0 ? 1 : 0;
85
}
86
87
function getRealFilePath(string $filePath): string
88
{
89
    if ('.' === $filePath[0]) {
90
        $realFilePath = realpath(getcwd() . '/' . $filePath);
91
    } else {
92
        $realFilePath = $filePath;
93
    }
94
95
    if (!file_exists($realFilePath)) {
96
        throw new Exception(sprintf('File "%s" does not exist!', $filePath));
97
    }
98
99
    return $realFilePath;
100
}
101
102
function getLineHash(string $fileLine, string $errorLine): string
103
{
104
    return md5(trim($fileLine . $errorLine));
105
}
106
107
function findViolationId(string $line): ?string
108
{
109
    $matches = [];
110
    preg_match('#\[(\w{16})\]#', $line, $matches);
111
112
    return $matches[1] ?? null;
113
}
114