3 final class ConpherenceThread
extends ConpherenceDAO
5 PhabricatorPolicyInterface
,
6 PhabricatorApplicationTransactionInterface
,
7 PhabricatorMentionableInterface
,
8 PhabricatorDestructibleInterface
,
9 PhabricatorNgramsInterface
{
13 protected $profileImagePHID;
14 protected $messageCount;
16 protected $viewPolicy;
17 protected $editPolicy;
18 protected $joinPolicy;
20 private $participants = self
::ATTACHABLE
;
21 private $transactions = self
::ATTACHABLE
;
22 private $profileImageFile = self
::ATTACHABLE
;
23 private $handles = self
::ATTACHABLE
;
25 public static function initializeNewRoom(PhabricatorUser
$sender) {
26 $default_policy = id(new ConpherenceThreadMembersPolicyRule())
27 ->getObjectPolicyFullKey();
28 return id(new ConpherenceThread())
32 ->attachParticipants(array())
33 ->setViewPolicy($default_policy)
34 ->setEditPolicy($default_policy)
38 protected function getConfiguration() {
40 self
::CONFIG_AUX_PHID
=> true,
41 self
::CONFIG_COLUMN_SCHEMA
=> array(
42 'title' => 'text255?',
44 'messageCount' => 'uint64',
45 'mailKey' => 'text20',
46 'joinPolicy' => 'policy',
47 'profileImagePHID' => 'phid?',
49 self
::CONFIG_KEY_SCHEMA
=> array(
52 'columns' => array('phid'),
56 ) + parent
::getConfiguration();
59 public function generatePHID() {
60 return PhabricatorPHID
::generateNewPHID(
61 PhabricatorConpherenceThreadPHIDType
::TYPECONST
);
64 public function save() {
65 if (!$this->getMailKey()) {
66 $this->setMailKey(Filesystem
::readRandomCharacters(20));
68 return parent
::save();
71 public function getMonogram() {
72 return 'Z'.$this->getID();
75 public function getURI() {
76 return '/'.$this->getMonogram();
79 public function attachParticipants(array $participants) {
80 assert_instances_of($participants, 'ConpherenceParticipant');
81 $this->participants
= $participants;
85 public function getParticipants() {
86 return $this->assertAttached($this->participants
);
89 public function getParticipant($phid) {
90 $participants = $this->getParticipants();
91 return $participants[$phid];
94 public function getParticipantIfExists($phid, $default = null) {
95 $participants = $this->getParticipants();
96 return idx($participants, $phid, $default);
99 public function getParticipantPHIDs() {
100 $participants = $this->getParticipants();
101 return array_keys($participants);
104 public function attachHandles(array $handles) {
105 assert_instances_of($handles, 'PhabricatorObjectHandle');
106 $this->handles
= $handles;
110 public function getHandles() {
111 return $this->assertAttached($this->handles
);
114 public function attachTransactions(array $transactions) {
115 assert_instances_of($transactions, 'ConpherenceTransaction');
116 $this->transactions
= $transactions;
120 public function getTransactions($assert_attached = true) {
121 return $this->assertAttached($this->transactions
);
124 public function hasAttachedTransactions() {
125 return $this->transactions
!== self
::ATTACHABLE
;
128 public function getTransactionsFrom($begin = 0, $amount = null) {
129 $length = count($this->transactions
);
132 $this->getTransactions(),
133 $length - $begin - $amount,
137 public function getProfileImageURI() {
138 return $this->getProfileImageFile()->getBestURI();
141 public function attachProfileImageFile(PhabricatorFile
$file) {
142 $this->profileImageFile
= $file;
146 public function getProfileImageFile() {
147 return $this->assertAttached($this->profileImageFile
);
151 * Get a thread title which doesn't require handles to be attached.
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.
157 * @return string Lower quality human-readable title.
159 public function getStaticTitle() {
160 $title = $this->getTitle();
161 if (strlen($title)) {
165 return pht('Private Room');
168 public function getDisplayData(PhabricatorUser
$viewer) {
169 $handles = $this->getHandles();
171 if ($this->hasAttachedTransactions()) {
172 $transactions = $this->getTransactions();
174 $transactions = array();
177 $img_src = $this->getProfileImageURI();
179 $message_transaction = null;
180 foreach ($transactions as $transaction) {
181 if ($message_transaction) {
184 switch ($transaction->getTransactionType()) {
185 case PhabricatorTransactions
::TYPE_COMMENT
:
186 $message_transaction = $transaction;
192 if ($message_transaction) {
193 $message_handle = $handles[$message_transaction->getAuthorPHID()];
196 $message_handle->getName(),
197 id(new PhutilUTF8StringTruncator())
198 ->setMaximumGlyphs(60)
200 $message_transaction->getComment()->getContent()));
202 // Kinda lame, but maybe add last message to cache?
203 $subtitle = pht('No recent messages');
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);
214 $user_seen_count = 0;
217 $unread_count = $this->getMessageCount() - $user_seen_count;
218 $theme_class = ConpherenceRoomSettings
::getThemeClass($theme);
220 $title = $this->getTitle();
221 $topic = $this->getTopic();
226 'subtitle' => $subtitle,
227 'unread_count' => $unread_count,
228 'epoch' => $this->getDateModified(),
230 'theme' => $theme_class,
235 /* -( PhabricatorPolicyInterface Implementation )-------------------------- */
238 public function getCapabilities() {
240 PhabricatorPolicyCapability
::CAN_VIEW
,
241 PhabricatorPolicyCapability
::CAN_EDIT
,
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();
252 return PhabricatorPolicies
::POLICY_NOONE
;
255 public function hasAutomaticCapability($capability, PhabricatorUser
$user) {
256 // this bad boy isn't even created yet so go nuts $user
257 if (!$this->getID()) {
261 switch ($capability) {
262 case PhabricatorPolicyCapability
::CAN_EDIT
:
266 $participants = $this->getParticipants();
267 return isset($participants[$user->getPHID()]);
270 public function describeAutomaticCapability($capability) {
271 switch ($capability) {
272 case PhabricatorPolicyCapability
::CAN_VIEW
:
273 return pht('Participants in a room can always view it.');
278 public static function loadViewPolicyObjects(
279 PhabricatorUser
$viewer,
280 array $conpherences) {
282 assert_instances_of($conpherences, __CLASS__
);
285 foreach ($conpherences as $room) {
286 $policies[$room->getViewPolicy()] = 1;
288 $policy_objects = array();
290 $policy_objects = id(new PhabricatorPolicyQuery())
292 ->withPHIDs(array_keys($policies))
296 return $policy_objects;
299 public function getPolicyIconName(array $policy_objects) {
300 assert_instances_of($policy_objects, 'PhabricatorPolicy');
302 $icon = $policy_objects[$this->getViewPolicy()]->getIcon();
307 /* -( PhabricatorApplicationTransactionInterface )------------------------- */
310 public function getApplicationTransactionEditor() {
311 return new ConpherenceEditor();
314 public function getApplicationTransactionTemplate() {
315 return new ConpherenceTransaction();
319 /* -( PhabricatorNgramInterface )------------------------------------------ */
322 public function newNgrams() {
324 id(new ConpherenceThreadTitleNgrams())
325 ->setValue($this->getTitle()),
330 /* -( PhabricatorDestructibleInterface )----------------------------------- */
333 public function destroyObjectPermanently(
334 PhabricatorDestructionEngine
$engine) {
336 $this->openTransaction();
339 $participants = id(new ConpherenceParticipant())
340 ->loadAllWhere('conpherencePHID = %s', $this->getPHID());
341 foreach ($participants as $participant) {
342 $participant->delete();
345 $this->saveTransaction();