[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class DifferentialChangesetTwoUpRenderer 4 extends DifferentialChangesetHTMLRenderer { 5 6 public function isOneUpRenderer() { 7 return false; 8 } 9 10 protected function renderColgroup() { 11 return phutil_tag('colgroup', array(), array( 12 phutil_tag('col', array('class' => 'num')), 13 phutil_tag('col', array('class' => 'left')), 14 phutil_tag('col', array('class' => 'num')), 15 phutil_tag('col', array('class' => 'copy')), 16 phutil_tag('col', array('class' => 'right')), 17 phutil_tag('col', array('class' => 'cov')), 18 )); 19 } 20 21 public function renderTextChange( 22 $range_start, 23 $range_len, 24 $rows) { 25 26 $hunk_starts = $this->getHunkStartLines(); 27 28 $context_not_available = null; 29 if ($hunk_starts) { 30 $context_not_available = javelin_tag( 31 'tr', 32 array( 33 'sigil' => 'context-target', 34 ), 35 phutil_tag( 36 'td', 37 array( 38 'colspan' => 6, 39 'class' => 'show-more', 40 ), 41 pht('Context not available.'))); 42 } 43 44 $html = array(); 45 46 $old_lines = $this->getOldLines(); 47 $new_lines = $this->getNewLines(); 48 $gaps = $this->getGaps(); 49 $reference = $this->getRenderingReference(); 50 $left_id = $this->getOldChangesetID(); 51 $right_id = $this->getNewChangesetID(); 52 53 // "N" stands for 'new' and means the comment should attach to the new file 54 // when stored, i.e. DifferentialInlineComment->setIsNewFile(). 55 // "O" stands for 'old' and means the comment should attach to the old file. 56 57 $left_char = $this->getOldAttachesToNewFile() 58 ? 'N' 59 : 'O'; 60 $right_char = $this->getNewAttachesToNewFile() 61 ? 'N' 62 : 'O'; 63 64 $changeset = $this->getChangeset(); 65 $copy_lines = idx($changeset->getMetadata(), 'copy:lines', array()); 66 $highlight_old = $this->getHighlightOld(); 67 $highlight_new = $this->getHighlightNew(); 68 $old_render = $this->getOldRender(); 69 $new_render = $this->getNewRender(); 70 $original_left = $this->getOriginalOld(); 71 $original_right = $this->getOriginalNew(); 72 $depths = $this->getDepths(); 73 $mask = $this->getMask(); 74 75 for ($ii = $range_start; $ii < $range_start + $range_len; $ii++) { 76 if (empty($mask[$ii])) { 77 // If we aren't going to show this line, we've just entered a gap. 78 // Pop information about the next gap off the $gaps stack and render 79 // an appropriate "Show more context" element. This branch eventually 80 // increments $ii by the entire size of the gap and then continues 81 // the loop. 82 $gap = array_pop($gaps); 83 $top = $gap[0]; 84 $len = $gap[1]; 85 86 $end = $top + $len - 20; 87 88 $contents = array(); 89 90 if ($len > 40) { 91 $is_first_block = false; 92 if ($ii == 0) { 93 $is_first_block = true; 94 } 95 96 $contents[] = javelin_tag( 97 'a', 98 array( 99 'href' => '#', 100 'mustcapture' => true, 101 'sigil' => 'show-more', 102 'meta' => array( 103 'ref' => $reference, 104 'range' => "{$top}-{$len}/{$top}-20", 105 ), 106 ), 107 $is_first_block 108 ? pht('Show First 20 Lines') 109 : pht("\xE2\x96\xB2 Show 20 Lines")); 110 } 111 112 $contents[] = javelin_tag( 113 'a', 114 array( 115 'href' => '#', 116 'mustcapture' => true, 117 'sigil' => 'show-more', 118 'meta' => array( 119 'type' => 'all', 120 'ref' => $reference, 121 'range' => "{$top}-{$len}/{$top}-{$len}", 122 ), 123 ), 124 pht('Show All %d Lines', $len)); 125 126 $is_last_block = false; 127 if ($ii + $len >= $rows) { 128 $is_last_block = true; 129 } 130 131 if ($len > 40) { 132 $contents[] = javelin_tag( 133 'a', 134 array( 135 'href' => '#', 136 'mustcapture' => true, 137 'sigil' => 'show-more', 138 'meta' => array( 139 'ref' => $reference, 140 'range' => "{$top}-{$len}/{$end}-20", 141 ), 142 ), 143 $is_last_block 144 ? pht('Show Last 20 Lines') 145 : pht("\xE2\x96\xBC Show 20 Lines")); 146 } 147 148 $context = null; 149 $context_line = null; 150 if (!$is_last_block && $depths[$ii + $len]) { 151 for ($l = $ii + $len - 1; $l >= $ii; $l--) { 152 $line = $new_lines[$l]['text']; 153 if ($depths[$l] < $depths[$ii + $len] && trim($line) != '') { 154 $context = $new_render[$l]; 155 $context_line = $new_lines[$l]['line']; 156 break; 157 } 158 } 159 } 160 161 $container = javelin_tag( 162 'tr', 163 array( 164 'sigil' => 'context-target', 165 ), 166 array( 167 phutil_tag( 168 'td', 169 array( 170 'colspan' => 2, 171 'class' => 'show-more', 172 ), 173 phutil_implode_html( 174 " \xE2\x80\xA2 ", // Bullet 175 $contents)), 176 phutil_tag( 177 'th', 178 array( 179 'class' => 'show-context-line', 180 ), 181 $context_line ? (int)$context_line : null), 182 phutil_tag( 183 'td', 184 array( 185 'colspan' => 3, 186 'class' => 'show-context', 187 ), 188 // TODO: [HTML] Escaping model here isn't ideal. 189 phutil_safe_html($context)), 190 )); 191 192 $html[] = $container; 193 194 $ii += ($len - 1); 195 continue; 196 } 197 198 $o_num = null; 199 $o_classes = ''; 200 $o_text = null; 201 if (isset($old_lines[$ii])) { 202 $o_num = $old_lines[$ii]['line']; 203 $o_text = isset($old_render[$ii]) ? $old_render[$ii] : null; 204 if ($old_lines[$ii]['type']) { 205 if ($old_lines[$ii]['type'] == '\\') { 206 $o_text = $old_lines[$ii]['text']; 207 $o_class = 'comment'; 208 } else if ($original_left && !isset($highlight_old[$o_num])) { 209 $o_class = 'old-rebase'; 210 } else if (empty($new_lines[$ii])) { 211 $o_class = 'old old-full'; 212 } else { 213 $o_class = 'old'; 214 } 215 $o_classes = $o_class; 216 } 217 } 218 219 $n_copy = hsprintf('<td class="copy" />'); 220 $n_cov = null; 221 $n_colspan = 2; 222 $n_classes = ''; 223 $n_num = null; 224 $n_text = null; 225 226 if (isset($new_lines[$ii])) { 227 $n_num = $new_lines[$ii]['line']; 228 $n_text = isset($new_render[$ii]) ? $new_render[$ii] : null; 229 $coverage = $this->getCodeCoverage(); 230 231 if ($coverage !== null) { 232 if (empty($coverage[$n_num - 1])) { 233 $cov_class = 'N'; 234 } else { 235 $cov_class = $coverage[$n_num - 1]; 236 } 237 $cov_class = 'cov-'.$cov_class; 238 $n_cov = phutil_tag('td', array('class' => "cov {$cov_class}")); 239 $n_colspan--; 240 } 241 242 if ($new_lines[$ii]['type']) { 243 if ($new_lines[$ii]['type'] == '\\') { 244 $n_text = $new_lines[$ii]['text']; 245 $n_class = 'comment'; 246 } else if ($original_right && !isset($highlight_new[$n_num])) { 247 $n_class = 'new-rebase'; 248 } else if (empty($old_lines[$ii])) { 249 $n_class = 'new new-full'; 250 } else { 251 $n_class = 'new'; 252 } 253 $n_classes = $n_class; 254 255 if ($new_lines[$ii]['type'] == '\\' || !isset($copy_lines[$n_num])) { 256 $n_copy = phutil_tag('td', array('class' => "copy {$n_class}")); 257 } else { 258 list($orig_file, $orig_line, $orig_type) = $copy_lines[$n_num]; 259 $title = ($orig_type == '-' ? 'Moved' : 'Copied').' from '; 260 if ($orig_file == '') { 261 $title .= "line {$orig_line}"; 262 } else { 263 $title .= 264 basename($orig_file). 265 ":{$orig_line} in dir ". 266 dirname('/'.$orig_file); 267 } 268 $class = ($orig_type == '-' ? 'new-move' : 'new-copy'); 269 $n_copy = javelin_tag( 270 'td', 271 array( 272 'meta' => array( 273 'msg' => $title, 274 ), 275 'class' => 'copy '.$class, 276 ), 277 ''); 278 } 279 } 280 } 281 282 if (isset($hunk_starts[$o_num])) { 283 $html[] = $context_not_available; 284 } 285 286 if ($o_num && $left_id) { 287 $o_id = 'C'.$left_id.$left_char.'L'.$o_num; 288 } else { 289 $o_id = null; 290 } 291 292 if ($n_num && $right_id) { 293 $n_id = 'C'.$right_id.$right_char.'L'.$n_num; 294 } else { 295 $n_id = null; 296 } 297 298 // NOTE: This is a unicode zero-width space, which we use as a hint when 299 // intercepting 'copy' events to make sure sensible text ends up on the 300 // clipboard. See the 'phabricator-oncopy' behavior. 301 $zero_space = "\xE2\x80\x8B"; 302 303 // NOTE: The Javascript is sensitive to whitespace changes in this 304 // block! 305 306 $html[] = phutil_tag('tr', array(), array( 307 phutil_tag('th', array('id' => $o_id), $o_num), 308 phutil_tag('td', array('class' => $o_classes), $o_text), 309 phutil_tag('th', array('id' => $n_id), $n_num), 310 $n_copy, 311 phutil_tag( 312 'td', 313 array('class' => $n_classes, 'colspan' => $n_colspan), 314 array( 315 phutil_tag('span', array('class' => 'zwsp'), $zero_space), 316 $n_text, 317 )), 318 $n_cov, 319 )); 320 321 if ($context_not_available && ($ii == $rows - 1)) { 322 $html[] = $context_not_available; 323 } 324 325 $old_comments = $this->getOldComments(); 326 $new_comments = $this->getNewComments(); 327 328 if ($o_num && isset($old_comments[$o_num])) { 329 foreach ($old_comments[$o_num] as $comment) { 330 $comment_html = $this->renderInlineComment($comment, 331 $on_right = false); 332 $new = ''; 333 if ($n_num && isset($new_comments[$n_num])) { 334 foreach ($new_comments[$n_num] as $key => $new_comment) { 335 if ($comment->isCompatible($new_comment)) { 336 $new = $this->renderInlineComment($new_comment, 337 $on_right = true); 338 unset($new_comments[$n_num][$key]); 339 } 340 } 341 } 342 $html[] = phutil_tag('tr', array('class' => 'inline'), array( 343 phutil_tag('th', array()), 344 phutil_tag('td', array(), $comment_html), 345 phutil_tag('th', array()), 346 phutil_tag('td', array('colspan' => 3), $new), 347 )); 348 } 349 } 350 if ($n_num && isset($new_comments[$n_num])) { 351 foreach ($new_comments[$n_num] as $comment) { 352 $comment_html = $this->renderInlineComment($comment, 353 $on_right = true); 354 $html[] = phutil_tag('tr', array('class' => 'inline'), array( 355 phutil_tag('th', array()), 356 phutil_tag('td', array()), 357 phutil_tag('th', array()), 358 phutil_tag( 359 'td', 360 array('colspan' => 3), 361 $comment_html), 362 )); 363 } 364 } 365 } 366 367 return $this->wrapChangeInTable(phutil_implode_html('', $html)); 368 } 369 370 public function renderFileChange($old_file = null, 371 $new_file = null, 372 $id = 0, 373 $vs = 0) { 374 $old = null; 375 if ($old_file) { 376 $old = phutil_tag( 377 'div', 378 array( 379 'class' => 'differential-image-stage', 380 ), 381 phutil_tag( 382 'img', 383 array( 384 'src' => $old_file->getBestURI(), 385 ))); 386 } 387 388 $new = null; 389 if ($new_file) { 390 $new = phutil_tag( 391 'div', 392 array( 393 'class' => 'differential-image-stage', 394 ), 395 phutil_tag( 396 'img', 397 array( 398 'src' => $new_file->getBestURI(), 399 ))); 400 } 401 402 $html_old = array(); 403 $html_new = array(); 404 foreach ($this->getOldComments() as $on_line => $comment_group) { 405 foreach ($comment_group as $comment) { 406 $comment_html = $this->renderInlineComment($comment, $on_right = false); 407 $html_old[] = phutil_tag('tr', array('class' => 'inline'), array( 408 phutil_tag('th', array()), 409 phutil_tag('td', array(), $comment_html), 410 phutil_tag('th', array()), 411 phutil_tag('td', array('colspan' => 3)), 412 )); 413 } 414 } 415 foreach ($this->getNewComments() as $lin_line => $comment_group) { 416 foreach ($comment_group as $comment) { 417 $comment_html = $this->renderInlineComment($comment, $on_right = true); 418 $html_new[] = phutil_tag('tr', array('class' => 'inline'), array( 419 phutil_tag('th', array()), 420 phutil_tag('td', array()), 421 phutil_tag('th', array()), 422 phutil_tag( 423 'td', 424 array('colspan' => 3), 425 $comment_html), 426 )); 427 } 428 } 429 430 if (!$old) { 431 $th_old = phutil_tag('th', array()); 432 } else { 433 $th_old = phutil_tag('th', array('id' => "C{$vs}OL1"), 1); 434 } 435 436 if (!$new) { 437 $th_new = phutil_tag('th', array()); 438 } else { 439 $th_new = phutil_tag('th', array('id' => "C{$id}OL1"), 1); 440 } 441 442 $output = hsprintf( 443 '<tr class="differential-image-diff">'. 444 '%s'. 445 '<td class="differential-old-image">%s</td>'. 446 '%s'. 447 '<td class="differential-new-image" colspan="3">%s</td>'. 448 '</tr>'. 449 '%s'. 450 '%s', 451 $th_old, 452 $old, 453 $th_new, 454 $new, 455 phutil_implode_html('', $html_old), 456 phutil_implode_html('', $html_new)); 457 458 $output = $this->wrapChangeInTable($output); 459 460 return $this->renderChangesetTable($output); 461 } 462 463 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |