@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
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update Legalpad for EditEngine

Summary: Updates Legalpad to use EditEngine, paving the way for //transaction comments//. Spooky.

Test Plan:
- New Document
- Require signing, Corp - see fail
- Require signing, Noone - see fail
- Require signing, Ind - get asked to sign
- Edit Document

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin

Differential Revision: https://secure.phabricator.com/D17862

+239 -276
+2
src/__phutil_library_map__.php
··· 1408 1408 'LegalpadDocumentDatasource' => 'applications/legalpad/typeahead/LegalpadDocumentDatasource.php', 1409 1409 'LegalpadDocumentDoneController' => 'applications/legalpad/controller/LegalpadDocumentDoneController.php', 1410 1410 'LegalpadDocumentEditController' => 'applications/legalpad/controller/LegalpadDocumentEditController.php', 1411 + 'LegalpadDocumentEditEngine' => 'applications/legalpad/editor/LegalpadDocumentEditEngine.php', 1411 1412 'LegalpadDocumentEditor' => 'applications/legalpad/editor/LegalpadDocumentEditor.php', 1412 1413 'LegalpadDocumentListController' => 'applications/legalpad/controller/LegalpadDocumentListController.php', 1413 1414 'LegalpadDocumentManageController' => 'applications/legalpad/controller/LegalpadDocumentManageController.php', ··· 6434 6435 'LegalpadDocumentDatasource' => 'PhabricatorTypeaheadDatasource', 6435 6436 'LegalpadDocumentDoneController' => 'LegalpadController', 6436 6437 'LegalpadDocumentEditController' => 'LegalpadController', 6438 + 'LegalpadDocumentEditEngine' => 'PhabricatorEditEngine', 6437 6439 'LegalpadDocumentEditor' => 'PhabricatorApplicationTransactionEditor', 6438 6440 'LegalpadDocumentListController' => 'LegalpadController', 6439 6441 'LegalpadDocumentManageController' => 'LegalpadController',
+4 -3
src/applications/legalpad/application/PhabricatorLegalpadApplication.php
··· 53 53 '/L(?P<id>\d+)' => 'LegalpadDocumentSignController', 54 54 '/legalpad/' => array( 55 55 '' => 'LegalpadDocumentListController', 56 - '(?:query/(?P<queryKey>[^/]+)/)?' => 'LegalpadDocumentListController', 57 - 'create/' => 'LegalpadDocumentEditController', 58 - 'edit/(?P<id>\d+)/' => 'LegalpadDocumentEditController', 56 + '(?:query/(?P<queryKey>[^/]+)/)?' 57 + => 'LegalpadDocumentListController', 58 + $this->getEditRoutePattern('edit/') 59 + => 'LegalpadDocumentEditController', 59 60 'comment/(?P<id>\d+)/' => 'LegalpadDocumentCommentController', 60 61 'view/(?P<id>\d+)/' => 'LegalpadDocumentManageController', 61 62 'done/' => 'LegalpadDocumentDoneController',
+1 -1
src/applications/legalpad/controller/LegalpadController.php
··· 9 9 $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); 10 10 11 11 if ($for_app) { 12 - $nav->addFilter('create/', pht('Create Document')); 12 + $nav->addFilter('edit/', pht('Create Document')); 13 13 } 14 14 15 15 id(new LegalpadDocumentSearchEngine())
+3 -269
src/applications/legalpad/controller/LegalpadDocumentEditController.php
··· 3 3 final class LegalpadDocumentEditController extends LegalpadController { 4 4 5 5 public function handleRequest(AphrontRequest $request) { 6 - $viewer = $request->getViewer(); 7 - $id = $request->getURIData('id'); 8 - 9 - if (!$id) { 10 - $is_create = true; 11 - 12 - $this->requireApplicationCapability( 13 - LegalpadCreateDocumentsCapability::CAPABILITY); 14 - 15 - $document = LegalpadDocument::initializeNewDocument($viewer); 16 - $body = id(new LegalpadDocumentBody()) 17 - ->setCreatorPHID($viewer->getPHID()); 18 - $document->attachDocumentBody($body); 19 - $document->setDocumentBodyPHID(PhabricatorPHIDConstants::PHID_VOID); 20 - } else { 21 - $is_create = false; 22 - 23 - $document = id(new LegalpadDocumentQuery()) 24 - ->setViewer($viewer) 25 - ->needDocumentBodies(true) 26 - ->requireCapabilities( 27 - array( 28 - PhabricatorPolicyCapability::CAN_VIEW, 29 - PhabricatorPolicyCapability::CAN_EDIT, 30 - )) 31 - ->withIDs(array($id)) 32 - ->executeOne(); 33 - if (!$document) { 34 - return new Aphront404Response(); 35 - } 36 - } 37 - 38 - $e_title = true; 39 - $e_text = true; 40 - 41 - $title = $document->getDocumentBody()->getTitle(); 42 - $text = $document->getDocumentBody()->getText(); 43 - $v_signature_type = $document->getSignatureType(); 44 - $v_preamble = $document->getPreamble(); 45 - $v_require_signature = $document->getRequireSignature(); 46 - 47 - $errors = array(); 48 - $can_view = null; 49 - $can_edit = null; 50 - if ($request->isFormPost()) { 51 - 52 - $xactions = array(); 53 - 54 - $title = $request->getStr('title'); 55 - if (!strlen($title)) { 56 - $e_title = pht('Required'); 57 - $errors[] = pht('The document title may not be blank.'); 58 - } else { 59 - $xactions[] = id(new LegalpadTransaction()) 60 - ->setTransactionType( 61 - LegalpadDocumentTitleTransaction::TRANSACTIONTYPE) 62 - ->setNewValue($title); 63 - } 64 - 65 - $text = $request->getStr('text'); 66 - if (!strlen($text)) { 67 - $e_text = pht('Required'); 68 - $errors[] = pht('The document may not be blank.'); 69 - } else { 70 - $xactions[] = id(new LegalpadTransaction()) 71 - ->setTransactionType( 72 - LegalpadDocumentTextTransaction::TRANSACTIONTYPE) 73 - ->setNewValue($text); 74 - } 75 - 76 - $can_view = $request->getStr('can_view'); 77 - $xactions[] = id(new LegalpadTransaction()) 78 - ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY) 79 - ->setNewValue($can_view); 80 - $can_edit = $request->getStr('can_edit'); 81 - $xactions[] = id(new LegalpadTransaction()) 82 - ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY) 83 - ->setNewValue($can_edit); 84 - 85 - if ($is_create) { 86 - $v_signature_type = $request->getStr('signatureType'); 87 - $xactions[] = id(new LegalpadTransaction()) 88 - ->setTransactionType( 89 - LegalpadDocumentSignatureTypeTransaction::TRANSACTIONTYPE) 90 - ->setNewValue($v_signature_type); 91 - } 92 - 93 - $v_preamble = $request->getStr('preamble'); 94 - $xactions[] = id(new LegalpadTransaction()) 95 - ->setTransactionType( 96 - LegalpadDocumentPreambleTransaction::TRANSACTIONTYPE) 97 - ->setNewValue($v_preamble); 98 - 99 - $v_require_signature = $request->getBool('requireSignature', 0); 100 - if ($v_require_signature) { 101 - if (!$viewer->getIsAdmin()) { 102 - $errors[] = pht('Only admins may require signature.'); 103 - } 104 - $individual = LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL; 105 - if ($v_signature_type != $individual) { 106 - $errors[] = pht( 107 - 'Only documents with signature type "individual" may require '. 108 - 'signing to use Phabricator.'); 109 - } 110 - } 111 - if ($viewer->getIsAdmin()) { 112 - $xactions[] = id(new LegalpadTransaction()) 113 - ->setTransactionType( 114 - LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE) 115 - ->setNewValue($v_require_signature); 116 - } 117 - 118 - if (!$errors) { 119 - $editor = id(new LegalpadDocumentEditor()) 120 - ->setContentSourceFromRequest($request) 121 - ->setContinueOnNoEffect(true) 122 - ->setActor($viewer); 123 - 124 - $xactions = $editor->applyTransactions($document, $xactions); 125 - 126 - return id(new AphrontRedirectResponse()) 127 - ->setURI($this->getApplicationURI('view/'.$document->getID())); 128 - } 129 - } 130 - 131 - if ($errors) { 132 - // set these to what was specified in the form on post 133 - $document->setViewPolicy($can_view); 134 - $document->setEditPolicy($can_edit); 135 - } 136 - 137 - $form = id(new AphrontFormView()) 138 - ->setUser($viewer) 139 - ->appendChild( 140 - id(new AphrontFormTextControl()) 141 - ->setID('document-title') 142 - ->setLabel(pht('Title')) 143 - ->setError($e_title) 144 - ->setValue($title) 145 - ->setName('title')); 146 - 147 - if ($is_create) { 148 - $form->appendChild( 149 - id(new AphrontFormSelectControl()) 150 - ->setLabel(pht('Who Should Sign?')) 151 - ->setName(pht('signatureType')) 152 - ->setValue($v_signature_type) 153 - ->setOptions(LegalpadDocument::getSignatureTypeMap())); 154 - $show_require = true; 155 - $caption = pht('Applies only to documents individuals sign.'); 156 - } else { 157 - $form->appendChild( 158 - id(new AphrontFormMarkupControl()) 159 - ->setLabel(pht('Who Should Sign?')) 160 - ->setValue($document->getSignatureTypeName())); 161 - $individual = LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL; 162 - $show_require = $document->getSignatureType() == $individual; 163 - $caption = null; 164 - } 165 - 166 - if ($show_require) { 167 - $form 168 - ->appendChild( 169 - id(new AphrontFormCheckboxControl()) 170 - ->setDisabled(!$viewer->getIsAdmin()) 171 - ->setLabel(pht('Require Signature')) 172 - ->addCheckbox( 173 - 'requireSignature', 174 - 'requireSignature', 175 - pht('Should signing this document be required to use Phabricator?'), 176 - $v_require_signature) 177 - ->setCaption($caption)); 178 - } 179 - 180 - $form 181 - ->appendChild( 182 - id(new PhabricatorRemarkupControl()) 183 - ->setUser($viewer) 184 - ->setID('preamble') 185 - ->setLabel(pht('Preamble')) 186 - ->setValue($v_preamble) 187 - ->setName('preamble') 188 - ->setCaption( 189 - pht('Optional help text for users signing this document.'))) 190 - ->appendChild( 191 - id(new PhabricatorRemarkupControl()) 192 - ->setUser($viewer) 193 - ->setID('document-text') 194 - ->setLabel(pht('Document Body')) 195 - ->setError($e_text) 196 - ->setValue($text) 197 - ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL) 198 - ->setName('text')); 199 - 200 - $policies = id(new PhabricatorPolicyQuery()) 201 - ->setViewer($viewer) 202 - ->setObject($document) 203 - ->execute(); 204 - 205 - $form 206 - ->appendChild( 207 - id(new AphrontFormPolicyControl()) 208 - ->setUser($viewer) 209 - ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) 210 - ->setPolicyObject($document) 211 - ->setPolicies($policies) 212 - ->setName('can_view')) 213 - ->appendChild( 214 - id(new AphrontFormPolicyControl()) 215 - ->setUser($viewer) 216 - ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) 217 - ->setPolicyObject($document) 218 - ->setPolicies($policies) 219 - ->setName('can_edit')); 220 - 221 - $crumbs = $this->buildApplicationCrumbs(); 222 - $submit = new AphrontFormSubmitControl(); 223 - if ($is_create) { 224 - $submit->setValue(pht('Create Document')); 225 - $submit->addCancelButton($this->getApplicationURI()); 226 - $title = pht('Create Document'); 227 - $short = pht('Create'); 228 - $header_icon = 'fa-plus-square'; 229 - } else { 230 - $submit->setValue(pht('Save Document')); 231 - $submit->addCancelButton( 232 - $this->getApplicationURI('view/'.$document->getID())); 233 - $title = pht('Edit Document: %s', $document->getTitle()); 234 - $short = pht('Edit'); 235 - $header_icon = 'fa-pencil'; 236 - 237 - $crumbs->addTextCrumb( 238 - $document->getMonogram(), 239 - $this->getApplicationURI('view/'.$document->getID())); 240 - } 241 - 242 - $form->appendChild($submit); 243 - 244 - $form_box = id(new PHUIObjectBoxView()) 245 - ->setHeaderText(pht('Document')) 246 - ->setFormErrors($errors) 247 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 248 - ->setForm($form); 249 - 250 - $crumbs->addTextCrumb($short); 251 - $crumbs->setBorder(true); 252 - 253 - $preview = id(new PHUIRemarkupPreviewPanel()) 254 - ->setHeader($document->getTitle()) 255 - ->setPreviewURI($this->getApplicationURI('document/preview/')) 256 - ->setControlID('document-text') 257 - ->setPreviewType(PHUIRemarkupPreviewPanel::DOCUMENT); 258 - 259 - $header = id(new PHUIHeaderView()) 260 - ->setHeader($title) 261 - ->setHeaderIcon($header_icon); 262 - 263 - $view = id(new PHUITwoColumnView()) 264 - ->setHeader($header) 265 - ->setFooter(array( 266 - $form_box, 267 - $preview, 268 - )); 269 - 270 - return $this->newPage() 271 - ->setTitle($title) 272 - ->setCrumbs($crumbs) 273 - ->appendChild($view); 274 - 6 + return id(new LegalpadDocumentEditEngine()) 7 + ->setController($this) 8 + ->buildResponse(); 275 9 } 276 10 277 11 }
+1 -1
src/applications/legalpad/controller/LegalpadDocumentListController.php
··· 26 26 $crumbs->addAction( 27 27 id(new PHUIListItemView()) 28 28 ->setName(pht('Create Document')) 29 - ->setHref($this->getApplicationURI('create/')) 29 + ->setHref($this->getApplicationURI('edit/')) 30 30 ->setIcon('fa-plus-square') 31 31 ->setDisabled(!$can_create) 32 32 ->setWorkflow(!$can_create));
+169
src/applications/legalpad/editor/LegalpadDocumentEditEngine.php
··· 1 + <?php 2 + 3 + final class LegalpadDocumentEditEngine 4 + extends PhabricatorEditEngine { 5 + 6 + const ENGINECONST = 'legalpad.document'; 7 + 8 + public function getEngineName() { 9 + return pht('Legalpad'); 10 + } 11 + 12 + public function getEngineApplicationClass() { 13 + return 'PhabricatorLegalpadApplication'; 14 + } 15 + 16 + public function getSummaryHeader() { 17 + return pht('Configure Legalpad Forms'); 18 + } 19 + 20 + public function getSummaryText() { 21 + return pht('Configure creation and editing documents in Legalpad.'); 22 + } 23 + 24 + public function isEngineConfigurable() { 25 + return false; 26 + } 27 + 28 + protected function newEditableObject() { 29 + $viewer = $this->getViewer(); 30 + 31 + $document = LegalpadDocument::initializeNewDocument($viewer); 32 + $body = id(new LegalpadDocumentBody()) 33 + ->setCreatorPHID($viewer->getPHID()); 34 + $document->attachDocumentBody($body); 35 + $document->setDocumentBodyPHID(PhabricatorPHIDConstants::PHID_VOID); 36 + 37 + return $document; 38 + } 39 + 40 + protected function newObjectQuery() { 41 + return id(new LegalpadDocumentQuery()) 42 + ->needDocumentBodies(true); 43 + } 44 + 45 + protected function getObjectCreateTitleText($object) { 46 + return pht('Create New Document'); 47 + } 48 + 49 + protected function getObjectEditTitleText($object) { 50 + $body = $object->getDocumentBody(); 51 + $title = $body->getTitle(); 52 + return pht('Edit Document: %s', $title); 53 + } 54 + 55 + protected function getObjectEditShortText($object) { 56 + $body = $object->getDocumentBody(); 57 + return $body->getTitle(); 58 + } 59 + 60 + protected function getObjectCreateShortText() { 61 + return pht('Create Document'); 62 + } 63 + 64 + protected function getObjectName() { 65 + return pht('Document'); 66 + } 67 + 68 + protected function getObjectCreateCancelURI($object) { 69 + return $this->getApplication()->getApplicationURI('/'); 70 + } 71 + 72 + protected function getEditorURI() { 73 + return $this->getApplication()->getApplicationURI('edit/'); 74 + } 75 + 76 + protected function getObjectViewURI($object) { 77 + $id = $object->getID(); 78 + return $this->getApplication()->getApplicationURI('view/'.$id.'/'); 79 + } 80 + 81 + 82 + protected function getCreateNewObjectPolicy() { 83 + return $this->getApplication()->getPolicy( 84 + LegalpadCreateDocumentsCapability::CAPABILITY); 85 + } 86 + 87 + protected function buildCustomEditFields($object) { 88 + $viewer = $this->getViewer(); 89 + 90 + $body = $object->getDocumentBody(); 91 + $document_body = $body->getText(); 92 + 93 + $is_create = $this->getIsCreate(); 94 + $is_admin = $viewer->getIsAdmin(); 95 + 96 + $fields = array(); 97 + $fields[] = 98 + id(new PhabricatorTextEditField()) 99 + ->setKey('title') 100 + ->setLabel(pht('Title')) 101 + ->setDescription(pht('Document Title.')) 102 + ->setConduitTypeDescription(pht('New document title.')) 103 + ->setValue($object->getTitle()) 104 + ->setIsRequired(true) 105 + ->setTransactionType( 106 + LegalpadDocumentTitleTransaction::TRANSACTIONTYPE); 107 + 108 + if ($is_create) { 109 + $fields[] = 110 + id(new PhabricatorSelectEditField()) 111 + ->setKey('signatureType') 112 + ->setLabel(pht('Who Should Sign?')) 113 + ->setDescription(pht('Type of signature required')) 114 + ->setConduitTypeDescription(pht('New document signature type.')) 115 + ->setValue($object->getSignatureType()) 116 + ->setOptions(LegalpadDocument::getSignatureTypeMap()) 117 + ->setTransactionType( 118 + LegalpadDocumentSignatureTypeTransaction::TRANSACTIONTYPE); 119 + $show_require = true; 120 + } else { 121 + $fields[] = id(new PhabricatorStaticEditField()) 122 + ->setLabel(pht('Who Should Sign?')) 123 + ->setValue($object->getSignatureTypeName()); 124 + $individual = LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL; 125 + $show_require = $object->getSignatureType() == $individual; 126 + } 127 + 128 + if ($show_require && $is_admin) { 129 + $fields[] = 130 + id(new PhabricatorBoolEditField()) 131 + ->setKey('requireSignature') 132 + ->setOptions( 133 + pht('No Signature Required'), 134 + pht('Signature Required to use Phabricator')) 135 + ->setAsCheckbox(true) 136 + ->setTransactionType( 137 + LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE) 138 + ->setDescription(pht('Marks this document as required signing.')) 139 + ->setConduitDescription( 140 + pht('Marks this document as required signing.')) 141 + ->setValue($object->getRequireSignature()); 142 + } 143 + 144 + $fields[] = 145 + id(new PhabricatorRemarkupEditField()) 146 + ->setKey('preamble') 147 + ->setLabel(pht('Preamble')) 148 + ->setDescription(pht('The preamble of the document.')) 149 + ->setConduitTypeDescription(pht('New document preamble.')) 150 + ->setValue($object->getPreamble()) 151 + ->setTransactionType( 152 + LegalpadDocumentPreambleTransaction::TRANSACTIONTYPE); 153 + 154 + $fields[] = 155 + id(new PhabricatorRemarkupEditField()) 156 + ->setKey('text') 157 + ->setLabel(pht('Document Body')) 158 + ->setDescription(pht('The body of text of the document.')) 159 + ->setConduitTypeDescription(pht('New document body.')) 160 + ->setValue($document_body) 161 + ->setIsRequired(true) 162 + ->setTransactionType( 163 + LegalpadDocumentTextTransaction::TRANSACTIONTYPE); 164 + 165 + return $fields; 166 + 167 + } 168 + 169 + }
+39
src/applications/legalpad/editor/LegalpadDocumentEditor.php
··· 21 21 return $types; 22 22 } 23 23 24 + public function getCreateObjectTitle($author, $object) { 25 + return pht('%s created this document.', $author); 26 + } 27 + 28 + public function getCreateObjectTitleForFeed($author, $object) { 29 + return pht('%s created %s.', $author, $object); 30 + } 31 + 24 32 protected function applyFinalEffects( 25 33 PhabricatorLiskDAO $object, 26 34 array $xactions) { ··· 62 70 } 63 71 64 72 return $xactions; 73 + } 74 + 75 + protected function validateAllTransactions(PhabricatorLiskDAO $object, 76 + array $xactions) { 77 + $errors = array(); 78 + 79 + $is_required = (bool)$object->getRequireSignature(); 80 + $document_type = $object->getSignatureType(); 81 + $individual = LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL; 82 + 83 + foreach ($xactions as $xaction) { 84 + switch ($xaction->getTransactionType()) { 85 + case LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE: 86 + $is_required = (bool)$xaction->getNewValue(); 87 + break; 88 + case LegalpadDocumentSignatureTypeTransaction::TRANSACTIONTYPE: 89 + $document_type = $xaction->getNewValue(); 90 + break; 91 + } 92 + } 93 + 94 + if ($is_required && ($document_type != $individual)) { 95 + $errors[] = new PhabricatorApplicationTransactionValidationError( 96 + LegalpadDocumentRequireSignatureTransaction::TRANSACTIONTYPE, 97 + pht('Invalid'), 98 + pht('Only documents with signature type "individual" may '. 99 + 'require signing to use Phabricator.'), 100 + null); 101 + } 102 + 103 + return $errors; 65 104 } 66 105 67 106
+4
src/applications/legalpad/storage/LegalpadDocument.php
··· 120 120 return 'L'.$this->getID(); 121 121 } 122 122 123 + public function getViewURI() { 124 + return '/'.$this->getMonogram(); 125 + } 126 + 123 127 public function getUserSignature($phid) { 124 128 return $this->assertAttachedKey($this->userSignatures, $phid); 125 129 }
+16 -2
src/applications/legalpad/xaction/LegalpadDocumentRequireSignatureTransaction.php
··· 10 10 } 11 11 12 12 public function applyInternalEffects($object, $value) { 13 - $object->setRequireSignature($value); 13 + $object->setRequireSignature((int)$value); 14 14 } 15 15 16 16 public function applyExternalEffects($object, $value) { 17 - if (strlen($value)) { 17 + if ($value) { 18 18 $session = new PhabricatorAuthSession(); 19 19 queryfx( 20 20 $session->establishConnection('w'), ··· 25 25 26 26 public function getTitle() { 27 27 $new = $this->getNewValue(); 28 + 28 29 if ($new) { 29 30 return pht( 30 31 '%s set the document to require signatures.', ··· 49 50 $this->renderAuthor(), 50 51 $this->renderObject()); 51 52 } 53 + } 54 + 55 + public function validateTransactions($object, array $xactions) { 56 + $errors = array(); 57 + 58 + $is_admin = $this->getActor()->getIsAdmin(); 59 + 60 + if (!$is_admin) { 61 + $errors[] = $this->newInvalidError( 62 + pht('Only admins may require signature.')); 63 + } 64 + 65 + return $errors; 52 66 } 53 67 54 68 public function getIcon() {