Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/conpherence/storage/ConpherenceThread.php
12256 views
1
<?php
2
3
final class ConpherenceThread extends ConpherenceDAO
4
implements
5
PhabricatorPolicyInterface,
6
PhabricatorApplicationTransactionInterface,
7
PhabricatorMentionableInterface,
8
PhabricatorDestructibleInterface,
9
PhabricatorNgramsInterface {
10
11
protected $title;
12
protected $topic;
13
protected $profileImagePHID;
14
protected $messageCount;
15
protected $mailKey;
16
protected $viewPolicy;
17
protected $editPolicy;
18
protected $joinPolicy;
19
20
private $participants = self::ATTACHABLE;
21
private $transactions = self::ATTACHABLE;
22
private $profileImageFile = self::ATTACHABLE;
23
private $handles = self::ATTACHABLE;
24
25
public static function initializeNewRoom(PhabricatorUser $sender) {
26
$default_policy = id(new ConpherenceThreadMembersPolicyRule())
27
->getObjectPolicyFullKey();
28
return id(new ConpherenceThread())
29
->setMessageCount(0)
30
->setTitle('')
31
->setTopic('')
32
->attachParticipants(array())
33
->setViewPolicy($default_policy)
34
->setEditPolicy($default_policy)
35
->setJoinPolicy('');
36
}
37
38
protected function getConfiguration() {
39
return array(
40
self::CONFIG_AUX_PHID => true,
41
self::CONFIG_COLUMN_SCHEMA => array(
42
'title' => 'text255?',
43
'topic' => 'text255',
44
'messageCount' => 'uint64',
45
'mailKey' => 'text20',
46
'joinPolicy' => 'policy',
47
'profileImagePHID' => 'phid?',
48
),
49
self::CONFIG_KEY_SCHEMA => array(
50
'key_phid' => null,
51
'phid' => array(
52
'columns' => array('phid'),
53
'unique' => true,
54
),
55
),
56
) + parent::getConfiguration();
57
}
58
59
public function generatePHID() {
60
return PhabricatorPHID::generateNewPHID(
61
PhabricatorConpherenceThreadPHIDType::TYPECONST);
62
}
63
64
public function save() {
65
if (!$this->getMailKey()) {
66
$this->setMailKey(Filesystem::readRandomCharacters(20));
67
}
68
return parent::save();
69
}
70
71
public function getMonogram() {
72
return 'Z'.$this->getID();
73
}
74
75
public function getURI() {
76
return '/'.$this->getMonogram();
77
}
78
79
public function attachParticipants(array $participants) {
80
assert_instances_of($participants, 'ConpherenceParticipant');
81
$this->participants = $participants;
82
return $this;
83
}
84
85
public function getParticipants() {
86
return $this->assertAttached($this->participants);
87
}
88
89
public function getParticipant($phid) {
90
$participants = $this->getParticipants();
91
return $participants[$phid];
92
}
93
94
public function getParticipantIfExists($phid, $default = null) {
95
$participants = $this->getParticipants();
96
return idx($participants, $phid, $default);
97
}
98
99
public function getParticipantPHIDs() {
100
$participants = $this->getParticipants();
101
return array_keys($participants);
102
}
103
104
public function attachHandles(array $handles) {
105
assert_instances_of($handles, 'PhabricatorObjectHandle');
106
$this->handles = $handles;
107
return $this;
108
}
109
110
public function getHandles() {
111
return $this->assertAttached($this->handles);
112
}
113
114
public function attachTransactions(array $transactions) {
115
assert_instances_of($transactions, 'ConpherenceTransaction');
116
$this->transactions = $transactions;
117
return $this;
118
}
119
120
public function getTransactions($assert_attached = true) {
121
return $this->assertAttached($this->transactions);
122
}
123
124
public function hasAttachedTransactions() {
125
return $this->transactions !== self::ATTACHABLE;
126
}
127
128
public function getTransactionsFrom($begin = 0, $amount = null) {
129
$length = count($this->transactions);
130
131
return array_slice(
132
$this->getTransactions(),
133
$length - $begin - $amount,
134
$amount);
135
}
136
137
public function getProfileImageURI() {
138
return $this->getProfileImageFile()->getBestURI();
139
}
140
141
public function attachProfileImageFile(PhabricatorFile $file) {
142
$this->profileImageFile = $file;
143
return $this;
144
}
145
146
public function getProfileImageFile() {
147
return $this->assertAttached($this->profileImageFile);
148
}
149
150
/**
151
* Get a thread title which doesn't require handles to be attached.
152
*
153
* This is a less rich title than @{method:getDisplayTitle}, but does not
154
* require handles to be attached. We use it to build thread handles without
155
* risking cycles or recursion while querying.
156
*
157
* @return string Lower quality human-readable title.
158
*/
159
public function getStaticTitle() {
160
$title = $this->getTitle();
161
if (strlen($title)) {
162
return $title;
163
}
164
165
return pht('Private Room');
166
}
167
168
public function getDisplayData(PhabricatorUser $viewer) {
169
$handles = $this->getHandles();
170
171
if ($this->hasAttachedTransactions()) {
172
$transactions = $this->getTransactions();
173
} else {
174
$transactions = array();
175
}
176
177
$img_src = $this->getProfileImageURI();
178
179
$message_transaction = null;
180
foreach ($transactions as $transaction) {
181
if ($message_transaction) {
182
break;
183
}
184
switch ($transaction->getTransactionType()) {
185
case PhabricatorTransactions::TYPE_COMMENT:
186
$message_transaction = $transaction;
187
break;
188
default:
189
break;
190
}
191
}
192
if ($message_transaction) {
193
$message_handle = $handles[$message_transaction->getAuthorPHID()];
194
$subtitle = sprintf(
195
'%s: %s',
196
$message_handle->getName(),
197
id(new PhutilUTF8StringTruncator())
198
->setMaximumGlyphs(60)
199
->truncateString(
200
$message_transaction->getComment()->getContent()));
201
} else {
202
// Kinda lame, but maybe add last message to cache?
203
$subtitle = pht('No recent messages');
204
}
205
206
$user_participation = $this->getParticipantIfExists($viewer->getPHID());
207
$theme = ConpherenceRoomSettings::COLOR_LIGHT;
208
if ($user_participation) {
209
$user_seen_count = $user_participation->getSeenMessageCount();
210
$participant = $this->getParticipant($viewer->getPHID());
211
$settings = $participant->getSettings();
212
$theme = idx($settings, 'theme', $theme);
213
} else {
214
$user_seen_count = 0;
215
}
216
217
$unread_count = $this->getMessageCount() - $user_seen_count;
218
$theme_class = ConpherenceRoomSettings::getThemeClass($theme);
219
220
$title = $this->getTitle();
221
$topic = $this->getTopic();
222
223
return array(
224
'title' => $title,
225
'topic' => $topic,
226
'subtitle' => $subtitle,
227
'unread_count' => $unread_count,
228
'epoch' => $this->getDateModified(),
229
'image' => $img_src,
230
'theme' => $theme_class,
231
);
232
}
233
234
235
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
236
237
238
public function getCapabilities() {
239
return array(
240
PhabricatorPolicyCapability::CAN_VIEW,
241
PhabricatorPolicyCapability::CAN_EDIT,
242
);
243
}
244
245
public function getPolicy($capability) {
246
switch ($capability) {
247
case PhabricatorPolicyCapability::CAN_VIEW:
248
return $this->getViewPolicy();
249
case PhabricatorPolicyCapability::CAN_EDIT:
250
return $this->getEditPolicy();
251
}
252
return PhabricatorPolicies::POLICY_NOONE;
253
}
254
255
public function hasAutomaticCapability($capability, PhabricatorUser $user) {
256
// this bad boy isn't even created yet so go nuts $user
257
if (!$this->getID()) {
258
return true;
259
}
260
261
switch ($capability) {
262
case PhabricatorPolicyCapability::CAN_EDIT:
263
return false;
264
}
265
266
$participants = $this->getParticipants();
267
return isset($participants[$user->getPHID()]);
268
}
269
270
public function describeAutomaticCapability($capability) {
271
switch ($capability) {
272
case PhabricatorPolicyCapability::CAN_VIEW:
273
return pht('Participants in a room can always view it.');
274
break;
275
}
276
}
277
278
public static function loadViewPolicyObjects(
279
PhabricatorUser $viewer,
280
array $conpherences) {
281
282
assert_instances_of($conpherences, __CLASS__);
283
284
$policies = array();
285
foreach ($conpherences as $room) {
286
$policies[$room->getViewPolicy()] = 1;
287
}
288
$policy_objects = array();
289
if ($policies) {
290
$policy_objects = id(new PhabricatorPolicyQuery())
291
->setViewer($viewer)
292
->withPHIDs(array_keys($policies))
293
->execute();
294
}
295
296
return $policy_objects;
297
}
298
299
public function getPolicyIconName(array $policy_objects) {
300
assert_instances_of($policy_objects, 'PhabricatorPolicy');
301
302
$icon = $policy_objects[$this->getViewPolicy()]->getIcon();
303
return $icon;
304
}
305
306
307
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
308
309
310
public function getApplicationTransactionEditor() {
311
return new ConpherenceEditor();
312
}
313
314
public function getApplicationTransactionTemplate() {
315
return new ConpherenceTransaction();
316
}
317
318
319
/* -( PhabricatorNgramInterface )------------------------------------------ */
320
321
322
public function newNgrams() {
323
return array(
324
id(new ConpherenceThreadTitleNgrams())
325
->setValue($this->getTitle()),
326
);
327
}
328
329
330
/* -( PhabricatorDestructibleInterface )----------------------------------- */
331
332
333
public function destroyObjectPermanently(
334
PhabricatorDestructionEngine $engine) {
335
336
$this->openTransaction();
337
$this->delete();
338
339
$participants = id(new ConpherenceParticipant())
340
->loadAllWhere('conpherencePHID = %s', $this->getPHID());
341
foreach ($participants as $participant) {
342
$participant->delete();
343
}
344
345
$this->saveTransaction();
346
347
}
348
}
349
350