Skip to content

Commit 0d8c872

Browse files
committed
Code Optimization, cleanup, refactoring and commenting.
1 The constructor now accepts both string and array values as data to compare to eachother. 2 Method Diff::setOptions() added to merge user defined options into the default options. 3 methods Diff::getOld() and Diff::getNew() now return an entire array. 4 Method Diff::getArrayRange() added. 5 Method Diff::getArgumentType() added. As a result of change 3 and 4, text renderers Context and Unified are also changed to keep functionality the same.
1 parent e6cd9e0 commit 0d8c872

File tree

3 files changed

+147
-71
lines changed

3 files changed

+147
-71
lines changed

lib/jblond/Diff.php

Lines changed: 142 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
/**
1010
* Diff
1111
*
12-
* A comprehensive library for generating differences between two strings
13-
* in multiple formats (unified, side by side HTML etc)
12+
* A comprehensive library for comparing two strings and generating the differences between them in multiple formats.
13+
* (unified, side by side, inline, HTML, etc.)
1414
*
1515
* PHP version 7.1 or greater
1616
*
@@ -24,132 +24,208 @@
2424
class Diff
2525
{
2626
/**
27-
* @var array The "old" sequence to use as the basis for the comparison.
27+
* @var array The "old" string to compare to.
28+
* Each element contains a line of this string.
2829
*/
29-
private $old = null;
30+
private $old;
3031

3132
/**
32-
* @var array The "new" sequence to generate the changes for.
33+
* @var array The "new" string to compare.
34+
* Each element contains a line of this string.
3335
*/
34-
private $new = null;
36+
private $new;
3537

3638
/**
37-
* @var array Array containing the generated op codes for the differences between the two items.
39+
* @var array Contains generated op-codes which represent the differences between "old" and "new".
3840
*/
39-
private $groupedCodes = null;
41+
private $groupedCodes;
4042

4143
/**
42-
* @var array Associative array of the default options available for the diff class and their default value.
44+
* @var array Associative array containing the default options available for the diff class and their default
45+
* value.
46+
* - context The amount of lines to include around blocks that differ.
47+
* - ignoreWhitespace When true, tabs and spaces are ignored while comparing.
48+
* - ignoreCase When true, character casing is ignored while comparing.
4349
*/
44-
private $defaultOptions = array(
45-
'context' => 3,
46-
'ignoreNewLines' => false,
47-
'ignoreWhitespace' => false,
48-
'ignoreCase' => false,
49-
'labelDifferences' => 'Differences'
50-
);
50+
private $defaultOptions = [
51+
'context' => 3,
52+
'ignoreWhitespace' => false,
53+
'ignoreCase' => false,
54+
];
5155

5256
/**
53-
* @var array Array of the options that have been applied for generating the diff.
57+
* @var array Associative array containing the options that will be applied for generating the diff.
58+
* The key-value pairs are set at the contructor of this class.
59+
* @see Diff::setOptions()
5460
*/
55-
public $options = array();
61+
private $options = [];
5662

5763
/**
5864
* The constructor.
5965
*
60-
* @param array $oldArray Array containing the lines of the first string to compare.
61-
* @param array $newArray Array containing the lines for the second string to compare.
62-
* @param array $options Array for the options
66+
* The first two parameters define the data to compare to eachother.
67+
* The values can be of type string or array.
68+
* If the type is string, it's splitted into array elements by line-end characters.
69+
*
70+
* Options for comparison can be set by using the third parameter. The format of this value is expected to be a
71+
* associative array where each key-value pair represents an option and its value (E.g. ['context' => 3], ...).
72+
* When a keyName matches the name of a default option, that option's value will be overridden by the key's value.
73+
* Any other keyName (and it's value) can be added as an option, but will not be used if not implemented.
74+
* @see Diff::$defaultOptions
75+
*
76+
* @param string|array $old Data to compare to.
77+
* @param string|array $new Data to compare.
78+
* @param array $options User defined option values.
6379
*/
64-
public function __construct(array $oldArray, array $newArray, array $options = array())
80+
public function __construct($old, $new, array $options = [])
6581
{
66-
$this->old = $oldArray;
67-
$this->new = $newArray;
82+
//Convert "old" and "new" into an array of lines when they are strings.
83+
$this->old = $this->getArgumentType($old) ? preg_split("/\r\n|\n|\r/", $old) : $old;
84+
$this->new = $this->getArgumentType($new) ? preg_split("/\r\n|\n|\r/", $new) : $new;
6885

69-
if (is_array($options)) {
70-
$this->options = array_merge($this->defaultOptions, $options);
71-
} else {
72-
$this->options = $this->defaultOptions;
73-
}
86+
//Override the default options, define others.
87+
$this->setOptions($options);
88+
}
89+
90+
/**
91+
* Set the options to be used by the sequence matcher, called by this class.
92+
* @see Diff::getGroupedOpcodes()
93+
*
94+
* When a keyName matches the name of a default option, that option's value will be overridden by the key's value.
95+
* Any other keyName (and it's value) will be added as an option, but will not be used if not implemented.
96+
* @see Diff::$defaultOptions
97+
*
98+
* @param array $options User defined option names and values.
99+
*/
100+
public function setOptions(array $options)
101+
{
102+
$this->options = array_merge($this->defaultOptions, $options);
103+
}
104+
105+
/**
106+
* Get the lines of "old".
107+
*
108+
* @return array Contains the lines of the "old" string to compare to.
109+
*/
110+
public function getOld(): array
111+
{
112+
return $this->old;
113+
}
114+
115+
/**
116+
* Get the lines of "new".
117+
*
118+
* @return array Contains the lines of the "new" string to compare.
119+
*/
120+
public function getNew(): array
121+
{
122+
return $this->new;
74123
}
75124

76125

77126
/**
78-
* Render a diff using the supplied rendering class and return it.
127+
* Render a diff-view using a rendering class and get its results.
128+
*
129+
* @param object $renderer An instance of the rendering object, used for generating the diff-view.
79130
*
80-
* @param object $renderer object $renderer An instance of the rendering object to use for generating the diff.
81-
* @return mixed The generated diff. Exact return value depends on the rendered.
131+
* @return mixed The generated diff-view. The type of the return value depends on the applied rendereder.
82132
*/
83-
public function render($renderer)
133+
public function render(object $renderer)
84134
{
85135
$renderer->diff = $this;
136+
86137
return $renderer->render();
87138
}
88139

89140
/**
90-
* Get a range of lines from $start to $end from the first comparison string
91-
* and return them as an array. If no values are supplied, the entire string
92-
* is returned. It's also possible to specify just one line to return only
93-
* that line.
94-
*
95-
* @param int $start The starting number.
96-
* @param int|null $end The ending number. If not supplied, only the item in $start will be returned.
97-
* @return array Array of all of the lines between the specified range.
141+
* Get a range of elements of an array.
142+
*
143+
* The range must be defined as numeric
144+
* Start of the range is defined by the first parameter.
145+
* End of the range is defined by the second parameter.
146+
*
147+
* If the arguments for both parameters are omitted, the entire array will be returned.
148+
* If the argument for the second parameter is ommitted, the element defined as start will be returned.
149+
*
150+
* @param array $array The source array.
151+
* @param int $start The first element of the range to get.
152+
* @param int|null $end The last element of the range to get.
153+
* If not supplied, only the element at start will be returned.
154+
*
155+
* @throws \OutOfRangeException When the value of start or end are invalid to define a range.
156+
*
157+
* @return array Array containing all of the elements of the specified range.
98158
*/
99-
public function getOld(int $start = 0, $end = null): array
159+
public function getArrayRange(array $array, int $start = 0, $end = null): array
100160
{
161+
if ($start < 0 || $end < 0 || $end < $start) {
162+
throw new \OutOfRangeException('Start parameter must be lower than End parameter while both are positive!');
163+
}
164+
101165
if ($start == 0 && $end === null) {
102-
return $this->old;
166+
//Return entire array.
167+
return $array;
103168
}
104169

105170
if ($end === null) {
106-
return array_slice($this->old, $start, 1);
171+
//Return single element.
172+
return array_slice($array, $start, 1);
107173
}
108174

175+
//Return range of elements.
109176
$length = $end - $start;
110-
return array_slice($this->old, $start, $length);
177+
178+
return array_slice($array, $start, $length);
111179
}
112180

113181
/**
114-
* Get a range of lines from $start to $end from the second comparison string
115-
* and return them as an array. If no values are supplied, the entire string
116-
* is returned. It's also possible to specify just one line to return only
117-
* that line.
118-
*
119-
* @param int $start The starting number.
120-
* @param int|null $end The ending number. If not supplied, only the item in $start will be returned.
121-
* @return array Array of all of the lines between the specified range.
182+
* Get the type of a variable.
183+
*
184+
* The return value depend on the type of variable:
185+
* 0 If the type is 'array'
186+
* 1 if the type is 'string'
187+
*
188+
* @param mixed $var Variable to get type from.
189+
*
190+
* @throws \InvalidArgumentException When the type isn't 'array' or 'string'.
191+
*
192+
* @return int Number indicating the type of the variable. 0 for array type and 1 for string type.
122193
*/
123-
public function getNew(int $start = 0, $end = null): array
194+
public function getArgumentType($var): int
124195
{
125-
if ($start == 0 && $end === null) {
126-
return $this->new;
127-
}
128-
129-
if ($end === null) {
130-
return array_slice($this->new, $start, 1);
196+
switch (true) {
197+
case (is_array($var)):
198+
return 0;
199+
case (is_string($var)):
200+
return 1;
201+
default:
202+
throw new \InvalidArgumentException('Invalid argument type! Argument must be of type array or string.');
131203
}
132204

133205
$length = $end - $start;
134206
return array_slice($this->new, $start, $length);
135207
}
136208

137209
/**
138-
* Generate a list of the compiled and grouped op codes for the differences between the
139-
* two strings. Generally called by the renderer, this class instantiates the sequence
140-
* matcher and performs the actual diff generation and return an array of the op codes
141-
* for it. Once generated, the results are cached in the diff class instance.
210+
* Generate a list of the compiled and grouped op-codes for the differences between two strings.
142211
*
143-
* @return array Array of the grouped op codes for the generated diff.
212+
* Generally called by the renderer, this class instantiates the sequence matcher and performs the actual diff
213+
* generation and return an array of the op-codes for it.
214+
* Once generated, the results are cached in the diff class instance.
215+
*
216+
* @return array Array of the grouped op-codes for the generated diff.
144217
*/
145218
public function getGroupedOpcodes(): array
146219
{
147220
if (!is_null($this->groupedCodes)) {
221+
//Return the cached results.
148222
return $this->groupedCodes;
149223
}
150224

151-
$sequenceMatcher = new SequenceMatcher($this->old, $this->new, $this->options, null);
225+
//Get and cahche the grouped op-codes.
226+
$sequenceMatcher = new SequenceMatcher($this->old, $this->new, $this->options, null);
152227
$this->groupedCodes = $sequenceMatcher->getGroupedOpcodes($this->options['context']);
228+
153229
return $this->groupedCodes;
154230
}
155231
}

lib/jblond/Diff/Renderer/Text/Context.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public function render(): string
7474
continue;
7575
}
7676
$diff .= $this->tagMap[$tag] . ' ' .
77-
implode("\n" . $this->tagMap[$tag] . ' ', $this->diff->getOld($i1, $i2)) . "\n";
77+
implode("\n" . $this->tagMap[$tag] . ' ', $this->diff->getArrayRange($this->diff->getOld(), $i1, $i2)) . "\n";
7878
}
7979
}
8080

@@ -95,7 +95,7 @@ public function render(): string
9595
continue;
9696
}
9797
$diff .= $this->tagMap[$tag] . ' ' .
98-
implode("\n" . $this->tagMap[$tag] . ' ', $this->diff->getNew($j1, $j2)) . "\n";
98+
implode("\n" . $this->tagMap[$tag] . ' ', $this->diff->getArrayRange($this->diff->getNew(), $j1, $j2)) . "\n";
9999
}
100100
}
101101
}

lib/jblond/Diff/Renderer/Text/Unified.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ public function render(): string
4949
foreach ($group as $code) {
5050
list($tag, $i1, $i2, $j1, $j2) = $code;
5151
if ($tag == 'equal') {
52-
$diff .= ' ' . implode("\n ", $this->diff->getOld($i1, $i2)) . "\n";
52+
$diff .= ' ' . implode("\n ", $this->diff->getArrayRange($this->diff->getOld(), $i1, $i2)) . "\n";
5353
} else {
5454
if ($tag == 'replace' || $tag == 'delete') {
55-
$diff .= '-' . implode("\n-", $this->diff->getOld($i1, $i2)) . "\n";
55+
$diff .= '-' . implode("\n-", $this->diff->getArrayRange($this->diff->getOld(), $i1, $i2)) . "\n";
5656
}
5757

5858
if ($tag == 'replace' || $tag == 'insert') {
59-
$diff .= '+' . implode("\n+", $this->diff->getNew($j1, $j2)) . "\n";
59+
$diff .= '+' . implode("\n+", $this->diff->getArrayRange($this->diff->getNew(), $j1, $j2)) . "\n";
6060
}
6161
}
6262
}

0 commit comments

Comments
 (0)