When a Paste has a useful alternative rendering in Files, provide a hint
[phabricator/blender.git] / src / applications / paste / controller / PhabricatorPasteViewController.php
blobb5736b784e3368b4e64e8e34674a2b7a612ccacc
1 <?php
3 final class PhabricatorPasteViewController extends PhabricatorPasteController {
5 public function shouldAllowPublic() {
6 return true;
9 public function handleRequest(AphrontRequest $request) {
10 $viewer = $request->getViewer();
11 $id = $request->getURIData('id');
13 $paste = id(new PhabricatorPasteQuery())
14 ->setViewer($viewer)
15 ->withIDs(array($id))
16 ->needContent(true)
17 ->needRawContent(true)
18 ->executeOne();
19 if (!$paste) {
20 return new Aphront404Response();
23 $lines = $request->getURILineRange('lines', 1000);
24 if ($lines) {
25 $map = range($lines[0], $lines[1]);
26 } else {
27 $map = array();
30 $header = $this->buildHeaderView($paste);
31 $curtain = $this->buildCurtain($paste);
33 $subheader = $this->buildSubheaderView($paste);
34 $source_code = $this->buildSourceCodeView($paste, $map);
36 require_celerity_resource('paste-css');
38 $monogram = $paste->getMonogram();
39 $crumbs = $this->buildApplicationCrumbs()
40 ->addTextCrumb($monogram)
41 ->setBorder(true);
43 $timeline = $this->buildTransactionTimeline(
44 $paste,
45 new PhabricatorPasteTransactionQuery());
47 $comment_view = id(new PhabricatorPasteEditEngine())
48 ->setViewer($viewer)
49 ->buildEditEngineCommentView($paste);
51 $timeline->setQuoteRef($monogram);
52 $comment_view->setTransactionTimeline($timeline);
54 $recommendation_view = $this->newDocumentRecommendationView($paste);
56 $paste_view = id(new PHUITwoColumnView())
57 ->setHeader($header)
58 ->setSubheader($subheader)
59 ->setMainColumn(
60 array(
61 $recommendation_view,
62 $source_code,
63 $timeline,
64 $comment_view,
66 ->setCurtain($curtain);
68 return $this->newPage()
69 ->setTitle($paste->getFullName())
70 ->setCrumbs($crumbs)
71 ->setPageObjectPHIDs(
72 array(
73 $paste->getPHID(),
75 ->appendChild($paste_view);
78 private function buildHeaderView(PhabricatorPaste $paste) {
79 $title = (nonempty($paste->getTitle())) ?
80 $paste->getTitle() : pht('(An Untitled Masterwork)');
82 if ($paste->isArchived()) {
83 $header_icon = 'fa-ban';
84 $header_name = pht('Archived');
85 $header_color = 'dark';
86 } else {
87 $header_icon = 'fa-check';
88 $header_name = pht('Active');
89 $header_color = 'bluegrey';
92 $header = id(new PHUIHeaderView())
93 ->setHeader($title)
94 ->setUser($this->getRequest()->getUser())
95 ->setStatus($header_icon, $header_color, $header_name)
96 ->setPolicyObject($paste)
97 ->setHeaderIcon('fa-clipboard');
99 return $header;
102 private function buildCurtain(PhabricatorPaste $paste) {
103 $viewer = $this->getViewer();
104 $curtain = $this->newCurtainView($paste);
106 $can_edit = PhabricatorPolicyFilter::hasCapability(
107 $viewer,
108 $paste,
109 PhabricatorPolicyCapability::CAN_EDIT);
111 $id = $paste->getID();
112 $edit_uri = $this->getApplicationURI("edit/{$id}/");
113 $archive_uri = $this->getApplicationURI("archive/{$id}/");
114 $raw_uri = $this->getApplicationURI("raw/{$id}/");
116 $curtain->addAction(
117 id(new PhabricatorActionView())
118 ->setName(pht('Edit Paste'))
119 ->setIcon('fa-pencil')
120 ->setDisabled(!$can_edit)
121 ->setHref($edit_uri));
123 if ($paste->isArchived()) {
124 $curtain->addAction(
125 id(new PhabricatorActionView())
126 ->setName(pht('Activate Paste'))
127 ->setIcon('fa-check')
128 ->setDisabled(!$can_edit)
129 ->setWorkflow($can_edit)
130 ->setHref($archive_uri));
131 } else {
132 $curtain->addAction(
133 id(new PhabricatorActionView())
134 ->setName(pht('Archive Paste'))
135 ->setIcon('fa-ban')
136 ->setDisabled(!$can_edit)
137 ->setWorkflow($can_edit)
138 ->setHref($archive_uri));
141 $curtain->addAction(
142 id(new PhabricatorActionView())
143 ->setName(pht('View Raw File'))
144 ->setIcon('fa-file-text-o')
145 ->setHref($raw_uri));
147 return $curtain;
151 private function buildSubheaderView(
152 PhabricatorPaste $paste) {
153 $viewer = $this->getViewer();
155 $author = $viewer->renderHandle($paste->getAuthorPHID())->render();
156 $date = phabricator_datetime($paste->getDateCreated(), $viewer);
157 $author = phutil_tag('strong', array(), $author);
159 $author_info = id(new PhabricatorPeopleQuery())
160 ->setViewer($viewer)
161 ->withPHIDs(array($paste->getAuthorPHID()))
162 ->needProfileImage(true)
163 ->executeOne();
165 $image_uri = $author_info->getProfileImageURI();
166 $image_href = '/p/'.$author_info->getUsername();
168 $content = pht('Authored by %s on %s.', $author, $date);
170 return id(new PHUIHeadThingView())
171 ->setImage($image_uri)
172 ->setImageHref($image_href)
173 ->setContent($content);
176 private function newDocumentRecommendationView(PhabricatorPaste $paste) {
177 $viewer = $this->getViewer();
179 // See PHI1703. If a viewer is looking at a document in Paste which has
180 // a good rendering via a DocumentEngine, suggest they view the content
181 // in Files instead so they can see it rendered.
183 $ref = id(new PhabricatorDocumentRef())
184 ->setName($paste->getTitle())
185 ->setData($paste->getRawContent());
187 $engines = PhabricatorDocumentEngine::getEnginesForRef($viewer, $ref);
188 if (!$engines) {
189 return null;
192 $engine = head($engines);
193 if (!$engine->shouldSuggestEngine($ref)) {
194 return null;
197 $file = id(new PhabricatorFileQuery())
198 ->setViewer($viewer)
199 ->withPHIDs(array($paste->getFilePHID()))
200 ->executeOne();
201 if (!$file) {
202 return null;
205 $file_ref = id(new PhabricatorDocumentRef())
206 ->setFile($file);
208 $view_uri = id(new PhabricatorFileDocumentRenderingEngine())
209 ->getRefViewURI($file_ref, $engine);
211 $view_as_label = $engine->getViewAsLabel($file_ref);
213 $view_as_hint = pht(
214 'This content can be rendered as a document in Files.');
216 return id(new PHUIInfoView())
217 ->setSeverity(PHUIInfoView::SEVERITY_NOTICE)
218 ->addButton(
219 id(new PHUIButtonView())
220 ->setTag('a')
221 ->setText($view_as_label)
222 ->setHref($view_uri)
223 ->setColor('grey'))
224 ->setErrors(
225 array(
226 $view_as_hint,