Passed
Push — master ( 0c214a...b07957 )
by Fabian
07:06
created

Hunk::setType()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * This file is part of the php-merge package.
4
 *
5
 * (c) Fabian Bircher <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace PhpMerge\internal;
12
13
/**
14
 * Class Hunk
15
 *
16
 * This represents a collection of changed lines.
17
 *
18
 * @package    PhpMerge
19
 * @author     Fabian Bircher <[email protected]>
20
 * @copyright  Fabian Bircher <[email protected]>
21
 * @license    https://opensource.org/licenses/MIT
22
 * @version    Release: @package_version@
23
 * @link       http://github.com/bircher/php-merge
24
 * @internal   This class is not part of the public api.
25
 */
26
final class Hunk
27
{
28
29
    const ADDED = 1;
30
    const REMOVED = 2;
31
    const REPLACED = 3;
32
33
    /**
34
     * @var int
35
     */
36
    protected $start;
37
    /**
38
     * @var int
39
     */
40
    protected $end;
41
    /**
42
     * @var Line[]
43
     */
44
    protected $lines;
45
    /**
46
     * @var int
47
     */
48
    protected $type;
49
50
    /**
51
     * The Hunk constructor.
52
     *
53
     * @param Line|Line[] $lines
54
     *   The lines belonging to the hunk.
55
     * @param int $type
56
     *   The type of the hunk: Hunk::ADDED Hunk::REMOVED Hunk::REPLACED
57
     * @param int $start
58
     *   The line index where the hunk starts.
59
     * @param int $end
60
     *   The line index where the hunk stops.
61
     */
62 52
    public function __construct($lines, $type, $start, $end = null)
63
    {
64 52
        $this->start = $start;
65 52
        if ($end === null) {
66 52
            $end= $start;
67
        }
68 52
        $this->end = $end;
69 52
        if (!is_array($lines)) {
70 52
            $lines = array($lines);
71
        }
72 52
        $this->lines = $lines;
73 52
        $this->type = $type;
74 52
    }
75
76
    /**
77
     * Add a new line to the hunk.
78
     *
79
     * @param \PhpMerge\Line $line
80
     *   The line to add.
81
     */
82 36
    public function addLine(Line $line)
83
    {
84 36
        $this->lines[] = $line;
85 36
        $this->end = $line->getIndex();
86 36
    }
87
88
    /**
89
     * Create an array of hunks out of an array of lines.
90
     *
91
     * @param Line[] $lines
92
     *   The lines of the diff.
93
     * @return Hunk[]
94
     *   The hunks in the lines.
95
     */
96 52
    public static function createArray($lines)
97
    {
98 52
        $op = Line::UNCHANGED;
99 52
        $hunks = [];
100
        /** @var Hunk $current */
101 52
        $current = null;
102 52
        foreach ($lines as $line) {
103 52
            switch ($line->getType()) {
104 52
                case Line::REMOVED:
105 52
                    if ($op != Line::REMOVED) {
106
                        // The last line was not removed so we start a new hunk.
107 52
                        $current = new Hunk($line, Hunk::REMOVED, $line->getIndex());
108
                    } else {
109
                        // continue adding the line to the hunk.
110 8
                        $current->addLine($line);
111
                    }
112 52
                    break;
113 52
                case Line::ADDED:
114
                    switch ($op) {
115 52
                        case Line::REMOVED:
116
                            // The hunk is a replacement.
117 36
                            $current->setType(Hunk::REPLACED);
118 36
                            $current->addLine($line);
119 36
                            break;
120 48
                        case Line::ADDED:
121 12
                            $current->addLine($line);
122 12
                            break;
123 48
                        case Line::UNCHANGED:
124
                            // Add a new hunk with the added type.
125 48
                            $current = new Hunk($line, Hunk::ADDED, $line->getIndex());
126 48
                            break;
127
                    }
128 52
                    break;
129 52
                case Line::UNCHANGED:
130 52
                    if ($current) {
131
                        // The hunk exists so add it to the array.
132 48
                        $hunks[] = $current;
133 48
                        $current = null;
134
                    }
135 52
                    break;
136
            }
137 52
            $op = $line->getType();
138
        }
139 52
        if ($current) {
140
            // The last line was part of a hunk, so add it.
141 12
            $hunks[] = $current;
142
        }
143
144 52
        return $hunks;
145
    }
146
147
    /**
148
     * Set the type of the hunk.
149
     *
150
     * @param int $type
151
     */
152 36
    protected function setType($type)
153
    {
154 36
        $this->type = $type;
155 36
    }
156
157
    /**
158
     * Get the line index where the hunk starts.
159
     *
160
     * @return int
161
     */
162 48
    public function getStart()
163
    {
164 48
        return $this->start;
165
    }
166
167
    /**
168
     * Get the line index where the hunk ends.
169
     *
170
     * @return int
171
     */
172 28
    public function getEnd()
173
    {
174 28
        return $this->end;
175
    }
176
177
    /**
178
     * Get the type of the hunk.
179
     *
180
     * @return int
181
     */
182 40
    public function getType()
183
    {
184 40
        return $this->type;
185
    }
186
187
    /**
188
     * Get the lines of the hunk.
189
     *
190
     * @return Line[]
191
     */
192 4
    public function getLines()
193
    {
194 4
        return $this->lines;
195
    }
196
197
    /**
198
     * Get the removed lines.
199
     *
200
     * @return Line[]
201
     */
202 12
    public function getRemovedLines()
203
    {
204 12
        return array_values(array_filter(
205 12
            $this->lines,
206
            function (Line $line) {
207 12
                return $line->getType() == Line::REMOVED;
208 12
            }
209
        ));
210
    }
211
212
    /**
213
     * Get the added lines.
214
     *
215
     * @return Line[]
216
     */
217 40
    public function getAddedLines()
218
    {
219 40
        return array_values(array_filter(
220 40
            $this->lines,
221
            function (Line $line) {
222 40
                return $line->getType() == Line::ADDED;
223 40
            }
224
        ));
225
    }
226
227
    /**
228
     * Get the lines content.
229
     *
230
     * @return string[]
231
     */
232 24
    public function getLinesContent()
233
    {
234 24
        return array_map(
235 24
            function (Line $line) {
236 24
                return $line->getContent();
237 24
            },
238 24
            $this->getAddedLines()
239
        );
240
    }
241
242
    /**
243
     * Test whether the hunk is to be considered for a conflict resolution.
244
     *
245
     * @param int $line
246
     *   The line number in the original text to test.
247
     *
248
     * @return bool
249
     *   Whether the line is affected by the hunk.
250
     */
251 28
    public function isLineNumberAffected($line)
252
    {
253
        // Added lines also affect the ones afterwards in conflict resolution,
254
        // because they are added in between.
255 28
        $bleed = ($this->type == self::ADDED ? 1 : 0);
256 28
        return ($line >= $this->start && $line <= $this->end + $bleed);
257
    }
258
259
    /**
260
     * @param \PhpMerge\Hunk|null $hunk
261
     * @return bool
262
     */
263 36
    public function hasIntersection(Hunk $hunk = null)
264
    {
265 36
        if (!$hunk) {
266 24
            return false;
267
        }
268 32
        if ($this->type == self::ADDED && $hunk->type == self::ADDED) {
269 8
            return $this->start == $hunk->start;
270
        }
271 28
        return $this->isLineNumberAffected($hunk->start) || $this->isLineNumberAffected($hunk->end)
272 28
          || $hunk->isLineNumberAffected($this->start) || $hunk->isLineNumberAffected($this->end);
273
    }
274
}
275