diff --git a/resources/sql/autopatches/20140722.audit.4.migtext.php b/resources/sql/autopatches/20140722.audit.4.migtext.php new file mode 100644 index 0000000000..1bcd3d36b8 --- /dev/null +++ b/resources/sql/autopatches/20140722.audit.4.migtext.php @@ -0,0 +1,61 @@ +establishConnection('w'); +$rows = new LiskRawMigrationIterator($conn_w, 'audit_comment'); + +$content_source = PhabricatorContentSource::newForSource( + PhabricatorContentSource::SOURCE_LEGACY, + array())->serialize(); + +echo "Migrating Audit comment text to modern storage...\n"; +foreach ($rows as $row) { + $id = $row['id']; + echo "Migrating Audit comment {$id}...\n"; + if (!strlen($row['content'])) { + echo "Comment has no text, continuing.\n"; + continue; + } + + $xaction_phid = PhabricatorPHID::generateNewPHID( + PhabricatorApplicationTransactionTransactionPHIDType::TYPECONST, + PhabricatorRepositoryCommitPHIDType::TYPECONST); + + $comment_phid = PhabricatorPHID::generateNewPHID( + PhabricatorPHIDConstants::PHID_TYPE_XCMT, + PhabricatorRepositoryCommitPHIDType::TYPECONST); + + queryfx( + $conn_w, + 'INSERT IGNORE INTO %T + (phid, transactionPHID, authorPHID, viewPolicy, editPolicy, + commentVersion, content, contentSource, isDeleted, + dateCreated, dateModified, commitPHID, pathID, + legacyCommentID) + VALUES (%s, %s, %s, %s, %s, + %d, %s, %s, %d, + %d, %d, %s, %nd, + %d)', + 'audit_transaction_comment', + + // phid, transactionPHID, authorPHID, viewPolicy, editPolicy + $comment_phid, + $xaction_phid, + $row['actorPHID'], + 'public', + $row['actorPHID'], + + // commentVersion, content, contentSource, isDeleted + 1, + $row['content'], + $content_source, + 0, + + // dateCreated, dateModified, commitPHID, pathID, legacyCommentID + $row['dateCreated'], + $row['dateModified'], + $row['targetPHID'], + null, + $row['id']); +} + +echo "Done.\n"; diff --git a/src/applications/audit/storage/PhabricatorAuditComment.php b/src/applications/audit/storage/PhabricatorAuditComment.php index ffb0912e57..97fdf92a63 100644 --- a/src/applications/audit/storage/PhabricatorAuditComment.php +++ b/src/applications/audit/storage/PhabricatorAuditComment.php @@ -1,64 +1,152 @@ loadAllWhere( + $comments = id(new PhabricatorAuditComment())->loadAllWhere( 'targetPHID = %s', $commit_phid); + + if ($comments) { + $table = new PhabricatorAuditTransactionComment(); + $conn_r = $table->establishConnection('r'); + + $data = queryfx_all( + $conn_r, + 'SELECT * FROM %T WHERE legacyCommentID IN (%Ld) AND pathID IS NULL', + $table->getTableName(), + mpull($comments, 'getID')); + $texts = $table->loadAllFromArray($data); + $texts = mpull($texts, null, 'getLegacyCommentID'); + + foreach ($comments as $comment) { + $text = idx($texts, $comment->getID()); + if ($text) { + $comment->setProxyComment($text); + } + } + } + + return $comments; } public function getConfiguration() { return array( self::CONFIG_SERIALIZATION => array( 'metadata' => self::SERIALIZATION_JSON, ), self::CONFIG_AUX_PHID => true, ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID('ACMT'); } + public function getContent() { + return $this->getProxyComment()->getContent(); + } + + public function setContent($content) { + // NOTE: We no longer read this field, but there's no cost to continuing + // to write it in case something goes horribly wrong, since it makes it + // far easier to back out of this. + $this->content = $content; + $this->getProxyComment()->setContent($content); + return $this; + } + + private function getProxyComment() { + if (!$this->proxyComment) { + $this->proxyComment = new PhabricatorAuditTransactionComment(); + } + return $this->proxyComment; + } + + public function setProxyComment(PhabricatorAuditTransactionComment $proxy) { + if ($this->proxyComment) { + throw new Exception(pht('You can not overwrite a proxy comment.')); + } + $this->proxyComment = $proxy; + return $this; + } + + public function setTargetPHID($target_phid) { + $this->getProxyComment()->setCommitPHID($target_phid); + return parent::setTargetPHID($target_phid); + } + + public function save() { + $this->openTransaction(); + $result = parent::save(); + + if (strlen($this->getContent())) { + $content_source = PhabricatorContentSource::newForSource( + PhabricatorContentSource::SOURCE_LEGACY, + array()); + + $xaction_phid = PhabricatorPHID::generateNewPHID( + PhabricatorApplicationTransactionTransactionPHIDType::TYPECONST, + PhabricatorRepositoryCommitPHIDType::TYPECONST); + + $proxy = $this->getProxyComment(); + $proxy + ->setAuthorPHID($this->getActorPHID()) + ->setViewPolicy('public') + ->setEditPolicy($this->getActorPHID()) + ->setContentSource($content_source) + ->setCommentVersion(1) + ->setLegacyCommentID($this->getID()) + ->setTransactionPHID($xaction_phid) + ->save(); + } + + $this->saveTransaction(); + + return $result; + } + + /* -( PhabricatorMarkupInterface Implementation )-------------------------- */ public function getMarkupFieldKey($field) { return 'AC:'.$this->getID(); } public function newMarkupEngine($field) { return PhabricatorMarkupEngine::newDiffusionMarkupEngine(); } public function getMarkupText($field) { return $this->getContent(); } public function didMarkupText($field, $output, PhutilMarkupEngine $engine) { return $output; } public function shouldUseMarkupCache($field) { return (bool)$this->getID(); } } diff --git a/src/applications/audit/storage/PhabricatorAuditInlineComment.php b/src/applications/audit/storage/PhabricatorAuditInlineComment.php index bb9d947b71..e39d20cd54 100644 --- a/src/applications/audit/storage/PhabricatorAuditInlineComment.php +++ b/src/applications/audit/storage/PhabricatorAuditInlineComment.php @@ -1,262 +1,265 @@ proxy = new PhabricatorAuditTransactionComment(); } public function __clone() { $this->proxy = clone $this->proxy; } public function getTransactionCommentForSave() { $content_source = PhabricatorContentSource::newForSource( PhabricatorContentSource::SOURCE_LEGACY, array()); $this->proxy ->setViewPolicy('public') ->setEditPolicy($this->getAuthorPHID()) ->setContentSource($content_source) ->setCommentVersion(1); return $this->proxy; } public static function loadDraftComments( PhabricatorUser $viewer, $commit_phid) { $inlines = id(new PhabricatorAuditTransactionComment())->loadAllWhere( - 'authorPHID = %s AND commitPHID = %s AND transactionPHID IS NULL', + 'authorPHID = %s AND commitPHID = %s AND transactionPHID IS NULL + AND pathID IS NOT NULL', $viewer->getPHID(), $commit_phid); return self::buildProxies($inlines); } public static function loadPublishedComments( PhabricatorUser $viewer, $commit_phid) { $inlines = id(new PhabricatorAuditTransactionComment())->loadAllWhere( - 'commitPHID = %s AND transactionPHID IS NOT NULL', + 'commitPHID = %s AND transactionPHID IS NOT NULL + AND pathID IS NOT NULL', $commit_phid); return self::buildProxies($inlines); } public static function loadDraftAndPublishedComments( PhabricatorUser $viewer, $commit_phid, $path_id = null) { if ($path_id === null) { $inlines = id(new PhabricatorAuditTransactionComment())->loadAllWhere( - 'commitPHID = %s AND (transactionPHID IS NOT NULL OR authorPHID = %s)', + 'commitPHID = %s AND (transactionPHID IS NOT NULL OR authorPHID = %s) + AND pathID IS NOT NULL', $commit_phid, $viewer->getPHID()); } else { $inlines = id(new PhabricatorAuditTransactionComment())->loadAllWhere( 'commitPHID = %s AND pathID = %d AND (authorPHID = %s OR transactionPHID IS NOT NULL)', $commit_phid, $path_id, $viewer->getPHID()); } return self::buildProxies($inlines); } private static function buildProxies(array $inlines) { $results = array(); foreach ($inlines as $key => $inline) { $results[$key] = PhabricatorAuditInlineComment::newFromModernComment( $inline); } return $results; } public function setSyntheticAuthor($synthetic_author) { $this->syntheticAuthor = $synthetic_author; return $this; } public function getSyntheticAuthor() { return $this->syntheticAuthor; } public function openTransaction() { $this->proxy->openTransaction(); } public function saveTransaction() { $this->proxy->saveTransaction(); } public function save() { $this->getTransactionCommentForSave()->save(); return $this; } public function delete() { $this->proxy->delete(); return $this; } public function getID() { return $this->proxy->getID(); } public function getPHID() { return $this->proxy->getPHID(); } public static function newFromModernComment( PhabricatorAuditTransactionComment $comment) { $obj = new PhabricatorAuditInlineComment(); $obj->proxy = $comment; return $obj; } public function isCompatible(PhabricatorInlineCommentInterface $comment) { return ($this->getAuthorPHID() === $comment->getAuthorPHID()) && ($this->getSyntheticAuthor() === $comment->getSyntheticAuthor()) && ($this->getContent() === $comment->getContent()); } public function setContent($content) { $this->proxy->setContent($content); return $this; } public function getContent() { return $this->proxy->getContent(); } public function isDraft() { return !$this->proxy->getTransactionPHID(); } public function setPathID($id) { $this->proxy->setPathID($id); return $this; } public function getPathID() { return $this->proxy->getPathID(); } public function setIsNewFile($is_new) { $this->proxy->setIsNewFile($is_new); return $this; } public function getIsNewFile() { return $this->proxy->getIsNewFile(); } public function setLineNumber($number) { $this->proxy->setLineNumber($number); return $this; } public function getLineNumber() { return $this->proxy->getLineNumber(); } public function setLineLength($length) { $this->proxy->setLineLength($length); return $this; } public function getLineLength() { return $this->proxy->getLineLength(); } public function setCache($cache) { return $this; } public function getCache() { return null; } public function setAuthorPHID($phid) { $this->proxy->setAuthorPHID($phid); return $this; } public function getAuthorPHID() { return $this->proxy->getAuthorPHID(); } public function setCommitPHID($commit_phid) { $this->proxy->setCommitPHID($commit_phid); return $this; } public function getCommitPHID() { return $this->proxy->getCommitPHID(); } // When setting a comment ID, we also generate a phantom transaction PHID for // the future transaction. public function setAuditCommentID($id) { $this->proxy->setLegacyCommentID($id); $this->proxy->setTransactionPHID( PhabricatorPHID::generateNewPHID( PhabricatorApplicationTransactionTransactionPHIDType::TYPECONST, PhabricatorRepositoryCommitPHIDType::TYPECONST)); return $this; } public function getAuditCommentID() { return $this->proxy->getLegacyCommentID(); } public function setChangesetID($id) { return $this->setPathID($id); } public function getChangesetID() { return $this->getPathID(); } /* -( PhabricatorMarkupInterface Implementation )-------------------------- */ public function getMarkupFieldKey($field) { return 'AI:'.$this->getID(); } public function newMarkupEngine($field) { return PhabricatorMarkupEngine::newDifferentialMarkupEngine(); } public function getMarkupText($field) { return $this->getContent(); } public function didMarkupText($field, $output, PhutilMarkupEngine $engine) { return $output; } public function shouldUseMarkupCache($field) { // Only cache submitted comments. return ($this->getID() && $this->getAuditCommentID()); } }