Text_Diff_Engine_native   F
last analyzed

Complexity

Total Complexity 95

Size/Duplication

Total Lines 536
Duplicated Lines 2.05 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 11
loc 536
rs 2
c 0
b 0
f 0
wmc 95
lcom 1
cbo 4

5 Methods

Rating   Name   Duplication   Size   Complexity  
F diff() 0 132 29
F _diag() 11 104 20
A _lcsPos() 0 34 5
C _compareseq() 0 57 13
F _shiftBoundaries() 0 135 28

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Text_Diff_Engine_native often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Text_Diff_Engine_native, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Text_Diff
5
 *
6
 * General API for generating and formatting diffs - the differences between
7
 * two sequences of strings.
8
 *
9
 * The PHP diff code used in this package was originally written by Geoffrey
10
 * T. Dairiki and is used with his permission.
11
 *
12
 * $Horde: framework/Text_Diff/Diff.php,v 1.13 2005/05/26 20:26:06 selsky Exp $
13
 *
14
 * @package Text_Diff
15
 * @author  Geoffrey T. Dairiki <[email protected]>
16
 */
17
class Text_Diff
18
{
19
    /**
20
     * Array of changes.
21
     *
22
     * @var array
23
     */
24
25
    public $_edits;
26
27
    /**
28
     * Computes diffs between sequences of strings.
29
     *
30
     * @param array $from_lines  An array of strings.  Typically these are
31
     *                           lines from a file.
32
     * @param array $to_lines    An array of strings.
33
     */
34
35
    //HACK by domifara
36
37
    //  function Text_Diff($from_lines, $to_lines)
38
39
    public function __construct($from_lines, $to_lines)
40
    {
41
        array_walk($from_lines, [$this, '_trimNewlines']);
42
43
        array_walk($to_lines, [$this, '_trimNewlines']);
44
45
        if (extension_loaded('xdiff')) {
46
            $engine = new Text_Diff_Engine_xdiff();
47
        } else {
48
            $engine = new Text_Diff_Engine_native();
49
        }
50
51
        $this->_edits = $engine->diff($from_lines, $to_lines);
52
    }
53
54
    /**
55
     * Returns the array of differences.
56
     */
57
58
    public function getDiff()
59
    {
60
        return $this->_edits;
61
    }
62
63
    /**
64
     * Computes a reversed diff.
65
     *
66
     * Example:
67
     * <code>
68
     * $diff = new Text_Diff($lines1, $lines2);
69
     * $rev = $diff->reverse();
70
     * </code>
71
     *
72
     * @return Text_Diff  A Diff object representing the inverse of the
73
     *                    original diff.  Note that we purposely don't return a
74
     *                    reference here, since this essentially is a clone()
75
     *                    method.
76
     */
77
78
    public function reverse()
79
    {
80
        if (version_compare(zend_version(), '2', '>')) {
81
            $rev = clone$obj;
0 ignored issues
show
Bug introduced by
The variable $obj does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
82
        } else {
83
            $rev = $this;
84
        }
85
86
        $rev->_edits = [];
87
88
        foreach ($this->_edits as $edit) {
89
            $rev->_edits[] = $edit->reverse();
90
        }
91
92
        return $rev;
93
    }
94
95
    /**
96
     * Checks for an empty diff.
97
     *
98
     * @return bool  True if two sequences were identical.
99
     */
100
101
    public function isEmpty()
102
    {
103
        foreach ($this->_edits as $edit) {
104
            if (!is_a($edit, 'Text_Diff_Op_copy')) {
105
                return false;
106
            }
107
        }
108
109
        return true;
110
    }
111
112
    /**
113
     * Computes the length of the Longest Common Subsequence (LCS).
114
     *
115
     * This is mostly for diagnostic purposes.
116
     *
117
     * @return int  The length of the LCS.
118
     */
119
120
    public function lcs()
121
    {
122
        $lcs = 0;
123
124
        foreach ($this->_edits as $edit) {
125
            if (is_a($edit, 'Text_Diff_Op_copy')) {
126
                $lcs += count($edit->orig);
127
            }
128
        }
129
130
        return $lcs;
131
    }
132
133
    /**
134
     * Gets the original set of lines.
135
     *
136
     * This reconstructs the $from_lines parameter passed to the constructor.
137
     *
138
     * @return array  The original sequence of strings.
139
     */
140
141 View Code Duplication
    public function getOriginal()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
142
    {
143
        $lines = [];
144
145
        foreach ($this->_edits as $edit) {
146
            if ($edit->orig) {
147
                array_splice($lines, count($lines), 0, $edit->orig);
148
            }
149
        }
150
151
        return $lines;
152
    }
153
154
    /**
155
     * Gets the final set of lines.
156
     *
157
     * This reconstructs the $to_lines parameter passed to the constructor.
158
     *
159
     * @return array  The sequence of strings.
160
     */
161
162 View Code Duplication
    public function getFinal()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
163
    {
164
        $lines = [];
165
166
        foreach ($this->_edits as $edit) {
167
            if ($edit->final) {
168
                array_splice($lines, count($lines), 0, $edit->final);
169
            }
170
        }
171
172
        return $lines;
173
    }
174
175
    /**
176
     * Removes trailing newlines from a line of text. This is meant to be used
177
     * with array_walk().
178
     *
179
     * @param string  $line The line to trim.
180
     * @param int $key  The index of the line in the array. Not used.
181
     */
182
183
    public function _trimNewlines(&$line, $key)
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
184
    {
185
        $line = str_replace(["\n", "\r"], '', $line);
186
    }
187
188
    /**
189
     * Checks a diff for validity.
190
     *
191
     * This is here only for debugging purposes.
192
     * @param $from_lines
193
     * @param $to_lines
194
     * @return bool
195
     */
196
197
    public function _check($from_lines, $to_lines)
198
    {
199
        if (serialize($from_lines) != serialize($this->getOriginal())) {
200
            trigger_error("Reconstructed original doesn't match", E_USER_ERROR);
201
        }
202
203
        if (serialize($to_lines) != serialize($this->getFinal())) {
204
            trigger_error("Reconstructed final doesn't match", E_USER_ERROR);
205
        }
206
207
        $rev = $this->reverse();
208
209
        if (serialize($to_lines) != serialize($rev->getOriginal())) {
210
            trigger_error("Reversed original doesn't match", E_USER_ERROR);
211
        }
212
213
        if (serialize($from_lines) != serialize($rev->getFinal())) {
214
            trigger_error("Reversed final doesn't match", E_USER_ERROR);
215
        }
216
217
        $prevtype = null;
218
219
        foreach ($this->_edits as $edit) {
220
            if ($prevtype == get_class($edit)) {
221
                trigger_error('Edit sequence is non-optimal', E_USER_ERROR);
222
            }
223
224
            $prevtype = get_class($edit);
225
        }
226
227
        return true;
228
    }
229
}
230
231
/**
232
 * $Horde: framework/Text_Diff/Diff.php,v 1.13 2005/05/26 20:26:06 selsky Exp $
233
 *
234
 * @package Text_Diff
235
 * @author  Geoffrey T. Dairiki <[email protected]>
236
 */
237
class Text_MappedDiff extends Text_Diff
238
{
239
    /**
240
     * Computes a diff between sequences of strings.
241
     *
242
     * This can be used to compute things like case-insensitve diffs, or diffs
243
     * which ignore changes in white-space.
244
     *
245
     * @param array $from_lines         An array of strings.
246
     * @param array $to_lines           An array of strings.
247
     * @param array $mapped_from_lines  This array should have the same size
248
     *                                  number of elements as $from_lines.  The
249
     *                                  elements in $mapped_from_lines and
250
     *                                  $mapped_to_lines are what is actually
251
     *                                  compared when computing the diff.
252
     * @param array $mapped_to_lines    This array should have the same number
253
     *                                  of elements as $to_lines.
254
     */
255
256
    public function __construct(
257
        $from_lines,
258
        $to_lines,
259
        $mapped_from_lines,
260
        $mapped_to_lines
261
    ) {
262
        assert(count($from_lines) == count($mapped_from_lines));
263
264
        assert(count($to_lines) == count($mapped_to_lines));
265
266
        parent::__construct($mapped_from_lines, $mapped_to_lines);
267
268
        $xi = $yi = 0;
269
270
        for ($i = 0; $i < count($this->_edits); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
271
            $orig = &$this->_edits[$i]->orig;
272
273
            if (is_array($orig)) {
274
                $orig = array_slice($from_lines, $xi, count($orig));
275
276
                $xi += count($orig);
277
            }
278
279
            $final = &$this->_edits[$i]->final;
280
281
            if (is_array($final)) {
282
                $final = array_slice($to_lines, $yi, count($final));
283
284
                $yi += count($final);
285
            }
286
        }
287
    }
288
}
289
290
/**
291
 * Class used internally by Diff to actually compute the diffs.  This class
292
 * uses the xdiff PECL package (https://pecl.php.net/package/xdiff) to compute
293
 * the differences between the two input arrays.
294
 *
295
 * @author  Jon Parise <[email protected]>
296
 * @package Text_Diff
297
 *
298
 * @access  private
299
 */
300
class Text_Diff_Engine_xdiff
301
{
302
    /**
303
     * @param $from_lines
304
     * @param $to_lines
305
     * @return array
306
     */
307
308
    public function diff($from_lines, $to_lines)
309
    {
310
        /* Convert the two input arrays into strings for xdiff processing. */
311
312
        $from_string = implode("\n", $from_lines);
313
314
        $to_string = implode("\n", $to_lines);
315
316
        /* Diff the two strings and convert the result to an array. */
317
318
        $diff = xdiff_string_diff($from_string, $to_string, count($to_lines));
319
320
        $diff = explode("\n", $diff);
321
322
        /* Walk through the diff one line at a time.  We build the $edits
323
         * array of diff operations by reading the first character of the
324
         * xdiff output (which is in the "unified diff" format).
325
         *
326
         * Note that we don't have enough information to detect "changed"
327
         * lines using this approach, so we can't add Text_Diff_Op_changed
328
         * instances to the $edits array.  The result is still perfectly
329
         * valid, albeit a little less descriptive and efficient. */
330
331
        $edits = [];
332
333
        foreach ($diff as $line) {
334
            switch ($line[0]) {
335
                case ' ':
336
                    $edits[] = new Text_Diff_Op_copy([mb_substr($line, 1)]);
337
                    break;
338
                case '+':
339
                    $edits[] = new Text_Diff_Op_add([mb_substr($line, 1)]);
340
                    break;
341
                case '-':
342
                    $edits[] = new Text_Diff_Op_delete([mb_substr($line, 1)]);
343
                    break;
344
            }
345
        }
346
347
        return $edits;
348
    }
349
}
350
351
/**
352
 * Class used internally by Diff to actually compute the diffs.  This class is
353
 * implemented using native PHP code.
354
 *
355
 * The algorithm used here is mostly lifted from the perl module
356
 * Algorithm::Diff (version 1.06) by Ned Konz, which is available at:
357
 * https://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip
358
 *
359
 * More ideas are taken from:
360
 * https://www.ics.uci.edu/~eppstein/161/960229.html
361
 *
362
 * Some ideas (and a bit of code) are taken from analyze.c, of GNU
363
 * diffutils-2.7, which can be found at:
364
 * ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz
365
 *
366
 * Some ideas (subdivision by NCHUNKS > 2, and some optimizations) are from
367
 * Geoffrey T. Dairiki <[email protected]>. The original PHP version of this
368
 * code was written by him, and is used/adapted with his permission.
369
 *
370
 * @author  Geoffrey T. Dairiki <[email protected]>
371
 * @package Text_Diff
372
 *
373
 * @access  private
374
 */
375
class Text_Diff_Engine_native
376
{
377
    /**
378
     * @param $from_lines
379
     * @param $to_lines
380
     * @return array
381
     */
382
383
    public function diff($from_lines, $to_lines)
384
    {
385
        $n_from = count($from_lines);
386
387
        $n_to = count($to_lines);
388
389
        $this->xchanged = $this->ychanged = [];
0 ignored issues
show
Bug introduced by
The property ychanged does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The property xchanged does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
390
391
        $this->xv = $this->yv = [];
0 ignored issues
show
Bug introduced by
The property xv does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The property yv does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
392
393
        $this->xind = $this->yind = [];
0 ignored issues
show
Bug introduced by
The property xind does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The property yind does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
394
395
        unset($this->seq, $this->in_seq, $this->lcs);
396
397
        // Skip leading common lines.
398
399
        for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) {
400
            if ($from_lines[$skip] != $to_lines[$skip]) {
401
                break;
402
            }
403
404
            $this->xchanged[$skip] = $this->ychanged[$skip] = false;
405
        }
406
407
        // Skip trailing common lines.
408
409
        $xi = $n_from;
410
411
        $yi = $n_to;
412
413
        for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) {
414
            if ($from_lines[$xi] != $to_lines[$yi]) {
415
                break;
416
            }
417
418
            $this->xchanged[$xi] = $this->ychanged[$yi] = false;
419
        }
420
421
        // Ignore lines which do not exist in both files.
422
423
        for ($xi = $skip; $xi < $n_from - $endskip; $xi++) {
424
            $xhash[$from_lines[$xi]] = 1;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$xhash was never initialized. Although not strictly required by PHP, it is generally a good practice to add $xhash = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
425
        }
426
427
        for ($yi = $skip; $yi < $n_to - $endskip; $yi++) {
428
            $line = $to_lines[$yi];
429
430
            if ($this->ychanged[$yi] = empty($xhash[$line])) {
431
                continue;
432
            }
433
434
            $yhash[$line] = 1;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$yhash was never initialized. Although not strictly required by PHP, it is generally a good practice to add $yhash = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
435
436
            $this->yv[] = $line;
437
438
            $this->yind[] = $yi;
439
        }
440
441
        for ($xi = $skip; $xi < $n_from - $endskip; $xi++) {
442
            $line = $from_lines[$xi];
443
444
            if ($this->xchanged[$xi] = empty($yhash[$line])) {
445
                continue;
446
            }
447
448
            $this->xv[] = $line;
449
450
            $this->xind[] = $xi;
451
        }
452
453
        // Find the LCS.
454
455
        $this->_compareseq(0, count($this->xv), 0, count($this->yv));
456
457
        // Merge edits when possible.
458
459
        $this->_shiftBoundaries($from_lines, $this->xchanged, $this->ychanged);
460
461
        $this->_shiftBoundaries($to_lines, $this->ychanged, $this->xchanged);
462
463
        // Compute the edit operations.
464
465
        $edits = [];
466
467
        $xi = $yi = 0;
468
469
        while ($xi < $n_from || $yi < $n_to) {
470
            assert($yi < $n_to || $this->xchanged[$xi]);
471
472
            assert($xi < $n_from || $this->ychanged[$yi]);
473
474
            // Skip matching "snake".
475
476
            $copy = [];
477
478
            while ($xi < $n_from && $yi < $n_to
479
                   && !$this->xchanged[$xi]
480
                   && !$this->ychanged[$yi]) {
481
                $copy[] = $from_lines[$xi++];
482
483
                ++$yi;
484
            }
485
486
            if ($copy) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $copy of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
487
                $edits[] = new Text_Diff_Op_copy($copy);
488
            }
489
490
            // Find deletes & adds.
491
492
            $delete = [];
493
494
            while ($xi < $n_from && $this->xchanged[$xi]) {
495
                $delete[] = $from_lines[$xi++];
496
            }
497
498
            $add = [];
499
500
            while ($yi < $n_to && $this->ychanged[$yi]) {
501
                $add[] = $to_lines[$yi++];
502
            }
503
504
            if ($delete && $add) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $delete of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
Bug Best Practice introduced by
The expression $add of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
505
                $edits[] = new Text_Diff_Op_change($delete, $add);
506
            } elseif ($delete) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $delete of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
507
                $edits[] = new Text_Diff_Op_delete($delete);
508
            } elseif ($add) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $add of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
509
                $edits[] = new Text_Diff_Op_add($add);
510
            }
511
        }
512
513
        return $edits;
514
    }
515
516
    /**
517
     * Divides the Largest Common Subsequence (LCS) of the sequences (XOFF,
518
     * XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized
519
     * segments.
520
     *
521
     * Returns (LCS, PTS).  LCS is the length of the LCS. PTS is an array of
522
     * NCHUNKS+1 (X, Y) indexes giving the diving points between sub
523
     * sequences.  The first sub-sequence is contained in (X0, X1), (Y0, Y1),
524
     * the second in (X1, X2), (Y1, Y2) and so on.  Note that (X0, Y0) ==
525
     * (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM).
526
     *
527
     * This function assumes that the first lines of the specified portions of
528
     * the two files do not match, and likewise that the last lines do not
529
     * match.  The caller must trim matching lines from the beginning and end
530
     * of the portions it is going to specify.
531
     * @param $xoff
532
     * @param $xlim
533
     * @param $yoff
534
     * @param $ylim
535
     * @param $nchunks
536
     * @return array
537
     */
538
539
    public function _diag($xoff, $xlim, $yoff, $ylim, $nchunks)
540
    {
541
        $flip = false;
542
543
        if ($xlim - $xoff > $ylim - $yoff) {
544
            /* Things seems faster (I'm not sure I understand why) when the
545
             * shortest sequence is in X. */
546
547
            $flip = true;
548
549
            list($xoff, $xlim, $yoff, $ylim) = [$yoff, $ylim, $xoff, $xlim];
550
        }
551
552
        if ($flip) {
553
            for ($i = $ylim - 1; $i >= $yoff; $i--) {
554
                $ymatches[$this->xv[$i]][] = $i;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ymatches was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ymatches = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
555
            }
556
        } else {
557
            for ($i = $ylim - 1; $i >= $yoff; $i--) {
558
                $ymatches[$this->yv[$i]][] = $i;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ymatches was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ymatches = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
559
            }
560
        }
561
562
        $this->lcs = 0;
0 ignored issues
show
Bug introduced by
The property lcs does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
563
564
        $this->seq[0] = $yoff - 1;
0 ignored issues
show
Bug introduced by
The property seq does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
565
566
        $this->in_seq = [];
0 ignored issues
show
Bug introduced by
The property in_seq does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
567
568
        $ymids[0] = [];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ymids was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ymids = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
569
570
        $numer = $xlim - $xoff + $nchunks - 1;
571
572
        $x = $xoff;
573
574
        for ($chunk = 0; $chunk < $nchunks; $chunk++) {
575
            if ($chunk > 0) {
576
                for ($i = 0; $i <= $this->lcs; ++$i) {
577
                    $ymids[$i][$chunk - 1] = $this->seq[$i];
578
                }
579
            }
580
581
            $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks);
582
583
            for (; $x < $x1; $x++) {
584
                $line = $flip ? $this->yv[$x] : $this->xv[$x];
585
586
                if (empty($ymatches[$line])) {
587
                    continue;
588
                }
589
590
                $matches = $ymatches[$line];
591
592
                foreach ($matches as $y) {
593 View Code Duplication
                    if (empty($this->in_seq[$y])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
594
                        $k = $this->_lcsPos($y);
595
596
                        assert($k > 0);
597
598
                        $ymids[$k] = $ymids[$k - 1];
599
600
                        break;
601
                    }
602
                }
603
604
                while (list($junk, $y) = each($matches)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $junk is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
605
                    if ($y > $this->seq[$k - 1]) {
606
                        // assert($y < $this->seq[$k]); // GIJ Patched
607
608
                        /* Optimization: this is a common case: next match is
609
                         * just replacing previous match. */
610
611
                        $this->in_seq[$this->seq[$k]] = false;
0 ignored issues
show
Bug introduced by
The variable $k does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
612
613
                        $this->seq[$k] = $y;
614
615
                        $this->in_seq[$y] = 1;
616 View Code Duplication
                    } elseif (empty($this->in_seq[$y])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
617
                        $k = $this->_lcsPos($y);
618
619
                        assert($k > 0);
620
621
                        $ymids[$k] = $ymids[$k - 1];
622
                    }
623
                }
624
            }
625
        }
626
627
        $seps[] = $flip ? [$yoff, $xoff] : [$xoff, $yoff];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$seps was never initialized. Although not strictly required by PHP, it is generally a good practice to add $seps = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
628
629
        $ymid = $ymids[$this->lcs];
630
631
        for ($n = 0; $n < $nchunks - 1; $n++) {
632
            $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks);
633
634
            $y1 = $ymid[$n] + 1;
635
636
            $seps[] = $flip ? [$y1, $x1] : [$x1, $y1];
637
        }
638
639
        $seps[] = $flip ? [$ylim, $xlim] : [$xlim, $ylim];
640
641
        return [$this->lcs, $seps];
642
    }
643
644
    /**
645
     * @param $ypos
646
     * @return int
647
     */
648
649
    public function _lcsPos($ypos)
650
    {
651
        $end = $this->lcs;
652
653
        if (0 == $end || $ypos > $this->seq[$end]) {
654
            $this->seq[++$this->lcs] = $ypos;
655
656
            $this->in_seq[$ypos] = 1;
657
658
            return $this->lcs;
659
        }
660
661
        $beg = 1;
662
663
        while ($beg < $end) {
664
            $mid = (int)(($beg + $end) / 2);
665
666
            if ($ypos > $this->seq[$mid]) {
667
                $beg = $mid + 1;
668
            } else {
669
                $end = $mid;
670
            }
671
        }
672
673
        assert($ypos != $this->seq[$end]);
674
675
        $this->in_seq[$this->seq[$end]] = false;
676
677
        $this->seq[$end] = $ypos;
678
679
        $this->in_seq[$ypos] = 1;
680
681
        return $end;
682
    }
683
684
    /**
685
     * Finds LCS of two sequences.
686
     *
687
     * The results are recorded in the vectors $this->{x,y}changed[], by
688
     * storing a 1 in the element for each line that is an insertion or
689
     * deletion (ie. is not in the LCS).
690
     *
691
     * The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1.
692
     *
693
     * Note that XLIM, YLIM are exclusive bounds.  All line numbers are
694
     * origin-0 and discarded lines are not counted.
695
     * @param $xoff
696
     * @param $xlim
697
     * @param $yoff
698
     * @param $ylim
699
     */
700
701
    public function _compareseq($xoff, $xlim, $yoff, $ylim)
702
    {
703
        /* Slide down the bottom initial diagonal. */
704
705
        while ($xoff < $xlim && $yoff < $ylim
706
               && $this->xv[$xoff] == $this->yv[$yoff]) {
707
            ++$xoff;
708
709
            ++$yoff;
710
        }
711
712
        /* Slide up the top initial diagonal. */
713
714
        while ($xlim > $xoff && $ylim > $yoff
715
               && $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) {
716
            --$xlim;
717
718
            --$ylim;
719
        }
720
721
        if ($xoff == $xlim || $yoff == $ylim) {
722
            $lcs = 0;
723
        } else {
724
            /* This is ad hoc but seems to work well.  $nchunks =
725
             * sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5); $nchunks =
726
             * max(2,min(8,(int)$nchunks)); */
727
728
            $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1;
729
730
            list($lcs, $seps) = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks);
731
        }
732
733
        if (0 == $lcs) {
734
            /* X and Y sequences have no common subsequence: mark all
735
             * changed. */
736
737
            while ($yoff < $ylim) {
738
                $this->ychanged[$this->yind[$yoff++]] = 1;
739
            }
740
741
            while ($xoff < $xlim) {
742
                $this->xchanged[$this->xind[$xoff++]] = 1;
743
            }
744
        } else {
745
            /* Use the partitions to split this problem into subproblems. */
746
747
            reset($seps);
748
749
            $pt1 = $seps[0];
750
751
            while ($pt2 = next($seps)) {
752
                $this->_compareseq($pt1[0], $pt2[0], $pt1[1], $pt2[1]);
753
754
                $pt1 = $pt2;
755
            }
756
        }
757
    }
758
759
    /**
760
     * Adjusts inserts/deletes of identical lines to join changes as much as
761
     * possible.
762
     *
763
     * We do something when a run of changed lines include a line at one end
764
     * and has an excluded, identical line at the other.  We are free to
765
     * choose which identical line is included.  `compareseq' usually chooses
766
     * the one at the beginning, but usually it is cleaner to consider the
767
     * following identical line to be the "change".
768
     *
769
     * This is extracted verbatim from analyze.c (GNU diffutils-2.7).
770
     * @param $lines
771
     * @param $other_changed
772
     * @param mixed $changed
773
     */
774
775
    public function _shiftBoundaries($lines, &$changed, $other_changed)
776
    {
777
        $i = 0;
778
779
        $j = 0;
780
781
        assert('count($lines) == count($changed)');
782
783
        $len = count($lines);
784
785
        $other_len = count($other_changed);
786
787
        while (1) {
788
            /* Scan forward to find the beginning of another run of
789
             * changes. Also keep track of the corresponding point in the
790
             * other file.
791
             *
792
             * Throughout this code, $i and $j are adjusted together so that
793
             * the first $i elements of $changed and the first $j elements of
794
             * $other_changed both contain the same number of zeros (unchanged
795
             * lines).
796
             *
797
             * Furthermore, $j is always kept so that $j == $other_len or
798
             * $other_changed[$j] === false. */
799
800
            while ($j < $other_len && $other_changed[$j]) {
801
                $j++;
802
            }
803
804
            while ($i < $len && !$changed[$i]) {
805
                assert('$j < $other_len && ! $other_changed[$j]');
806
807
                $i++;
808
809
                $j++;
810
811
                while ($j < $other_len && $other_changed[$j]) {
812
                    $j++;
813
                }
814
            }
815
816
            if ($i == $len) {
817
                break;
818
            }
819
820
            $start = $i;
821
822
            /* Find the end of this run of changes. */
823
824
            while (++$i < $len && $changed[$i]) {
825
                continue;
826
            }
827
828
            do {
829
                /* Record the length of this run of changes, so that we can
830
                 * later determine whether the run has grown. */
831
832
                $runlength = $i - $start;
833
834
                /* Move the changed region back, so long as the previous
835
                 * unchanged line matches the last changed one.  This merges
836
                 * with previous changed regions. */
837
838
                while ($start > 0 && $lines[$start - 1] == $lines[$i - 1]) {
839
                    $changed[--$start] = 1;
840
841
                    $changed[--$i] = false;
842
843
                    while ($start > 0 && $changed[$start - 1]) {
844
                        $start--;
845
                    }
846
847
                    assert('$j > 0');
848
849
                    while ($other_changed[--$j]) {
850
                        continue;
851
                    }
852
853
                    assert('$j >= 0 && !$other_changed[$j]');
854
                }
855
856
                /* Set CORRESPONDING to the end of the changed run, at the
857
                 * last point where it corresponds to a changed run in the
858
                 * other file. CORRESPONDING == LEN means no such point has
859
                 * been found. */
860
861
                $corresponding = $j < $other_len ? $i : $len;
862
863
                /* Move the changed region forward, so long as the first
864
                 * changed line matches the following unchanged one.  This
865
                 * merges with following changed regions.  Do this second, so
866
                 * that if there are no merges, the changed region is moved
867
                 * forward as far as possible. */
868
869
                while ($i < $len && $lines[$start] == $lines[$i]) {
870
                    $changed[$start++] = false;
871
872
                    $changed[$i++] = 1;
873
874
                    while ($i < $len && $changed[$i]) {
875
                        $i++;
876
                    }
877
878
                    assert('$j < $other_len && ! $other_changed[$j]');
879
880
                    $j++;
881
882
                    if ($j < $other_len && $other_changed[$j]) {
883
                        $corresponding = $i;
884
885
                        while ($j < $other_len && $other_changed[$j]) {
886
                            $j++;
887
                        }
888
                    }
889
                }
890
            } while ($runlength != $i - $start);
891
892
            /* If possible, move the fully-merged run of changes back to a
893
             * corresponding run in the other file. */
894
895
            while ($corresponding < $i) {
896
                $changed[--$start] = 1;
897
898
                $changed[--$i] = 0;
899
900
                assert('$j > 0');
901
902
                while ($other_changed[--$j]) {
903
                    continue;
904
                }
905
906
                assert('$j >= 0 && !$other_changed[$j]');
907
            }
908
        }
909
    }
910
}
911
912
/**
913
 * @package Text_Diff
914
 * @author  Geoffrey T. Dairiki <[email protected]>
915
 *
916
 * @access  private
917
 */
918
class Text_Diff_Op
919
{
920
    public $orig;
921
922
    public $final;
923
924
    public function reverse()
925
    {
926
        trigger_error('Abstract method', E_USER_ERROR);
927
    }
928
929
    /**
930
     * @return int|void
931
     */
932
933
    public function norig()
934
    {
935
        return $this->orig ? count($this->orig) : 0;
936
    }
937
938
    /**
939
     * @return int|void
940
     */
941
942
    public function nfinal()
943
    {
944
        return $this->final ? count($this->final) : 0;
945
    }
946
}
947
948
/**
949
 * @package Text_Diff
950
 * @author  Geoffrey T. Dairiki <[email protected]>
951
 *
952
 * @access  private
953
 */
954
class Text_Diff_Op_copy extends Text_Diff_Op
955
{
956
    /**
957
     * Text_Diff_Op_copy constructor.
958
     * @param      $orig
959
     * @param bool $final
960
     */
961
962
    public function __construct($orig, $final = false)
963
    {
964
        if (!is_array($final)) {
965
            $final = $orig;
966
        }
967
968
        $this->orig = $orig;
969
970
        $this->final = $final;
971
    }
972
973
    /**
974
     * @return \Text_Diff_Op_copy
975
     */
976
977
    public function &reverse()
978
    {
979
        return $reverse = new self($this->final, $this->orig);
0 ignored issues
show
Unused Code introduced by
$reverse is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
980
    }
981
}
982
983
/**
984
 * @package Text_Diff
985
 * @author  Geoffrey T. Dairiki <[email protected]>
986
 *
987
 * @access  private
988
 */
989 View Code Duplication
class Text_Diff_Op_delete extends Text_Diff_Op
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
990
{
991
    /**
992
     * Text_Diff_Op_delete constructor.
993
     * @param $lines
994
     */
995
996
    public function __construct($lines)
997
    {
998
        $this->orig = $lines;
999
1000
        $this->final = false;
1001
    }
1002
1003
    /**
1004
     * @return \Text_Diff_Op_add
1005
     */
1006
1007
    public function &reverse()
1008
    {
1009
        return $reverse = new Text_Diff_Op_add($this->orig);
0 ignored issues
show
Unused Code introduced by
$reverse is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1010
    }
1011
}
1012
1013
/**
1014
 * @package Text_Diff
1015
 * @author  Geoffrey T. Dairiki <[email protected]>
1016
 *
1017
 * @access  private
1018
 */
1019 View Code Duplication
class Text_Diff_Op_add extends Text_Diff_Op
0 ignored issues
show
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1020
{
1021
    /**
1022
     * Text_Diff_Op_add constructor.
1023
     * @param $lines
1024
     */
1025
1026
    public function __construct($lines)
1027
    {
1028
        $this->final = $lines;
1029
1030
        $this->orig = false;
1031
    }
1032
1033
    /**
1034
     * @return \Text_Diff_Op_delete
1035
     */
1036
1037
    public function &reverse()
1038
    {
1039
        return $reverse = new Text_Diff_Op_delete($this->final);
0 ignored issues
show
Unused Code introduced by
$reverse is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1040
    }
1041
}
1042
1043
/**
1044
 * @package Text_Diff
1045
 * @author  Geoffrey T. Dairiki <[email protected]>
1046
 *
1047
 * @access  private
1048
 */
1049
class Text_Diff_Op_change extends Text_Diff_Op
1050
{
1051
    /**
1052
     * Text_Diff_Op_change constructor.
1053
     * @param $orig
1054
     * @param $final
1055
     */
1056
1057
    public function __construct($orig, $final)
1058
    {
1059
        $this->orig = $orig;
1060
1061
        $this->final = $final;
1062
    }
1063
1064
    /**
1065
     * @return \Text_Diff_Op_change
1066
     */
1067
1068
    public function &reverse()
1069
    {
1070
        return $reverse = new self($this->final, $this->orig);
0 ignored issues
show
Unused Code introduced by
$reverse is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1071
    }
1072
}
1073