[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/differential/view/ -> DifferentialDiffTableOfContentsView.php (source)

   1  <?php
   2  
   3  final class DifferentialDiffTableOfContentsView extends AphrontView {
   4  
   5    private $changesets = array();
   6    private $visibleChangesets = array();
   7    private $references = array();
   8    private $repository;
   9    private $diff;
  10    private $renderURI = '/differential/changeset/';
  11    private $revisionID;
  12    private $whitespace;
  13    private $unitTestData;
  14  
  15    public function setChangesets($changesets) {
  16      $this->changesets = $changesets;
  17      return $this;
  18    }
  19  
  20    public function setVisibleChangesets($visible_changesets) {
  21      $this->visibleChangesets = $visible_changesets;
  22      return $this;
  23    }
  24  
  25    public function setRenderingReferences(array $references) {
  26      $this->references = $references;
  27      return $this;
  28    }
  29  
  30    public function setRepository(PhabricatorRepository $repository) {
  31      $this->repository = $repository;
  32      return $this;
  33    }
  34  
  35    public function setDiff(DifferentialDiff $diff) {
  36      $this->diff = $diff;
  37      return $this;
  38    }
  39  
  40    public function setUnitTestData($unit_test_data) {
  41      $this->unitTestData = $unit_test_data;
  42      return $this;
  43    }
  44  
  45    public function setRevisionID($revision_id) {
  46      $this->revisionID = $revision_id;
  47      return $this;
  48    }
  49  
  50    public function setWhitespace($whitespace) {
  51      $this->whitespace = $whitespace;
  52      return $this;
  53    }
  54  
  55    public function render() {
  56  
  57      $this->requireResource('differential-core-view-css');
  58      $this->requireResource('differential-table-of-contents-css');
  59  
  60      $rows = array();
  61  
  62      $coverage = array();
  63      if ($this->unitTestData) {
  64        $coverage_by_file = array();
  65        foreach ($this->unitTestData as $result) {
  66          $test_coverage = idx($result, 'coverage');
  67          if (!$test_coverage) {
  68            continue;
  69          }
  70          foreach ($test_coverage as $file => $results) {
  71            $coverage_by_file[$file][] = $results;
  72          }
  73        }
  74        foreach ($coverage_by_file as $file => $coverages) {
  75          $coverage[$file] = ArcanistUnitTestResult::mergeCoverage($coverages);
  76        }
  77      }
  78  
  79      $changesets = $this->changesets;
  80      $paths = array();
  81      foreach ($changesets as $id => $changeset) {
  82        $type = $changeset->getChangeType();
  83        $ftype = $changeset->getFileType();
  84        $ref = idx($this->references, $id);
  85        $display_file = $changeset->getDisplayFilename();
  86  
  87        $meta = null;
  88        if (DifferentialChangeType::isOldLocationChangeType($type)) {
  89          $away = $changeset->getAwayPaths();
  90          if (count($away) > 1) {
  91            $meta = array();
  92            if ($type == DifferentialChangeType::TYPE_MULTICOPY) {
  93              $meta[] = pht('Deleted after being copied to multiple locations:');
  94            } else {
  95              $meta[] = pht('Copied to multiple locations:');
  96            }
  97            foreach ($away as $path) {
  98              $meta[] = $path;
  99            }
 100            $meta = phutil_implode_html(phutil_tag('br'), $meta);
 101          } else {
 102            if ($type == DifferentialChangeType::TYPE_MOVE_AWAY) {
 103              $display_file = $this->renderRename(
 104                $display_file,
 105                reset($away),
 106                "\xE2\x86\x92");
 107            } else {
 108              $meta = pht('Copied to %s', reset($away));
 109            }
 110          }
 111        } else if ($type == DifferentialChangeType::TYPE_MOVE_HERE) {
 112          $old_file = $changeset->getOldFile();
 113          $display_file = $this->renderRename(
 114            $display_file,
 115            $old_file,
 116            "\xE2\x86\x90");
 117        } else if ($type == DifferentialChangeType::TYPE_COPY_HERE) {
 118          $meta = pht('Copied from %s', $changeset->getOldFile());
 119        }
 120  
 121        $link = $this->renderChangesetLink($changeset, $ref, $display_file);
 122  
 123        $line_count = $changeset->getAffectedLineCount();
 124        if ($line_count == 0) {
 125          $lines = '';
 126        } else {
 127          $lines = ' '.pht('(%d line(s))', $line_count);
 128        }
 129  
 130        $char = DifferentialChangeType::getSummaryCharacterForChangeType($type);
 131        $chartitle = DifferentialChangeType::getFullNameForChangeType($type);
 132        $desc = DifferentialChangeType::getShortNameForFileType($ftype);
 133        if ($desc) {
 134          $desc = '('.$desc.')';
 135        }
 136        $pchar =
 137          ($changeset->getOldProperties() === $changeset->getNewProperties())
 138            ? ''
 139            : phutil_tag(
 140                'span',
 141                array('title' => pht('Properties Changed')),
 142                'M');
 143  
 144        $fname = $changeset->getFilename();
 145        $cov  = $this->renderCoverage($coverage, $fname);
 146        if ($cov === null) {
 147          $mcov = $cov = phutil_tag('em', array(), '-');
 148        } else {
 149          $mcov = phutil_tag(
 150            'div',
 151            array(
 152              'id' => 'differential-mcoverage-'.md5($fname),
 153              'class' => 'differential-mcoverage-loading',
 154            ),
 155            (isset($this->visibleChangesets[$id]) ?
 156              pht('Loading...') : pht('?')));
 157        }
 158  
 159        if ($meta) {
 160          $meta = phutil_tag(
 161            'div',
 162            array(
 163              'class' => 'differential-toc-meta',
 164            ),
 165            $meta);
 166        }
 167  
 168        if ($this->diff && $this->repository) {
 169          $paths[] =
 170            $changeset->getAbsoluteRepositoryPath($this->repository, $this->diff);
 171        }
 172  
 173        $rows[] = array(
 174          $char,
 175          $pchar,
 176          $desc,
 177          array($link, $lines, $meta),
 178          $cov,
 179          $mcov,
 180        );
 181      }
 182  
 183      $editor_link = null;
 184      if ($paths && $this->user) {
 185        $editor_link = $this->user->loadEditorLink(
 186          $paths,
 187          1, // line number
 188          $this->repository->getCallsign());
 189        if ($editor_link) {
 190          $editor_link =
 191            phutil_tag(
 192              'a',
 193              array(
 194                'href' => $editor_link,
 195                'class' => 'button differential-toc-edit-all',
 196              ),
 197              pht('Open All in Editor'));
 198        }
 199      }
 200  
 201      $reveal_link = javelin_tag(
 202          'a',
 203          array(
 204            'sigil' => 'differential-reveal-all',
 205            'mustcapture' => true,
 206            'class' => 'button differential-toc-reveal-all',
 207          ),
 208          pht('Show All Context'));
 209  
 210      $buttons = phutil_tag(
 211        'div',
 212        array(
 213          'class' => 'differential-toc-buttons grouped',
 214        ),
 215        array(
 216          $editor_link,
 217          $reveal_link,
 218        ));
 219  
 220      $table = id(new AphrontTableView($rows));
 221      $table->setHeaders(
 222        array(
 223          '',
 224          '',
 225          '',
 226          pht('Path'),
 227          pht('Coverage (All)'),
 228          pht('Coverage (Touched)'),
 229        ));
 230      $table->setColumnClasses(
 231        array(
 232          'differential-toc-char center',
 233          'differential-toc-prop center',
 234          'differential-toc-ftype center',
 235          'differential-toc-file wide',
 236          'differential-toc-cov',
 237          'differential-toc-cov',
 238        ));
 239      $table->setDeviceVisibility(
 240        array(
 241          true,
 242          true,
 243          true,
 244          true,
 245          false,
 246          false,
 247        ));
 248      $anchor = id(new PhabricatorAnchorView())
 249          ->setAnchorName('toc')
 250          ->setNavigationMarker(true);
 251  
 252      return id(new PHUIObjectBoxView())
 253        ->setHeaderText(pht('Table of Contents'))
 254        ->appendChild($anchor)
 255        ->appendChild($table)
 256        ->appendChild($buttons);
 257    }
 258  
 259    private function renderRename($display_file, $other_file, $arrow) {
 260      $old = explode('/', $display_file);
 261      $new = explode('/', $other_file);
 262  
 263      $start = count($old);
 264      foreach ($old as $index => $part) {
 265        if (!isset($new[$index]) || $part != $new[$index]) {
 266          $start = $index;
 267          break;
 268        }
 269      }
 270  
 271      $end = count($old);
 272      foreach (array_reverse($old) as $from_end => $part) {
 273        $index = count($new) - $from_end - 1;
 274        if (!isset($new[$index]) || $part != $new[$index]) {
 275          $end = $from_end;
 276          break;
 277        }
 278      }
 279  
 280      $rename =
 281        '{'.
 282        implode('/', array_slice($old, $start, count($old) - $end - $start)).
 283        ' '.$arrow.' '.
 284        implode('/', array_slice($new, $start, count($new) - $end - $start)).
 285        '}';
 286  
 287      array_splice($new, $start, count($new) - $end - $start, $rename);
 288      return implode('/', $new);
 289    }
 290  
 291    private function renderCoverage(array $coverage, $file) {
 292      $info = idx($coverage, $file);
 293      if (!$info) {
 294        return null;
 295      }
 296  
 297      $not_covered = substr_count($info, 'U');
 298      $covered     = substr_count($info, 'C');
 299  
 300      if (!$not_covered && !$covered) {
 301        return null;
 302      }
 303  
 304      return sprintf('%d%%', 100 * ($covered / ($covered + $not_covered)));
 305    }
 306  
 307  
 308    private function renderChangesetLink(
 309      DifferentialChangeset $changeset,
 310      $ref,
 311      $display_file) {
 312  
 313      return javelin_tag(
 314        'a',
 315        array(
 316          'href' => '#'.$changeset->getAnchorName(),
 317          'sigil' => 'differential-load',
 318          'meta' => array(
 319            'id' => 'diff-'.$changeset->getAnchorName(),
 320          ),
 321        ),
 322        $display_file);
 323    }
 324  
 325  }


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