[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/differential/render/ -> DifferentialChangesetTwoUpRenderer.php (source)

   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  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1