@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 ConpherenceThreadParticipantsTransaction
4 extends ConpherenceThreadTransactionType {
5
6 const TRANSACTIONTYPE = 'participants';
7
8 public function generateOldValue($object) {
9 return $object->getParticipantPHIDs();
10 }
11
12 public function generateNewValue($object, $value) {
13 $old = $this->generateOldValue($object);
14 return $this->getPHIDList($old, $value);
15 }
16
17 public function applyExternalEffects($object, $value) {
18 $participants = $object->getParticipants();
19
20 $old = array_keys($participants);
21 $new = $value;
22
23 $add_map = array_fuse(array_diff($new, $old));
24 $rem_map = array_fuse(array_diff($old, $new));
25
26 foreach ($rem_map as $phid) {
27 $remove_participant = $participants[$phid];
28 $remove_participant->delete();
29 unset($participants[$phid]);
30 }
31
32 foreach ($add_map as $phid) {
33 if (isset($participants[$phid])) {
34 continue;
35 }
36
37 $participants[$phid] = id(new ConpherenceParticipant())
38 ->setConpherencePHID($object->getPHID())
39 ->setParticipantPHID($phid)
40 ->setSeenMessageCount(0)
41 ->save();
42 }
43
44 $object->attachParticipants($participants);
45 }
46
47 public function getTitle() {
48 $old = $this->getOldValue();
49 $new = $this->getNewValue();
50
51 $add = array_diff($new, $old);
52 $rem = array_diff($old, $new);
53
54 $author_phid = $this->getAuthorPHID();
55
56 if ($add && $rem) {
57 return pht(
58 '%s edited participant(s), added %d: %s; removed %d: %s.',
59 $this->renderAuthor(),
60 count($add),
61 $this->renderHandleList($add),
62 count($rem),
63 $this->renderHandleList($rem));
64 } else if ((in_array($author_phid, $add)) && (count($add) == 1)) {
65 return pht(
66 '%s joined the room.',
67 $this->renderAuthor());
68 } else if ((in_array($author_phid, $rem)) && (count($rem) == 1)) {
69 return pht(
70 '%s left the room.',
71 $this->renderAuthor());
72 } else if ($add) {
73 return pht(
74 '%s added %d participant(s): %s.',
75 $this->renderAuthor(),
76 count($add),
77 $this->renderHandleList($add));
78 } else {
79 return pht(
80 '%s removed %d participant(s): %s.',
81 $this->renderAuthor(),
82 count($rem),
83 $this->renderHandleList($rem));
84 }
85 }
86
87 public function validateTransactions($object, array $xactions) {
88 $errors = array();
89
90 foreach ($xactions as $xaction) {
91 $old = $object->getParticipantPHIDs();
92
93 $new = $xaction->getNewValue();
94 $new = $this->getPHIDList($old, $new);
95
96 $add_map = array_fuse(array_diff($new, $old));
97 $rem_map = array_fuse(array_diff($old, $new));
98
99 foreach ($add_map as $user_phid) {
100 $user = id(new PhabricatorPeopleQuery())
101 ->setViewer($this->getActor())
102 ->withPHIDs(array($user_phid))
103 ->executeOne();
104 if (!$user) {
105 $errors[] = $this->newInvalidError(
106 pht(
107 'Participant PHID "%s" is not a valid user PHID.',
108 $user_phid));
109 continue;
110 }
111 }
112 }
113
114 return $errors;
115 }
116
117 public function getRequiredCapabilities(
118 $object,
119 PhabricatorApplicationTransaction $xaction) {
120
121 $old_map = array_fuse($xaction->getOldValue());
122 $new_map = array_fuse($xaction->getNewValue());
123
124 $add = array_keys(array_diff_key($new_map, $old_map));
125 $rem = array_keys(array_diff_key($old_map, $new_map));
126
127 $actor_phid = $this->getActingAsPHID();
128
129 $is_join = (($add === array($actor_phid)) && !$rem);
130 $is_leave = (($rem === array($actor_phid)) && !$add);
131
132 if ($is_join) {
133 // Anyone can join a thread they can see.
134 return null;
135 }
136
137 if ($is_leave) {
138 // Anyone can leave a thread.
139 return null;
140 }
141
142 // You need CAN_EDIT to add or remove participants. For additional
143 // discussion, see D17696 and T4411.
144 return PhabricatorPolicyCapability::CAN_EDIT;
145 }
146
147}