diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index c9e540312e..ca7804315c 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2095,6 +2095,7 @@ phutil_register_library_map(array( 'PhabricatorSubscriptionsEditController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php', 'PhabricatorSubscriptionsEditor' => 'applications/subscriptions/editor/PhabricatorSubscriptionsEditor.php', 'PhabricatorSubscriptionsListController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsListController.php', + 'PhabricatorSubscriptionsTransactionController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsTransactionController.php', 'PhabricatorSubscriptionsUIEventListener' => 'applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php', 'PhabricatorSymbolNameLinter' => 'infrastructure/lint/hook/PhabricatorSymbolNameLinter.php', 'PhabricatorSyntaxHighlighter' => 'infrastructure/markup/PhabricatorSyntaxHighlighter.php', @@ -4897,6 +4898,7 @@ phutil_register_library_map(array( 'PhabricatorSubscriptionsEditController' => 'PhabricatorController', 'PhabricatorSubscriptionsEditor' => 'PhabricatorEditor', 'PhabricatorSubscriptionsListController' => 'PhabricatorController', + 'PhabricatorSubscriptionsTransactionController' => 'PhabricatorController', 'PhabricatorSubscriptionsUIEventListener' => 'PhabricatorEventListener', 'PhabricatorSymbolNameLinter' => 'ArcanistXHPASTLintNamingHook', 'PhabricatorSyntaxHighlightingConfigOptions' => 'PhabricatorApplicationConfigOptions', diff --git a/src/applications/subscriptions/application/PhabricatorApplicationSubscriptions.php b/src/applications/subscriptions/application/PhabricatorApplicationSubscriptions.php index f78b6ae1df..21b32a7f28 100644 --- a/src/applications/subscriptions/application/PhabricatorApplicationSubscriptions.php +++ b/src/applications/subscriptions/application/PhabricatorApplicationSubscriptions.php @@ -22,6 +22,8 @@ final class PhabricatorApplicationSubscriptions extends PhabricatorApplication { '(?Padd|delete)/'. '(?P[^/]+)/' => 'PhabricatorSubscriptionsEditController', 'list/(?P[^/]+)/' => 'PhabricatorSubscriptionsListController', + 'transaction/(?Padd|rem)/(?[^/]+)/' => + 'PhabricatorSubscriptionsTransactionController', ), ); } diff --git a/src/applications/subscriptions/controller/PhabricatorSubscriptionsTransactionController.php b/src/applications/subscriptions/controller/PhabricatorSubscriptionsTransactionController.php new file mode 100644 index 0000000000..70760f3e1e --- /dev/null +++ b/src/applications/subscriptions/controller/PhabricatorSubscriptionsTransactionController.php @@ -0,0 +1,81 @@ +phid = idx($data, 'phid'); + $this->changeType = idx($data, 'type'); + } + + public function processRequest() { + $request = $this->getRequest(); + + $viewer = $request->getUser(); + $xaction_phid = $this->phid; + + $xaction = id(new PhabricatorObjectQuery()) + ->withPHIDs(array($xaction_phid)) + ->setViewer($viewer) + ->executeOne(); + if (!$xaction) { + return new Aphront404Response(); + } + + $old = $xaction->getOldValue(); + $new = $xaction->getNewValue(); + switch ($this->changeType) { + case 'add': + $subscriber_phids = array_diff($new, $old); + break; + case 'rem': + $subscriber_phids = array_diff($old, $new); + break; + default: + return id(new Aphront404Response()); + } + + $object_phid = $xaction->getObjectPHID(); + $author_phid = $xaction->getAuthorPHID(); + $handle_phids = $subscriber_phids; + $handle_phids[] = $object_phid; + $handle_phids[] = $author_phid; + + $handles = id(new PhabricatorHandleQuery()) + ->setViewer($viewer) + ->withPHIDs($handle_phids) + ->execute(); + $author_handle = $handles[$author_phid]; + if (!in_array($author_phid, $subscriber_phids)) { + unset($handles[$author_phid]); + } + + switch ($this->changeType) { + case 'add': + $title = pht( + 'All %d subscribers added by %s', + count($subscriber_phids), + $author_handle->renderLink()); + break; + case 'rem': + $title = pht( + 'All %d subscribers removed by %s', + count($subscriber_phids), + $author_handle->renderLink()); + break; + } + + $dialog = id(new SubscriptionListDialogBuilder()) + ->setViewer($viewer) + ->setTitle($title) + ->setObjectPHID($object_phid) + ->setHandles($handles) + ->buildDialog(); + + return id(new AphrontDialogResponse())->setDialog($dialog); + } + +} diff --git a/src/applications/subscriptions/view/SubscriptionListStringBuilder.php b/src/applications/subscriptions/view/SubscriptionListStringBuilder.php index 37bdbe468a..71564b994b 100644 --- a/src/applications/subscriptions/view/SubscriptionListStringBuilder.php +++ b/src/applications/subscriptions/view/SubscriptionListStringBuilder.php @@ -24,13 +24,29 @@ final class SubscriptionListStringBuilder { return $this->objectPHID; } + public function buildTransactionString($change_type) { + $handles = $this->getHandles(); + if (!$handles) { + return; + } + $list_uri = '/subscriptions/transaction/'. + $change_type.'/'. + $this->getObjectPHID().'/'; + return $this->buildString($list_uri); + } + public function buildPropertyString() { - $phid = $this->getObjectPHID(); $handles = $this->getHandles(); if (!$handles) { return phutil_tag('em', array(), pht('None')); } + $list_uri = '/subscriptions/list/'.$this->getObjectPHID().'/'; + return $this->buildString($list_uri); + } + + private function buildString($list_uri) { + $handles = $this->getHandles(); $html = array(); $show_count = 3; @@ -53,7 +69,7 @@ final class SubscriptionListStringBuilder { $args[] = javelin_tag( 'a', array( - 'href' => '/subscriptions/list/'.$phid.'/', + 'href' => $list_uri, 'sigil' => 'workflow' ), $not_shown_txt); diff --git a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php index b2672e4373..6587876abe 100644 --- a/src/applications/transactions/storage/PhabricatorApplicationTransaction.php +++ b/src/applications/transactions/storage/PhabricatorApplicationTransaction.php @@ -289,6 +289,18 @@ abstract class PhabricatorApplicationTransaction } } + private function renderSubscriberList(array $phids, $change_type) { + if ($this->getRenderingTarget() == self::TARGET_TEXT) { + return $this->renderHandleList($phids); + } else { + $handles = array_select_keys($this->getHandles(), $phids); + return id(new SubscriptionListStringBuilder()) + ->setHandles($handles) + ->setObjectPHID($this->getPHID()) + ->buildTransactionString($change_type); + } + } + public function renderPolicyName($phid) { $policy = PhabricatorPolicy::newFromPolicyAndHandle( $phid, @@ -455,21 +467,21 @@ abstract class PhabricatorApplicationTransaction '%s edited subscriber(s), added %d: %s; removed %d: %s.', $this->renderHandleLink($author_phid), count($add), - $this->renderHandleList($add), + $this->renderSubscriberList($add, 'add'), count($rem), - $this->renderHandleList($rem)); + $this->renderSubscriberList($rem, 'rem')); } else if ($add) { return pht( '%s added %d subscriber(s): %s.', $this->renderHandleLink($author_phid), count($add), - $this->renderHandleList($add)); + $this->renderSubscriberList($add, 'add')); } else if ($rem) { return pht( '%s removed %d subscriber(s): %s.', $this->renderHandleLink($author_phid), count($rem), - $this->renderHandleList($rem)); + $this->renderSubscriberList($rem, 'rem')); } else { // This is used when rendering previews, before the user actually // selects any CCs.