@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

Move Owners to EditEngine

Summary:
Ref T9132. Paste is in fairly good shape so Owners is up next. Reasoning:

- One install wants API access for it.
- It's a simple application for getting CustomFields working with EditEngine.

This only does the EditEngine part, so CustomFields are no longer editable until I make that work. That will be up next, and I'll hold this until that's ready.

Test Plan:
- Created and edited packages via web UI.
- Created and edited package editing forms via web UI.
- Created and edited packages via Conduit.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9132

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

+159 -249
+4
src/__phutil_library_map__.php
··· 1403 1403 'NuanceSourceViewController' => 'applications/nuance/controller/NuanceSourceViewController.php', 1404 1404 'NuanceTransaction' => 'applications/nuance/storage/NuanceTransaction.php', 1405 1405 'OwnersConduitAPIMethod' => 'applications/owners/conduit/OwnersConduitAPIMethod.php', 1406 + 'OwnersEditConduitAPIMethod' => 'applications/owners/conduit/OwnersEditConduitAPIMethod.php', 1406 1407 'OwnersPackageReplyHandler' => 'applications/owners/mail/OwnersPackageReplyHandler.php', 1407 1408 'OwnersQueryConduitAPIMethod' => 'applications/owners/conduit/OwnersQueryConduitAPIMethod.php', 1408 1409 'PHIDConduitAPIMethod' => 'applications/phid/conduit/PHIDConduitAPIMethod.php', ··· 2564 2565 'PhabricatorOwnersOwner' => 'applications/owners/storage/PhabricatorOwnersOwner.php', 2565 2566 'PhabricatorOwnersPackage' => 'applications/owners/storage/PhabricatorOwnersPackage.php', 2566 2567 'PhabricatorOwnersPackageDatasource' => 'applications/owners/typeahead/PhabricatorOwnersPackageDatasource.php', 2568 + 'PhabricatorOwnersPackageEditEngine' => 'applications/owners/editor/PhabricatorOwnersPackageEditEngine.php', 2567 2569 'PhabricatorOwnersPackageFunctionDatasource' => 'applications/owners/typeahead/PhabricatorOwnersPackageFunctionDatasource.php', 2568 2570 'PhabricatorOwnersPackageOwnerDatasource' => 'applications/owners/typeahead/PhabricatorOwnersPackageOwnerDatasource.php', 2569 2571 'PhabricatorOwnersPackagePHIDType' => 'applications/owners/phid/PhabricatorOwnersPackagePHIDType.php', ··· 5398 5400 'NuanceSourceViewController' => 'NuanceController', 5399 5401 'NuanceTransaction' => 'PhabricatorApplicationTransaction', 5400 5402 'OwnersConduitAPIMethod' => 'ConduitAPIMethod', 5403 + 'OwnersEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 5401 5404 'OwnersPackageReplyHandler' => 'PhabricatorMailReplyHandler', 5402 5405 'OwnersQueryConduitAPIMethod' => 'OwnersConduitAPIMethod', 5403 5406 'PHIDConduitAPIMethod' => 'ConduitAPIMethod', ··· 6741 6744 'PhabricatorCustomFieldInterface', 6742 6745 ), 6743 6746 'PhabricatorOwnersPackageDatasource' => 'PhabricatorTypeaheadDatasource', 6747 + 'PhabricatorOwnersPackageEditEngine' => 'PhabricatorEditEngine', 6744 6748 'PhabricatorOwnersPackageFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 6745 6749 'PhabricatorOwnersPackageOwnerDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 6746 6750 'PhabricatorOwnersPackagePHIDType' => 'PhabricatorPHIDType',
+3 -1
src/applications/owners/application/PhabricatorOwnersApplication.php
··· 43 43 return array( 44 44 '/owners/' => array( 45 45 '(?:query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorOwnersListController', 46 - 'edit/(?P<id>[1-9]\d*)/' => 'PhabricatorOwnersEditController', 47 46 'new/' => 'PhabricatorOwnersEditController', 48 47 'package/(?P<id>[1-9]\d*)/' => 'PhabricatorOwnersDetailController', 49 48 'paths/(?P<id>[1-9]\d*)/' => 'PhabricatorOwnersPathsController', 49 + 50 + $this->getEditRoutePattern('edit/') 51 + => 'PhabricatorOwnersEditController', 50 52 ), 51 53 ); 52 54 }
+20
src/applications/owners/conduit/OwnersEditConduitAPIMethod.php
··· 1 + <?php 2 + 3 + final class OwnersEditConduitAPIMethod 4 + extends PhabricatorEditEngineAPIMethod { 5 + 6 + public function getAPIMethodName() { 7 + return 'owners.edit'; 8 + } 9 + 10 + public function newEditEngine() { 11 + return new PhabricatorOwnersPackageEditEngine(); 12 + } 13 + 14 + public function getMethodSummary() { 15 + return pht( 16 + 'Apply transactions to create a new Owners package or edit an existing '. 17 + 'one.'); 18 + } 19 + 20 + }
+3 -195
src/applications/owners/controller/PhabricatorOwnersEditController.php
··· 4 4 extends PhabricatorOwnersController { 5 5 6 6 public function handleRequest(AphrontRequest $request) { 7 - $viewer = $request->getUser(); 8 - 9 - $id = $request->getURIData('id'); 10 - if ($id) { 11 - $package = id(new PhabricatorOwnersPackageQuery()) 12 - ->setViewer($viewer) 13 - ->withIDs(array($id)) 14 - ->requireCapabilities( 15 - array( 16 - PhabricatorPolicyCapability::CAN_VIEW, 17 - // TODO: Support this capability. 18 - // PhabricatorPolicyCapability::CAN_EDIT, 19 - )) 20 - ->needOwners(true) 21 - ->executeOne(); 22 - if (!$package) { 23 - return new Aphront404Response(); 24 - } 25 - $is_new = false; 26 - } else { 27 - $package = PhabricatorOwnersPackage::initializeNewPackage($viewer); 28 - $is_new = true; 29 - } 30 - 31 - $e_name = true; 32 - 33 - $v_name = $package->getName(); 34 - $v_owners = mpull($package->getOwners(), 'getUserPHID'); 35 - $v_auditing = $package->getAuditingEnabled(); 36 - $v_description = $package->getDescription(); 37 - $v_status = $package->getStatus(); 38 - 39 - $field_list = PhabricatorCustomField::getObjectFields( 40 - $package, 41 - PhabricatorCustomField::ROLE_EDIT); 42 - $field_list->setViewer($viewer); 43 - $field_list->readFieldsFromStorage($package); 44 - 45 - $errors = array(); 46 - if ($request->isFormPost()) { 47 - $xactions = array(); 48 - 49 - $v_name = $request->getStr('name'); 50 - $v_owners = $request->getArr('owners'); 51 - $v_auditing = ($request->getStr('auditing') == 'enabled'); 52 - $v_description = $request->getStr('description'); 53 - $v_status = $request->getStr('status'); 54 - 55 - $type_name = PhabricatorOwnersPackageTransaction::TYPE_NAME; 56 - $type_owners = PhabricatorOwnersPackageTransaction::TYPE_OWNERS; 57 - $type_auditing = PhabricatorOwnersPackageTransaction::TYPE_AUDITING; 58 - $type_description = PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION; 59 - $type_status = PhabricatorOwnersPackageTransaction::TYPE_STATUS; 60 - 61 - $xactions[] = id(new PhabricatorOwnersPackageTransaction()) 62 - ->setTransactionType($type_name) 63 - ->setNewValue($v_name); 64 - 65 - $xactions[] = id(new PhabricatorOwnersPackageTransaction()) 66 - ->setTransactionType($type_owners) 67 - ->setNewValue($v_owners); 68 - 69 - $xactions[] = id(new PhabricatorOwnersPackageTransaction()) 70 - ->setTransactionType($type_auditing) 71 - ->setNewValue($v_auditing); 72 - 73 - $xactions[] = id(new PhabricatorOwnersPackageTransaction()) 74 - ->setTransactionType($type_description) 75 - ->setNewValue($v_description); 76 - 77 - if (!$is_new) { 78 - $xactions[] = id(new PhabricatorOwnersPackageTransaction()) 79 - ->setTransactionType($type_status) 80 - ->setNewValue($v_status); 81 - } 82 - 83 - $field_xactions = $field_list->buildFieldTransactionsFromRequest( 84 - new PhabricatorOwnersPackageTransaction(), 85 - $request); 86 - 87 - $xactions = array_merge($xactions, $field_xactions); 88 - 89 - $editor = id(new PhabricatorOwnersPackageTransactionEditor()) 90 - ->setActor($viewer) 91 - ->setContentSourceFromRequest($request) 92 - ->setContinueOnNoEffect(true); 93 - 94 - try { 95 - $editor->applyTransactions($package, $xactions); 96 - 97 - $id = $package->getID(); 98 - if ($is_new) { 99 - $next_uri = '/owners/paths/'.$id.'/'; 100 - } else { 101 - $next_uri = '/owners/package/'.$id.'/'; 102 - } 103 - 104 - return id(new AphrontRedirectResponse())->setURI($next_uri); 105 - } catch (AphrontDuplicateKeyQueryException $ex) { 106 - $e_name = pht('Duplicate'); 107 - $errors[] = pht('Package name must be unique.'); 108 - } catch (PhabricatorApplicationTransactionValidationException $ex) { 109 - $validation_exception = $ex; 110 - 111 - $e_name = $ex->getShortMessage($type_name); 112 - } 113 - } 114 - 115 - if ($is_new) { 116 - $cancel_uri = '/owners/'; 117 - $title = pht('New Package'); 118 - $button_text = pht('Continue'); 119 - } else { 120 - $cancel_uri = '/owners/package/'.$package->getID().'/'; 121 - $title = pht('Edit Package'); 122 - $button_text = pht('Save Package'); 123 - } 124 - 125 - $form = id(new AphrontFormView()) 126 - ->setUser($viewer) 127 - ->appendChild( 128 - id(new AphrontFormTextControl()) 129 - ->setLabel(pht('Name')) 130 - ->setName('name') 131 - ->setValue($v_name) 132 - ->setError($e_name)) 133 - ->appendControl( 134 - id(new AphrontFormTokenizerControl()) 135 - ->setDatasource(new PhabricatorProjectOrUserDatasource()) 136 - ->setLabel(pht('Owners')) 137 - ->setName('owners') 138 - ->setValue($v_owners)); 139 - 140 - if (!$is_new) { 141 - $form->appendChild( 142 - id(new AphrontFormSelectControl()) 143 - ->setLabel(pht('Status')) 144 - ->setName('status') 145 - ->setValue($v_status) 146 - ->setOptions($package->getStatusNameMap())); 147 - } 148 - 149 - $form->appendChild( 150 - id(new AphrontFormSelectControl()) 151 - ->setName('auditing') 152 - ->setLabel(pht('Auditing')) 153 - ->setCaption( 154 - pht( 155 - 'With auditing enabled, all future commits that touch '. 156 - 'this package will be reviewed to make sure an owner '. 157 - 'of the package is involved and the commit message has '. 158 - 'a valid revision, reviewed by, and author.')) 159 - ->setOptions( 160 - array( 161 - 'disabled' => pht('Disabled'), 162 - 'enabled' => pht('Enabled'), 163 - )) 164 - ->setValue(($v_auditing ? 'enabled' : 'disabled'))) 165 - ->appendChild( 166 - id(new PhabricatorRemarkupControl()) 167 - ->setUser($viewer) 168 - ->setLabel(pht('Description')) 169 - ->setName('description') 170 - ->setValue($v_description)); 171 - 172 - $field_list->appendFieldsToForm($form); 173 - 174 - $form->appendChild( 175 - id(new AphrontFormSubmitControl()) 176 - ->addCancelButton($cancel_uri) 177 - ->setValue($button_text)); 178 - 179 - $form_box = id(new PHUIObjectBoxView()) 180 - ->setHeaderText($title) 181 - ->setFormErrors($errors) 182 - ->setForm($form); 183 - 184 - $crumbs = $this->buildApplicationCrumbs(); 185 - if ($package->getID()) { 186 - $crumbs->addTextCrumb( 187 - $package->getName(), 188 - $this->getApplicationURI('package/'.$package->getID().'/')); 189 - $crumbs->addTextCrumb(pht('Edit')); 190 - } else { 191 - $crumbs->addTextCrumb(pht('New Package')); 192 - } 193 - 194 - return $this->buildApplicationPage( 195 - array( 196 - $crumbs, 197 - $form_box, 198 - ), 199 - array( 200 - 'title' => $title, 201 - )); 7 + return id(new PhabricatorOwnersPackageEditEngine()) 8 + ->setController($this) 9 + ->buildResponse(); 202 10 } 203 11 204 12 }
+6 -34
src/applications/owners/controller/PhabricatorOwnersListController.php
··· 8 8 } 9 9 10 10 public function handleRequest(AphrontRequest $request) { 11 - $controller = id(new PhabricatorApplicationSearchController()) 12 - ->setQueryKey($request->getURIData('queryKey')) 13 - ->setSearchEngine(new PhabricatorOwnersPackageSearchEngine()) 14 - ->setNavigation($this->buildSideNavView()); 15 - 16 - return $this->delegateToController($controller); 17 - } 18 - 19 - public function buildSideNavView($for_app = false) { 20 - $viewer = $this->getViewer(); 21 - 22 - $nav = new AphrontSideNavFilterView(); 23 - $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); 24 - 25 - if ($for_app) { 26 - $nav->addFilter('new/', pht('Create Package')); 27 - } 28 - 29 - id(new PhabricatorOwnersPackageSearchEngine()) 30 - ->setViewer($viewer) 31 - ->addNavigationItems($nav->getMenu()); 32 - 33 - $nav->selectFilter(null); 34 - 35 - return $nav; 36 - } 37 - 38 - public function buildApplicationMenu() { 39 - return $this->buildSideNavView(true)->getMenu(); 11 + return id(new PhabricatorOwnersPackageSearchEngine()) 12 + ->setController($this) 13 + ->buildResponse(); 40 14 } 41 15 42 16 protected function buildApplicationCrumbs() { 43 17 $crumbs = parent::buildApplicationCrumbs(); 44 18 45 - $crumbs->addAction( 46 - id(new PHUIListItemView()) 47 - ->setName(pht('Create Package')) 48 - ->setHref($this->getApplicationURI('new/')) 49 - ->setIcon('fa-plus-square')); 19 + id(new PhabricatorOwnersPackageEditEngine()) 20 + ->setViewer($this->getViewer()) 21 + ->addActionToCrumbs($crumbs); 50 22 51 23 return $crumbs; 52 24 }
+93
src/applications/owners/editor/PhabricatorOwnersPackageEditEngine.php
··· 1 + <?php 2 + 3 + final class PhabricatorOwnersPackageEditEngine 4 + extends PhabricatorEditEngine { 5 + 6 + const ENGINECONST = 'owners.package'; 7 + 8 + public function getEngineName() { 9 + return pht('Owners Packages'); 10 + } 11 + 12 + public function getEngineApplicationClass() { 13 + return 'PhabricatorOwnersApplication'; 14 + } 15 + 16 + protected function newEditableObject() { 17 + return PhabricatorOwnersPackage::initializeNewPackage($this->getViewer()); 18 + } 19 + 20 + protected function newObjectQuery() { 21 + return id(new PhabricatorOwnersPackageQuery()) 22 + ->needOwners(true); 23 + } 24 + 25 + protected function getObjectCreateTitleText($object) { 26 + return pht('Create New Package'); 27 + } 28 + 29 + protected function getObjectEditTitleText($object) { 30 + return pht('Edit Package %s', $object->getName()); 31 + } 32 + 33 + protected function getObjectEditShortText($object) { 34 + return pht('Package %d', $object->getID()); 35 + } 36 + 37 + protected function getObjectCreateShortText() { 38 + return pht('Create Package'); 39 + } 40 + 41 + protected function getObjectViewURI($object) { 42 + $id = $object->getID(); 43 + return "/owners/package/{$id}/"; 44 + } 45 + 46 + protected function buildCustomEditFields($object) { 47 + return array( 48 + id(new PhabricatorTextEditField()) 49 + ->setKey('name') 50 + ->setLabel(pht('Name')) 51 + ->setDescription(pht('Name of the package.')) 52 + ->setTransactionType(PhabricatorOwnersPackageTransaction::TYPE_NAME) 53 + ->setIsRequired(true) 54 + ->setValue($object->getName()), 55 + id(new PhabricatorDatasourceEditField()) 56 + ->setKey('owners') 57 + ->setLabel(pht('Owners')) 58 + ->setDescription(pht('Users and projects which own the package.')) 59 + ->setTransactionType(PhabricatorOwnersPackageTransaction::TYPE_OWNERS) 60 + ->setDatasource(new PhabricatorProjectOrUserDatasource()) 61 + ->setValue($object->getOwnerPHIDs()), 62 + id(new PhabricatorSelectEditField()) 63 + ->setKey('status') 64 + ->setLabel(pht('Status')) 65 + ->setDescription(pht('Archive or enable the package.')) 66 + ->setTransactionType(PhabricatorOwnersPackageTransaction::TYPE_STATUS) 67 + ->setValue($object->getStatus()) 68 + ->setOptions($object->getStatusNameMap()), 69 + id(new PhabricatorSelectEditField()) 70 + ->setKey('auditing') 71 + ->setLabel(pht('Auditing')) 72 + ->setDescription( 73 + pht( 74 + 'Automatically trigger audits for commits affecting files in '. 75 + 'this package.')) 76 + ->setTransactionType(PhabricatorOwnersPackageTransaction::TYPE_AUDITING) 77 + ->setValue($object->getAuditingEnabled()) 78 + ->setOptions( 79 + array( 80 + '' => pht('Disabled'), 81 + '1' => pht('Enabled'), 82 + )), 83 + id(new PhabricatorRemarkupEditField()) 84 + ->setKey('description') 85 + ->setLabel(pht('Description')) 86 + ->setDescription(pht('Human-readable description of the package.')) 87 + ->setTransactionType( 88 + PhabricatorOwnersPackageTransaction::TYPE_DESCRIPTION) 89 + ->setValue($object->getDescription()), 90 + ); 91 + } 92 + 93 + }
+30 -19
src/applications/owners/storage/PhabricatorOwnersPackage.php
··· 27 27 ->setAuditingEnabled(0) 28 28 ->attachPaths(array()) 29 29 ->setStatus(self::STATUS_ACTIVE) 30 - ->attachOwners(array()); 31 - } 32 - 33 - public function getCapabilities() { 34 - return array( 35 - PhabricatorPolicyCapability::CAN_VIEW, 36 - ); 37 - } 38 - 39 - public function getPolicy($capability) { 40 - return PhabricatorPolicies::POLICY_USER; 41 - } 42 - 43 - public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 44 - return false; 45 - } 46 - 47 - public function describeAutomaticCapability($capability) { 48 - return null; 30 + ->attachOwners(array()) 31 + ->setDescription(''); 49 32 } 50 33 51 34 public static function getStatusNameMap() { ··· 282 265 283 266 public function getOwners() { 284 267 return $this->assertAttached($this->owners); 268 + } 269 + 270 + public function getOwnerPHIDs() { 271 + return mpull($this->getOwners(), 'getUserPHID'); 272 + } 273 + 274 + 275 + /* -( PhabricatorPolicyInterface )----------------------------------------- */ 276 + 277 + 278 + public function getCapabilities() { 279 + return array( 280 + PhabricatorPolicyCapability::CAN_VIEW, 281 + PhabricatorPolicyCapability::CAN_EDIT, 282 + ); 283 + } 284 + 285 + public function getPolicy($capability) { 286 + // TODO: Implement proper policies. 287 + return PhabricatorPolicies::POLICY_USER; 288 + } 289 + 290 + public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 291 + return false; 292 + } 293 + 294 + public function describeAutomaticCapability($capability) { 295 + return null; 285 296 } 286 297 287 298