@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.

Begin transacitonalizing repository edits and provide a more sensible edit interface

Summary:
Ref T2231, T603. Plan of attack here is pretty much:

- Built out a new (currently not linked in the UI) edit interface in Diffusion which is transaction-based and has a sensible layout.
- Build out a new create interface based on PagedForm which dumps into the new edit interface.
- Throw the old stuff away.
- Everyone lives happily ever after.

Test Plan:
{F44163}
{F44164}

Reviewers: chad, btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2231

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

+436 -1
+21
resources/sql/patches/20130524.repoxactions.sql
··· 1 + CREATE TABLE {$NAMESPACE}_repository.repository_transaction ( 2 + id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, 3 + phid VARCHAR(64) NOT NULL COLLATE utf8_bin, 4 + authorPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, 5 + objectPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, 6 + viewPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin, 7 + editPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin, 8 + commentPHID VARCHAR(64) COLLATE utf8_bin, 9 + commentVersion INT UNSIGNED NOT NULL, 10 + transactionType VARCHAR(32) NOT NULL COLLATE utf8_bin, 11 + oldValue LONGTEXT NOT NULL COLLATE utf8_bin, 12 + newValue LONGTEXT NOT NULL COLLATE utf8_bin, 13 + metadata LONGTEXT NOT NULL COLLATE utf8_bin, 14 + contentSource LONGTEXT NOT NULL COLLATE utf8_bin, 15 + dateCreated INT UNSIGNED NOT NULL, 16 + dateModified INT UNSIGNED NOT NULL, 17 + 18 + UNIQUE KEY `key_phid` (phid), 19 + KEY `key_object` (objectPHID) 20 + 21 + ) ENGINE=InnoDB, COLLATE utf8_general_ci;
+10
src/__phutil_library_map__.php
··· 478 478 'DiffusionRemarkupRule' => 'applications/diffusion/remarkup/DiffusionRemarkupRule.php', 479 479 'DiffusionRenameHistoryQuery' => 'applications/diffusion/query/DiffusionRenameHistoryQuery.php', 480 480 'DiffusionRepositoryController' => 'applications/diffusion/controller/DiffusionRepositoryController.php', 481 + 'DiffusionRepositoryEditBasicController' => 'applications/diffusion/controller/DiffusionRepositoryEditBasicController.php', 482 + 'DiffusionRepositoryEditController' => 'applications/diffusion/controller/DiffusionRepositoryEditController.php', 481 483 'DiffusionRepositoryPath' => 'applications/diffusion/data/DiffusionRepositoryPath.php', 482 484 'DiffusionRepositoryTag' => 'applications/diffusion/data/DiffusionRepositoryTag.php', 483 485 'DiffusionRequest' => 'applications/diffusion/request/DiffusionRequest.php', ··· 1320 1322 'PhabricatorRepositoryDeleteController' => 'applications/repository/controller/PhabricatorRepositoryDeleteController.php', 1321 1323 'PhabricatorRepositoryDiscoveryEngine' => 'applications/repository/engine/PhabricatorRepositoryDiscoveryEngine.php', 1322 1324 'PhabricatorRepositoryEditController' => 'applications/repository/controller/PhabricatorRepositoryEditController.php', 1325 + 'PhabricatorRepositoryEditor' => 'applications/repository/editor/PhabricatorRepositoryEditor.php', 1323 1326 'PhabricatorRepositoryEngine' => 'applications/repository/engine/PhabricatorRepositoryEngine.php', 1324 1327 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryGitCommitChangeParserWorker.php', 1325 1328 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryGitCommitMessageParserWorker.php', ··· 1339 1342 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositorySvnCommitMessageParserWorker.php', 1340 1343 'PhabricatorRepositorySymbol' => 'applications/repository/storage/PhabricatorRepositorySymbol.php', 1341 1344 'PhabricatorRepositoryTestCase' => 'applications/repository/storage/__tests__/PhabricatorRepositoryTestCase.php', 1345 + 'PhabricatorRepositoryTransaction' => 'applications/repository/storage/PhabricatorRepositoryTransaction.php', 1346 + 'PhabricatorRepositoryTransactionQuery' => 'applications/repository/query/PhabricatorRepositoryTransactionQuery.php', 1342 1347 'PhabricatorRepositoryType' => 'applications/repository/constants/PhabricatorRepositoryType.php', 1343 1348 'PhabricatorS3FileStorageEngine' => 'applications/files/engine/PhabricatorS3FileStorageEngine.php', 1344 1349 'PhabricatorSQLPatchList' => 'infrastructure/storage/patch/PhabricatorSQLPatchList.php', ··· 2274 2279 'DiffusionRawDiffQuery' => 'DiffusionQuery', 2275 2280 'DiffusionRemarkupRule' => 'PhabricatorRemarkupRuleObject', 2276 2281 'DiffusionRepositoryController' => 'DiffusionController', 2282 + 'DiffusionRepositoryEditBasicController' => 'DiffusionController', 2283 + 'DiffusionRepositoryEditController' => 'DiffusionController', 2277 2284 'DiffusionSetupException' => 'AphrontUsageException', 2278 2285 'DiffusionStableCommitNameQuery' => 'DiffusionQuery', 2279 2286 'DiffusionSvnCommitParentsQuery' => 'DiffusionCommitParentsQuery', ··· 3090 3097 'PhabricatorRepositoryDeleteController' => 'PhabricatorRepositoryController', 3091 3098 'PhabricatorRepositoryDiscoveryEngine' => 'PhabricatorRepositoryEngine', 3092 3099 'PhabricatorRepositoryEditController' => 'PhabricatorRepositoryController', 3100 + 'PhabricatorRepositoryEditor' => 'PhabricatorApplicationTransactionEditor', 3093 3101 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 3094 3102 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 3095 3103 'PhabricatorRepositoryListController' => 'PhabricatorRepositoryController', ··· 3108 3116 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 3109 3117 'PhabricatorRepositorySymbol' => 'PhabricatorRepositoryDAO', 3110 3118 'PhabricatorRepositoryTestCase' => 'PhabricatorTestCase', 3119 + 'PhabricatorRepositoryTransaction' => 'PhabricatorApplicationTransaction', 3120 + 'PhabricatorRepositoryTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 3111 3121 'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine', 3112 3122 'PhabricatorSSHWorkflow' => 'PhutilArgumentWorkflow', 3113 3123 'PhabricatorSavedQuery' => 'PhabricatorSearchDAO',
+4
src/applications/diffusion/application/PhabricatorApplicationDiffusion.php
··· 62 62 => 'DiffusionCommitTagsController', 63 63 'commit/(?P<commit>[a-z0-9]+)/edit/' 64 64 => 'DiffusionCommitEditController', 65 + 'edit/' => array( 66 + '' => 'DiffusionRepositoryEditController', 67 + 'basic/' => 'DiffusionRepositoryEditBasicController', 68 + ), 65 69 ), 66 70 'inline/' => array( 67 71 'edit/(?P<phid>[^/]+)/' => 'DiffusionInlineCommentController',
+7
src/applications/diffusion/controller/DiffusionController.php
··· 334 334 $method, 335 335 $params); 336 336 } 337 + 338 + protected function getRepositoryControllerURI( 339 + PhabricatorRepository $repository, 340 + $path) { 341 + return $this->getApplicationURI($repository->getCallsign().'/'.$path); 342 + } 343 + 337 344 }
+115
src/applications/diffusion/controller/DiffusionRepositoryEditBasicController.php
··· 1 + <?php 2 + 3 + final class DiffusionRepositoryEditBasicController extends DiffusionController { 4 + 5 + public function processRequest() { 6 + $request = $this->getRequest(); 7 + $user = $request->getUser(); 8 + $drequest = $this->diffusionRequest; 9 + $repository = $drequest->getRepository(); 10 + 11 + $repository = id(new PhabricatorRepositoryQuery()) 12 + ->setViewer($user) 13 + ->requireCapabilities( 14 + array( 15 + PhabricatorPolicyCapability::CAN_VIEW, 16 + PhabricatorPolicyCapability::CAN_EDIT, 17 + )) 18 + ->withIDs(array($repository->getID())) 19 + ->executeOne(); 20 + 21 + if (!$repository) { 22 + return new Aphront404Response(); 23 + } 24 + 25 + $edit_uri = $this->getRepositoryControllerURI($repository, 'edit/'); 26 + 27 + $v_name = $repository->getName(); 28 + $v_desc = $repository->getDetail('description'); 29 + $e_name = true; 30 + $errors = array(); 31 + 32 + if ($request->isFormPost()) { 33 + $v_name = $request->getStr('name'); 34 + $v_desc = $request->getStr('description'); 35 + 36 + if (!strlen($v_name)) { 37 + $e_name = pht('Required'); 38 + $errors[] = pht('Repository name is required.'); 39 + } else { 40 + $e_name = null; 41 + } 42 + 43 + if (!$errors) { 44 + $xactions = array(); 45 + $template = id(new PhabricatorRepositoryTransaction()); 46 + 47 + $type_name = PhabricatorRepositoryTransaction::TYPE_NAME; 48 + $type_desc = PhabricatorRepositoryTransaction::TYPE_DESCRIPTION; 49 + 50 + $xactions[] = id(clone $template) 51 + ->setTransactionType($type_name) 52 + ->setNewValue($v_name); 53 + 54 + $xactions[] = id(clone $template) 55 + ->setTransactionType($type_desc) 56 + ->setNewValue($v_desc); 57 + 58 + id(new PhabricatorRepositoryEditor()) 59 + ->setContinueOnNoEffect(true) 60 + ->setContentSourceFromRequest($request) 61 + ->setActor($user) 62 + ->applyTransactions($repository, $xactions); 63 + 64 + return id(new AphrontRedirectResponse())->setURI($edit_uri); 65 + } 66 + } 67 + 68 + $content = array(); 69 + 70 + $crumbs = $this->buildCrumbs(); 71 + $crumbs->addCrumb( 72 + id(new PhabricatorCrumbView()) 73 + ->setName(pht('Edit Basics'))); 74 + $content[] = $crumbs; 75 + 76 + $title = pht('Edit %s', $repository->getName()); 77 + 78 + if ($errors) { 79 + $content[] = id(new AphrontErrorView()) 80 + ->setTitle(pht('Form Errors')) 81 + ->setErrors($errors); 82 + } 83 + 84 + $form = id(new AphrontFormView()) 85 + ->setUser($user) 86 + ->setFlexible(true) 87 + ->appendChild( 88 + id(new AphrontFormTextControl()) 89 + ->setName('name') 90 + ->setLabel(pht('Name')) 91 + ->setValue($v_name) 92 + ->setError($e_name)) 93 + ->appendChild( 94 + id(new AphrontFormTextAreaControl()) 95 + ->setName('description') 96 + ->setLabel(pht('Description')) 97 + ->setValue($v_desc)) 98 + ->appendChild( 99 + id(new AphrontFormSubmitControl()) 100 + ->setValue(pht('Save')) 101 + ->addCancelButton($edit_uri)); 102 + 103 + $content[] = $form; 104 + 105 + return $this->buildApplicationPage( 106 + $content, 107 + array( 108 + 'title' => $title, 109 + 'dust' => true, 110 + 'device' => true, 111 + )); 112 + } 113 + 114 + 115 + }
+112
src/applications/diffusion/controller/DiffusionRepositoryEditController.php
··· 1 + <?php 2 + 3 + final class DiffusionRepositoryEditController extends DiffusionController { 4 + 5 + public function processRequest() { 6 + $request = $this->getRequest(); 7 + $user = $request->getUser(); 8 + $drequest = $this->diffusionRequest; 9 + $repository = $drequest->getRepository(); 10 + 11 + $content = array(); 12 + 13 + $crumbs = $this->buildCrumbs(); 14 + $crumbs->addCrumb( 15 + id(new PhabricatorCrumbView()) 16 + ->setName(pht('Edit'))); 17 + $content[] = $crumbs; 18 + 19 + $title = pht('Edit %s', $repository->getName()); 20 + 21 + $content[] = id(new PhabricatorHeaderView()) 22 + ->setHeader($title); 23 + 24 + $content[] = $this->buildBasicActions($repository); 25 + $content[] = $this->buildBasicProperties($repository); 26 + 27 + 28 + $content[] = id(new PhabricatorHeaderView()) 29 + ->setHeader(pht('Edit History')); 30 + 31 + $xactions = id(new PhabricatorRepositoryTransactionQuery()) 32 + ->setViewer($user) 33 + ->withObjectPHIDs(array($repository->getPHID())) 34 + ->execute(); 35 + 36 + $engine = id(new PhabricatorMarkupEngine()) 37 + ->setViewer($user); 38 + foreach ($xactions as $xaction) { 39 + if ($xaction->getComment()) { 40 + $engine->addObject( 41 + $xaction->getComment(), 42 + PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT); 43 + } 44 + } 45 + $engine->process(); 46 + 47 + $xaction_view = id(new PhabricatorApplicationTransactionView()) 48 + ->setUser($user) 49 + ->setTransactions($xactions) 50 + ->setMarkupEngine($engine); 51 + 52 + $content[] = $xaction_view; 53 + 54 + 55 + return $this->buildApplicationPage( 56 + $content, 57 + array( 58 + 'title' => $title, 59 + 'device' => true, 60 + 'dust' => true, 61 + )); 62 + } 63 + 64 + private function buildBasicActions(PhabricatorRepository $repository) { 65 + $user = $this->getRequest()->getUser(); 66 + 67 + $view = id(new PhabricatorActionListView()) 68 + ->setUser($user); 69 + 70 + $can_edit = PhabricatorPolicyFilter::hasCapability( 71 + $user, 72 + $repository, 73 + PhabricatorPolicyCapability::CAN_EDIT); 74 + 75 + $edit = id(new PhabricatorActionView()) 76 + ->setIcon('edit') 77 + ->setName(pht('Edit Basic Information')) 78 + ->setHref($this->getRepositoryControllerURI($repository, 'edit/basic/')) 79 + ->setDisabled(!$can_edit); 80 + $view->addAction($edit); 81 + 82 + return $view; 83 + } 84 + 85 + private function buildBasicProperties(PhabricatorRepository $repository) { 86 + $view = id(new PhabricatorPropertyListView()) 87 + ->setUser($this->getRequest()->getUser()) 88 + ->setObject($repository); 89 + 90 + $view->addProperty(pht('Name'), $repository->getName()); 91 + $view->addProperty(pht('ID'), $repository->getID()); 92 + $view->addProperty(pht('PHID'), $repository->getPHID()); 93 + 94 + $type = PhabricatorRepositoryType::getNameForRepositoryType( 95 + $repository->getVersionControlSystem()); 96 + 97 + $view->addProperty(pht('Type'), $type); 98 + $view->addProperty(pht('Callsign'), $repository->getCallsign()); 99 + 100 + $description = $repository->getDetail('description'); 101 + if (!strlen($description)) { 102 + $description = phutil_tag('em', array(), pht('None')); 103 + } 104 + $view->addProperty(pht('Description'), $description); 105 + 106 + 107 + return $view; 108 + } 109 + 110 + 111 + 112 + }
+84
src/applications/repository/editor/PhabricatorRepositoryEditor.php
··· 1 + <?php 2 + 3 + final class PhabricatorRepositoryEditor 4 + extends PhabricatorApplicationTransactionEditor { 5 + 6 + public function getTransactionTypes() { 7 + $types = parent::getTransactionTypes(); 8 + 9 + $types[] = PhabricatorRepositoryTransaction::TYPE_NAME; 10 + $types[] = PhabricatorRepositoryTransaction::TYPE_DESCRIPTION; 11 + 12 + return $types; 13 + } 14 + 15 + protected function getCustomTransactionOldValue( 16 + PhabricatorLiskDAO $object, 17 + PhabricatorApplicationTransaction $xaction) { 18 + 19 + switch ($xaction->getTransactionType()) { 20 + case PhabricatorRepositoryTransaction::TYPE_NAME: 21 + return $object->getName(); 22 + case PhabricatorRepositoryTransaction::TYPE_DESCRIPTION: 23 + return $object->getDetail('description'); 24 + } 25 + } 26 + 27 + protected function getCustomTransactionNewValue( 28 + PhabricatorLiskDAO $object, 29 + PhabricatorApplicationTransaction $xaction) { 30 + 31 + switch ($xaction->getTransactionType()) { 32 + case PhabricatorRepositoryTransaction::TYPE_NAME: 33 + case PhabricatorRepositoryTransaction::TYPE_DESCRIPTION: 34 + return $xaction->getNewValue(); 35 + } 36 + } 37 + 38 + protected function applyCustomInternalTransaction( 39 + PhabricatorLiskDAO $object, 40 + PhabricatorApplicationTransaction $xaction) { 41 + 42 + switch ($xaction->getTransactionType()) { 43 + case PhabricatorRepositoryTransaction::TYPE_NAME: 44 + $object->setName($xaction->getNewValue()); 45 + break; 46 + case PhabricatorRepositoryTransaction::TYPE_DESCRIPTION: 47 + $object->setDetail('description', $xaction->getNewValue()); 48 + break; 49 + } 50 + } 51 + 52 + protected function applyCustomExternalTransaction( 53 + PhabricatorLiskDAO $object, 54 + PhabricatorApplicationTransaction $xaction) { 55 + return; 56 + } 57 + 58 + protected function mergeTransactions( 59 + PhabricatorApplicationTransaction $u, 60 + PhabricatorApplicationTransaction $v) { 61 + 62 + $type = $u->getTransactionType(); 63 + switch ($type) { 64 + } 65 + 66 + return parent::mergeTransactions($u, $v); 67 + } 68 + 69 + protected function transactionHasEffect( 70 + PhabricatorLiskDAO $object, 71 + PhabricatorApplicationTransaction $xaction) { 72 + 73 + $old = $xaction->getOldValue(); 74 + $new = $xaction->getNewValue(); 75 + 76 + $type = $xaction->getTransactionType(); 77 + switch ($type) { 78 + 79 + } 80 + 81 + return parent::transactionHasEffect($object, $xaction); 82 + } 83 + 84 + }
+10
src/applications/repository/query/PhabricatorRepositoryTransactionQuery.php
··· 1 + <?php 2 + 3 + final class PhabricatorRepositoryTransactionQuery 4 + extends PhabricatorApplicationTransactionQuery { 5 + 6 + protected function getTemplateApplicationTransaction() { 7 + return new PhabricatorRepositoryTransaction(); 8 + } 9 + 10 + }
+69
src/applications/repository/storage/PhabricatorRepositoryTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorRepositoryTransaction 4 + extends PhabricatorApplicationTransaction { 5 + 6 + const TYPE_NAME = 'repo:name'; 7 + const TYPE_DESCRIPTION = 'repo:description'; 8 + 9 + public function getApplicationName() { 10 + return 'repository'; 11 + } 12 + 13 + public function getApplicationTransactionType() { 14 + return PhabricatorPHIDConstants::PHID_TYPE_REPO; 15 + } 16 + 17 + public function getApplicationTransactionCommentObject() { 18 + return null; 19 + } 20 + 21 + public function getApplicationObjectTypeName() { 22 + return pht('repository'); 23 + } 24 + 25 + public function getTitle() { 26 + $author_phid = $this->getAuthorPHID(); 27 + 28 + $old = $this->getOldValue(); 29 + $new = $this->getNewValue(); 30 + 31 + switch ($this->getTransactionType()) { 32 + case self::TYPE_NAME: 33 + return pht( 34 + '%s renamed this repository from "%s" to "%s".', 35 + $this->renderHandleLink($author_phid), 36 + $old, 37 + $new); 38 + case self::TYPE_DESCRIPTION: 39 + return pht( 40 + '%s updated the description of this repository.', 41 + $this->renderHandleLink($author_phid)); 42 + } 43 + 44 + return parent::getTitle(); 45 + } 46 + 47 + public function hasChangeDetails() { 48 + switch ($this->getTransactionType()) { 49 + case self::TYPE_DESCRIPTION: 50 + return true; 51 + } 52 + return parent::hasChangeDetails(); 53 + } 54 + 55 + public function renderChangeDetails(PhabricatorUser $viewer) { 56 + $old = $this->getOldValue(); 57 + $new = $this->getNewValue(); 58 + 59 + $view = id(new PhabricatorApplicationTransactionTextDiffDetailView()) 60 + ->setUser($viewer) 61 + ->setOldText($old) 62 + ->setNewText($new); 63 + 64 + return $view->render(); 65 + } 66 + 67 + 68 + } 69 +
+4 -1
src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
··· 1314 1314 'type' => 'sql', 1315 1315 'name' => $this->getPatchPath('20130523.maniphest_owners.sql'), 1316 1316 ), 1317 - 1317 + '20130524.repoxactions.sql' => array( 1318 + 'type' => 'sql', 1319 + 'name' => $this->getPatchPath('20130524.repoxactions.sql'), 1320 + ), 1318 1321 ); 1319 1322 } 1320 1323 }