protected function saveComment(PhabricatorInlineCommentInterface $inline) { $inline->openTransaction(); $inline->save(); DifferentialDraft::markHasDraft($inline->getAuthorPHID(), $inline->getRevisionPHID(), $inline->getPHID()); $inline->saveTransaction(); }
/** * @task internal */ private function buildJoinsClause($conn_r) { $joins = array(); if ($this->pathIDs) { $path_table = new DifferentialAffectedPath(); $joins[] = qsprintf($conn_r, 'JOIN %T p ON p.revisionID = r.id', $path_table->getTableName()); } if ($this->commitHashes) { $joins[] = qsprintf($conn_r, 'JOIN %T hash_rel ON hash_rel.revisionID = r.id', ArcanistDifferentialRevisionHash::TABLE_NAME); } if ($this->ccs) { $joins[] = qsprintf($conn_r, 'JOIN %T e_ccs ON e_ccs.src = r.phid ' . 'AND e_ccs.type = %s ' . 'AND e_ccs.dst in (%Ls)', PhabricatorEdgeConfig::TABLE_NAME_EDGE, PhabricatorEdgeConfig::TYPE_OBJECT_HAS_SUBSCRIBER, $this->ccs); } if ($this->reviewers) { $joins[] = qsprintf($conn_r, 'JOIN %T e_reviewers ON e_reviewers.src = r.phid ' . 'AND e_reviewers.type = %s ' . 'AND e_reviewers.dst in (%Ls)', PhabricatorEdgeConfig::TABLE_NAME_EDGE, PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER, $this->reviewers); } if ($this->draftAuthors) { $differential_draft = new DifferentialDraft(); $joins[] = qsprintf($conn_r, 'JOIN %T has_draft ON has_draft.objectPHID = r.phid ' . 'AND has_draft.authorPHID IN (%Ls)', $differential_draft->getTableName(), $this->draftAuthors); } $joins = implode(' ', $joins); return $joins; }
public function processRequest() { $request = $this->getRequest(); $viewer = $request->getUser(); if (!$request->isFormPost()) { return new Aphront400Response(); } $revision = id(new DifferentialRevisionQuery())->setViewer($viewer)->withIDs(array($this->id))->needReviewerStatus(true)->needReviewerAuthority(true)->executeOne(); if (!$revision) { return new Aphront404Response(); } $type_action = DifferentialTransaction::TYPE_ACTION; $type_subscribers = PhabricatorTransactions::TYPE_SUBSCRIBERS; $type_edge = PhabricatorTransactions::TYPE_EDGE; $type_comment = PhabricatorTransactions::TYPE_COMMENT; $type_inline = DifferentialTransaction::TYPE_INLINE; $edge_reviewer = PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER; $xactions = array(); $action = $request->getStr('action'); switch ($action) { case DifferentialAction::ACTION_COMMENT: case DifferentialAction::ACTION_ADDREVIEWERS: case DifferentialAction::ACTION_ADDCCS: // These transaction types have no direct effect, they just // accompany other transaction types which can have an effect. break; default: $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_action)->setNewValue($request->getStr('action')); break; } $ccs = $request->getArr('ccs'); if ($ccs) { $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_subscribers)->setNewValue(array('+' => $ccs)); } $current_reviewers = mpull($revision->getReviewerStatus(), null, 'getReviewerPHID'); $reviewer_edges = array(); $add_reviewers = $request->getArr('reviewers'); foreach ($add_reviewers as $reviewer_phid) { if (isset($current_reviewers[$reviewer_phid])) { continue; } $reviewer = new DifferentialReviewer($reviewer_phid, array('status' => DifferentialReviewerStatus::STATUS_ADDED)); $reviewer_edges[$reviewer_phid] = array('data' => $reviewer->getEdgeData()); } if ($add_reviewers) { $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_edge)->setMetadataValue('edge:type', $edge_reviewer)->setNewValue(array('+' => $reviewer_edges)); } $inlines = DifferentialTransactionQuery::loadUnsubmittedInlineComments($viewer, $revision); foreach ($inlines as $inline) { $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_inline)->attachComment($inline); } // NOTE: If there are no other transactions, add an empty comment // transaction so that we'll raise a more user-friendly error message, // to the effect of "you can not post an empty comment". $no_xactions = !$xactions; $comment = $request->getStr('comment'); if (strlen($comment) || $no_xactions) { $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_comment)->attachComment(id(new DifferentialTransactionComment())->setRevisionPHID($revision->getPHID())->setContent($comment)); } $editor = id(new DifferentialTransactionEditor())->setActor($viewer)->setContentSourceFromRequest($request)->setContinueOnMissingFields(true)->setContinueOnNoEffect($request->isContinueRequest()); $revision_uri = '/D' . $revision->getID(); try { $editor->applyTransactions($revision, $xactions); } catch (PhabricatorApplicationTransactionNoEffectException $ex) { return id(new PhabricatorApplicationTransactionNoEffectResponse())->setCancelURI($revision_uri)->setException($ex); } catch (PhabricatorApplicationTransactionValidationException $ex) { // TODO: Provide a nice Response for rendering these in a clean way. throw $ex; } $user = $request->getUser(); $draft = id(new PhabricatorDraft())->loadOneWhere('authorPHID = %s AND draftKey = %s', $user->getPHID(), 'differential-comment-' . $revision->getID()); if ($draft) { $draft->delete(); } DifferentialDraft::deleteAllDrafts($user->getPHID(), $revision->getPHID()); return id(new AphrontRedirectResponse())->setURI('/D' . $revision->getID()); }
/** * @task internal */ private function buildJoinsClause($conn_r) { $joins = array(); if ($this->pathIDs) { $path_table = new DifferentialAffectedPath(); $joins[] = qsprintf($conn_r, 'JOIN %T p ON p.revisionID = r.id', $path_table->getTableName()); } if ($this->commitHashes) { $joins[] = qsprintf($conn_r, 'JOIN %T hash_rel ON hash_rel.revisionID = r.id', ArcanistDifferentialRevisionHash::TABLE_NAME); } if ($this->ccs) { $joins[] = qsprintf($conn_r, 'JOIN %T e_ccs ON e_ccs.src = r.phid ' . 'AND e_ccs.type = %s ' . 'AND e_ccs.dst in (%Ls)', PhabricatorEdgeConfig::TABLE_NAME_EDGE, PhabricatorObjectHasSubscriberEdgeType::EDGECONST, $this->ccs); } if ($this->reviewers) { $joins[] = qsprintf($conn_r, 'JOIN %T e_reviewers ON e_reviewers.src = r.phid ' . 'AND e_reviewers.type = %s ' . 'AND e_reviewers.dst in (%Ls)', PhabricatorEdgeConfig::TABLE_NAME_EDGE, DifferentialRevisionHasReviewerEdgeType::EDGECONST, $this->reviewers); } if ($this->draftAuthors) { $differential_draft = new DifferentialDraft(); $joins[] = qsprintf($conn_r, 'JOIN %T has_draft ON has_draft.objectPHID = r.phid ' . 'AND has_draft.authorPHID IN (%Ls)', $differential_draft->getTableName(), $this->draftAuthors); } if ($this->commitPHIDs) { $joins[] = qsprintf($conn_r, 'JOIN %T commits ON commits.revisionID = r.id', DifferentialRevision::TABLE_COMMIT); } $joins[] = $this->buildJoinClauseParts($conn_r); return $this->formatJoinClause($joins); }
public function handleRequest(AphrontRequest $request) { $viewer = $this->getViewer(); $id = $request->getURIData('id'); $revision = id(new DifferentialRevisionQuery())->setViewer($viewer)->withIDs(array($id))->executeOne(); if (!$revision) { return new Aphront404Response(); } $type_comment = PhabricatorTransactions::TYPE_COMMENT; $type_action = DifferentialTransaction::TYPE_ACTION; $type_edge = PhabricatorTransactions::TYPE_EDGE; $type_subscribers = PhabricatorTransactions::TYPE_SUBSCRIBERS; $xactions = array(); $action = $request->getStr('action'); switch ($action) { case DifferentialAction::ACTION_COMMENT: case DifferentialAction::ACTION_ADDREVIEWERS: case DifferentialAction::ACTION_ADDCCS: break; default: $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_action)->setNewValue($action); break; } $edge_reviewer = DifferentialRevisionHasReviewerEdgeType::EDGECONST; $reviewers = $request->getStrList('reviewers'); if (DifferentialAction::allowReviewers($action) && $reviewers) { $faux_edges = array(); foreach ($reviewers as $phid) { $faux_edges[$phid] = array('src' => $revision->getPHID(), 'type' => $edge_reviewer, 'dst' => $phid); } $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_edge)->setMetadataValue('edge:type', $edge_reviewer)->setOldValue(array())->setNewValue($faux_edges); } $ccs = $request->getStrList('ccs'); if ($ccs) { $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_subscribers)->setOldValue(array())->setNewValue(array_fuse($ccs)); } // Add a comment transaction if there's nothing, so we'll generate a // nonempty result. if (strlen($request->getStr('content')) || !$xactions) { $xactions[] = id(new DifferentialTransaction())->setTransactionType($type_comment)->attachComment(id(new ManiphestTransactionComment())->setContent($request->getStr('content'))); } foreach ($xactions as $xaction) { $xaction->setAuthorPHID($viewer->getPHID()); } $engine = new PhabricatorMarkupEngine(); $engine->setViewer($request->getUser()); foreach ($xactions as $xaction) { if ($xaction->hasComment()) { $engine->addObject($xaction->getComment(), PhabricatorApplicationTransactionComment::MARKUP_FIELD_COMMENT); } } $engine->process(); $phids = mpull($xactions, 'getRequiredHandlePHIDs'); $phids = array_mergev($phids); $handles = id(new PhabricatorHandleQuery())->setViewer($viewer)->withPHIDs($phids)->execute(); foreach ($xactions as $xaction) { $xaction->setHandles($handles); } $view = id(new DifferentialTransactionView())->setUser($viewer)->setTransactions($xactions)->setIsPreview(true); $metadata = array('reviewers' => $reviewers, 'ccs' => $ccs); if ($action != DifferentialAction::ACTION_COMMENT) { $metadata['action'] = $action; } $draft_key = 'differential-comment-' . $id; $draft = id(new PhabricatorDraft())->setAuthorPHID($viewer->getPHID())->setDraftKey($draft_key)->setDraft($request->getStr('content'))->setMetadata($metadata)->replaceOrDelete(); if ($draft->isDeleted()) { DifferentialDraft::deleteHasDraft($viewer->getPHID(), $revision->getPHID(), $draft_key); } else { DifferentialDraft::markHasDraft($viewer->getPHID(), $revision->getPHID(), $draft_key); } return id(new AphrontAjaxResponse())->setContent((string) phutil_implode_html('', $view->buildEvents())); }
<?php // Destroy duplicate drafts before storage adjustment adds a unique key to this // table. See T1191. We retain the newest draft. // (We can't easily do this in a single SQL statement because MySQL won't let us // modify a table that's joined in a subquery.) $table = new DifferentialDraft(); $conn_w = $table->establishConnection('w'); $duplicates = queryfx_all($conn_w, 'SELECT DISTINCT u.id id FROM %T u JOIN %T v ON u.objectPHID = v.objectPHID AND u.authorPHID = v.authorPHID AND u.draftKey = v.draftKey AND u.id < v.id', $table->getTableName(), $table->getTableName()); $duplicates = ipull($duplicates, 'id'); foreach (PhabricatorLiskDAO::chunkSQL($duplicates) as $chunk) { queryfx($conn_w, 'DELETE FROM %T WHERE id IN (%Q)', $table->getTableName(), $chunk); }