object = $object; return $this; } /** * Add explicit subscribers. These subscribers have explicitly subscribed * (or been subscribed) to the object, and will be added even if they * had previously unsubscribed. * * @param list List of PHIDs to explicitly subscribe. * @return this */ public function subscribeExplicit(array $phids) { $this->explicitSubscribePHIDs += array_fill_keys($phids, true); return $this; } /** * Add implicit subscribers. These subscribers have taken some action which * implicitly subscribes them (e.g., adding a comment) but it will be * suppressed if they've previously unsubscribed from the object. * * @param list List of PHIDs to implicitly subscribe. * @return this */ public function subscribeImplicit(array $phids) { $this->implicitSubscribePHIDs += array_fill_keys($phids, true); return $this; } /** * Unsubscribe PHIDs and mark them as unsubscribed, so implicit subscriptions * will not resubscribe them. * * @param list List of PHIDs to unsubscribe. * @return this */ public function unsubscribe(array $phids) { $this->unsubscribePHIDs += array_fill_keys($phids, true); return $this; } public function save() { if (!$this->object) { throw new Exception('Call setObject() before save()!'); } $actor = $this->requireActor(); $src = $this->object->getPHID(); if ($this->implicitSubscribePHIDs) { $unsub = PhabricatorEdgeQuery::loadDestinationPHIDs( $src, PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER); $unsub = array_fill_keys($unsub, true); $this->implicitSubscribePHIDs = array_diff_key( $this->implicitSubscribePHIDs, $unsub); } $add = $this->implicitSubscribePHIDs + $this->explicitSubscribePHIDs; $del = $this->unsubscribePHIDs; // If a PHID is marked for both subscription and unsubscription, treat // unsubscription as the stronger action. $add = array_diff_key($add, $del); if ($add || $del) { $u_type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER; $s_type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_SUBSCRIBER; $editor = new PhabricatorEdgeEditor(); foreach ($add as $phid => $ignored) { $editor->removeEdge($src, $u_type, $phid); $editor->addEdge($src, $s_type, $phid); } foreach ($del as $phid => $ignored) { $editor->removeEdge($src, $s_type, $phid); $editor->addEdge($src, $u_type, $phid); } $editor->save(); } } }