@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 260 lines 7.1 kB view raw
1<?php 2 3final class PhrictionDiffController extends PhrictionController { 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 $document = id(new PhrictionDocumentQuery()) 14 ->setViewer($viewer) 15 ->withIDs(array($id)) 16 ->needContent(true) 17 ->executeOne(); 18 if (!$document) { 19 return new Aphront404Response(); 20 } 21 22 $current = $document->getContent(); 23 24 $l = $request->getInt('l'); 25 $r = $request->getInt('r'); 26 27 $ref = $request->getStr('ref'); 28 if ($ref) { 29 list($l, $r) = explode(',', $ref); 30 } 31 32 $content = id(new PhrictionContentQuery()) 33 ->setViewer($viewer) 34 ->withDocumentPHIDs(array($document->getPHID())) 35 ->withVersions(array($l, $r)) 36 ->execute(); 37 $content = mpull($content, null, 'getVersion'); 38 39 $content_l = idx($content, $l, null); 40 $content_r = idx($content, $r, null); 41 42 if (!$content_l || !$content_r) { 43 return new Aphront404Response(); 44 } 45 46 $text_l = $content_l->getContent(); 47 $text_r = $content_r->getContent(); 48 49 $diff_view = id(new PhabricatorApplicationTransactionTextDiffDetailView()) 50 ->setOldText($text_l) 51 ->setNewText($text_r); 52 53 $changes = id(new PHUIObjectBoxView()) 54 ->setHeaderText(pht('Content Changes')) 55 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 56 ->appendChild( 57 phutil_tag( 58 'div', 59 array( 60 'class' => 'prose-diff-frame', 61 ), 62 $diff_view)); 63 64 require_celerity_resource('phriction-document-css'); 65 66 $slug = $document->getSlug(); 67 68 $revert_l = $this->renderRevertButton($document, $content_l, $current); 69 $revert_r = $this->renderRevertButton($document, $content_r, $current); 70 71 $crumbs = $this->buildApplicationCrumbs(); 72 $crumb_views = $this->renderBreadcrumbs($slug); 73 foreach ($crumb_views as $view) { 74 $crumbs->addCrumb($view); 75 } 76 77 $crumbs->addTextCrumb( 78 pht('History'), 79 PhrictionDocument::getSlugURI($slug, 'history')); 80 81 $title = pht('Version %s vs %s', $l, $r); 82 83 $header = id(new PHUIHeaderView()) 84 ->setHeader($title) 85 ->setHeaderIcon('fa-history'); 86 87 $crumbs->addTextCrumb($title, $request->getRequestURI()); 88 89 $comparison_table = $this->renderComparisonTable( 90 array( 91 $content_r, 92 $content_l, 93 )); 94 95 $navigation_table = null; 96 if ($l + 1 == $r) { 97 $nav_l = ($l > 1); 98 $nav_r = ($r != $document->getMaxVersion()); 99 100 $uri = $request->getRequestURI(); 101 102 if ($nav_l) { 103 $link_l = phutil_tag( 104 'a', 105 array( 106 'href' => $uri->alter('l', $l - 1)->alter('r', $r - 1), 107 'class' => 'button button-grey', 108 ), 109 pht("\xC2\xAB Previous Change")); 110 } else { 111 $link_l = phutil_tag( 112 'a', 113 array( 114 'href' => '#', 115 'class' => 'button button-grey disabled', 116 ), 117 pht('Original Change')); 118 } 119 120 $link_r = null; 121 if ($nav_r) { 122 $link_r = phutil_tag( 123 'a', 124 array( 125 'href' => $uri->alter('l', $l + 1)->alter('r', $r + 1), 126 'class' => 'button button-grey', 127 ), 128 pht("Next Change \xC2\xBB")); 129 } else { 130 $link_r = phutil_tag( 131 'a', 132 array( 133 'href' => '#', 134 'class' => 'button button-grey disabled', 135 ), 136 pht('Most Recent Change')); 137 } 138 139 $navigation_table = phutil_tag( 140 'table', 141 array('class' => 'phriction-history-nav-table'), 142 phutil_tag('tr', array(), array( 143 phutil_tag('td', array('class' => 'nav-prev'), $link_l), 144 phutil_tag('td', array('class' => 'nav-next'), $link_r), 145 ))); 146 } 147 148 $output = hsprintf( 149 '<div class="phriction-document-history-diff">'. 150 '%s%s'. 151 '<table class="phriction-revert-table">'. 152 '<tr><td>%s</td><td>%s</td>'. 153 '</table>'. 154 '</div>', 155 $comparison_table->render(), 156 $navigation_table, 157 $revert_l, 158 $revert_r); 159 160 $object_box = id(new PHUIObjectBoxView()) 161 ->setHeaderText(pht('Edits')) 162 ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 163 ->appendChild($output); 164 165 $crumbs->setBorder(true); 166 167 $view = id(new PHUITwoColumnView()) 168 ->setHeader($header) 169 ->setFooter(array( 170 $object_box, 171 $changes, 172 )); 173 174 return $this->newPage() 175 ->setTitle(pht('Document History')) 176 ->setCrumbs($crumbs) 177 ->appendChild($view); 178 179 } 180 181 private function renderRevertButton( 182 PhrictionDocument $document, 183 PhrictionContent $content, 184 PhrictionContent $current) { 185 186 $document_id = $document->getID(); 187 $version = $content->getVersion(); 188 189 $hidden_statuses = array( 190 PhrictionChangeType::CHANGE_DELETE => true, // Silly 191 PhrictionChangeType::CHANGE_MOVE_AWAY => true, // Plain silly 192 PhrictionChangeType::CHANGE_STUB => true, // Utterly silly 193 ); 194 195 if (isset($hidden_statuses[$content->getChangeType()])) { 196 // Don't show an edit/revert button for changes which deleted, moved or 197 // stubbed the content since it's silly. 198 return null; 199 } 200 201 if ($version == $current->getVersion()) { 202 $label = pht('Edit Current Version %s...', new PhutilNumber($version)); 203 } else if ($version < $current->getVersion()) { 204 $label = pht('Edit Older Version %s...', new PhutilNumber($version)); 205 } else { 206 $label = pht('Edit Draft Version %s...', new PhutilNumber($version)); 207 } 208 209 return phutil_tag( 210 'a', 211 array( 212 'href' => '/phriction/edit/'.$document_id.'/?revert='.$version, 213 'class' => 'button button-grey', 214 ), 215 $label); 216 } 217 218 /** 219 * @param array<PhrictionContent> $content 220 */ 221 private function renderComparisonTable(array $content) { 222 assert_instances_of($content, PhrictionContent::class); 223 224 $viewer = $this->getViewer(); 225 226 $phids = mpull($content, 'getAuthorPHID'); 227 $handles = $this->loadViewerHandles($phids); 228 229 $list = new PHUIObjectItemListView(); 230 231 $first = true; 232 foreach ($content as $c) { 233 $author = $handles[$c->getAuthorPHID()]->renderLink(); 234 $item = id(new PHUIObjectItemView()) 235 ->setHeader(pht('%s by %s, %s', 236 PhrictionChangeType::getChangeTypeLabel($c->getChangeType()), 237 $author, 238 pht('Version %s', $c->getVersion()))) 239 ->addAttribute(pht('%s %s', 240 phabricator_date($c->getDateCreated(), $viewer), 241 phabricator_time($c->getDateCreated(), $viewer))); 242 243 if ($c->getDescription()) { 244 $item->addAttribute($c->getDescription()); 245 } 246 247 if ($first == true) { 248 $item->setStatusIcon('fa-file green'); 249 $first = false; 250 } else { 251 $item->setStatusIcon('fa-file red'); 252 } 253 254 $list->addItem($item); 255 } 256 257 return $list; 258 } 259 260}