|
9 | 9 | /**
|
10 | 10 | * Diff
|
11 | 11 | *
|
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.) |
14 | 14 | *
|
15 | 15 | * PHP version 7.1 or greater
|
16 | 16 | *
|
|
24 | 24 | class Diff
|
25 | 25 | {
|
26 | 26 | /**
|
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. |
28 | 29 | */
|
29 |
| - private $old = null; |
| 30 | + private $old; |
30 | 31 |
|
31 | 32 | /**
|
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. |
33 | 35 | */
|
34 |
| - private $new = null; |
| 36 | + private $new; |
35 | 37 |
|
36 | 38 | /**
|
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". |
38 | 40 | */
|
39 |
| - private $groupedCodes = null; |
| 41 | + private $groupedCodes; |
40 | 42 |
|
41 | 43 | /**
|
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. |
43 | 49 | */
|
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 | + ]; |
51 | 55 |
|
52 | 56 | /**
|
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() |
54 | 60 | */
|
55 |
| - public $options = array(); |
| 61 | + private $options = []; |
56 | 62 |
|
57 | 63 | /**
|
58 | 64 | * The constructor.
|
59 | 65 | *
|
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. |
63 | 79 | */
|
64 |
| - public function __construct(array $oldArray, array $newArray, array $options = array()) |
| 80 | + public function __construct($old, $new, array $options = []) |
65 | 81 | {
|
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; |
68 | 85 |
|
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; |
74 | 123 | }
|
75 | 124 |
|
76 | 125 |
|
77 | 126 | /**
|
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. |
79 | 130 | *
|
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. |
82 | 132 | */
|
83 |
| - public function render($renderer) |
| 133 | + public function render(object $renderer) |
84 | 134 | {
|
85 | 135 | $renderer->diff = $this;
|
| 136 | + |
86 | 137 | return $renderer->render();
|
87 | 138 | }
|
88 | 139 |
|
89 | 140 | /**
|
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. |
98 | 158 | */
|
99 |
| - public function getOld(int $start = 0, $end = null): array |
| 159 | + public function getArrayRange(array $array, int $start = 0, $end = null): array |
100 | 160 | {
|
| 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 | + |
101 | 165 | if ($start == 0 && $end === null) {
|
102 |
| - return $this->old; |
| 166 | + //Return entire array. |
| 167 | + return $array; |
103 | 168 | }
|
104 | 169 |
|
105 | 170 | if ($end === null) {
|
106 |
| - return array_slice($this->old, $start, 1); |
| 171 | + //Return single element. |
| 172 | + return array_slice($array, $start, 1); |
107 | 173 | }
|
108 | 174 |
|
| 175 | + //Return range of elements. |
109 | 176 | $length = $end - $start;
|
110 |
| - return array_slice($this->old, $start, $length); |
| 177 | + |
| 178 | + return array_slice($array, $start, $length); |
111 | 179 | }
|
112 | 180 |
|
113 | 181 | /**
|
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. |
122 | 193 | */
|
123 |
| - public function getNew(int $start = 0, $end = null): array |
| 194 | + public function getArgumentType($var): int |
124 | 195 | {
|
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.'); |
131 | 203 | }
|
132 | 204 |
|
133 | 205 | $length = $end - $start;
|
134 | 206 | return array_slice($this->new, $start, $length);
|
135 | 207 | }
|
136 | 208 |
|
137 | 209 | /**
|
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. |
142 | 211 | *
|
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. |
144 | 217 | */
|
145 | 218 | public function getGroupedOpcodes(): array
|
146 | 219 | {
|
147 | 220 | if (!is_null($this->groupedCodes)) {
|
| 221 | + //Return the cached results. |
148 | 222 | return $this->groupedCodes;
|
149 | 223 | }
|
150 | 224 |
|
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); |
152 | 227 | $this->groupedCodes = $sequenceMatcher->getGroupedOpcodes($this->options['context']);
|
| 228 | + |
153 | 229 | return $this->groupedCodes;
|
154 | 230 | }
|
155 | 231 | }
|
0 commit comments