From fd27538e8927e6ad9210270112d63f1f49f26f05 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 22 Oct 2013 13:49:37 -0700 Subject: [PATCH] Add project history and title strings Summary: Ref T4010. Adds a history page and restores the transaction title strings, which previously sort-of existed in the defunct feed story class. Test Plan: See screenshots. Reviewers: chad, btrahan Reviewed By: chad CC: aran Maniphest Tasks: T4010 Differential Revision: https://secure.phabricator.com/D7371 --- src/__phutil_library_map__.php | 4 + .../PhabricatorApplicationProject.php | 1 + .../PhabricatorProjectHistoryController.php | 60 +++++++++++++ .../PhabricatorProjectProfileController.php | 6 ++ .../PhabricatorProjectTransactionQuery.php | 10 +++ .../storage/PhabricatorProjectTransaction.php | 87 +++++++++++++++++++ .../PhabricatorApplicationTransaction.php | 20 +++++ .../PhabricatorBaseEnglishTranslation.php | 17 ++++ 8 files changed, 205 insertions(+) create mode 100644 src/applications/project/controller/PhabricatorProjectHistoryController.php create mode 100644 src/applications/project/query/PhabricatorProjectTransactionQuery.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 62dc507443..a57a4f0865 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1526,6 +1526,7 @@ phutil_register_library_map(array( 'PhabricatorProjectDAO' => 'applications/project/storage/PhabricatorProjectDAO.php', 'PhabricatorProjectEditor' => 'applications/project/editor/PhabricatorProjectEditor.php', 'PhabricatorProjectEditorTestCase' => 'applications/project/editor/__tests__/PhabricatorProjectEditorTestCase.php', + 'PhabricatorProjectHistoryController' => 'applications/project/controller/PhabricatorProjectHistoryController.php', 'PhabricatorProjectListController' => 'applications/project/controller/PhabricatorProjectListController.php', 'PhabricatorProjectMembersEditController' => 'applications/project/controller/PhabricatorProjectMembersEditController.php', 'PhabricatorProjectNameCollisionException' => 'applications/project/exception/PhabricatorProjectNameCollisionException.php', @@ -1541,6 +1542,7 @@ phutil_register_library_map(array( 'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php', 'PhabricatorProjectTestDataGenerator' => 'applications/project/lipsum/PhabricatorProjectTestDataGenerator.php', 'PhabricatorProjectTransaction' => 'applications/project/storage/PhabricatorProjectTransaction.php', + 'PhabricatorProjectTransactionQuery' => 'applications/project/query/PhabricatorProjectTransactionQuery.php', 'PhabricatorProjectUpdateController' => 'applications/project/controller/PhabricatorProjectUpdateController.php', 'PhabricatorQuery' => 'infrastructure/query/PhabricatorQuery.php', 'PhabricatorRecaptchaConfigOptions' => 'applications/config/option/PhabricatorRecaptchaConfigOptions.php', @@ -3752,6 +3754,7 @@ phutil_register_library_map(array( 'PhabricatorProjectDAO' => 'PhabricatorLiskDAO', 'PhabricatorProjectEditor' => 'PhabricatorEditor', 'PhabricatorProjectEditorTestCase' => 'PhabricatorTestCase', + 'PhabricatorProjectHistoryController' => 'PhabricatorProjectController', 'PhabricatorProjectListController' => array( 0 => 'PhabricatorProjectController', @@ -3770,6 +3773,7 @@ phutil_register_library_map(array( 'PhabricatorProjectSearchIndexer' => 'PhabricatorSearchDocumentIndexer', 'PhabricatorProjectTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorProjectTransaction' => 'PhabricatorApplicationTransaction', + 'PhabricatorProjectTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorProjectUpdateController' => 'PhabricatorProjectController', 'PhabricatorRecaptchaConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorRedirectController' => 'PhabricatorController', diff --git a/src/applications/project/application/PhabricatorApplicationProject.php b/src/applications/project/application/PhabricatorApplicationProject.php index e3c455385f..ba7590a56c 100644 --- a/src/applications/project/application/PhabricatorApplicationProject.php +++ b/src/applications/project/application/PhabricatorApplicationProject.php @@ -48,6 +48,7 @@ final class PhabricatorApplicationProject extends PhabricatorApplication { 'board/(?P[1-9]\d*)/' => 'PhabricatorProjectBoardController', 'update/(?P[1-9]\d*)/(?P[^/]+)/' => 'PhabricatorProjectUpdateController', + 'history/(?P[1-9]\d*)/' => 'PhabricatorProjectHistoryController', ), ); } diff --git a/src/applications/project/controller/PhabricatorProjectHistoryController.php b/src/applications/project/controller/PhabricatorProjectHistoryController.php new file mode 100644 index 0000000000..d42c05afe4 --- /dev/null +++ b/src/applications/project/controller/PhabricatorProjectHistoryController.php @@ -0,0 +1,60 @@ +id = $data['id']; + } + + public function processRequest() { + $request = $this->getRequest(); + $viewer = $request->getUser(); + + $id = $this->id; + + $project = id(new PhabricatorProjectQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->executeOne(); + if (!$project) { + return new Aphront404Response(); + } + + $xactions = id(new PhabricatorProjectTransactionQuery()) + ->setViewer($viewer) + ->withObjectPHIDs(array($project->getPHID())) + ->execute(); + + $timeline = id(new PhabricatorApplicationTransactionView()) + ->setUser($viewer) + ->setObjectPHID($project->getPHID()) + ->setTransactions($xactions); + + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName($project->getName()) + ->setHref($this->getApplicationURI("view/{$id}/"))); + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName(pht('History'))); + + return $this->buildApplicationPage( + array( + $crumbs, + $timeline, + ), + array( + 'title' => $project->getName(), + 'device' => true, + )); + } + +} diff --git a/src/applications/project/controller/PhabricatorProjectProfileController.php b/src/applications/project/controller/PhabricatorProjectProfileController.php index d10998444c..826f5e72ac 100644 --- a/src/applications/project/controller/PhabricatorProjectProfileController.php +++ b/src/applications/project/controller/PhabricatorProjectProfileController.php @@ -256,6 +256,12 @@ final class PhabricatorProjectProfileController } $view->addAction($action); + $view->addAction( + id(new PhabricatorActionView()) + ->setName(pht('View History')) + ->setHref($this->getApplicationURI("history/{$id}/")) + ->setIcon('transcript')); + return $view; } diff --git a/src/applications/project/query/PhabricatorProjectTransactionQuery.php b/src/applications/project/query/PhabricatorProjectTransactionQuery.php new file mode 100644 index 0000000000..0211f6c5bc --- /dev/null +++ b/src/applications/project/query/PhabricatorProjectTransactionQuery.php @@ -0,0 +1,10 @@ +getOldValue(); + $new = $this->getNewValue(); + + $req_phids = array(); + switch ($this->getTransactionType()) { + case PhabricatorProjectTransaction::TYPE_MEMBERS: + $add = array_diff($new, $old); + $rem = array_diff($old, $new); + $req_phids = array_merge($add, $rem); + break; + } + + return array_merge($req_phids, parent::getRequiredHandlePHIDs()); + } + + public function getTitle() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + $author_handle = $this->renderHandleLink($this->getAuthorPHID()); + + switch ($this->getTransactionType()) { + case PhabricatorProjectTransaction::TYPE_NAME: + if ($old === null) { + return pht( + '%s created this project.', + $author_handle); + } else { + return pht( + '%s renamed this project from "%s" to "%s".', + $author_handle, + $old, + $new); + } + case PhabricatorProjectTransaction::TYPE_STATUS: + if ($old == 0) { + return pht( + '%s closed this project.', + $author_handle); + } else { + return pht( + '%s reopened this project.', + $author_handle); + } + case PhabricatorProjectTransaction::TYPE_MEMBERS: + $add = array_diff($new, $old); + $rem = array_diff($old, $new); + + if ($add && $rem) { + return pht( + '%s changed project member(s), added %d: %s; removed %d: %s', + $author_handle, + count($add), + $this->renderHandleList($add), + count($rem), + $this->renderHandleList($rem)); + } else if ($add) { + if (count($add) == 1 && (head($add) == $this->getAuthorPHID())) { + return pht( + '%s joined this project.', + $author_handle); + } else { + return pht( + '%s added %d project member(s): %s', + $author_handle, + count($add), + $this->renderHandleList($add)); + } + } else if ($rem) { + if (count($rem) == 1 && (head($rem) == $this->getAuthorPHID())) { + return pht( + '%s left this project.', + $author_handle); + } else { + return pht( + '%s removed %d project member(s): %s', + $author_handle, + count($rem), + $this->renderHandleList($rem)); + } + } + } + + return parent::getTitle(); + } + + } diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index 35b06f11b6..e4fb7c52b9 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -148,6 +148,7 @@ abstract class PhabricatorApplicationTransaction break; case PhabricatorTransactions::TYPE_EDIT_POLICY: case PhabricatorTransactions::TYPE_VIEW_POLICY: + case PhabricatorTransactions::TYPE_JOIN_POLICY: if (!PhabricatorPolicyQuery::isGlobalPolicy($old)) { $phids[] = array($old); } @@ -226,6 +227,7 @@ abstract class PhabricatorApplicationTransaction return 'message'; case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: + case PhabricatorTransactions::TYPE_JOIN_POLICY: return 'lock'; case PhabricatorTransactions::TYPE_EDGE: return 'link'; @@ -242,6 +244,7 @@ abstract class PhabricatorApplicationTransaction switch ($this->getTransactionType()) { case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: + case PhabricatorTransactions::TYPE_JOIN_POLICY: if ($this->getOldValue() === null) { return true; } else { @@ -270,6 +273,10 @@ abstract class PhabricatorApplicationTransaction return pht( 'This %s already has that edit policy.', $this->getApplicationObjectTypeName()); + case PhabricatorTransactions::TYPE_JOIN_POLICY: + return pht( + 'This %s already has that join policy.', + $this->getApplicationObjectTypeName()); case PhabricatorTransactions::TYPE_SUBSCRIBERS: return pht( 'All users are already subscribed to this %s.', @@ -306,6 +313,13 @@ abstract class PhabricatorApplicationTransaction $this->getApplicationObjectTypeName(), $this->renderPolicyName($old), $this->renderPolicyName($new)); + case PhabricatorTransactions::TYPE_JOIN_POLICY: + return pht( + '%s changed the join policy of this %s from "%s" to "%s".', + $this->renderHandleLink($author_phid), + $this->getApplicationObjectTypeName(), + $this->renderPolicyName($old), + $this->renderPolicyName($new)); case PhabricatorTransactions::TYPE_SUBSCRIBERS: $add = array_diff($new, $old); $rem = array_diff($old, $new); @@ -420,6 +434,11 @@ abstract class PhabricatorApplicationTransaction '%s changed the edit policy for %s.', $this->renderHandleLink($author_phid), $this->renderHandleLink($object_phid)); + case PhabricatorTransactions::TYPE_JOIN_POLICY: + return pht( + '%s changed the join policy for %s.', + $this->renderHandleLink($author_phid), + $this->renderHandleLink($object_phid)); case PhabricatorTransactions::TYPE_SUBSCRIBERS: return pht( '%s updated subscribers of %s.', @@ -487,6 +506,7 @@ abstract class PhabricatorApplicationTransaction return pht('Commented On'); case PhabricatorTransactions::TYPE_VIEW_POLICY: case PhabricatorTransactions::TYPE_EDIT_POLICY: + case PhabricatorTransactions::TYPE_JOIN_POLICY: return pht('Changed Policy'); case PhabricatorTransactions::TYPE_SUBSCRIBERS: return pht('Changed Subscribers'); diff --git a/src/infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php b/src/infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php index 5164e7d923..f49c69ecaf 100644 --- a/src/infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php +++ b/src/infrastructure/internationalization/PhabricatorBaseEnglishTranslation.php @@ -793,6 +793,23 @@ abstract class PhabricatorBaseEnglishTranslation '%s edited commit(s), added %d: %s; removed %d: %s.' => '%s edited commits, added %3$s; removed %5$s.', + '%s changed project member(s), added %d: %s; removed %d: %s' => + '%s changed project members, added %3$s; removed %5$s', + + '%s added %d project member(s): %s' => array( + array( + '%s added a member: %3$s', + '%s added members: %3$s', + ), + ), + + '%s removed %d project member(s): %s' => array( + array( + '%s removed a member: %3$s', + '%s removed members: %3$s', + ), + ), + ); }