@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Remove DifferentialRevisionEditor

Summary: Ref T2222. This has no callsites and no functionality not present in the TransactionEditor.

Test Plan: awwyiss

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2222

Differential Revision: https://secure.phabricator.com/D8456

+3 -679
+3 -5
src/__phutil_library_map__.php
··· 468 468 'DifferentialRevisionControlSystem' => 'applications/differential/constants/DifferentialRevisionControlSystem.php', 469 469 'DifferentialRevisionDetailView' => 'applications/differential/view/DifferentialRevisionDetailView.php', 470 470 'DifferentialRevisionEditController' => 'applications/differential/controller/DifferentialRevisionEditController.php', 471 - 'DifferentialRevisionEditor' => 'applications/differential/editor/DifferentialRevisionEditor.php', 472 471 'DifferentialRevisionIDField' => 'applications/differential/customfield/DifferentialRevisionIDField.php', 473 472 'DifferentialRevisionIDFieldParserTestCase' => 'applications/differential/field/specification/__tests__/DifferentialRevisionIDFieldParserTestCase.php', 474 473 'DifferentialRevisionIDFieldSpecification' => 'applications/differential/field/specification/DifferentialRevisionIDFieldSpecification.php', ··· 2719 2718 'ConduitAPI_differential_creatediff_Method' => 'ConduitAPIMethod', 2720 2719 'ConduitAPI_differential_createinline_Method' => 'ConduitAPI_differential_Method', 2721 2720 'ConduitAPI_differential_createrawdiff_Method' => 'ConduitAPI_differential_Method', 2722 - 'ConduitAPI_differential_createrevision_Method' => 'ConduitAPIMethod', 2721 + 'ConduitAPI_differential_createrevision_Method' => 'ConduitAPI_differential_Method', 2723 2722 'ConduitAPI_differential_find_Method' => 'ConduitAPIMethod', 2724 2723 'ConduitAPI_differential_finishpostponedlinters_Method' => 'ConduitAPIMethod', 2725 2724 'ConduitAPI_differential_getalldiffs_Method' => 'ConduitAPIMethod', ··· 2733 2732 'ConduitAPI_differential_query_Method' => 'ConduitAPIMethod', 2734 2733 'ConduitAPI_differential_querydiffs_Method' => 'ConduitAPIMethod', 2735 2734 'ConduitAPI_differential_setdiffproperty_Method' => 'ConduitAPIMethod', 2736 - 'ConduitAPI_differential_updaterevision_Method' => 'ConduitAPIMethod', 2735 + 'ConduitAPI_differential_updaterevision_Method' => 'ConduitAPI_differential_Method', 2737 2736 'ConduitAPI_differential_updateunitresults_Method' => 'ConduitAPIMethod', 2738 2737 'ConduitAPI_diffusion_Method' => 'ConduitAPIMethod', 2739 2738 'ConduitAPI_diffusion_abstractquery_Method' => 'ConduitAPI_diffusion_Method', ··· 3003 3002 'DifferentialLintFieldSpecification' => 'DifferentialFieldSpecification', 3004 3003 'DifferentialLocalCommitsView' => 'AphrontView', 3005 3004 'DifferentialMail' => 'PhabricatorMail', 3006 - 'DifferentialManiphestTasksField' => 'DifferentialCustomField', 3005 + 'DifferentialManiphestTasksField' => 'DifferentialCoreCustomField', 3007 3006 'DifferentialManiphestTasksFieldSpecification' => 'DifferentialFieldSpecification', 3008 3007 'DifferentialNewDiffMail' => 'DifferentialReviewRequestMail', 3009 3008 'DifferentialPHIDTypeDiff' => 'PhabricatorPHIDType', ··· 3043 3042 ), 3044 3043 'DifferentialRevisionDetailView' => 'AphrontView', 3045 3044 'DifferentialRevisionEditController' => 'DifferentialController', 3046 - 'DifferentialRevisionEditor' => 'PhabricatorEditor', 3047 3045 'DifferentialRevisionIDField' => 'DifferentialCustomField', 3048 3046 'DifferentialRevisionIDFieldParserTestCase' => 'PhabricatorTestCase', 3049 3047 'DifferentialRevisionIDFieldSpecification' => 'DifferentialFieldSpecification',
-674
src/applications/differential/editor/DifferentialRevisionEditor.php
··· 1 - <?php 2 - 3 - /** 4 - * Handle major edit operations to DifferentialRevision -- adding and removing 5 - * reviewers, diffs, and CCs. Unlike simple edits, these changes trigger 6 - * complicated email workflows. 7 - */ 8 - final class DifferentialRevisionEditor extends PhabricatorEditor { 9 - 10 - protected $revision; 11 - 12 - protected $cc = null; 13 - protected $reviewers = null; 14 - protected $diff; 15 - protected $comments; 16 - protected $silentUpdate; 17 - 18 - private $auxiliaryFields = array(); 19 - private $contentSource; 20 - private $isCreate; 21 - 22 - public function __construct(DifferentialRevision $revision) { 23 - $this->revision = $revision; 24 - $this->isCreate = !($revision->getID()); 25 - } 26 - 27 - public function setAuxiliaryFields(array $auxiliary_fields) { 28 - assert_instances_of($auxiliary_fields, 'DifferentialFieldSpecification'); 29 - $this->auxiliaryFields = $auxiliary_fields; 30 - return $this; 31 - } 32 - 33 - public function getRevision() { 34 - return $this->revision; 35 - } 36 - 37 - public function setReviewers(array $reviewers) { 38 - $this->reviewers = $reviewers; 39 - return $this; 40 - } 41 - 42 - public function setCCPHIDs(array $cc) { 43 - $this->cc = $cc; 44 - return $this; 45 - } 46 - 47 - public function setContentSource(PhabricatorContentSource $content_source) { 48 - $this->contentSource = $content_source; 49 - return $this; 50 - } 51 - 52 - public function addDiff(DifferentialDiff $diff, $comments) { 53 - if ($diff->getRevisionID() && 54 - $diff->getRevisionID() != $this->getRevision()->getID()) { 55 - $diff_id = (int)$diff->getID(); 56 - $targ_id = (int)$this->getRevision()->getID(); 57 - $real_id = (int)$diff->getRevisionID(); 58 - throw new Exception( 59 - "Can not attach diff #{$diff_id} to Revision D{$targ_id}, it is ". 60 - "already attached to D{$real_id}."); 61 - } 62 - $this->diff = $diff; 63 - $this->comments = $comments; 64 - 65 - $repository = id(new DifferentialRepositoryLookup()) 66 - ->setViewer($this->getActor()) 67 - ->setDiff($diff) 68 - ->lookupRepository(); 69 - 70 - if ($repository) { 71 - $this->getRevision()->setRepositoryPHID($repository->getPHID()); 72 - } 73 - 74 - return $this; 75 - } 76 - 77 - protected function getDiff() { 78 - return $this->diff; 79 - } 80 - 81 - protected function getComments() { 82 - return $this->comments; 83 - } 84 - 85 - protected function getActorPHID() { 86 - return $this->getActor()->getPHID(); 87 - } 88 - 89 - public function isNewRevision() { 90 - return !$this->getRevision()->getID(); 91 - } 92 - 93 - 94 - public function save() { 95 - $revision = $this->getRevision(); 96 - 97 - $is_new = $this->isNewRevision(); 98 - 99 - $revision->loadRelationships(); 100 - 101 - if ($this->reviewers === null) { 102 - $this->reviewers = $revision->getReviewers(); 103 - } 104 - 105 - if ($this->cc === null) { 106 - $this->cc = $revision->getCCPHIDs(); 107 - } 108 - 109 - if ($is_new) { 110 - $content_blocks = array(); 111 - foreach ($this->auxiliaryFields as $field) { 112 - if ($field->shouldExtractMentions()) { 113 - $content_blocks[] = $field->renderValueForCommitMessage(false); 114 - } 115 - } 116 - $phids = PhabricatorMarkupEngine::extractPHIDsFromMentions( 117 - $content_blocks); 118 - $this->cc = array_unique(array_merge($this->cc, $phids)); 119 - } 120 - 121 - $diff = $this->getDiff(); 122 - if ($diff) { 123 - $revision->setLineCount($diff->getLineCount()); 124 - } 125 - 126 - // Save the revision, to generate its ID and PHID if it is new. We need 127 - // the ID/PHID in order to record them in Herald transcripts, but don't 128 - // want to hold a transaction open while running Herald because it is 129 - // potentially somewhat slow. The downside is that we may end up with a 130 - // saved revision/diff pair without appropriate CCs. We could be better 131 - // about this -- for example: 132 - // 133 - // - Herald can't affect reviewers, so we could compute them before 134 - // opening the transaction and then save them in the transaction. 135 - // - Herald doesn't *really* need PHIDs to compute its effects, we could 136 - // run it before saving these objects and then hand over the PHIDs later. 137 - // 138 - // But this should address the problem of orphaned revisions, which is 139 - // currently the only problem we experience in practice. 140 - 141 - $revision->openTransaction(); 142 - 143 - if ($diff) { 144 - $revision->setBranchName($diff->getBranch()); 145 - $revision->setArcanistProjectPHID($diff->getArcanistProjectPHID()); 146 - } 147 - 148 - $revision->save(); 149 - 150 - if ($diff) { 151 - $diff->setRevisionID($revision->getID()); 152 - $diff->save(); 153 - } 154 - 155 - $revision->saveTransaction(); 156 - 157 - 158 - // We're going to build up three dictionaries: $add, $rem, and $stable. The 159 - // $add dictionary has added reviewers/CCs. The $rem dictionary has 160 - // reviewers/CCs who have been removed, and the $stable array is 161 - // reviewers/CCs who haven't changed. We're going to send new reviewers/CCs 162 - // a different ("welcome") email than we send stable reviewers/CCs. 163 - 164 - $old = array( 165 - 'rev' => array_fill_keys($revision->getReviewers(), true), 166 - 'ccs' => array_fill_keys($revision->getCCPHIDs(), true), 167 - ); 168 - 169 - $xscript_header = null; 170 - $xscript_uri = null; 171 - 172 - $new = array( 173 - 'rev' => array_fill_keys($this->reviewers, true), 174 - 'ccs' => array_fill_keys($this->cc, true), 175 - ); 176 - 177 - $rem_ccs = array(); 178 - $xscript_phid = null; 179 - if ($diff) { 180 - $unsubscribed_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( 181 - $revision->getPHID(), 182 - PhabricatorEdgeConfig::TYPE_OBJECT_HAS_UNSUBSCRIBER); 183 - 184 - $adapter = HeraldDifferentialRevisionAdapter::newLegacyAdapter( 185 - $revision, 186 - $diff); 187 - $adapter->setExplicitCCs($new['ccs']); 188 - $adapter->setExplicitReviewers($new['rev']); 189 - $adapter->setForbiddenCCs($unsubscribed_phids); 190 - $adapter->setIsNewObject($is_new); 191 - 192 - $xscript = HeraldEngine::loadAndApplyRules($adapter); 193 - $xscript_uri = '/herald/transcript/'.$xscript->getID().'/'; 194 - $xscript_phid = $xscript->getPHID(); 195 - $xscript_header = $xscript->getXHeraldRulesHeader(); 196 - 197 - $xscript_header = HeraldTranscript::saveXHeraldRulesHeader( 198 - $revision->getPHID(), 199 - $xscript_header); 200 - 201 - $sub = array( 202 - 'rev' => $adapter->getReviewersAddedByHerald(), 203 - 'ccs' => $adapter->getCCsAddedByHerald(), 204 - ); 205 - $rem_ccs = $adapter->getCCsRemovedByHerald(); 206 - $blocking_reviewers = array_keys( 207 - $adapter->getBlockingReviewersAddedByHerald()); 208 - 209 - HarbormasterBuildable::applyBuildPlans( 210 - $diff->getPHID(), 211 - $revision->getPHID(), 212 - $adapter->getBuildPlans()); 213 - } else { 214 - $sub = array( 215 - 'rev' => array(), 216 - 'ccs' => array(), 217 - ); 218 - $blocking_reviewers = array(); 219 - } 220 - 221 - // Remove any CCs which are prevented by Herald rules. 222 - $sub['ccs'] = array_diff_key($sub['ccs'], $rem_ccs); 223 - $new['ccs'] = array_diff_key($new['ccs'], $rem_ccs); 224 - 225 - $add = array(); 226 - $rem = array(); 227 - $stable = array(); 228 - foreach (array('rev', 'ccs') as $key) { 229 - $add[$key] = array(); 230 - if ($new[$key] !== null) { 231 - $add[$key] += array_diff_key($new[$key], $old[$key]); 232 - } 233 - $add[$key] += array_diff_key($sub[$key], $old[$key]); 234 - 235 - $combined = $sub[$key]; 236 - if ($new[$key] !== null) { 237 - $combined += $new[$key]; 238 - } 239 - $rem[$key] = array_diff_key($old[$key], $combined); 240 - 241 - $stable[$key] = array_diff_key($old[$key], $add[$key] + $rem[$key]); 242 - } 243 - 244 - // Prevent Herald rules from adding a revision's owner as a reviewer. 245 - unset($add['rev'][$revision->getAuthorPHID()]); 246 - 247 - self::updateReviewers( 248 - $revision, 249 - $this->getActor(), 250 - array_keys($add['rev']), 251 - array_keys($rem['rev']), 252 - $blocking_reviewers); 253 - 254 - // We want to attribute new CCs to a "reasonPHID", representing the reason 255 - // they were added. This is either a user (if some user explicitly CCs 256 - // them, or uses "Add CCs...") or a Herald transcript PHID, indicating that 257 - // they were added by a Herald rule. 258 - 259 - if ($add['ccs'] || $rem['ccs']) { 260 - $reasons = array(); 261 - foreach ($add['ccs'] as $phid => $ignored) { 262 - if (empty($new['ccs'][$phid])) { 263 - $reasons[$phid] = $xscript_phid; 264 - } else { 265 - $reasons[$phid] = $this->getActorPHID(); 266 - } 267 - } 268 - foreach ($rem['ccs'] as $phid => $ignored) { 269 - if (empty($new['ccs'][$phid])) { 270 - $reasons[$phid] = $this->getActorPHID(); 271 - } else { 272 - $reasons[$phid] = $xscript_phid; 273 - } 274 - } 275 - } else { 276 - $reasons = $this->getActorPHID(); 277 - } 278 - 279 - self::alterCCs( 280 - $revision, 281 - $this->cc, 282 - array_keys($rem['ccs']), 283 - array_keys($add['ccs']), 284 - $reasons); 285 - 286 - $this->updateAuxiliaryFields(); 287 - 288 - // Add the author and users included from Herald rules to the relevant set 289 - // of users so they get a copy of the email. 290 - if (!$this->silentUpdate) { 291 - if ($is_new) { 292 - $add['rev'][$this->getActorPHID()] = true; 293 - if ($diff) { 294 - $add['rev'] += $adapter->getEmailPHIDsAddedByHerald(); 295 - } 296 - } else { 297 - $stable['rev'][$this->getActorPHID()] = true; 298 - if ($diff) { 299 - $stable['rev'] += $adapter->getEmailPHIDsAddedByHerald(); 300 - } 301 - } 302 - } 303 - 304 - $mail = array(); 305 - 306 - $phids = array($this->getActorPHID()); 307 - 308 - $handles = id(new PhabricatorHandleQuery()) 309 - ->setViewer($this->getActor()) 310 - ->withPHIDs($phids) 311 - ->execute(); 312 - $actor_handle = $handles[$this->getActorPHID()]; 313 - 314 - $changesets = null; 315 - $old_status = $revision->getStatus(); 316 - 317 - if ($diff) { 318 - $changesets = $diff->loadChangesets(); 319 - // TODO: This should probably be in DifferentialFeedbackEditor? 320 - if (!$is_new) { 321 - $this->createComment(); 322 - $mail[] = id(new DifferentialNewDiffMail( 323 - $revision, 324 - $actor_handle, 325 - $changesets)) 326 - ->setActor($this->getActor()) 327 - ->setIsFirstMailAboutRevision(false) 328 - ->setIsFirstMailToRecipients(false) 329 - ->setCommentText($this->getComments()) 330 - ->setToPHIDs(array_keys($stable['rev'])) 331 - ->setCCPHIDs(array_keys($stable['ccs'])); 332 - } 333 - 334 - // Save the changes we made above. 335 - 336 - $diff->setDescription(preg_replace('/\n.*/s', '', $this->getComments())); 337 - $diff->save(); 338 - 339 - // An updated diff should require review, as long as it's not closed 340 - // or accepted. The "accepted" status is "sticky" to encourage courtesy 341 - // re-diffs after someone accepts with minor changes/suggestions. 342 - 343 - $status = $revision->getStatus(); 344 - if ($status != ArcanistDifferentialRevisionStatus::CLOSED && 345 - $status != ArcanistDifferentialRevisionStatus::ACCEPTED) { 346 - $revision->setStatus(ArcanistDifferentialRevisionStatus::NEEDS_REVIEW); 347 - } 348 - 349 - } else { 350 - $diff = $revision->loadActiveDiff(); 351 - if ($diff) { 352 - $changesets = $diff->loadChangesets(); 353 - } else { 354 - $changesets = array(); 355 - } 356 - } 357 - 358 - $revision->save(); 359 - 360 - // If the actor just deleted all the blocking/rejected reviewers, we may 361 - // be able to put the revision into "accepted". 362 - switch ($revision->getStatus()) { 363 - case ArcanistDifferentialRevisionStatus::NEEDS_REVISION: 364 - case ArcanistDifferentialRevisionStatus::CHANGES_PLANNED: 365 - case ArcanistDifferentialRevisionStatus::NEEDS_REVIEW: 366 - $revision = self::updateAcceptedStatus( 367 - $this->getActor(), 368 - $revision); 369 - break; 370 - } 371 - 372 - $event_data = array( 373 - 'revision_id' => $revision->getID(), 374 - 'revision_phid' => $revision->getPHID(), 375 - 'revision_name' => $revision->getTitle(), 376 - 'revision_author_phid' => $revision->getAuthorPHID(), 377 - 'action' => $is_new 378 - ? DifferentialAction::ACTION_CREATE 379 - : DifferentialAction::ACTION_UPDATE, 380 - 'feedback_content' => $is_new 381 - ? phutil_utf8_shorten($revision->getSummary(), 140) 382 - : $this->getComments(), 383 - 'actor_phid' => $revision->getAuthorPHID(), 384 - ); 385 - 386 - $mailed_phids = array(); 387 - if (!$this->silentUpdate) { 388 - $revision->loadRelationships(); 389 - 390 - if ($add['rev']) { 391 - $message = id(new DifferentialNewDiffMail( 392 - $revision, 393 - $actor_handle, 394 - $changesets)) 395 - ->setActor($this->getActor()) 396 - ->setIsFirstMailAboutRevision($is_new) 397 - ->setIsFirstMailToRecipients(true) 398 - ->setToPHIDs(array_keys($add['rev'])); 399 - 400 - if ($is_new) { 401 - // The first time we send an email about a revision, put the CCs in 402 - // the "CC:" field of the same "Review Requested" email that reviewers 403 - // get, so you don't get two initial emails if you're on a list that 404 - // is CC'd. 405 - $message->setCCPHIDs(array_keys($add['ccs'])); 406 - } 407 - 408 - $mail[] = $message; 409 - } 410 - 411 - // If we added CCs, we want to send them an email, but only if they were 412 - // not already a reviewer and were not added as one (in these cases, they 413 - // got a "NewDiff" mail, either in the past or just a moment ago). You can 414 - // still get two emails, but only if a revision is updated and you are 415 - // added as a reviewer at the same time a list you are on is added as a 416 - // CC, which is rare and reasonable. 417 - 418 - $implied_ccs = self::getImpliedCCs($revision); 419 - $implied_ccs = array_fill_keys($implied_ccs, true); 420 - $add['ccs'] = array_diff_key($add['ccs'], $implied_ccs); 421 - 422 - if (!$is_new && $add['ccs']) { 423 - $mail[] = id(new DifferentialCCWelcomeMail( 424 - $revision, 425 - $actor_handle, 426 - $changesets)) 427 - ->setActor($this->getActor()) 428 - ->setIsFirstMailToRecipients(true) 429 - ->setToPHIDs(array_keys($add['ccs'])); 430 - } 431 - 432 - foreach ($mail as $message) { 433 - $message->setHeraldTranscriptURI($xscript_uri); 434 - $message->setXHeraldRulesHeader($xscript_header); 435 - $message->send(); 436 - 437 - $mailed_phids[] = $message->getRawMail()->buildRecipientList(); 438 - } 439 - $mailed_phids = array_mergev($mailed_phids); 440 - } 441 - 442 - id(new PhabricatorFeedStoryPublisher()) 443 - ->setStoryType('PhabricatorFeedStoryDifferential') 444 - ->setStoryData($event_data) 445 - ->setStoryTime(time()) 446 - ->setStoryAuthorPHID($revision->getAuthorPHID()) 447 - ->setRelatedPHIDs( 448 - array( 449 - $revision->getPHID(), 450 - $revision->getAuthorPHID(), 451 - )) 452 - ->setPrimaryObjectPHID($revision->getPHID()) 453 - ->setSubscribedPHIDs( 454 - array_merge( 455 - array($revision->getAuthorPHID()), 456 - $revision->getReviewers(), 457 - $revision->getCCPHIDs())) 458 - ->setMailRecipientPHIDs($mailed_phids) 459 - ->publish(); 460 - 461 - id(new PhabricatorSearchIndexer()) 462 - ->queueDocumentForIndexing($revision->getPHID()); 463 - } 464 - 465 - protected static function alterCCs( 466 - DifferentialRevision $revision, 467 - array $stable_phids, 468 - array $rem_phids, 469 - array $add_phids, 470 - $reason_phid) { 471 - 472 - $dont_add = self::getImpliedCCs($revision); 473 - $add_phids = array_diff($add_phids, $dont_add); 474 - 475 - id(new PhabricatorSubscriptionsEditor()) 476 - ->setActor(PhabricatorUser::getOmnipotentUser()) 477 - ->setObject($revision) 478 - ->subscribeExplicit($add_phids) 479 - ->unsubscribe($rem_phids) 480 - ->save(); 481 - } 482 - 483 - private static function getImpliedCCs(DifferentialRevision $revision) { 484 - return array_merge( 485 - $revision->getReviewers(), 486 - array($revision->getAuthorPHID())); 487 - } 488 - 489 - public static function updateReviewers( 490 - DifferentialRevision $revision, 491 - PhabricatorUser $actor, 492 - array $add_phids, 493 - array $remove_phids, 494 - array $blocking_phids = array()) { 495 - 496 - $reviewers = $revision->getReviewers(); 497 - 498 - $editor = id(new PhabricatorEdgeEditor()) 499 - ->setActor($actor); 500 - 501 - $reviewer_phids_map = array_fill_keys($reviewers, true); 502 - 503 - $blocking_phids = array_fuse($blocking_phids); 504 - foreach ($add_phids as $phid) { 505 - 506 - // Adding an already existing edge again would have cause memory loss 507 - // That is, the previous state for that reviewer would be lost 508 - if (isset($reviewer_phids_map[$phid])) { 509 - // TODO: If we're writing a blocking edge, we should overwrite an 510 - // existing weaker edge (like "added" or "commented"), just not a 511 - // stronger existing edge. 512 - continue; 513 - } 514 - 515 - if (isset($blocking_phids[$phid])) { 516 - $status = DifferentialReviewerStatus::STATUS_BLOCKING; 517 - } else { 518 - $status = DifferentialReviewerStatus::STATUS_ADDED; 519 - } 520 - 521 - $options = array( 522 - 'data' => array( 523 - 'status' => $status, 524 - ) 525 - ); 526 - 527 - $editor->addEdge( 528 - $revision->getPHID(), 529 - PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER, 530 - $phid, 531 - $options); 532 - } 533 - 534 - foreach ($remove_phids as $phid) { 535 - $editor->removeEdge( 536 - $revision->getPHID(), 537 - PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER, 538 - $phid); 539 - } 540 - 541 - $editor->save(); 542 - } 543 - 544 - private function createComment() { 545 - $template = id(new DifferentialComment()) 546 - ->setAuthorPHID($this->getActorPHID()) 547 - ->setRevision($this->revision); 548 - 549 - if ($this->contentSource) { 550 - $content_source = $this->contentSource; 551 - } else { 552 - $content_source = PhabricatorContentSource::newForSource( 553 - PhabricatorContentSource::SOURCE_LEGACY, 554 - array()); 555 - } 556 - 557 - $template->setContentSource($content_source); 558 - 559 - 560 - // Write the "update active diff" transaction. 561 - id(clone $template) 562 - ->setAction(DifferentialAction::ACTION_UPDATE) 563 - ->setMetadata( 564 - array( 565 - DifferentialComment::METADATA_DIFF_ID => $this->getDiff()->getID(), 566 - )) 567 - ->save(); 568 - 569 - // If we have a comment, write the "add a comment" transaction. 570 - if (strlen($this->getComments())) { 571 - id(clone $template) 572 - ->setAction(DifferentialAction::ACTION_COMMENT) 573 - ->setContent($this->getComments()) 574 - ->save(); 575 - } 576 - } 577 - 578 - private function updateAuxiliaryFields() { 579 - $aux_map = array(); 580 - foreach ($this->auxiliaryFields as $aux_field) { 581 - $key = $aux_field->getStorageKey(); 582 - if ($key !== null) { 583 - $val = $aux_field->getValueForStorage(); 584 - $aux_map[$key] = $val; 585 - } 586 - } 587 - 588 - if (!$aux_map) { 589 - return; 590 - } 591 - 592 - $revision = $this->revision; 593 - 594 - $fields = id(new DifferentialCustomFieldStorage())->loadAllWhere( 595 - 'objectPHID = %s', 596 - $revision->getPHID()); 597 - $fields = mpull($fields, null, 'getFieldIndex'); 598 - 599 - foreach ($aux_map as $key => $val) { 600 - $index = PhabricatorHash::digestForIndex($key); 601 - $obj = idx($fields, $index); 602 - if (!strlen($val)) { 603 - // If the new value is empty, just delete the old row if one exists and 604 - // don't add a new row if it doesn't. 605 - if ($obj) { 606 - $obj->delete(); 607 - } 608 - } else { 609 - if (!$obj) { 610 - $obj = new DifferentialCustomFieldStorage(); 611 - $obj->setObjectPHID($revision->getPHID()); 612 - $obj->setFieldIndex($index); 613 - } 614 - 615 - if ($obj->getFieldValue() !== $val) { 616 - $obj->setFieldValue($val); 617 - $obj->save(); 618 - } 619 - } 620 - } 621 - } 622 - 623 - 624 - 625 - /** 626 - * Try to move a revision to "accepted". We look for: 627 - * 628 - * - at least one accepting reviewer who is a user; and 629 - * - no rejects; and 630 - * - no blocking reviewers. 631 - */ 632 - public static function updateAcceptedStatus( 633 - PhabricatorUser $viewer, 634 - DifferentialRevision $revision) { 635 - 636 - $revision = id(new DifferentialRevisionQuery()) 637 - ->setViewer($viewer) 638 - ->withIDs(array($revision->getID())) 639 - ->needRelationships(true) 640 - ->needReviewerStatus(true) 641 - ->needReviewerAuthority(true) 642 - ->executeOne(); 643 - 644 - $has_user_accept = false; 645 - foreach ($revision->getReviewerStatus() as $reviewer) { 646 - $status = $reviewer->getStatus(); 647 - if ($status == DifferentialReviewerStatus::STATUS_BLOCKING) { 648 - // We have a blocking reviewer, so just leave the revision in its 649 - // existing state. 650 - return $revision; 651 - } 652 - 653 - if ($status == DifferentialReviewerStatus::STATUS_REJECTED) { 654 - // We have a rejecting reviewer, so leave the revisoin as is. 655 - return $revision; 656 - } 657 - 658 - if ($reviewer->isUser()) { 659 - if ($status == DifferentialReviewerStatus::STATUS_ACCEPTED) { 660 - $has_user_accept = true; 661 - } 662 - } 663 - } 664 - 665 - if ($has_user_accept) { 666 - $revision 667 - ->setStatus(ArcanistDifferentialRevisionStatus::ACCEPTED) 668 - ->save(); 669 - } 670 - 671 - return $revision; 672 - } 673 - 674 - }