Generate file attachment transactions for explicit Remarkup attachments on common...
[phabricator.git] / src / applications / differential / view / DifferentialRevisionListView.php
blobab0abcc386ddc3e48dee8e50c27d89a75d0fe15e
1 <?php
3 /**
4 * Render a table of Differential revisions.
5 */
6 final class DifferentialRevisionListView extends AphrontView {
8 private $revisions = array();
9 private $header;
10 private $noDataString;
11 private $noBox;
12 private $background = null;
13 private $unlandedDependencies = array();
15 public function setUnlandedDependencies(array $unlanded_dependencies) {
16 $this->unlandedDependencies = $unlanded_dependencies;
17 return $this;
20 public function getUnlandedDependencies() {
21 return $this->unlandedDependencies;
24 public function setNoDataString($no_data_string) {
25 $this->noDataString = $no_data_string;
26 return $this;
29 public function setHeader($header) {
30 $this->header = $header;
31 return $this;
34 public function setRevisions(array $revisions) {
35 assert_instances_of($revisions, 'DifferentialRevision');
36 $this->revisions = $revisions;
37 return $this;
40 public function setNoBox($box) {
41 $this->noBox = $box;
42 return $this;
45 public function setBackground($background) {
46 $this->background = $background;
47 return $this;
50 public function render() {
51 $viewer = $this->getViewer();
53 $this->initBehavior('phabricator-tooltips', array());
54 $this->requireResource('aphront-tooltip-css');
56 $reviewer_limit = 7;
58 $reviewer_phids = array();
59 $reviewer_more = array();
60 $handle_phids = array();
61 foreach ($this->revisions as $key => $revision) {
62 $reviewers = $revision->getReviewers();
64 // Don't show reviewers who have resigned. The "Reviewers" constraint
65 // does not respect these reviewers and they largely don't count as
66 // reviewers.
67 foreach ($reviewers as $reviewer_key => $reviewer) {
68 if ($reviewer->isResigned()) {
69 unset($reviewers[$reviewer_key]);
73 if (count($reviewers) > $reviewer_limit) {
74 $reviewers = array_slice($reviewers, 0, $reviewer_limit);
75 $reviewer_more[$key] = true;
76 } else {
77 $reviewer_more[$key] = false;
80 $phids = mpull($reviewers, 'getReviewerPHID');
82 $reviewer_phids[$key] = $phids;
83 foreach ($phids as $phid) {
84 $handle_phids[$phid] = $phid;
87 $author_phid = $revision->getAuthorPHID();
88 $handle_phids[$author_phid] = $author_phid;
91 $handles = $viewer->loadHandles($handle_phids);
93 $list = new PHUIObjectItemListView();
94 foreach ($this->revisions as $key => $revision) {
95 $item = id(new PHUIObjectItemView())
96 ->setViewer($viewer);
98 $icons = array();
100 $phid = $revision->getPHID();
101 $flag = $revision->getFlag($viewer);
102 if ($flag) {
103 $flag_class = PhabricatorFlagColor::getCSSClass($flag->getColor());
104 $icons['flag'] = phutil_tag(
105 'div',
106 array(
107 'class' => 'phabricator-flag-icon '.$flag_class,
109 '');
112 $modified = $revision->getDateModified();
114 if (isset($icons['flag'])) {
115 $item->addHeadIcon($icons['flag']);
118 $item->setObjectName($revision->getMonogram());
119 $item->setHeader($revision->getTitle());
120 $item->setHref($revision->getURI());
122 $size = $this->renderRevisionSize($revision);
123 if ($size !== null) {
124 $item->addAttribute($size);
127 if ($revision->getHasDraft($viewer)) {
128 $draft = id(new PHUIIconView())
129 ->setIcon('fa-comment yellow')
130 ->addSigil('has-tooltip')
131 ->setMetadata(
132 array(
133 'tip' => pht('Unsubmitted Comments'),
135 $item->addAttribute($draft);
138 $author_handle = $handles[$revision->getAuthorPHID()];
139 $item->addByline(pht('Author: %s', $author_handle->renderLink()));
141 $unlanded = idx($this->unlandedDependencies, $phid);
142 if ($unlanded) {
143 $item->addAttribute(
144 array(
145 id(new PHUIIconView())->setIcon('fa-chain-broken', 'red'),
146 ' ',
147 pht('Open Dependencies'),
151 $more = null;
152 if ($reviewer_more[$key]) {
153 $more = pht(', ...');
154 } else {
155 $more = null;
158 if ($reviewer_phids[$key]) {
159 $item->addAttribute(
160 array(
161 pht('Reviewers:'),
162 ' ',
163 $viewer->renderHandleList($reviewer_phids[$key])
164 ->setAsInline(true),
165 $more,
167 } else {
168 $item->addAttribute(phutil_tag('em', array(), pht('No Reviewers')));
171 $item->setEpoch($revision->getDateModified());
173 if ($revision->isClosed()) {
174 $item->setDisabled(true);
177 $icon = $revision->getStatusIcon();
178 $color = $revision->getStatusIconColor();
180 $item->setStatusIcon(
181 "{$icon} {$color}",
182 $revision->getStatusDisplayName());
184 $list->addItem($item);
187 $list->setNoDataString($this->noDataString);
190 if ($this->header && !$this->noBox) {
191 $list->setFlush(true);
192 $list = id(new PHUIObjectBoxView())
193 ->setBackground($this->background)
194 ->setObjectList($list);
196 if ($this->header instanceof PHUIHeaderView) {
197 $list->setHeader($this->header);
198 } else {
199 $list->setHeaderText($this->header);
201 } else {
202 $list->setHeader($this->header);
205 return $list;
208 private function renderRevisionSize(DifferentialRevision $revision) {
209 if (!$revision->hasLineCounts()) {
210 return null;
213 $size = array();
215 $glyphs = $revision->getRevisionScaleGlyphs();
216 $plus_count = 0;
217 for ($ii = 0; $ii < 7; $ii++) {
218 $c = $glyphs[$ii];
220 switch ($c) {
221 case '+':
222 $size[] = id(new PHUIIconView())
223 ->setIcon('fa-plus');
224 $plus_count++;
225 break;
226 case '-':
227 $size[] = id(new PHUIIconView())
228 ->setIcon('fa-minus');
229 break;
230 default:
231 $size[] = id(new PHUIIconView())
232 ->setIcon('fa-square-o invisible');
233 break;
237 $n = $revision->getAddedLineCount() + $revision->getRemovedLineCount();
239 $classes = array();
240 $classes[] = 'differential-revision-size';
242 $tip = array();
243 $tip[] = pht('%s Lines', new PhutilNumber($n));
245 if ($plus_count <= 1) {
246 $classes[] = 'differential-revision-small';
247 $tip[] = pht('Smaller Change');
250 if ($plus_count >= 4) {
251 $classes[] = 'differential-revision-large';
252 $tip[] = pht('Larger Change');
255 $tip = phutil_implode_html(" \xC2\xB7 ", $tip);
257 return javelin_tag(
258 'span',
259 array(
260 'class' => implode(' ', $classes),
261 'sigil' => 'has-tooltip',
262 'meta' => array(
263 'tip' => $tip,
264 'align' => 'E',
265 'size' => 400,
268 $size);