Index: src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php =================================================================== --- src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php +++ src/applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php @@ -5,6 +5,7 @@ public function register() { $this->listen(PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS); + $this->listen(PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD); } public function handleEvent(PhutilEvent $event) { @@ -12,6 +13,9 @@ case PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS: $this->handleActionEvent($event); break; + case PhabricatorEventType::TYPE_UI_DIDRENDERHOVERCARD: + $this->handleHovercardEvent($event); + break; } } @@ -41,16 +45,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) { @@ -81,4 +76,61 @@ $event->setValue('actions', $actions); } + 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 (!$user->isLoggedIn()) { + // I don't think we should unnecessarily increase the height of the + // hovercard for non-logged in users. They should just feel the sleekness + // of this beauty and get hooked up to pay my subscriptions instead :D. + 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]); + } + } Index: src/view/widget/hovercard/PhabricatorHovercardView.php =================================================================== --- src/view/widget/hovercard/PhabricatorHovercardView.php +++ src/view/widget/hovercard/PhabricatorHovercardView.php @@ -42,11 +42,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; } @@ -67,6 +68,7 @@ } $handle = $this->handle; + $user = $this->getUser(); require_celerity_resource("phabricator-hovercard-view-css"); @@ -131,7 +133,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',