Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/differential/render/DifferentialChangesetOneUpRenderer.php
12256 views
1
<?php
2
3
final class DifferentialChangesetOneUpRenderer
4
extends DifferentialChangesetHTMLRenderer {
5
6
private $simpleMode;
7
8
public function setSimpleMode($simple_mode) {
9
$this->simpleMode = $simple_mode;
10
return $this;
11
}
12
13
public function getSimpleMode() {
14
return $this->simpleMode;
15
}
16
17
public function isOneUpRenderer() {
18
return true;
19
}
20
21
protected function getRendererTableClass() {
22
return 'diff-1up';
23
}
24
25
public function getRendererKey() {
26
return '1up';
27
}
28
29
protected function renderColgroup() {
30
return phutil_tag('colgroup', array(), array(
31
phutil_tag('col', array('class' => 'num')),
32
phutil_tag('col', array('class' => 'num')),
33
phutil_tag('col', array('class' => 'copy')),
34
phutil_tag('col', array('class' => 'unified')),
35
));
36
}
37
38
public function renderTextChange(
39
$range_start,
40
$range_len,
41
$rows) {
42
43
$primitives = $this->buildPrimitives($range_start, $range_len);
44
return $this->renderPrimitives($primitives, $rows);
45
}
46
47
protected function renderPrimitives(array $primitives, $rows) {
48
list($left_prefix, $right_prefix) = $this->getLineIDPrefixes();
49
50
$is_simple = $this->getSimpleMode();
51
52
$no_copy = phutil_tag('td', array('class' => 'copy'));
53
$no_coverage = null;
54
55
$column_width = 4;
56
57
$aural_minus = javelin_tag(
58
'span',
59
array(
60
'aural' => true,
61
'data-aural' => true,
62
),
63
'- ');
64
65
$aural_plus = javelin_tag(
66
'span',
67
array(
68
'aural' => true,
69
'data-aural' => true,
70
),
71
'+ ');
72
73
$out = array();
74
foreach ($primitives as $k => $p) {
75
$type = $p['type'];
76
switch ($type) {
77
case 'old':
78
case 'new':
79
case 'old-file':
80
case 'new-file':
81
$is_old = ($type == 'old' || $type == 'old-file');
82
83
$cells = array();
84
if ($is_old) {
85
if ($p['htype']) {
86
if ($p['htype'] === '\\') {
87
$class = 'comment';
88
} else if (empty($p['oline'])) {
89
$class = 'left old old-full';
90
} else {
91
$class = 'left old';
92
}
93
$aural = $aural_minus;
94
} else {
95
$class = 'left';
96
$aural = null;
97
}
98
99
if ($type == 'old-file') {
100
$class = "{$class} differential-old-image";
101
}
102
103
if ($left_prefix) {
104
$left_id = $left_prefix.$p['line'];
105
} else {
106
$left_id = null;
107
}
108
109
$line = $p['line'];
110
111
$cells[] = phutil_tag(
112
'td',
113
array(
114
'id' => $left_id,
115
'class' => $class.' n',
116
'data-n' => $line,
117
));
118
119
$render = $p['render'];
120
if ($aural !== null) {
121
$render = array($aural, $render);
122
}
123
124
$cells[] = phutil_tag(
125
'td',
126
array(
127
'class' => $class.' n',
128
));
129
$cells[] = $no_copy;
130
$cells[] = phutil_tag('td', array('class' => $class), $render);
131
$cells[] = $no_coverage;
132
} else {
133
if ($p['htype']) {
134
if ($p['htype'] === '\\') {
135
$class = 'comment';
136
} else if (empty($p['oline'])) {
137
$class = 'right new new-full';
138
} else {
139
$class = 'right new';
140
}
141
$cells[] = phutil_tag(
142
'td',
143
array(
144
'class' => $class.' n',
145
));
146
$aural = $aural_plus;
147
} else {
148
$class = 'right';
149
if ($left_prefix) {
150
$left_id = $left_prefix.$p['oline'];
151
} else {
152
$left_id = null;
153
}
154
155
$oline = $p['oline'];
156
157
$cells[] = phutil_tag(
158
'td',
159
array(
160
'id' => $left_id,
161
'class' => 'n',
162
'data-n' => $oline,
163
));
164
$aural = null;
165
}
166
167
if ($type == 'new-file') {
168
$class = "{$class} differential-new-image";
169
}
170
171
if ($right_prefix) {
172
$right_id = $right_prefix.$p['line'];
173
} else {
174
$right_id = null;
175
}
176
177
$line = $p['line'];
178
179
$cells[] = phutil_tag(
180
'td',
181
array(
182
'id' => $right_id,
183
'class' => $class.' n',
184
'data-n' => $line,
185
));
186
187
$render = $p['render'];
188
if ($aural !== null) {
189
$render = array($aural, $render);
190
}
191
192
$cells[] = $no_copy;
193
194
$cells[] = phutil_tag(
195
'td',
196
array(
197
'class' => $class,
198
'data-copy-mode' => 'copy-unified',
199
),
200
$render);
201
202
$cells[] = $no_coverage;
203
}
204
205
// In simple mode, only render the text. This is used to render
206
// "Edit Suggestions" in inline comments.
207
if ($is_simple) {
208
$cells = array($cells[3]);
209
}
210
211
$out[] = phutil_tag('tr', array(), $cells);
212
213
break;
214
case 'inline':
215
$inline = $this->buildInlineComment(
216
$p['comment'],
217
$p['right']);
218
$out[] = $this->getRowScaffoldForInline($inline);
219
break;
220
case 'no-context':
221
$out[] = phutil_tag(
222
'tr',
223
array(),
224
phutil_tag(
225
'td',
226
array(
227
'class' => 'show-more',
228
'colspan' => $column_width,
229
),
230
pht('Context not available.')));
231
break;
232
case 'context':
233
$top = $p['top'];
234
$len = $p['len'];
235
236
$links = $this->renderShowContextLinks($top, $len, $rows);
237
238
$out[] = javelin_tag(
239
'tr',
240
array(
241
'sigil' => 'context-target',
242
),
243
phutil_tag(
244
'td',
245
array(
246
'class' => 'show-more',
247
'colspan' => $column_width,
248
),
249
$links));
250
break;
251
default:
252
$out[] = hsprintf('<tr><th /><th /><td>%s</td></tr>', $type);
253
break;
254
}
255
}
256
257
$result = null;
258
259
if ($out) {
260
if ($is_simple) {
261
$result = $this->newSimpleTable($out);
262
} else {
263
$result = $this->wrapChangeInTable(phutil_implode_html('', $out));
264
}
265
}
266
267
return $result;
268
}
269
270
public function renderDocumentEngineBlocks(
271
PhabricatorDocumentEngineBlocks $block_list,
272
$old_changeset_key,
273
$new_changeset_key) {
274
275
$engine = $this->getDocumentEngine();
276
$layout = $block_list->newTwoUpLayout();
277
278
$old_comments = $this->getOldComments();
279
$new_comments = $this->getNewComments();
280
281
$unchanged = array();
282
foreach ($layout as $key => $row) {
283
list($old, $new) = $row;
284
285
if (!$old) {
286
continue;
287
}
288
289
if (!$new) {
290
continue;
291
}
292
293
if ($old->getDifferenceType() !== null) {
294
continue;
295
}
296
297
if ($new->getDifferenceType() !== null) {
298
continue;
299
}
300
301
$unchanged[$key] = true;
302
}
303
304
$rows = array();
305
$count = count($layout);
306
for ($ii = 0; $ii < $count;) {
307
$start = $ii;
308
309
for ($jj = $ii; $jj < $count; $jj++) {
310
list($old, $new) = $layout[$jj];
311
312
if (empty($unchanged[$jj])) {
313
break;
314
}
315
316
$rows[] = array(
317
'type' => 'unchanged',
318
'layoutKey' => $jj,
319
);
320
}
321
$ii = $jj;
322
323
for ($jj = $ii; $jj < $count; $jj++) {
324
list($old, $new) = $layout[$jj];
325
326
if (!empty($unchanged[$jj])) {
327
break;
328
}
329
330
$rows[] = array(
331
'type' => 'old',
332
'layoutKey' => $jj,
333
);
334
}
335
336
for ($jj = $ii; $jj < $count; $jj++) {
337
list($old, $new) = $layout[$jj];
338
339
if (!empty($unchanged[$jj])) {
340
break;
341
}
342
343
$rows[] = array(
344
'type' => 'new',
345
'layoutKey' => $jj,
346
);
347
}
348
$ii = $jj;
349
350
// We always expect to consume at least one row when iterating through
351
// the loop and make progress. If we don't, bail out to avoid spinning
352
// to death.
353
if ($ii === $start) {
354
throw new Exception(
355
pht(
356
'Failed to make progress during 1up diff layout.'));
357
}
358
}
359
360
$old_ref = null;
361
$new_ref = null;
362
$refs = $block_list->getDocumentRefs();
363
if ($refs) {
364
list($old_ref, $new_ref) = $refs;
365
}
366
367
$view = array();
368
foreach ($rows as $row) {
369
$row_type = $row['type'];
370
$layout_key = $row['layoutKey'];
371
$row_layout = $layout[$layout_key];
372
list($old, $new) = $row_layout;
373
374
if ($old) {
375
$old_key = $old->getBlockKey();
376
} else {
377
$old_key = null;
378
}
379
380
if ($new) {
381
$new_key = $new->getBlockKey();
382
} else {
383
$new_key = null;
384
}
385
386
$cells = array();
387
$cell_classes = array();
388
389
if ($row_type === 'unchanged') {
390
$cell_content = $engine->newBlockContentView(
391
$old_ref,
392
$old);
393
} else if ($old && $new) {
394
$block_diff = $engine->newBlockDiffViews(
395
$old_ref,
396
$old,
397
$new_ref,
398
$new);
399
400
// TODO: We're currently double-rendering this: once when building
401
// the old row, and once when building the new one. In both cases,
402
// we throw away the other half of the output. We could cache this
403
// to improve performance.
404
405
if ($row_type === 'old') {
406
$cell_content = $block_diff->getOldContent();
407
$cell_classes = $block_diff->getOldClasses();
408
} else {
409
$cell_content = $block_diff->getNewContent();
410
$cell_classes = $block_diff->getNewClasses();
411
}
412
} else if ($row_type === 'old') {
413
if (!$old_ref || !$old) {
414
continue;
415
}
416
417
$cell_content = $engine->newBlockContentView(
418
$old_ref,
419
$old);
420
421
$cell_classes[] = 'old';
422
$cell_classes[] = 'old-full';
423
424
$new_key = null;
425
} else if ($row_type === 'new') {
426
if (!$new_ref || !$new) {
427
continue;
428
}
429
430
$cell_content = $engine->newBlockContentView(
431
$new_ref,
432
$new);
433
434
$cell_classes[] = 'new';
435
$cell_classes[] = 'new-full';
436
437
$old_key = null;
438
}
439
440
if ($old_key === null) {
441
$old_id = null;
442
} else {
443
$old_id = "C{$old_changeset_key}OL{$old_key}";
444
}
445
446
if ($new_key === null) {
447
$new_id = null;
448
} else {
449
$new_id = "C{$new_changeset_key}NL{$new_key}";
450
}
451
452
$cells[] = phutil_tag(
453
'td',
454
array(
455
'id' => $old_id,
456
'data-n' => $old_key,
457
'class' => 'n',
458
));
459
460
$cells[] = phutil_tag(
461
'td',
462
array(
463
'id' => $new_id,
464
'data-n' => $new_key,
465
'class' => 'n',
466
));
467
468
$cells[] = phutil_tag(
469
'td',
470
array(
471
'class' => 'copy',
472
));
473
474
$cell_classes[] = 'diff-flush';
475
$cell_classes = implode(' ', $cell_classes);
476
477
$cells[] = phutil_tag(
478
'td',
479
array(
480
'class' => $cell_classes,
481
'data-copy-mode' => 'copy-unified',
482
),
483
$cell_content);
484
485
$view[] = phutil_tag(
486
'tr',
487
array(),
488
$cells);
489
490
if ($old_key !== null) {
491
$old_inlines = idx($old_comments, $old_key, array());
492
foreach ($old_inlines as $inline) {
493
$inline = $this->buildInlineComment(
494
$inline,
495
$on_right = false);
496
$view[] = $this->getRowScaffoldForInline($inline);
497
}
498
}
499
500
if ($new_key !== null) {
501
$new_inlines = idx($new_comments, $new_key, array());
502
foreach ($new_inlines as $inline) {
503
$inline = $this->buildInlineComment(
504
$inline,
505
$on_right = true);
506
$view[] = $this->getRowScaffoldForInline($inline);
507
}
508
}
509
}
510
511
$output = $this->wrapChangeInTable($view);
512
return $this->renderChangesetTable($output);
513
}
514
515
public function getRowScaffoldForInline(PHUIDiffInlineCommentView $view) {
516
return id(new PHUIDiffOneUpInlineCommentRowScaffold())
517
->addInlineView($view);
518
}
519
520
521
private function newSimpleTable($content) {
522
return phutil_tag(
523
'table',
524
array(
525
'class' => 'diff-1up-simple-table',
526
),
527
$content);
528
}
529
530
}
531
532