@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3final class PhabricatorSubscriptionsEditor extends PhabricatorEditor {
4
5 private $object;
6
7 private $explicitSubscribePHIDs = array();
8 private $implicitSubscribePHIDs = array();
9 private $unsubscribePHIDs = array();
10
11 public function setObject(PhabricatorSubscribableInterface $object) {
12 $this->object = $object;
13 return $this;
14 }
15
16 /**
17 * Add explicit subscribers. These subscribers have explicitly subscribed
18 * (or been subscribed) to the object, and will be added even if they
19 * had previously unsubscribed.
20 *
21 * @param list<string> $phids List of PHIDs to explicitly subscribe.
22 * @return $this
23 */
24 public function subscribeExplicit(array $phids) {
25 $this->explicitSubscribePHIDs += array_fill_keys($phids, true);
26 return $this;
27 }
28
29
30 /**
31 * Add implicit subscribers. These subscribers have taken some action which
32 * implicitly subscribes them (e.g., adding a comment) but it will be
33 * suppressed if they've previously unsubscribed from the object.
34 *
35 * @param list<string> $phids List of PHIDs to implicitly subscribe.
36 * @return $this
37 */
38 public function subscribeImplicit(array $phids) {
39 $this->implicitSubscribePHIDs += array_fill_keys($phids, true);
40 return $this;
41 }
42
43
44 /**
45 * Unsubscribe PHIDs and mark them as unsubscribed, so implicit subscriptions
46 * will not resubscribe them.
47 *
48 * @param list<string> $phids List of PHIDs to unsubscribe.
49 * @return $this
50 */
51 public function unsubscribe(array $phids) {
52 $this->unsubscribePHIDs += array_fill_keys($phids, true);
53 return $this;
54 }
55
56
57 public function save() {
58 if (!$this->object) {
59 throw new PhutilInvalidStateException('setObject');
60 }
61 $actor = $this->requireActor();
62
63 $src = $this->object->getPHID();
64
65 if ($this->implicitSubscribePHIDs) {
66 $unsub = PhabricatorEdgeQuery::loadDestinationPHIDs(
67 $src,
68 PhabricatorObjectHasUnsubscriberEdgeType::EDGECONST);
69 $unsub = array_fill_keys($unsub, true);
70 $this->implicitSubscribePHIDs = array_diff_key(
71 $this->implicitSubscribePHIDs,
72 $unsub);
73 }
74
75 $add = $this->implicitSubscribePHIDs + $this->explicitSubscribePHIDs;
76 $del = $this->unsubscribePHIDs;
77
78 // If a PHID is marked for both subscription and unsubscription, treat
79 // unsubscription as the stronger action.
80 $add = array_diff_key($add, $del);
81
82 if ($add || $del) {
83 $u_type = PhabricatorObjectHasUnsubscriberEdgeType::EDGECONST;
84 $s_type = PhabricatorObjectHasSubscriberEdgeType::EDGECONST;
85
86 $editor = new PhabricatorEdgeEditor();
87
88 foreach ($add as $phid => $ignored) {
89 $editor->removeEdge($src, $u_type, $phid);
90 $editor->addEdge($src, $s_type, $phid);
91 }
92
93 foreach ($del as $phid => $ignored) {
94 $editor->removeEdge($src, $s_type, $phid);
95 $editor->addEdge($src, $u_type, $phid);
96 }
97
98 $editor->save();
99 }
100 }
101
102}