diff --git a/src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php b/src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php --- a/src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php +++ b/src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php @@ -6,6 +6,7 @@ public function register() { $this->listen(PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS); $this->listen(PhabricatorEventType::TYPE_UI_WILLRENDERPROPERTIES); + $this->listen(PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD); } public function handleEvent(PhutilEvent $event) { @@ -16,6 +17,9 @@ case PhabricatorEventType::TYPE_UI_WILLRENDERPROPERTIES: $this->handlePropertyEvent($event); break; + case PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD: + $this->handleHovercardEvent($event); + break; } } @@ -49,16 +53,7 @@ } else { $subscribed = false; if ($user->isLoggedIn()) { - $src_phid = $object->getPHID(); - $dst_phid = $user->getPHID(); - $edge_type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_SUBSCRIBER; - - $edges = id(new PhabricatorEdgeQuery()) - ->withSourcePHIDs(array($src_phid)) - ->withEdgeTypes(array($edge_type)) - ->withDestinationPHIDs(array($user->getPHID())) - ->execute(); - $subscribed = isset($edges[$src_phid][$edge_type][$dst_phid]); + $subscribed = $this->fetchStatusFromEdge($object, $user); } if ($subscribed) { @@ -125,4 +120,59 @@ $view->addProperty(pht('Subscribers'), $sub_view); } + private function handleHovercardEvent(PhutilEvent $event) { + $user = $event->getUser(); + $object = $event->getValue('object'); + $hc = $event->getValue('hovercard'); + + if (!$object || !$object->getPHID()) { + // No object, or the object has no PHID yet. No way to subscribe. + return; + } + + if (!($object instanceof PhabricatorSubscribableInterface)) { + // This object isn't subscribable. + return; + } + + if (!$object->shouldAllowSubscription($user->getPHID())) { + // This object doesn't allow the viewer to subscribe. + return; + } + + if ($object->isAutomaticallySubscribed($user->getPHID())) { + $hc->addAction(pht('Uhh...'), null); + } else { + $subscribed = $this->fetchStatusFromEdge($object, $user); + $hc->setUser($user); + + // Workflow no work? You just get a page reload + if ($subscribed) { + $hc->addAction(pht('Unsubscribe'), + '/subscriptions/delete/'.$object->getPHID().'/', + true, + true); + } else { + $hc->addAction(pht('Subscribe'), + '/subscriptions/add/'.$object->getPHID().'/', + true, + true); + } + } + $event->setValue('hovercard', $hc); + } + + private function fetchStatusFromEdge($object, $user) { + $src_phid = $object->getPHID(); + $dst_phid = $user->getPHID(); + $edge_type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_SUBSCRIBER; + + $edges = id(new PhabricatorEdgeQuery()) + ->withSourcePHIDs(array($src_phid)) + ->withEdgeTypes(array($edge_type)) + ->withDestinationPHIDs(array($dst_phid)) + ->execute(); + return isset($edges[$src_phid][$edge_type][$dst_phid]); + } + } diff --git a/src/view/widget/hovercard/PhabricatorHovercardView.php b/src/view/widget/hovercard/PhabricatorHovercardView.php --- a/src/view/widget/hovercard/PhabricatorHovercardView.php +++ b/src/view/widget/hovercard/PhabricatorHovercardView.php @@ -41,11 +41,12 @@ return $this; } - public function addAction($label, $uri, $workflow = false) { + public function addAction($label, $uri, $workflow = false, $form = false) { $this->actions[] = array( 'label' => $label, 'uri' => $uri, 'workflow' => $workflow, + 'form' => $form, ); return $this; } @@ -66,6 +67,7 @@ } $handle = $this->handle; + $user = $this->getUser(); require_celerity_resource("phabricator-hovercard-view-css"); @@ -133,7 +135,23 @@ 'href' => $action['uri'], ); - if ($action['workflow']) { + if ($action['form']) { + if (!$user) { + throw new Exception( + 'Call setUser() when rendering an action as a form.'); + } + $buttons[] = phabricator_form($user, + array( + 'action' => $action['uri'], + 'method' => 'POST', + 'sigil' => $action['workflow'] ? 'workflow' : null, + ), + phutil_tag('button', + array( + 'class' => 'button grey', + ), + $action['label'])); + } else if ($action['workflow']) { $options['sigil'] = 'workflow'; $buttons[] = javelin_tag( 'a',