@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at upstream/main 230 lines 6.4 kB view raw
1<?php 2 3final class PhabricatorPasteViewController extends PhabricatorPasteController { 4 5 public function shouldAllowPublic() { 6 return true; 7 } 8 9 public function handleRequest(AphrontRequest $request) { 10 $viewer = $request->getViewer(); 11 $id = $request->getURIData('id'); 12 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(); 21 } 22 23 $lines = $request->getURILineRange('lines', 1000); 24 if ($lines) { 25 $map = range($lines[0], $lines[1]); 26 } else { 27 $map = array(); 28 } 29 30 $header = $this->buildHeaderView($paste); 31 $curtain = $this->buildCurtain($paste); 32 33 $subheader = $this->buildSubheaderView($paste); 34 $source_code = $this->buildSourceCodeView($paste, $map); 35 36 require_celerity_resource('paste-css'); 37 38 $monogram = $paste->getMonogram(); 39 $crumbs = $this->buildApplicationCrumbs() 40 ->addTextCrumb($monogram) 41 ->setBorder(true); 42 43 $timeline = $this->buildTransactionTimeline( 44 $paste, 45 new PhabricatorPasteTransactionQuery()); 46 47 $comment_view = id(new PhabricatorPasteEditEngine()) 48 ->setViewer($viewer) 49 ->buildEditEngineCommentView($paste); 50 51 $timeline->setQuoteRef($monogram); 52 $comment_view->setTransactionTimeline($timeline); 53 54 $recommendation_view = $this->newDocumentRecommendationView($paste); 55 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, 65 )) 66 ->setCurtain($curtain); 67 68 return $this->newPage() 69 ->setTitle($paste->getFullName()) 70 ->setCrumbs($crumbs) 71 ->setPageObjectPHIDs( 72 array( 73 $paste->getPHID(), 74 )) 75 ->appendChild($paste_view); 76 } 77 78 private function buildHeaderView(PhabricatorPaste $paste) { 79 $title = (nonempty($paste->getTitle())) ? 80 $paste->getTitle() : pht('(An Untitled Masterwork)'); 81 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'; 90 } 91 92 $header = id(new PHUIHeaderView()) 93 ->setHeader($title) 94 ->setViewer($this->getRequest()->getUser()) 95 ->setStatus($header_icon, $header_color, $header_name) 96 ->setPolicyObject($paste) 97 ->setHeaderIcon('fa-clipboard'); 98 99 return $header; 100 } 101 102 private function buildCurtain(PhabricatorPaste $paste) { 103 $viewer = $this->getViewer(); 104 $curtain = $this->newCurtainView($paste); 105 106 $can_edit = PhabricatorPolicyFilter::hasCapability( 107 $viewer, 108 $paste, 109 PhabricatorPolicyCapability::CAN_EDIT); 110 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}/"); 115 116 $curtain->addAction( 117 id(new PhabricatorActionView()) 118 ->setName(pht('Edit Paste')) 119 ->setIcon('fa-pencil') 120 ->setDisabled(!$can_edit) 121 ->setHref($edit_uri)); 122 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)); 139 } 140 141 $curtain->addAction( 142 id(new PhabricatorActionView()) 143 ->setName(pht('View Raw File')) 144 ->setIcon('fa-file-text-o') 145 ->setHref($raw_uri)); 146 147 return $curtain; 148 } 149 150 151 private function buildSubheaderView( 152 PhabricatorPaste $paste) { 153 $viewer = $this->getViewer(); 154 155 $author = $viewer->renderHandle($paste->getAuthorPHID())->render(); 156 $date = phabricator_datetime($paste->getDateCreated(), $viewer); 157 $author = phutil_tag('strong', array(), $author); 158 159 $author_info = id(new PhabricatorPeopleQuery()) 160 ->setViewer($viewer) 161 ->withPHIDs(array($paste->getAuthorPHID())) 162 ->needProfileImage(true) 163 ->executeOne(); 164 165 $image_uri = $author_info->getProfileImageURI(); 166 $image_href = '/p/'.$author_info->getUsername(); 167 168 $content = pht('Authored by %s on %s.', $author, $date); 169 170 return id(new PHUIHeadThingView()) 171 ->setImage($image_uri) 172 ->setImageHref($image_href) 173 ->setContent($content); 174 } 175 176 private function newDocumentRecommendationView(PhabricatorPaste $paste) { 177 $viewer = $this->getViewer(); 178 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. 182 183 $ref = id(new PhabricatorDocumentRef()) 184 ->setName($paste->getTitle()) 185 ->setData($paste->getRawContent()); 186 187 $engines = PhabricatorDocumentEngine::getEnginesForRef($viewer, $ref); 188 if (!$engines) { 189 return null; 190 } 191 192 $engine = head($engines); 193 if (!$engine->shouldSuggestEngine($ref)) { 194 return null; 195 } 196 197 $file = id(new PhabricatorFileQuery()) 198 ->setViewer($viewer) 199 ->withPHIDs(array($paste->getFilePHID())) 200 ->executeOne(); 201 if (!$file) { 202 return null; 203 } 204 205 $file_ref = id(new PhabricatorDocumentRef()) 206 ->setFile($file); 207 208 $view_uri = id(new PhabricatorFileDocumentRenderingEngine()) 209 ->getRefViewURI($file_ref, $engine); 210 211 $view_as_label = $engine->getViewAsLabel($file_ref); 212 213 $view_as_hint = pht( 214 'This content can be rendered as a document in Files.'); 215 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, 227 )); 228 } 229 230}