Completed
Push — master ( 7cb780...532294 )
by
unknown
04:14 queued 02:10
created

DiffChunk::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * GitElephant - An abstraction layer for git written in PHP
4
 * Copyright (C) 2013  Matteo Giachino
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program.  If not, see [http://www.gnu.org/licenses/].
18
 */
19
20
namespace GitElephant\Objects\Diff;
21
22
/**
23
 * A single portion of a file changed in a diff
24
 *
25
 * @author Matteo Giachino <[email protected]>
26
 */
27
class DiffChunk implements \ArrayAccess, \Countable, \Iterator
28
{
29
    /**
30
     * the cursor position
31
     *
32
     * @var int
33
     */
34
    private $position;
35
36
    /**
37
     * diff start line from original file
38
     *
39
     * @var int
40
     */
41
    private $originStartLine;
42
43
    /**
44
     * diff end line from original file
45
     *
46
     * @var int
47
     */
48
    private $originEndLine;
49
50
    /**
51
     * diff start line from destination file
52
     *
53
     * @var int
54
     */
55
    private $destStartLine;
56
57
    /**
58
     * diff end line from destination file
59
     *
60
     * @var int
61
     */
62
    private $destEndLine;
63
64
    /**
65
     * hunk header line
66
     *
67
     * @var string
68
     */
69
    private $headerLine;
70
71
    /**
72
     * array of lines
73
     *
74
     * @var array
75
     */
76
    private $lines;
77
78
    /**
79
     * Class constructor
80
     *
81
     * @param array $lines output lines from git binary
82
     *
83
     * @throws \Exception
84
     */
85 2
    public function __construct(array $lines)
86
    {
87 2
        $this->position = 0;
88
89 2
        $this->getLinesNumbers($lines[0]);
90 2
        $this->parseLines(array_slice($lines, 1));
91 2
    }
92
93
    /**
94
     * Parse lines
95
     *
96
     * @param array $lines output lines
97
     *
98
     * @throws \Exception
99
     */
100 2
    private function parseLines(array $lines)
101
    {
102 2
        $originUnchanged = $this->originStartLine;
103 2
        $destUnchanged = $this->destStartLine;
104
105 2
        $deleted = $this->originStartLine;
106 2
        $new = $this->destStartLine;
107 2
        foreach ($lines as $line) {
108 2
            if (preg_match('/^\+(.*)/', $line)) {
109 2
                $this->lines[] = new DiffChunkLineAdded($new++, preg_replace('/\+(.*)/', ' $1', $line));
110 2
                $destUnchanged++;
111 2
            } else if (preg_match('/^-(.*)/', $line)) {
112 1
                $this->lines[] = new DiffChunkLineDeleted($deleted++, preg_replace('/-(.*)/', ' $1', $line));
113 1
                $originUnchanged++;
114 2
            } else if (preg_match('/^ (.*)/', $line) || $line == '') {
115 2
                $this->lines[] = new DiffChunkLineUnchanged($originUnchanged++, $destUnchanged++, $line);
116 2
                $deleted++;
117 2
                $new++;
118 2
            } else if (!preg_match('/\\ No newline at end of file/', $line)) {
119
                throw new \Exception(sprintf('GitElephant was unable to parse the line %s', $line));
120
            }
121
        }
122 2
    }
123
124
    /**
125
     * Get line numbers
126
     *
127
     * @param string $line a single line
128
     */
129 2
    private function getLinesNumbers(string $line)
130
    {
131 2
        $matches = [];
132 2
        preg_match('/@@ -(.*) \+(.*) @@?(.*)/', $line, $matches);
133 2
        if (!strpos($matches[1], ',')) {
134
            // one line
135
            $this->originStartLine = $matches[1];
0 ignored issues
show
Documentation Bug introduced by
The property $originStartLine was declared of type integer, but $matches[1] is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
136
            $this->originEndLine = $matches[1];
0 ignored issues
show
Documentation Bug introduced by
The property $originEndLine was declared of type integer, but $matches[1] is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
137
        } else {
138 2
            list($this->originStartLine, $this->originEndLine) = explode(',', $matches[1]);
139
        }
140
141 2
        if (!strpos($matches[2], ',')) {
142
            // one line
143 1
            $this->destStartLine = $matches[2];
0 ignored issues
show
Documentation Bug introduced by
The property $destStartLine was declared of type integer, but $matches[2] is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
144 1
            $this->destEndLine = $matches[2];
0 ignored issues
show
Documentation Bug introduced by
The property $destEndLine was declared of type integer, but $matches[2] is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
145
        } else {
146 1
            list($this->destStartLine, $this->destEndLine) = explode(',', $matches[2]);
147
        }
148 2
    }
149
150
    /**
151
     * destStartLine getter
152
     *
153
     * @return int
154
     */
155
    public function getDestStartLine()
156
    {
157
        return $this->destStartLine;
158
    }
159
160
    /**
161
     * destEndLine getter
162
     *
163
     * @return int
164
     */
165
    public function getDestEndLine()
166
    {
167
        return $this->destEndLine;
168
    }
169
170
    /**
171
     * originStartLine getter
172
     *
173
     * @return int
174
     */
175
    public function getOriginStartLine()
176
    {
177
        return $this->originStartLine;
178
    }
179
180
    /**
181
     * originEndLine getter
182
     *
183
     * @return int
184
     */
185
    public function getOriginEndLine()
186
    {
187
        return $this->originEndLine;
188
    }
189
190
    /**
191
     * Get hunk header line
192
     *
193
     * @return string
194
     */
195
    public function getHeaderLine()
196
    {
197
        if (null === $this->headerLine) {
198
            $line = '@@';
199
            $line .= ' -' . $this->getOriginStartLine() . ',' . $this->getOriginEndLine();
200
            $line .= ' +' . $this->getDestStartLine() . ',' . $this->getDestEndLine();
201
            $line .= ' @@';
202
203
            $this->headerLine = $line;
204
        }
205
206
        return $this->headerLine;
207
    }
208
209
    /**
210
     * Get Lines
211
     *
212
     * @return array
213
     */
214
    public function getLines()
215
    {
216
        return $this->lines;
217
    }
218
219
    /**
220
     * ArrayAccess interface
221
     *
222
     * @param int $offset offset
223
     *
224
     * @return bool
225
     */
226
    public function offsetExists($offset)
227
    {
228
        return isset($this->lines[$offset]);
229
    }
230
231
    /**
232
     * ArrayAccess interface
233
     *
234
     * @param int $offset offset
235
     *
236
     * @return null
237
     */
238
    public function offsetGet($offset)
239
    {
240
        return isset($this->lines[$offset]) ? $this->lines[$offset] : null;
241
    }
242
243
    /**
244
     * ArrayAccess interface
245
     *
246
     * @param int   $offset offset
247
     * @param mixed $value  value
248
     */
249
    public function offsetSet($offset, $value)
250
    {
251
        if (is_null($offset)) {
252
            $this->lines[] = $value;
253
        } else {
254
            $this->lines[$offset] = $value;
255
        }
256
    }
257
258
    /**
259
     * ArrayAccess interface
260
     *
261
     * @param int $offset offset
262
     */
263
    public function offsetUnset($offset)
264
    {
265
        unset($this->lines[$offset]);
266
    }
267
268
    /**
269
     * Countable interface
270
     *
271
     * @return int|void
272
     */
273 1
    public function count()
274
    {
275 1
        return count($this->lines);
276
    }
277
278
    /**
279
     * Iterator interface
280
     *
281
     * @return mixed
282
     */
283 1
    public function current()
284
    {
285 1
        return $this->lines[$this->position];
286
    }
287
288
    /**
289
     * Iterator interface
290
     */
291 1
    public function next()
292
    {
293 1
        ++$this->position;
294 1
    }
295
296
    /**
297
     * Iterator interface
298
     *
299
     * @return int
300
     */
301
    public function key()
302
    {
303
        return $this->position;
304
    }
305
306
    /**
307
     * Iterator interface
308
     *
309
     * @return bool
310
     */
311 1
    public function valid()
312
    {
313 1
        return isset($this->lines[$this->position]);
314
    }
315
316
    /**
317
     * Iterator interface
318
     */
319 1
    public function rewind()
320
    {
321 1
        $this->position = 0;
322 1
    }
323
}
324