Correct a parameter order swap in "diffusion.historyquery" for Mercurial
[phabricator.git] / src / applications / conpherence / storage / ConpherenceThread.php
blob7a5f97ed418a9994f8735b76bfcbcaf7bfb1fcdc
1 <?php
3 final class ConpherenceThread extends ConpherenceDAO
4 implements
5 PhabricatorPolicyInterface,
6 PhabricatorApplicationTransactionInterface,
7 PhabricatorMentionableInterface,
8 PhabricatorDestructibleInterface,
9 PhabricatorNgramsInterface {
11 protected $title;
12 protected $topic;
13 protected $profileImagePHID;
14 protected $messageCount;
15 protected $mailKey;
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())
29 ->setMessageCount(0)
30 ->setTitle('')
31 ->setTopic('')
32 ->attachParticipants(array())
33 ->setViewPolicy($default_policy)
34 ->setEditPolicy($default_policy)
35 ->setJoinPolicy('');
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?',
49 self::CONFIG_KEY_SCHEMA => array(
50 'key_phid' => null,
51 'phid' => array(
52 'columns' => array('phid'),
53 'unique' => true,
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;
82 return $this;
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;
107 return $this;
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;
117 return $this;
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);
131 return array_slice(
132 $this->getTransactions(),
133 $length - $begin - $amount,
134 $amount);
137 public function getProfileImageURI() {
138 return $this->getProfileImageFile()->getBestURI();
141 public function attachProfileImageFile(PhabricatorFile $file) {
142 $this->profileImageFile = $file;
143 return $this;
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)) {
162 return $title;
165 return pht('Private Room');
168 public function getDisplayData(PhabricatorUser $viewer) {
169 $handles = $this->getHandles();
171 if ($this->hasAttachedTransactions()) {
172 $transactions = $this->getTransactions();
173 } else {
174 $transactions = array();
177 $img_src = $this->getProfileImageURI();
179 $message_transaction = null;
180 foreach ($transactions as $transaction) {
181 if ($message_transaction) {
182 break;
184 switch ($transaction->getTransactionType()) {
185 case PhabricatorTransactions::TYPE_COMMENT:
186 $message_transaction = $transaction;
187 break;
188 default:
189 break;
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');
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;
217 $unread_count = $this->getMessageCount() - $user_seen_count;
218 $theme_class = ConpherenceRoomSettings::getThemeClass($theme);
220 $title = $this->getTitle();
221 $topic = $this->getTopic();
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,
235 /* -( PhabricatorPolicyInterface Implementation )-------------------------- */
238 public function getCapabilities() {
239 return array(
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()) {
258 return true;
261 switch ($capability) {
262 case PhabricatorPolicyCapability::CAN_EDIT:
263 return false;
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.');
274 break;
278 public static function loadViewPolicyObjects(
279 PhabricatorUser $viewer,
280 array $conpherences) {
282 assert_instances_of($conpherences, __CLASS__);
284 $policies = array();
285 foreach ($conpherences as $room) {
286 $policies[$room->getViewPolicy()] = 1;
288 $policy_objects = array();
289 if ($policies) {
290 $policy_objects = id(new PhabricatorPolicyQuery())
291 ->setViewer($viewer)
292 ->withPHIDs(array_keys($policies))
293 ->execute();
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();
303 return $icon;
307 /* -( PhabricatorApplicationTransactionInterface )------------------------- */
310 public function getApplicationTransactionEditor() {
311 return new ConpherenceEditor();
314 public function getApplicationTransactionTemplate() {
315 return new ConpherenceTransaction();
319 /* -( PhabricatorNgramInterface )------------------------------------------ */
322 public function newNgrams() {
323 return array(
324 id(new ConpherenceThreadTitleNgrams())
325 ->setValue($this->getTitle()),
330 /* -( PhabricatorDestructibleInterface )----------------------------------- */
333 public function destroyObjectPermanently(
334 PhabricatorDestructionEngine $engine) {
336 $this->openTransaction();
337 $this->delete();
339 $participants = id(new ConpherenceParticipant())
340 ->loadAllWhere('conpherencePHID = %s', $this->getPHID());
341 foreach ($participants as $participant) {
342 $participant->delete();
345 $this->saveTransaction();