1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 00:42:41 +01:00

Prepare TransactionEditor for silent transactions via bulk edit

Summary:
Ref T13042. This adds a "silent" edit mechanism which suppresses feed stories, email, and notifications.

The other behaviors here are:

  - The transactions are marked as "silent" so we can render a hint in the UI in the future to make it clear to users that they aren't missing email.
  - If the editor uses Herald, mail rules are suppressed so they don't fire incorrectly (this mostly affects "the first time this rule matches, send me an email" rules: without this, they'd match "the first time" on the bulk edit, not send email, then never match again since they already matched).
  - If the edit queues additional edits, those are applied silently too.

This doesn't (or, at least, shouldn't) actually change any behavior since you can't apply silent edits yet.

Test Plan:
Somewhat theoretical, since this isn't reachable yet. Should get meaningful testing in an upcoming change.

Did a bit of var_dump() / debug poking to attempt to verify that nothing too crazy is happening.

Viewed and edited objects, no changes in behavior.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13042

Differential Revision: https://secure.phabricator.com/D18882
This commit is contained in:
epriestley 2018-01-19 07:59:35 -08:00
parent 8a5def8e0a
commit 8b12fa6d6e
6 changed files with 90 additions and 11 deletions

View file

@ -1356,6 +1356,7 @@ phutil_register_library_map(array(
'HeraldConditionTranscript' => 'applications/herald/storage/transcript/HeraldConditionTranscript.php', 'HeraldConditionTranscript' => 'applications/herald/storage/transcript/HeraldConditionTranscript.php',
'HeraldContentSourceField' => 'applications/herald/field/HeraldContentSourceField.php', 'HeraldContentSourceField' => 'applications/herald/field/HeraldContentSourceField.php',
'HeraldController' => 'applications/herald/controller/HeraldController.php', 'HeraldController' => 'applications/herald/controller/HeraldController.php',
'HeraldCoreStateReasons' => 'applications/herald/state/HeraldCoreStateReasons.php',
'HeraldDAO' => 'applications/herald/storage/HeraldDAO.php', 'HeraldDAO' => 'applications/herald/storage/HeraldDAO.php',
'HeraldDifferentialAdapter' => 'applications/differential/herald/HeraldDifferentialAdapter.php', 'HeraldDifferentialAdapter' => 'applications/differential/herald/HeraldDifferentialAdapter.php',
'HeraldDifferentialDiffAdapter' => 'applications/differential/herald/HeraldDifferentialDiffAdapter.php', 'HeraldDifferentialDiffAdapter' => 'applications/differential/herald/HeraldDifferentialDiffAdapter.php',
@ -6529,6 +6530,7 @@ phutil_register_library_map(array(
'HeraldConditionTranscript' => 'Phobject', 'HeraldConditionTranscript' => 'Phobject',
'HeraldContentSourceField' => 'HeraldField', 'HeraldContentSourceField' => 'HeraldField',
'HeraldController' => 'PhabricatorController', 'HeraldController' => 'PhabricatorController',
'HeraldCoreStateReasons' => 'HeraldStateReasons',
'HeraldDAO' => 'PhabricatorLiskDAO', 'HeraldDAO' => 'PhabricatorLiskDAO',
'HeraldDifferentialAdapter' => 'HeraldAdapter', 'HeraldDifferentialAdapter' => 'HeraldAdapter',
'HeraldDifferentialDiffAdapter' => 'HeraldDifferentialAdapter', 'HeraldDifferentialDiffAdapter' => 'HeraldDifferentialAdapter',

View file

@ -0,0 +1,18 @@
<?php
final class HeraldCoreStateReasons
extends HeraldStateReasons {
const REASON_SILENT = 'core.silent';
public function explainReason($reason) {
$reasons = array(
self::REASON_SILENT => pht(
'This change applied silently, so mail and other notifications '.
'will not be sent.'),
);
return idx($reasons, $reason);
}
}

View file

@ -68,7 +68,9 @@ abstract class PhabricatorApplicationTransactionEditor
private $feedNotifyPHIDs = array(); private $feedNotifyPHIDs = array();
private $feedRelatedPHIDs = array(); private $feedRelatedPHIDs = array();
private $feedShouldPublish = false; private $feedShouldPublish = false;
private $mailShouldSend = false;
private $modularTypes; private $modularTypes;
private $silent;
private $transactionQueue = array(); private $transactionQueue = array();
@ -187,6 +189,15 @@ abstract class PhabricatorApplicationTransactionEditor
return $this->isPreview; return $this->isPreview;
} }
public function setIsSilent($silent) {
$this->silent = $silent;
return $this;
}
public function getIsSilent() {
return $this->silent;
}
public function setIsInverseEdgeEditor($is_inverse_edge_editor) { public function setIsInverseEdgeEditor($is_inverse_edge_editor) {
$this->isInverseEdgeEditor = $is_inverse_edge_editor; $this->isInverseEdgeEditor = $is_inverse_edge_editor;
return $this; return $this;
@ -790,6 +801,10 @@ abstract class PhabricatorApplicationTransactionEditor
$xaction->setObjectPHID($object->getPHID()); $xaction->setObjectPHID($object->getPHID());
} }
if ($this->getIsSilent()) {
$xaction->setIsSilentTransaction(true);
}
return $xaction; return $xaction;
} }
@ -1136,15 +1151,22 @@ abstract class PhabricatorApplicationTransactionEditor
// Editors need to pass into workers. // Editors need to pass into workers.
$object = $this->willPublish($object, $xactions); $object = $this->willPublish($object, $xactions);
if (!$this->getIsSilent()) {
if ($this->shouldSendMail($object, $xactions)) { if ($this->shouldSendMail($object, $xactions)) {
$this->mailShouldSend = true;
$this->mailToPHIDs = $this->getMailTo($object); $this->mailToPHIDs = $this->getMailTo($object);
$this->mailCCPHIDs = $this->getMailCC($object); $this->mailCCPHIDs = $this->getMailCC($object);
} }
if ($this->shouldPublishFeedStory($object, $xactions)) { if ($this->shouldPublishFeedStory($object, $xactions)) {
$this->feedShouldPublish = true; $this->feedShouldPublish = true;
$this->feedRelatedPHIDs = $this->getFeedRelatedPHIDs($object, $xactions); $this->feedRelatedPHIDs = $this->getFeedRelatedPHIDs(
$this->feedNotifyPHIDs = $this->getFeedNotifyPHIDs($object, $xactions); $object,
$xactions);
$this->feedNotifyPHIDs = $this->getFeedNotifyPHIDs(
$object,
$xactions);
}
} }
PhabricatorWorker::scheduleTask( PhabricatorWorker::scheduleTask(
@ -1186,7 +1208,7 @@ abstract class PhabricatorApplicationTransactionEditor
$this->object = $object; $this->object = $object;
$messages = array(); $messages = array();
if ($this->shouldSendMail($object, $xactions)) { if ($this->mailShouldSend) {
$messages = $this->buildMail($object, $xactions); $messages = $this->buildMail($object, $xactions);
} }
@ -3138,6 +3160,16 @@ abstract class PhabricatorApplicationTransactionEditor
$adapter->setApplicationEmail($this->getApplicationEmail()); $adapter->setApplicationEmail($this->getApplicationEmail());
} }
// If this editor is operating in silent mode, tell Herald that we aren't
// going to send any mail. This allows it to skip "the first time this
// rule matches, send me an email" rules which would otherwise match even
// though we aren't going to send any mail.
if ($this->getIsSilent()) {
$adapter->setForbiddenAction(
HeraldMailableState::STATECONST,
HeraldCoreStateReasons::REASON_SILENT);
}
$xscript = HeraldEngine::loadAndApplyRules($adapter); $xscript = HeraldEngine::loadAndApplyRules($adapter);
$this->setHeraldAdapter($adapter); $this->setHeraldAdapter($adapter);
@ -3493,6 +3525,7 @@ abstract class PhabricatorApplicationTransactionEditor
'feedNotifyPHIDs', 'feedNotifyPHIDs',
'feedRelatedPHIDs', 'feedRelatedPHIDs',
'feedShouldPublish', 'feedShouldPublish',
'mailShouldSend',
); );
} }
@ -3875,7 +3908,8 @@ abstract class PhabricatorApplicationTransactionEditor
->setActor($this->getActor()) ->setActor($this->getActor())
->setContentSource($this->getContentSource()) ->setContentSource($this->getContentSource())
->setContinueOnNoEffect($this->getContinueOnNoEffect()) ->setContinueOnNoEffect($this->getContinueOnNoEffect())
->setContinueOnMissingFields($this->getContinueOnMissingFields()); ->setContinueOnMissingFields($this->getContinueOnMissingFields())
->setIsSilent($this->getIsSilent());
if ($this->actingAsPHID !== null) { if ($this->actingAsPHID !== null) {
$editor->setActingAsPHID($this->actingAsPHID); $editor->setActingAsPHID($this->actingAsPHID);

View file

@ -158,6 +158,14 @@ abstract class PhabricatorApplicationTransaction
return (bool)$this->getMetadataValue('core.default', false); return (bool)$this->getMetadataValue('core.default', false);
} }
public function setIsSilentTransaction($silent) {
return $this->setMetadataValue('core.silent', $silent);
}
public function getIsSilentTransaction() {
return (bool)$this->getMetadataValue('core.silent', false);
}
public function attachComment( public function attachComment(
PhabricatorApplicationTransactionComment $comment) { PhabricatorApplicationTransactionComment $comment) {
$this->comment = $comment; $this->comment = $comment;
@ -1515,6 +1523,12 @@ abstract class PhabricatorApplicationTransaction
if ($apart > (60 * 2)) { if ($apart > (60 * 2)) {
return false; return false;
} }
// Don't group silent and nonsilent transactions together.
$is_silent = $this->getIsSilentTransaction();
if ($is_silent != $xaction->getIsSilentTransaction()) {
return false;
}
} }
return true; return true;

View file

@ -423,7 +423,8 @@ class PhabricatorApplicationTransactionView extends AphrontView {
->setUserHandle($xaction->getHandle($xaction->getAuthorPHID())) ->setUserHandle($xaction->getHandle($xaction->getAuthorPHID()))
->setIcon($xaction->getIcon()) ->setIcon($xaction->getIcon())
->setColor($xaction->getColor()) ->setColor($xaction->getColor())
->setHideCommentOptions($this->getHideCommentOptions()); ->setHideCommentOptions($this->getHideCommentOptions())
->setIsSilent($xaction->getIsSilentTransaction());
list($token, $token_removed) = $xaction->getToken(); list($token, $token_removed) = $xaction->getToken();
if ($token) { if ($token) {

View file

@ -29,6 +29,7 @@ final class PHUITimelineEventView extends AphrontView {
private $authorPHID; private $authorPHID;
private $badges = array(); private $badges = array();
private $pinboardItems = array(); private $pinboardItems = array();
private $isSilent;
public function setAuthorPHID($author_phid) { public function setAuthorPHID($author_phid) {
$this->authorPHID = $author_phid; $this->authorPHID = $author_phid;
@ -177,6 +178,15 @@ final class PHUITimelineEventView extends AphrontView {
return $this; return $this;
} }
public function setIsSilent($is_silent) {
$this->isSilent = $is_silent;
return $this;
}
public function getIsSilent() {
return $this->isSilent;
}
public function setReallyMajorEvent($me) { public function setReallyMajorEvent($me) {
$this->reallyMajorEvent = $me; $this->reallyMajorEvent = $me;
return $this; return $this;