protected function renderTransactionContent(PhabricatorApplicationTransaction $xaction)
 {
     $field = PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT;
     $engine = $this->getOrBuildEngine();
     $comment = $xaction->getComment();
     if ($comment) {
         if ($comment->getIsRemoved()) {
             return javelin_tag('span', array('class' => 'comment-deleted', 'sigil' => 'transaction-comment', 'meta' => array('phid' => $comment->getTransactionPHID())), pht('This comment was removed by %s.', $xaction->getHandle($comment->getAuthorPHID())->renderLink()));
         } else {
             if ($comment->getIsDeleted()) {
                 return javelin_tag('span', array('class' => 'comment-deleted', 'sigil' => 'transaction-comment', 'meta' => array('phid' => $comment->getTransactionPHID())), pht('This comment has been deleted.'));
             } else {
                 if ($xaction->hasComment()) {
                     return javelin_tag('span', array('class' => 'transaction-comment', 'sigil' => 'transaction-comment', 'meta' => array('phid' => $comment->getTransactionPHID())), $engine->getOutput($comment, $field));
                 } else {
                     // This is an empty, non-deleted comment. Usually this happens when
                     // rendering previews.
                     return null;
                 }
             }
         }
     }
     return null;
 }
 protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction)
 {
     switch ($xaction->getTransactionType()) {
         case DifferentialTransaction::TYPE_ACTION:
             return;
         case DifferentialTransaction::TYPE_INLINE:
             $reply = $xaction->getComment()->getReplyToComment();
             if ($reply && !$reply->getHasReplies()) {
                 $reply->setHasReplies(1)->save();
             }
             return;
         case DifferentialTransaction::TYPE_UPDATE:
             // Now that we're inside the transaction, do a final check.
             $diff = $this->requireDiff($xaction->getNewValue());
             // TODO: It would be slightly cleaner to just revalidate this
             // transaction somehow using the same validation code, but that's
             // not easy to do at the moment.
             $revision_id = $diff->getRevisionID();
             if ($revision_id && $revision_id != $object->getID()) {
                 throw new Exception(pht('Diff is already attached to another revision. You lost ' . 'a race?'));
             }
             // TODO: This can race with diff updates, particularly those from
             // Harbormaster. See discussion in T8650.
             $diff->setRevisionID($object->getID());
             $diff->save();
             // Update Harbormaster to set the containerPHID correctly for any
             // existing buildables. We may otherwise have buildables stuck with
             // the old (`null`) container.
             // TODO: This is a bit iffy, maybe we can find a cleaner approach?
             // In particular, this could (rarely) be overwritten by Harbormaster
             // workers.
             $table = new HarbormasterBuildable();
             $conn_w = $table->establishConnection('w');
             queryfx($conn_w, 'UPDATE %T SET containerPHID = %s WHERE buildablePHID = %s', $table->getTableName(), $object->getPHID(), $diff->getPHID());
             return;
     }
     return parent::applyCustomExternalTransaction($object, $xaction);
 }
 protected function applyCustomExternalTransaction(PhabricatorLiskDAO $object, PhabricatorApplicationTransaction $xaction)
 {
     switch ($xaction->getTransactionType()) {
         case PhabricatorAuditActionConstants::ACTION:
         case PhabricatorAuditTransaction::TYPE_COMMIT:
             return;
         case PhabricatorAuditActionConstants::INLINE:
             $reply = $xaction->getComment()->getReplyToComment();
             if ($reply && !$reply->getHasReplies()) {
                 $reply->setHasReplies(1)->save();
             }
             return;
         case PhabricatorAuditActionConstants::ADD_AUDITORS:
             $new = $xaction->getNewValue();
             if (!is_array($new)) {
                 $new = array();
             }
             $old = $xaction->getOldValue();
             if (!is_array($old)) {
                 $old = array();
             }
             $add = array_diff_key($new, $old);
             $actor = $this->requireActor();
             $requests = $object->getAudits();
             $requests = mpull($requests, null, 'getAuditorPHID');
             foreach ($add as $phid) {
                 if (isset($requests[$phid])) {
                     continue;
                 }
                 if ($this->getIsHeraldEditor()) {
                     $audit_requested = $xaction->getMetadataValue('auditStatus');
                     $audit_reason_map = $xaction->getMetadataValue('auditReasonMap');
                     $audit_reason = $audit_reason_map[$phid];
                 } else {
                     $audit_requested = PhabricatorAuditStatusConstants::AUDIT_REQUESTED;
                     $audit_reason = $this->getAuditReasons($phid);
                 }
                 $requests[] = id(new PhabricatorRepositoryAuditRequest())->setCommitPHID($object->getPHID())->setAuditorPHID($phid)->setAuditStatus($audit_requested)->setAuditReasons($audit_reason)->save();
             }
             $object->attachAudits($requests);
             return;
     }
     return parent::applyCustomExternalTransaction($object, $xaction);
 }