1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* This file is part of dispositif/wikibot application (@github) |
4
|
|
|
* 2019-2024 © Philippe M./Irønie <[email protected]> |
5
|
|
|
* For the full copyright and MIT license information, view the license file. |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
declare(strict_types=1); |
9
|
|
|
|
10
|
|
|
namespace App\Infrastructure; |
11
|
|
|
|
12
|
|
|
use App\Application\InfrastructurePorts\DiffInterface; |
13
|
|
|
use Jfcherng\Diff\DiffHelper; |
14
|
|
|
use Jfcherng\Diff\Renderer\RendererConstant; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Diff lib PHP>=8.1 https://github.com/jfcherng/php-diff |
18
|
|
|
* https://github.com/jfcherng/php-diff/tree/v6/example |
19
|
|
|
*/ |
20
|
|
|
class DiffAdapter implements DiffInterface |
21
|
|
|
{ |
22
|
|
|
public const STYLE_UNIFIED = 'Unified'; |
23
|
|
|
public const STYLE_CONTEXT = 'Context'; |
24
|
|
|
protected const DEFAULT_STYLE = self::STYLE_UNIFIED; |
25
|
|
|
protected const DIFF_STYLES = [self::STYLE_UNIFIED, self::STYLE_CONTEXT]; |
26
|
|
|
protected array $colorStyles; |
27
|
|
|
protected array $diffOptions; |
28
|
|
|
protected array $rendererOptions; |
29
|
|
|
protected string $diffStyle; |
30
|
|
|
|
31
|
|
|
public function __construct(string $diffStyle = self::DEFAULT_STYLE) |
32
|
|
|
{ |
33
|
|
|
$this->diffStyle = in_array($diffStyle, self::DIFF_STYLES) ? $diffStyle : 'Unified'; |
34
|
|
|
$this->initialize(); |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
private function initialize(): void |
38
|
|
|
{ |
39
|
|
|
$this->colorStyles = [ |
40
|
|
|
'section' => ['f_black', 'b_cyan'], |
41
|
|
|
]; |
42
|
|
|
|
43
|
|
|
// options for Diff class |
44
|
|
|
$this->diffOptions = [ |
45
|
|
|
// show how many neighbor lines |
46
|
|
|
// Differ::CONTEXT_ALL can be used to show the whole file |
47
|
|
|
'context' => 2, |
48
|
|
|
// ignore case difference |
49
|
|
|
'ignoreCase' => false, |
50
|
|
|
// ignore line ending difference |
51
|
|
|
'ignoreLineEnding' => false, |
52
|
|
|
// ignore whitespace difference |
53
|
|
|
'ignoreWhitespace' => false, |
54
|
|
|
// if the input sequence is too long, it will just gives up (especially for char-level diff) |
55
|
|
|
'lengthLimit' => 2000, |
56
|
|
|
]; |
57
|
|
|
|
58
|
|
|
// options for renderer class |
59
|
|
|
$this->rendererOptions = [ |
60
|
|
|
// how detailed the rendered HTML is? (none, line, word, char) |
61
|
|
|
'detailLevel' => 'word', // line |
62
|
|
|
// renderer language: eng, cht, chs, jpn, ... |
63
|
|
|
// or an array which has the same keys with a language file |
64
|
|
|
// check the "Custom Language" section in the readme for more advanced usage |
65
|
|
|
'language' => 'fra', // eng |
66
|
|
|
// show line numbers in HTML renderers |
67
|
|
|
'lineNumbers' => false, |
68
|
|
|
// show a separator between different diff hunks in HTML renderers |
69
|
|
|
'separateBlock' => true, |
70
|
|
|
// show the (table) header |
71
|
|
|
'showHeader' => true, |
72
|
|
|
// convert spaces/tabs into HTML codes like `<span class="ch sp"> </span>` |
73
|
|
|
// and the frontend is responsible for rendering them with CSS. |
74
|
|
|
// when using this, "spacesToNbsp" should be false and "tabSize" is not respected. |
75
|
|
|
'spaceToHtmlTag' => false, |
76
|
|
|
// the frontend HTML could use CSS "white-space: pre;" to visualize consecutive whitespaces |
77
|
|
|
// but if you want to visualize them in the backend with " ", you can set this to true |
78
|
|
|
'spacesToNbsp' => false, |
79
|
|
|
// HTML renderer tab width (negative = do not convert into spaces) |
80
|
|
|
'tabSize' => 4, |
81
|
|
|
// this option is currently only for the Combined renderer. |
82
|
|
|
// it determines whether a replace-type block should be merged or not |
83
|
|
|
// depending on the content changed ratio, which values between 0 and 1. |
84
|
|
|
'mergeThreshold' => 0.8, |
85
|
|
|
// this option is currently only for the Unified and the Context renderers. |
86
|
|
|
// RendererConstant::CLI_COLOR_AUTO = colorize the output if possible (default) |
87
|
|
|
// RendererConstant::CLI_COLOR_ENABLE = force to colorize the output |
88
|
|
|
// RendererConstant::CLI_COLOR_DISABLE = force not to colorize the output |
89
|
|
|
'cliColorization' => RendererConstant::CLI_COLOR_AUTO, |
90
|
|
|
// this option is currently only for the Json renderer. |
91
|
|
|
// internally, ops (tags) are all int type but this is not good for human reading. |
92
|
|
|
// set this to "true" to convert them into string form before outputting. |
93
|
|
|
'outputTagAsString' => false, |
94
|
|
|
// this option is currently only for the Json renderer. |
95
|
|
|
// it controls how the output JSON is formatted. |
96
|
|
|
// see available options on https://www.php.net/manual/en/function.json-encode.php |
97
|
|
|
'jsonEncodeFlags' => \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE, |
98
|
|
|
// this option is currently effective when the "detailLevel" is "word" |
99
|
|
|
// characters listed in this array can be used to make diff segments into a whole |
100
|
|
|
// for example, making "<del>good</del>-<del>looking</del>" into "<del>good-looking</del>" |
101
|
|
|
// this should bring better readability but set this to empty array if you do not want it |
102
|
|
|
'wordGlues' => [' ', '-'], |
103
|
|
|
// change this value to a string as the returned diff if the two input strings are identical |
104
|
|
|
'resultForIdenticals' => null, |
105
|
|
|
// extra HTML classes added to the DOM of the diff container |
106
|
|
|
'wrapperClasses' => ['diff-wrapper'], |
107
|
|
|
]; |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
public function getDiff(string $oldText, string $newText): string |
111
|
|
|
{ |
112
|
|
|
//echo CliColor::color("$diffStyle Diff\n============", $this->colorStyles['section']) . "\n\n"; |
113
|
|
|
$unifiedResult = DiffHelper::calculate( |
114
|
|
|
$oldText, |
115
|
|
|
$newText, |
116
|
|
|
$this->diffStyle, |
117
|
|
|
$this->diffOptions, |
118
|
|
|
$this->rendererOptions, |
119
|
|
|
); |
120
|
|
|
|
121
|
|
|
return $unifiedResult . "\n\n"; |
122
|
|
|
} |
123
|
|
|
} |