@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3abstract class PhabricatorApplicationTransactionDetailView
4 extends AphrontView {
5 protected $oldText;
6 protected $newText;
7
8 public function setNewText($new_text) {
9 $this->newText = $new_text;
10 return $this;
11 }
12
13 public function setOldText($old_text) {
14 $this->oldText = $old_text;
15 return $this;
16 }
17
18 public function renderForMail() {
19 $diff = $this->buildDiff();
20
21 $viewer = $this->getViewer();
22 $old_bright = $viewer->getCSSValue('old-bright');
23 $new_bright = $viewer->getCSSValue('new-bright');
24
25 $old_styles = array(
26 'padding: 0 2px;',
27 'color: #333333;',
28 "background: {$old_bright};",
29 );
30 $old_styles = implode(' ', $old_styles);
31
32 $new_styles = array(
33 'padding: 0 2px;',
34 'color: #333333;',
35 "background: {$new_bright};",
36 );
37 $new_styles = implode(' ', $new_styles);
38
39 $omit_styles = array(
40 'padding: 8px 0;',
41 );
42 $omit_styles = implode(' ', $omit_styles);
43
44 $result = array();
45 foreach ($diff->getSummaryParts() as $part) {
46 $type = $part['type'];
47 $text = $part['text'];
48 switch ($type) {
49 case '.':
50 $result[] = phutil_tag(
51 'div',
52 array(
53 'style' => $omit_styles,
54 ),
55 pht('...'));
56 break;
57 case '-':
58 $result[] = phutil_tag(
59 'span',
60 array(
61 'style' => $old_styles,
62 ),
63 $text);
64 break;
65 case '+':
66 $result[] = phutil_tag(
67 'span',
68 array(
69 'style' => $new_styles,
70 ),
71 $text);
72 break;
73 case '=':
74 $result[] = $text;
75 break;
76 }
77 }
78
79 $styles = array(
80 'white-space: pre-wrap;',
81 'color: #74777D;',
82 );
83
84 // Beyond applying "pre-wrap", convert newlines to "<br />" explicitly
85 // to improve behavior in clients like Airmail.
86 $result = phutil_escape_html_newlines($result);
87
88 return phutil_tag(
89 'div',
90 array(
91 'style' => implode(' ', $styles),
92 ),
93 $result);
94 }
95
96 public function render() {
97 $diff = $this->buildDiff();
98
99 require_celerity_resource('differential-changeset-view-css');
100
101 $result = array();
102 foreach ($diff->getParts() as $part) {
103 $type = $part['type'];
104 $text = $part['text'];
105 switch ($type) {
106 case '-':
107 $result[] = phutil_tag(
108 'span',
109 array(
110 'class' => 'old',
111 ),
112 $text);
113 break;
114 case '+':
115 $result[] = phutil_tag(
116 'span',
117 array(
118 'class' => 'new',
119 ),
120 $text);
121 break;
122 case '=':
123 $result[] = $text;
124 break;
125 }
126 }
127
128 $diff_view = phutil_tag(
129 'div',
130 array(
131 'class' => 'prose-diff',
132 ),
133 $result);
134
135 $old_view = phutil_tag(
136 'div',
137 array(
138 'class' => 'prose-diff',
139 ),
140 $this->oldText);
141
142 $new_view = phutil_tag(
143 'div',
144 array(
145 'class' => 'prose-diff',
146 ),
147 $this->newText);
148
149 return id(new PHUITabGroupView())
150 ->addTab(
151 id(new PHUITabView())
152 ->setKey('old')
153 ->setName(pht('Old'))
154 ->appendChild($old_view))
155 ->addTab(
156 id(new PHUITabView())
157 ->setKey('new')
158 ->setName(pht('New'))
159 ->appendChild($new_view))
160 ->addTab(
161 id(new PHUITabView())
162 ->setKey('diff')
163 ->setName(pht('Diff'))
164 ->appendChild($diff_view))
165 ->selectTab('diff');
166 }
167
168 private function buildDiff() {
169 $engine = new PhutilProseDifferenceEngine();
170 return $engine->getDiff($this->oldText, $this->newText);
171 }
172}