Generate file attachment transactions for explicit Remarkup attachments on common...
[phabricator.git] / src / applications / differential / view / DifferentialChangesetDetailView.php
blob9d04d081ac821f7e6d9dc4b3bea2f81c78b1e8cc
1 <?php
3 final class DifferentialChangesetDetailView extends AphrontView {
5 private $changeset;
6 private $buttons = array();
7 private $editable;
8 private $symbolIndex;
9 private $id;
10 private $vsChangesetID;
11 private $renderURI;
12 private $renderingRef;
13 private $autoload;
14 private $repository;
15 private $diff;
16 private $changesetResponse;
17 private $branch;
19 public function setAutoload($autoload) {
20 $this->autoload = $autoload;
21 return $this;
24 public function getAutoload() {
25 return $this->autoload;
28 public function setRenderingRef($rendering_ref) {
29 $this->renderingRef = $rendering_ref;
30 return $this;
33 public function getRenderingRef() {
34 return $this->renderingRef;
37 public function setChangesetResponse(PhabricatorChangesetResponse $response) {
38 $this->changesetResponse = $response;
39 return $this;
42 public function getChangesetResponse() {
43 return $this->changesetResponse;
46 public function setRenderURI($render_uri) {
47 $this->renderURI = $render_uri;
48 return $this;
51 public function getRenderURI() {
52 return $this->renderURI;
55 public function setChangeset($changeset) {
56 $this->changeset = $changeset;
57 return $this;
60 public function addButton($button) {
61 $this->buttons[] = $button;
62 return $this;
65 public function setEditable($editable) {
66 $this->editable = $editable;
67 return $this;
70 public function setSymbolIndex($symbol_index) {
71 $this->symbolIndex = $symbol_index;
72 return $this;
75 public function setBranch($branch) {
76 $this->branch = $branch;
77 return $this;
80 public function getBranch() {
81 return $this->branch;
84 public function getID() {
85 if (!$this->id) {
86 $this->id = celerity_generate_unique_node_id();
88 return $this->id;
91 public function setID($id) {
92 $this->id = $id;
93 return $this;
96 public function setVsChangesetID($vs_changeset_id) {
97 $this->vsChangesetID = $vs_changeset_id;
98 return $this;
101 public function getVsChangesetID() {
102 return $this->vsChangesetID;
105 public function render() {
106 $viewer = $this->getViewer();
108 $this->requireResource('differential-changeset-view-css');
109 $this->requireResource('syntax-highlighting-css');
111 Javelin::initBehavior('phabricator-oncopy', array());
113 $changeset = $this->changeset;
114 $class = 'differential-changeset';
115 if (!$this->editable) {
116 $class .= ' differential-changeset-immutable';
119 $buttons = null;
120 if ($this->buttons) {
121 $buttons = phutil_tag(
122 'div',
123 array(
124 'class' => 'differential-changeset-buttons',
126 $this->buttons);
129 $id = $this->getID();
131 if ($this->symbolIndex) {
132 Javelin::initBehavior(
133 'repository-crossreference',
134 array(
135 'container' => $id,
136 ) + $this->symbolIndex);
139 $display_filename = $changeset->getDisplayFilename();
140 $display_icon = FileTypeIcon::getFileIcon($display_filename);
141 $icon = id(new PHUIIconView())
142 ->setIcon($display_icon);
144 $changeset_id = $this->changeset->getID();
146 $vs_id = $this->getVsChangesetID();
147 if (!$vs_id) {
148 // Showing a changeset normally.
149 $left_id = $changeset_id;
150 $right_id = $changeset_id;
151 } else if ($vs_id == -1) {
152 // Showing a synthetic "deleted" changeset for a file which was
153 // removed between changes.
154 $left_id = $changeset_id;
155 $right_id = null;
156 } else {
157 // Showing a diff-of-diffs.
158 $left_id = $vs_id;
159 $right_id = $changeset_id;
162 // In the persistent banner, emphasize the current filename.
163 $path_part = dirname($display_filename);
164 $file_part = basename($display_filename);
165 $display_parts = array();
166 if (strlen($path_part)) {
167 $path_part = $path_part.'/';
168 $display_parts[] = phutil_tag(
169 'span',
170 array(
171 'class' => 'diff-banner-path',
173 $path_part);
175 $display_parts[] = phutil_tag(
176 'span',
177 array(
178 'class' => 'diff-banner-file',
180 $file_part);
182 $response = $this->getChangesetResponse();
183 if ($response) {
184 $is_loaded = true;
185 $changeset_markup = $response->getRenderedChangeset();
186 $changeset_state = $response->getChangesetState();
187 } else {
188 $is_loaded = false;
189 $changeset_markup = null;
190 $changeset_state = null;
193 $path_parts = trim($display_filename, '/');
194 $path_parts = explode('/', $path_parts);
196 $show_path_uri = null;
197 $show_directory_uri = null;
199 $repository = $this->getRepository();
200 if ($repository) {
201 $diff = $this->getDiff();
202 if ($diff) {
203 $repo_path = $changeset->getAbsoluteRepositoryPath($repository, $diff);
205 $repo_dir = dirname($repo_path);
206 if ($repo_dir === $repo_path) {
207 $repo_dir = null;
210 $show_path_uri = $repository->getDiffusionBrowseURIForPath(
211 $viewer,
212 $repo_path,
213 idx($changeset->getMetadata(), 'line:first'),
214 $this->getBranch());
216 if ($repo_dir !== null) {
217 $repo_dir = rtrim($repo_dir, '/').'/';
219 $show_directory_uri = $repository->getDiffusionBrowseURIForPath(
220 $viewer,
221 $repo_dir,
222 null,
223 $this->getBranch());
228 if ($show_path_uri) {
229 $show_path_uri = phutil_string_cast($show_path_uri);
232 if ($show_directory_uri) {
233 $show_directory_uri = phutil_string_cast($show_directory_uri);
236 return javelin_tag(
237 'div',
238 array(
239 'sigil' => 'differential-changeset',
240 'meta' => array(
241 'left' => $left_id,
242 'right' => $right_id,
243 'renderURI' => $this->getRenderURI(),
244 'ref' => $this->getRenderingRef(),
245 'autoload' => $this->getAutoload(),
246 'displayPath' => hsprintf('%s', $display_parts),
247 'icon' => $display_icon,
248 'pathParts' => $path_parts,
249 'symbolPath' => $display_filename,
251 'pathIconIcon' => $changeset->getPathIconIcon(),
252 'pathIconColor' => $changeset->getPathIconColor(),
253 'isLowImportance' => $changeset->getIsLowImportanceChangeset(),
254 'isOwned' => $changeset->getIsOwnedChangeset(),
256 'editorURITemplate' => $this->getEditorURITemplate(),
257 'editorConfigureURI' => $this->getEditorConfigureURI(),
259 'loaded' => $is_loaded,
260 'changesetState' => $changeset_state,
262 'showPathURI' => $show_path_uri,
263 'showDirectoryURI' => $show_directory_uri,
265 'class' => $class,
266 'id' => $id,
268 array(
269 id(new PhabricatorAnchorView())
270 ->setAnchorName($changeset->getAnchorName())
271 ->setNavigationMarker(true)
272 ->render(),
273 $buttons,
274 javelin_tag(
275 'h1',
276 array(
277 'class' => 'differential-file-icon-header',
278 'sigil' => 'changeset-header',
280 array(
281 $icon,
282 javelin_tag(
283 'span',
284 array(
285 'class' => 'differential-changeset-path-name',
286 'sigil' => 'changeset-header-path-name',
288 $display_filename),
290 javelin_tag(
291 'div',
292 array(
293 'class' => 'changeset-view-content',
294 'sigil' => 'changeset-view-content',
296 array(
297 $changeset_markup,
298 $this->renderChildren(),
303 public function setRepository(PhabricatorRepository $repository) {
304 $this->repository = $repository;
305 return $this;
308 public function getRepository() {
309 return $this->repository;
312 public function getChangeset() {
313 return $this->changeset;
316 public function setDiff(DifferentialDiff $diff) {
317 $this->diff = $diff;
318 return $this;
321 public function getDiff() {
322 return $this->diff;
325 private function getEditorURITemplate() {
326 $repository = $this->getRepository();
327 if (!$repository) {
328 return null;
331 $viewer = $this->getViewer();
333 $link_engine = PhabricatorEditorURIEngine::newForViewer($viewer);
334 if (!$link_engine) {
335 return null;
338 $link_engine->setRepository($repository);
340 $changeset = $this->getChangeset();
341 $diff = $this->getDiff();
343 $path = $changeset->getAbsoluteRepositoryPath($repository, $diff);
344 $path = ltrim($path, '/');
346 return $link_engine->getURITokensForPath($path);
349 private function getEditorConfigureURI() {
350 $viewer = $this->getViewer();
352 if (!$viewer->isLoggedIn()) {
353 return null;
356 return '/settings/panel/editor/';