@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 379 lines 12 kB view raw
1<?php 2 3final class PhrictionEditController 4 extends PhrictionController { 5 6 public function handleRequest(AphrontRequest $request) { 7 $viewer = $request->getViewer(); 8 $id = $request->getURIData('id'); 9 10 $max_version = null; 11 if ($id) { 12 $is_new = false; 13 $document = id(new PhrictionDocumentQuery()) 14 ->setViewer($viewer) 15 ->withIDs(array($id)) 16 ->needContent(true) 17 ->requireCapabilities( 18 array( 19 PhabricatorPolicyCapability::CAN_VIEW, 20 PhabricatorPolicyCapability::CAN_EDIT, 21 )) 22 ->executeOne(); 23 if (!$document) { 24 return new Aphront404Response(); 25 } 26 27 $max_version = $document->getMaxVersion(); 28 29 $revert = $request->getInt('revert'); 30 if ($revert) { 31 $content = id(new PhrictionContentQuery()) 32 ->setViewer($viewer) 33 ->withDocumentPHIDs(array($document->getPHID())) 34 ->withVersions(array($revert)) 35 ->executeOne(); 36 if (!$content) { 37 return new Aphront404Response(); 38 } 39 } else { 40 $content = id(new PhrictionContentQuery()) 41 ->setViewer($viewer) 42 ->withDocumentPHIDs(array($document->getPHID())) 43 ->setLimit(1) 44 ->executeOne(); 45 } 46 } else { 47 $slug = $request->getStr('slug'); 48 $slug = PhabricatorSlug::normalize($slug); 49 if (!$slug) { 50 return new Aphront404Response(); 51 } 52 53 $document = id(new PhrictionDocumentQuery()) 54 ->setViewer($viewer) 55 ->withSlugs(array($slug)) 56 ->needContent(true) 57 ->executeOne(); 58 59 if ($document) { 60 $content = id(new PhrictionContentQuery()) 61 ->setViewer($viewer) 62 ->withDocumentPHIDs(array($document->getPHID())) 63 ->setLimit(1) 64 ->executeOne(); 65 66 $max_version = $document->getMaxVersion(); 67 $is_new = false; 68 } else { 69 $document = PhrictionDocument::initializeNewDocument($viewer, $slug); 70 $content = $document->getContent(); 71 $is_new = true; 72 } 73 } 74 75 require_celerity_resource('phriction-document-css'); 76 77 $e_title = true; 78 $e_content = true; 79 $validation_exception = null; 80 $notes = null; 81 $title = $content->getTitle(); 82 $overwrite = false; 83 $v_cc = PhabricatorSubscribersQuery::loadSubscribersForPHID( 84 $document->getPHID()); 85 86 if ($is_new) { 87 $v_projects = array(); 88 } else { 89 $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs( 90 $document->getPHID(), 91 PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); 92 $v_projects = array_reverse($v_projects); 93 } 94 95 $v_space = $document->getSpacePHID(); 96 97 $content_text = $content->getContent(); 98 $is_draft_mode = ($document->getContent()->getVersion() != $max_version); 99 100 $default_view = $document->getViewPolicy(); 101 $default_edit = $document->getEditPolicy(); 102 $default_space = $document->getSpacePHID(); 103 104 if ($request->isFormPost()) { 105 if ($is_new) { 106 $save_as_draft = false; 107 } else { 108 $save_as_draft = ($is_draft_mode || $request->getExists('draft')); 109 } 110 111 $title = $request->getStr('title'); 112 $content_text = $request->getStr('content'); 113 $notes = $request->getStr('description'); 114 $max_version = $request->getInt('contentVersion'); 115 $v_view = $request->getStr('viewPolicy'); 116 $v_edit = $request->getStr('editPolicy'); 117 $v_cc = $request->getArr('cc'); 118 $v_projects = $request->getArr('projects'); 119 $v_space = $request->getStr('spacePHID'); 120 121 if ($save_as_draft) { 122 $edit_type = PhrictionDocumentDraftTransaction::TRANSACTIONTYPE; 123 } else { 124 $edit_type = PhrictionDocumentContentTransaction::TRANSACTIONTYPE; 125 } 126 127 $xactions = array(); 128 129 if ($is_new) { 130 $xactions[] = id(new PhrictionTransaction()) 131 ->setTransactionType(PhabricatorTransactions::TYPE_CREATE); 132 } 133 134 $xactions[] = id(new PhrictionTransaction()) 135 ->setTransactionType(PhrictionDocumentTitleTransaction::TRANSACTIONTYPE) 136 ->setNewValue($title); 137 $content_xaction = id(new PhrictionTransaction()) 138 ->setTransactionType($edit_type) 139 ->setNewValue($content_text); 140 141 $content_metadata = $request->getStr('content_metadata'); 142 if ($content_metadata) { 143 $content_metadata = phutil_json_decode($content_metadata); 144 $attached_file_phids = idx( 145 $content_metadata, 146 'attachedFilePHIDs', 147 array()); 148 149 if ($attached_file_phids) { 150 $metadata_object = array( 151 'remarkup.control' => array( 152 'attachedFilePHIDs' => $attached_file_phids, 153 ), 154 ); 155 156 $content_xaction->setMetadata($metadata_object); 157 } 158 } 159 160 $xactions[] = $content_xaction; 161 162 $xactions[] = id(new PhrictionTransaction()) 163 ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) 164 ->setNewValue($v_view) 165 ->setIsDefaultTransaction($is_new && ($v_view === $default_view)); 166 $xactions[] = id(new PhrictionTransaction()) 167 ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY) 168 ->setNewValue($v_edit) 169 ->setIsDefaultTransaction($is_new && ($v_edit === $default_edit)); 170 $xactions[] = id(new PhrictionTransaction()) 171 ->setTransactionType(PhabricatorTransactions::TYPE_SPACE) 172 ->setNewValue($v_space) 173 ->setIsDefaultTransaction($is_new && ($v_space === $default_space)); 174 $xactions[] = id(new PhrictionTransaction()) 175 ->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS) 176 ->setNewValue(array('=' => $v_cc)); 177 178 $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; 179 $xactions[] = id(new PhrictionTransaction()) 180 ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) 181 ->setMetadataValue('edge:type', $proj_edge_type) 182 ->setNewValue(array('=' => array_fuse($v_projects))); 183 184 $editor = id(new PhrictionTransactionEditor()) 185 ->setActor($viewer) 186 ->setContentSourceFromRequest($request) 187 ->setContinueOnNoEffect(true) 188 ->setDescription($notes) 189 ->setProcessContentVersionError(!$request->getBool('overwrite')) 190 ->setContentVersion($max_version); 191 192 try { 193 $editor->applyTransactions($document, $xactions); 194 195 $uri = PhrictionDocument::getSlugURI($document->getSlug()); 196 $uri = new PhutilURI($uri); 197 198 // If the user clicked "Save as Draft", take them to the draft, not 199 // to the current published page. 200 if ($save_as_draft) { 201 $uri = $uri->alter('v', $document->getMaxVersion()); 202 } 203 204 return id(new AphrontRedirectResponse())->setURI($uri); 205 } catch (PhabricatorApplicationTransactionValidationException $ex) { 206 $validation_exception = $ex; 207 $e_title = nonempty( 208 $ex->getShortMessage( 209 PhrictionDocumentTitleTransaction::TRANSACTIONTYPE), 210 true); 211 $e_content = nonempty( 212 $ex->getShortMessage( 213 PhrictionDocumentContentTransaction::TRANSACTIONTYPE), 214 true); 215 216 // if we're not supposed to process the content version error, then 217 // overwrite that content...! 218 if (!$editor->getProcessContentVersionError()) { 219 $overwrite = true; 220 } 221 222 $document->setViewPolicy($v_view); 223 $document->setEditPolicy($v_edit); 224 $document->setSpacePHID($v_space); 225 } 226 } 227 228 if ($document->getID()) { 229 $page_title = pht('Edit Document: %s', $content->getTitle()); 230 if ($overwrite) { 231 $submit_button = pht('Overwrite Changes'); 232 } else { 233 $submit_button = pht('Save and Publish'); 234 } 235 } else { 236 $submit_button = pht('Create Document'); 237 $page_title = pht('Create Document'); 238 } 239 240 $uri = $document->getSlug(); 241 $uri = PhrictionDocument::getSlugURI($uri); 242 $uri = PhabricatorEnv::getProductionURI($uri); 243 244 $cancel_uri = PhrictionDocument::getSlugURI($document->getSlug()); 245 246 $policies = id(new PhabricatorPolicyQuery()) 247 ->setViewer($viewer) 248 ->setObject($document) 249 ->execute(); 250 $view_capability = PhabricatorPolicyCapability::CAN_VIEW; 251 $edit_capability = PhabricatorPolicyCapability::CAN_EDIT; 252 253 $form = id(new AphrontFormView()) 254 ->setUser($viewer) 255 ->addHiddenInput('slug', $document->getSlug()) 256 ->addHiddenInput('contentVersion', $max_version) 257 ->addHiddenInput('overwrite', $overwrite) 258 ->appendChild( 259 id(new AphrontFormTextControl()) 260 ->setLabel(pht('Title')) 261 ->setValue($title) 262 ->setError($e_title) 263 ->setName('title')) 264 ->appendChild( 265 id(new AphrontFormStaticControl()) 266 ->setLabel(pht('URI')) 267 ->setValue($uri)) 268 ->appendChild( 269 id(new PhabricatorRemarkupControl()) 270 ->setLabel(pht('Content')) 271 ->setValue($content_text) 272 ->setError($e_content) 273 ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL) 274 ->setName('content') 275 ->setID('document-textarea') 276 ->setUser($viewer)) 277 ->appendControl( 278 id(new AphrontFormTokenizerControl()) 279 ->setLabel(pht('Project Tags')) 280 ->setName('projects') 281 ->setValue($v_projects) 282 ->setDatasource(new PhabricatorProjectDatasource())) 283 ->appendControl( 284 id(new AphrontFormTokenizerControl()) 285 ->setLabel(pht('Subscribers')) 286 ->setName('cc') 287 ->setValue($v_cc) 288 ->setUser($viewer) 289 ->setDatasource(new PhabricatorMetaMTAMailableDatasource())) 290 ->appendChild( 291 id(new AphrontFormPolicyControl()) 292 ->setViewer($viewer) 293 ->setName('viewPolicy') 294 ->setSpacePHID($v_space) 295 ->setPolicyObject($document) 296 ->setCapability($view_capability) 297 ->setPolicies($policies)) 298 ->appendChild( 299 id(new AphrontFormPolicyControl()) 300 ->setName('editPolicy') 301 ->setPolicyObject($document) 302 ->setCapability($edit_capability) 303 ->setPolicies($policies)) 304 ->appendChild( 305 id(new AphrontFormTextControl()) 306 ->setLabel(pht('Edit Notes')) 307 ->setValue($notes) 308 ->setError(null) 309 ->setName('description')); 310 311 if ($is_draft_mode) { 312 $form->appendControl( 313 id(new AphrontFormSubmitControl()) 314 ->addCancelButton($cancel_uri) 315 ->setValue(pht('Save Draft'))); 316 } else { 317 $submit = new AphrontFormSubmitControl(); 318 319 if (!$is_new) { 320 $draft_button = id(new PHUIButtonView()) 321 ->setTag('input') 322 ->setName('draft') 323 ->setText(pht('Save as Draft')) 324 ->setColor(PHUIButtonView::GREEN); 325 $submit->addButton($draft_button); 326 } 327 328 $submit 329 ->addCancelButton($cancel_uri) 330 ->setValue($submit_button); 331 332 $form->appendControl($submit); 333 } 334 335 $form_box = id(new PHUIObjectBoxView()) 336 ->setHeaderText($page_title) 337 ->setValidationException($validation_exception) 338 ->setBackground(PHUIObjectBoxView::WHITE_CONFIG) 339 ->setForm($form); 340 341 $preview_uri = '/phriction/preview/'; 342 $preview_uri = new PhutilURI( 343 $preview_uri, 344 array( 345 'slug' => $document->getSlug(), 346 )); 347 $preview_uri = phutil_string_cast($preview_uri); 348 349 $preview = id(new PHUIRemarkupPreviewPanel()) 350 ->setHeader($content->getTitle()) 351 ->setPreviewURI($preview_uri) 352 ->setControlID('document-textarea') 353 ->setPreviewType(PHUIRemarkupPreviewPanel::DOCUMENT); 354 355 $crumbs = $this->buildApplicationCrumbs(); 356 if ($document->getID()) { 357 $crumbs->addTextCrumb( 358 $content->getTitle(), 359 PhrictionDocument::getSlugURI($document->getSlug())); 360 $crumbs->addTextCrumb(pht('Edit')); 361 } else { 362 $crumbs->addTextCrumb(pht('Create')); 363 } 364 $crumbs->setBorder(true); 365 366 $view = id(new PHUITwoColumnView()) 367 ->setFooter( 368 array( 369 $form_box, 370 $preview, 371 )); 372 373 return $this->newPage() 374 ->setTitle($page_title) 375 ->setCrumbs($crumbs) 376 ->appendChild($view); 377 } 378 379}