[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor { 4 5 const ERROR_EMPTY_PARTICIPANTS = 'error-empty-participants'; 6 const ERROR_EMPTY_MESSAGE = 'error-empty-message'; 7 8 public function getEditorApplicationClass() { 9 return 'PhabricatorConpherenceApplication'; 10 } 11 12 public function getEditorObjectsDescription() { 13 return pht('Conpherence Threads'); 14 } 15 16 public static function createConpherence( 17 PhabricatorUser $creator, 18 array $participant_phids, 19 $title, 20 $message, 21 PhabricatorContentSource $source) { 22 23 $conpherence = id(new ConpherenceThread()) 24 ->attachParticipants(array()) 25 ->attachFilePHIDs(array()) 26 ->setMessageCount(0); 27 $files = array(); 28 $errors = array(); 29 if (empty($participant_phids)) { 30 $errors[] = self::ERROR_EMPTY_PARTICIPANTS; 31 } else { 32 $participant_phids[] = $creator->getPHID(); 33 $participant_phids = array_unique($participant_phids); 34 $conpherence->setRecentParticipantPHIDs( 35 array_slice($participant_phids, 0, 10)); 36 } 37 38 if (empty($message)) { 39 $errors[] = self::ERROR_EMPTY_MESSAGE; 40 } 41 42 $file_phids = PhabricatorMarkupEngine::extractFilePHIDsFromEmbeddedFiles( 43 $creator, 44 array($message)); 45 if ($file_phids) { 46 $files = id(new PhabricatorFileQuery()) 47 ->setViewer($creator) 48 ->withPHIDs($file_phids) 49 ->execute(); 50 } 51 52 if (!$errors) { 53 $xactions = array(); 54 $xactions[] = id(new ConpherenceTransaction()) 55 ->setTransactionType(ConpherenceTransactionType::TYPE_PARTICIPANTS) 56 ->setNewValue(array('+' => $participant_phids)); 57 if ($files) { 58 $xactions[] = id(new ConpherenceTransaction()) 59 ->setTransactionType(ConpherenceTransactionType::TYPE_FILES) 60 ->setNewValue(array('+' => mpull($files, 'getPHID'))); 61 } 62 if ($title) { 63 $xactions[] = id(new ConpherenceTransaction()) 64 ->setTransactionType(ConpherenceTransactionType::TYPE_TITLE) 65 ->setNewValue($title); 66 } 67 $xactions[] = id(new ConpherenceTransaction()) 68 ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) 69 ->attachComment( 70 id(new ConpherenceTransactionComment()) 71 ->setContent($message) 72 ->setConpherencePHID($conpherence->getPHID())); 73 74 id(new ConpherenceEditor()) 75 ->setContentSource($source) 76 ->setContinueOnNoEffect(true) 77 ->setActor($creator) 78 ->applyTransactions($conpherence, $xactions); 79 80 } 81 82 return array($errors, $conpherence); 83 } 84 85 public function generateTransactionsFromText( 86 PhabricatorUser $viewer, 87 ConpherenceThread $conpherence, 88 $text) { 89 90 $files = array(); 91 $file_phids = PhabricatorMarkupEngine::extractFilePHIDsFromEmbeddedFiles( 92 $viewer, 93 array($text)); 94 // Since these are extracted from text, we might be re-including the 95 // same file -- e.g. a mock under discussion. Filter files we 96 // already have. 97 $existing_file_phids = $conpherence->getFilePHIDs(); 98 $file_phids = array_diff($file_phids, $existing_file_phids); 99 if ($file_phids) { 100 $files = id(new PhabricatorFileQuery()) 101 ->setViewer($this->getActor()) 102 ->withPHIDs($file_phids) 103 ->execute(); 104 } 105 $xactions = array(); 106 if ($files) { 107 $xactions[] = id(new ConpherenceTransaction()) 108 ->setTransactionType(ConpherenceTransactionType::TYPE_FILES) 109 ->setNewValue(array('+' => mpull($files, 'getPHID'))); 110 } 111 $xactions[] = id(new ConpherenceTransaction()) 112 ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) 113 ->attachComment( 114 id(new ConpherenceTransactionComment()) 115 ->setContent($text) 116 ->setConpherencePHID($conpherence->getPHID())); 117 return $xactions; 118 } 119 120 public function getTransactionTypes() { 121 $types = parent::getTransactionTypes(); 122 123 $types[] = PhabricatorTransactions::TYPE_COMMENT; 124 125 $types[] = ConpherenceTransactionType::TYPE_TITLE; 126 $types[] = ConpherenceTransactionType::TYPE_PARTICIPANTS; 127 $types[] = ConpherenceTransactionType::TYPE_FILES; 128 129 return $types; 130 } 131 132 protected function getCustomTransactionOldValue( 133 PhabricatorLiskDAO $object, 134 PhabricatorApplicationTransaction $xaction) { 135 136 switch ($xaction->getTransactionType()) { 137 case ConpherenceTransactionType::TYPE_TITLE: 138 return $object->getTitle(); 139 case ConpherenceTransactionType::TYPE_PARTICIPANTS: 140 return $object->getParticipantPHIDs(); 141 case ConpherenceTransactionType::TYPE_FILES: 142 return $object->getFilePHIDs(); 143 } 144 } 145 146 protected function getCustomTransactionNewValue( 147 PhabricatorLiskDAO $object, 148 PhabricatorApplicationTransaction $xaction) { 149 150 switch ($xaction->getTransactionType()) { 151 case ConpherenceTransactionType::TYPE_TITLE: 152 return $xaction->getNewValue(); 153 case ConpherenceTransactionType::TYPE_PARTICIPANTS: 154 case ConpherenceTransactionType::TYPE_FILES: 155 return $this->getPHIDTransactionNewValue($xaction); 156 } 157 } 158 159 /** 160 * We really only need a read lock if we have a comment. In that case, we 161 * must update the messagesCount field on the conpherence and 162 * seenMessagesCount(s) for the participant(s). 163 */ 164 protected function shouldReadLock( 165 PhabricatorLiskDAO $object, 166 PhabricatorApplicationTransaction $xaction) { 167 168 $lock = false; 169 switch ($xaction->getTransactionType()) { 170 case PhabricatorTransactions::TYPE_COMMENT: 171 $lock = true; 172 break; 173 } 174 175 return $lock; 176 } 177 178 /** 179 * We need to apply initial effects IFF the conpherence is new. We must 180 * save the conpherence first thing to make sure we have an id and a phid. 181 */ 182 protected function shouldApplyInitialEffects( 183 PhabricatorLiskDAO $object, 184 array $xactions) { 185 186 return !$object->getID(); 187 } 188 189 protected function applyInitialEffects( 190 PhabricatorLiskDAO $object, 191 array $xactions) { 192 193 $object->save(); 194 } 195 196 protected function applyCustomInternalTransaction( 197 PhabricatorLiskDAO $object, 198 PhabricatorApplicationTransaction $xaction) { 199 switch ($xaction->getTransactionType()) { 200 case PhabricatorTransactions::TYPE_COMMENT: 201 $object->setMessageCount((int)$object->getMessageCount() + 1); 202 break; 203 case ConpherenceTransactionType::TYPE_TITLE: 204 $object->setTitle($xaction->getNewValue()); 205 break; 206 } 207 $this->updateRecentParticipantPHIDs($object, $xaction); 208 } 209 210 private function updateRecentParticipantPHIDs( 211 PhabricatorLiskDAO $object, 212 PhabricatorApplicationTransaction $xaction) { 213 214 $participants = $object->getRecentParticipantPHIDs(); 215 array_unshift($participants, $xaction->getAuthorPHID()); 216 $participants = array_slice(array_unique($participants), 0, 10); 217 218 $object->setRecentParticipantPHIDs($participants); 219 } 220 221 protected function applyCustomExternalTransaction( 222 PhabricatorLiskDAO $object, 223 PhabricatorApplicationTransaction $xaction) { 224 225 switch ($xaction->getTransactionType()) { 226 case ConpherenceTransactionType::TYPE_FILES: 227 $editor = new PhabricatorEdgeEditor(); 228 $edge_type = PhabricatorEdgeConfig::TYPE_OBJECT_HAS_FILE; 229 $old = array_fill_keys($xaction->getOldValue(), true); 230 $new = array_fill_keys($xaction->getNewValue(), true); 231 $add_edges = array_keys(array_diff_key($new, $old)); 232 $remove_edges = array_keys(array_diff_key($old, $new)); 233 foreach ($add_edges as $file_phid) { 234 $editor->addEdge( 235 $object->getPHID(), 236 $edge_type, 237 $file_phid); 238 } 239 foreach ($remove_edges as $file_phid) { 240 $editor->removeEdge( 241 $object->getPHID(), 242 $edge_type, 243 $file_phid); 244 } 245 $editor->save(); 246 break; 247 case ConpherenceTransactionType::TYPE_PARTICIPANTS: 248 $participants = $object->getParticipants(); 249 250 $old_map = array_fuse($xaction->getOldValue()); 251 $new_map = array_fuse($xaction->getNewValue()); 252 253 $remove = array_keys(array_diff_key($old_map, $new_map)); 254 foreach ($remove as $phid) { 255 $remove_participant = $participants[$phid]; 256 $remove_participant->delete(); 257 unset($participants[$phid]); 258 } 259 260 $add = array_keys(array_diff_key($new_map, $old_map)); 261 foreach ($add as $phid) { 262 if ($phid == $this->getActor()->getPHID()) { 263 $status = ConpherenceParticipationStatus::UP_TO_DATE; 264 $message_count = $object->getMessageCount(); 265 } else { 266 $status = ConpherenceParticipationStatus::BEHIND; 267 $message_count = 0; 268 } 269 $participants[$phid] = 270 id(new ConpherenceParticipant()) 271 ->setConpherencePHID($object->getPHID()) 272 ->setParticipantPHID($phid) 273 ->setParticipationStatus($status) 274 ->setDateTouched(time()) 275 ->setBehindTransactionPHID($xaction->getPHID()) 276 ->setSeenMessageCount($message_count) 277 ->save(); 278 } 279 $object->attachParticipants($participants); 280 break; 281 } 282 } 283 284 protected function applyFinalEffects( 285 PhabricatorLiskDAO $object, 286 array $xactions) { 287 288 // update everyone's participation status on the last xaction -only- 289 $xaction = end($xactions); 290 $xaction_phid = $xaction->getPHID(); 291 $behind = ConpherenceParticipationStatus::BEHIND; 292 $up_to_date = ConpherenceParticipationStatus::UP_TO_DATE; 293 $participants = $object->getParticipants(); 294 $user = $this->getActor(); 295 $time = time(); 296 foreach ($participants as $phid => $participant) { 297 if ($phid != $user->getPHID()) { 298 if ($participant->getParticipationStatus() != $behind) { 299 $participant->setBehindTransactionPHID($xaction_phid); 300 // decrement one as this is the message putting them behind! 301 $participant->setSeenMessageCount($object->getMessageCount() - 1); 302 } 303 $participant->setParticipationStatus($behind); 304 $participant->setDateTouched($time); 305 } else { 306 $participant->setSeenMessageCount($object->getMessageCount()); 307 $participant->setParticipationStatus($up_to_date); 308 $participant->setDateTouched($time); 309 } 310 $participant->save(); 311 } 312 313 if ($xactions) { 314 $data = array( 315 'type' => 'message', 316 'threadPHID' => $object->getPHID(), 317 'messageID' => last($xactions)->getID(), 318 'subscribers' => array($object->getPHID()), 319 ); 320 321 PhabricatorNotificationClient::tryToPostMessage($data); 322 } 323 324 return $xactions; 325 } 326 327 protected function mergeTransactions( 328 PhabricatorApplicationTransaction $u, 329 PhabricatorApplicationTransaction $v) { 330 331 $type = $u->getTransactionType(); 332 switch ($type) { 333 case ConpherenceTransactionType::TYPE_TITLE: 334 return $v; 335 case ConpherenceTransactionType::TYPE_FILES: 336 case ConpherenceTransactionType::TYPE_PARTICIPANTS: 337 return $this->mergePHIDOrEdgeTransactions($u, $v); 338 } 339 340 return parent::mergeTransactions($u, $v); 341 } 342 343 protected function shouldSendMail( 344 PhabricatorLiskDAO $object, 345 array $xactions) { 346 return true; 347 } 348 349 protected function buildReplyHandler(PhabricatorLiskDAO $object) { 350 return id(new ConpherenceReplyHandler()) 351 ->setActor($this->getActor()) 352 ->setMailReceiver($object); 353 } 354 355 protected function buildMailTemplate(PhabricatorLiskDAO $object) { 356 $id = $object->getID(); 357 $title = $object->getTitle(); 358 if (!$title) { 359 $title = pht( 360 '%s sent you a message.', 361 $this->getActor()->getUserName()); 362 } 363 $phid = $object->getPHID(); 364 365 return id(new PhabricatorMetaMTAMail()) 366 ->setSubject("E{$id}: {$title}") 367 ->addHeader('Thread-Topic', "E{$id}: {$phid}"); 368 } 369 370 protected function getMailTo(PhabricatorLiskDAO $object) { 371 $to_phids = array(); 372 $participants = $object->getParticipants(); 373 if (empty($participants)) { 374 return $to_phids; 375 } 376 $preferences = id(new PhabricatorUserPreferences()) 377 ->loadAllWhere('userPHID in (%Ls)', array_keys($participants)); 378 $preferences = mpull($preferences, null, 'getUserPHID'); 379 foreach ($participants as $phid => $participant) { 380 $default = ConpherenceSettings::EMAIL_ALWAYS; 381 $preference = idx($preferences, $phid); 382 if ($preference) { 383 $default = $preference->getPreference( 384 PhabricatorUserPreferences::PREFERENCE_CONPH_NOTIFICATIONS, 385 ConpherenceSettings::EMAIL_ALWAYS); 386 } 387 $settings = $participant->getSettings(); 388 $notifications = idx( 389 $settings, 390 'notifications', 391 $default); 392 if ($notifications == ConpherenceSettings::EMAIL_ALWAYS) { 393 $to_phids[] = $phid; 394 } 395 } 396 return $to_phids; 397 } 398 399 protected function getMailCC(PhabricatorLiskDAO $object) { 400 return array(); 401 } 402 403 protected function buildMailBody( 404 PhabricatorLiskDAO $object, 405 array $xactions) { 406 407 $body = parent::buildMailBody($object, $xactions); 408 $body->addLinkSection( 409 pht('CONPHERENCE DETAIL'), 410 PhabricatorEnv::getProductionURI('/conpherence/'.$object->getID().'/')); 411 412 return $body; 413 } 414 415 protected function getMailSubjectPrefix() { 416 return PhabricatorEnv::getEnvConfig('metamta.conpherence.subject-prefix'); 417 } 418 419 protected function shouldPublishFeedStory( 420 PhabricatorLiskDAO $object, 421 array $xactions) { 422 return false; 423 } 424 425 protected function supportsSearch() { 426 return false; 427 } 428 429 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |