Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/view/layout/PhabricatorSourceCodeView.php
12241 views
1
<?php
2
3
final class PhabricatorSourceCodeView extends AphrontView {
4
5
private $lines;
6
private $uri;
7
private $highlights = array();
8
private $canClickHighlight = true;
9
private $truncatedFirstBytes = false;
10
private $truncatedFirstLines = false;
11
private $symbolMetadata;
12
private $blameMap;
13
private $coverage = array();
14
15
public function setLines(array $lines) {
16
$this->lines = $lines;
17
return $this;
18
}
19
20
public function setURI(PhutilURI $uri) {
21
$this->uri = $uri;
22
return $this;
23
}
24
25
public function setHighlights(array $array) {
26
$this->highlights = array_fuse($array);
27
return $this;
28
}
29
30
public function disableHighlightOnClick() {
31
$this->canClickHighlight = false;
32
return $this;
33
}
34
35
public function setTruncatedFirstBytes($truncated_first_bytes) {
36
$this->truncatedFirstBytes = $truncated_first_bytes;
37
return $this;
38
}
39
40
public function setTruncatedFirstLines($truncated_first_lines) {
41
$this->truncatedFirstLines = $truncated_first_lines;
42
return $this;
43
}
44
45
public function setSymbolMetadata(array $symbol_metadata) {
46
$this->symbolMetadata = $symbol_metadata;
47
return $this;
48
}
49
50
public function getSymbolMetadata() {
51
return $this->symbolMetadata;
52
}
53
54
public function setBlameMap(array $map) {
55
$this->blameMap = $map;
56
return $this;
57
}
58
59
public function getBlameMap() {
60
return $this->blameMap;
61
}
62
63
public function setCoverage(array $coverage) {
64
$this->coverage = $coverage;
65
return $this;
66
}
67
68
public function getCoverage() {
69
return $this->coverage;
70
}
71
72
public function render() {
73
$blame_map = $this->getBlameMap();
74
$has_blame = ($blame_map !== null);
75
76
require_celerity_resource('phabricator-source-code-view-css');
77
require_celerity_resource('syntax-highlighting-css');
78
79
if ($this->canClickHighlight) {
80
Javelin::initBehavior('phabricator-line-linker');
81
}
82
83
$line_number = 1;
84
85
$rows = array();
86
87
$lines = $this->lines;
88
if ($this->truncatedFirstLines) {
89
$lines[] = phutil_tag(
90
'span',
91
array(
92
'class' => 'c',
93
),
94
pht('...'));
95
} else if ($this->truncatedFirstBytes) {
96
$last_key = last_key($lines);
97
$lines[$last_key] = hsprintf(
98
'%s%s',
99
$lines[$last_key],
100
phutil_tag(
101
'span',
102
array(
103
'class' => 'c',
104
),
105
pht('...')));
106
}
107
108
$base_uri = (string)$this->uri;
109
$wrote_anchor = false;
110
111
$coverage = $this->getCoverage();
112
$coverage_count = count($coverage);
113
$coverage_data = ipull($coverage, 'data');
114
115
// TODO: Modularize this properly, see T13125.
116
$coverage_map = array(
117
'C' => 'background: #66bbff;',
118
'U' => 'background: #dd8866;',
119
'N' => 'background: #ddeeff;',
120
'X' => 'background: #aa00aa;',
121
);
122
123
foreach ($lines as $line) {
124
$row_attributes = array();
125
if (isset($this->highlights[$line_number])) {
126
$row_attributes['class'] = 'phabricator-source-highlight';
127
if (!$wrote_anchor) {
128
$row_attributes['id'] = 'phabricator-line-linker-anchor';
129
$wrote_anchor = true;
130
}
131
}
132
133
if ($this->canClickHighlight) {
134
if ($base_uri) {
135
$line_href = $base_uri.'$'.$line_number;
136
} else {
137
$line_href = null;
138
}
139
140
$tag_number = phutil_tag(
141
'a',
142
array(
143
'href' => $line_href,
144
'data-n' => $line_number,
145
));
146
} else {
147
$tag_number = phutil_tag(
148
'span',
149
array(),
150
$line_number);
151
}
152
153
if ($has_blame) {
154
$lines = idx($blame_map, $line_number);
155
156
if ($lines) {
157
$skip_blame = 'skip';
158
$info_blame = 'info';
159
} else {
160
$skip_blame = null;
161
$info_blame = null;
162
}
163
164
$blame_cells = array(
165
phutil_tag(
166
'th',
167
array(
168
'class' => 'phabricator-source-blame-skip',
169
'data-blame' => $skip_blame,
170
)),
171
phutil_tag(
172
'th',
173
array(
174
'class' => 'phabricator-source-blame-info',
175
'data-blame' => $info_blame,
176
'data-blame-lines' => $lines,
177
)),
178
);
179
} else {
180
$blame_cells = null;
181
}
182
183
$coverage_cells = array();
184
foreach ($coverage as $coverage_idx => $coverage_spec) {
185
if (isset($coverage_spec['data'][$line_number - 1])) {
186
$coverage_char = $coverage_spec['data'][$line_number - 1];
187
} else {
188
$coverage_char = null;
189
}
190
191
$coverage_style = idx($coverage_map, $coverage_char, null);
192
193
$coverage_cells[] = phutil_tag(
194
'th',
195
array(
196
'class' => 'phabricator-source-coverage',
197
'style' => $coverage_style,
198
'data-coverage' => $coverage_idx.'/'.$coverage_char,
199
));
200
}
201
202
$rows[] = phutil_tag(
203
'tr',
204
$row_attributes,
205
array(
206
$blame_cells,
207
phutil_tag(
208
'th',
209
array(
210
'class' => 'phabricator-source-line',
211
),
212
$tag_number),
213
phutil_tag(
214
'td',
215
array(
216
'class' => 'phabricator-source-code',
217
),
218
$line),
219
$coverage_cells,
220
));
221
222
$line_number++;
223
}
224
225
$classes = array();
226
$classes[] = 'phabricator-source-code-view';
227
$classes[] = 'remarkup-code';
228
$classes[] = 'PhabricatorMonospaced';
229
230
$symbol_metadata = $this->getSymbolMetadata();
231
232
$sigils = array();
233
$sigils[] = 'phabricator-source';
234
$sigils[] = 'has-symbols';
235
236
Javelin::initBehavior('repository-crossreference');
237
238
return phutil_tag_div(
239
'phabricator-source-code-container',
240
javelin_tag(
241
'table',
242
array(
243
'class' => implode(' ', $classes),
244
'sigil' => implode(' ', $sigils),
245
'meta' => array(
246
'uri' => (string)$this->uri,
247
'symbols' => $symbol_metadata,
248
),
249
),
250
phutil_implode_html('', $rows)));
251
}
252
253
}
254
255