GitDiffParser::parse()   B
last analyzed

Complexity

Conditions 10
Paths 14

Size

Total Lines 47
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 29
c 1
b 0
f 0
nc 14
nop 0
dl 0
loc 47
rs 7.6666

How to fix   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
2
// src/VersionControl/GitCommandBundle/GitCommands/GitDiffParser.php
3
4
/*
5
 * This file is part of the GitCommandBundle package.
6
 *
7
 * (c) Paul Schweppe <[email protected]>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace VersionControl\GitCommandBundle\GitCommands;
14
15
use VersionControl\GitCommandBundle\Entity\GitDiff;
16
use VersionControl\GitCommandBundle\Entity\GitDiffLine;
17
18
/**
19
 * Parses git diff command response.
20
 *
21
 * @author Paul Schweppe <[email protected]>
22
 */
23
class GitDiffParser
24
{
25
    protected $lines;
26
27
    protected $lineCount;
28
29
    /**
30
     * @param string $string
31
     */
32
    public function __construct($string)
33
    {
34
        $this->lines = $this->splitOnNewLine($string, false);
35
        $this->lineCount = count($this->lines);
36
    }
37
38
    public function parse()
39
    {
40
        $diffs = array();
41
        $diff = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $diff is dead and can be removed.
Loading history...
42
        $collected = array();
43
44
        for ($i = 0; $i < $this->lineCount; ++$i) {
45
            if (preg_match('(^---\\s+(?P<file>.+))', $this->lines[$i], $matchFileA) &&
46
                preg_match('(^\\+\\+\\+\\s+(?P<file>.+))', $this->lines[$i + 1], $matchFileB)) {
47
48
                //Second iteration
49
                if (count($collected) > 0 && count($diffs) > 0) {
50
                    $lastDiff = end($diffs);
51
                    $diffLines = $this->parseDiffLines($collected);
52
                    $lastDiff->setDiffLines($diffLines);
53
                    reset($diffs);
54
                }
55
56
                //All iteration
57
                $diff = new GitDiff();
58
                $diff->setFileA($matchFileA['file']);
59
                $diff->setFileB($matchFileB['file']);
60
                $diffs[] = $diff;
61
62
                $collected = array();
63
64
                ++$i;
65
66
                if ($i >= 300000) {
67
                    break;
68
                }
69
            } else {
70
                if (preg_match('/^(?:diff --git |index [\da-f\.]+|[+-]{3} [ab])/', $this->lines[$i])) {
71
                    continue;
72
                }
73
                $collected[] = $this->lines[$i];
74
            }
75
        }
76
77
        if (count($collected) > 0 && count($diffs) > 0) {
78
            $lastDiff = end($diffs);
79
            $diffLines = $this->parseDiffLines($collected);
80
            $lastDiff->setDiffLines($diffLines);
81
            reset($diffs);
82
        }
83
84
        return $diffs;
85
    }
86
87
    /**
88
     * @param array $lines
89
     *
90
     * @return array
91
     */
92
    private function parseDiffLines(array $lines)
93
    {
94
        $section = array();
0 ignored issues
show
Unused Code introduced by
The assignment to $section is dead and can be removed.
Loading history...
95
        $diffLines = array();
96
        $lineNumber = 0;
97
        foreach ($lines as $line) {
98
            $diffLine = new GitDiffLine($line);
99
            if (preg_match('/^@@\s+-(?P<start>\d+)(?:,\s*(?P<startrange>\d+))?\s+\+(?P<end>\d+)(?:,\s*(?P<endrange>\d+))?\s+@@/', $line, $match)) {
100
                $section = array(
101
                    $match['start'],
102
                    isset($match['startrange']) ? max(1, $match['startrange']) : 1,
103
                    $match['end'],
104
                    isset($match['endrange']) ? max(1, $match['endrange']) : 1,
105
                );
106
                $diffLine->setLineNumber('...');
107
                $lineNumber = $match['start'];
108
            } else {
109
                if ($diffLine->getType() === GitDiffLine::REMOVED) {
110
                    $diffLine->setLineNumber('');
111
                } else {
112
                    $diffLine->setLineNumber($lineNumber);
113
                    ++$lineNumber;
114
                }
115
            }
116
            $diffLines[] = $diffLine;
117
        }
118
119
        return $diffLines;
120
    }
121
122
    /**
123
     * Splits a block of text on newlines and returns an array.
124
     *
125
     * @param string $text       Text to split
126
     * @param bool   $trimSpaces If true then each line is trimmed of white spaces. Default true
127
     *
128
     * @return array Array of lines
129
     */
130
    protected function splitOnNewLine($text, $trimSpaces = true)
131
    {
132
        if (!trim($text)) {
133
            return array();
134
        }
135
        $lines = preg_split('/$\R?^/m', $text);
136
        if ($trimSpaces) {
137
            return array_map('trim', $lines);
0 ignored issues
show
Bug introduced by
It seems like $lines can also be of type false; however, parameter $arr1 of array_map() does only seem to accept array, 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

137
            return array_map('trim', /** @scrutinizer ignore-type */ $lines);
Loading history...
138
        }
139
140
        return $lines;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $lines could also return false which is incompatible with the documented return type array. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
141
    }
142
}
143