[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/conpherence/editor/ -> ConpherenceEditor.php (source)

   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  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1