@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.

When users resign from revisions, stop expanding projects/packages to include them

Summary:
Depends on D19019. Ref T13053. Fixes T12689. See PHI178.

Currently, if `@alice` resigns from a revision but `#alice-fan-club` is still a subscriber or reviewer, she'll continue to get mail. This is undesirable.

When users are associated with an object but have explicitly disengaged in an individal role (currently, only resign in audit/differential) mark them "unexpandable", so that they can no longer be included through implicit membership in a group (a project or package).

`@alice` can still get mail if she's a explicit recipient: as an author, owner, or if she adds herself back as a subscriber.

Test Plan:
- Added `@ducker` and `#users-named-ducker` as reviewers. Ducker got mail.
- Resigned as ducker, stopped getting future mail.
- Subscribed explicitly, got mail again.
- (Plus some `var_dump()` sanity checking in the internals.)

Reviewers: amckinley

Maniphest Tasks: T13053, T12689

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

+88 -5
+13 -2
src/applications/audit/editor/PhabricatorAuditEditor.php
··· 496 496 $phids[] = $object->getAuthorPHID(); 497 497 } 498 498 499 - $status_resigned = PhabricatorAuditStatusConstants::RESIGNED; 500 499 foreach ($object->getAudits() as $audit) { 501 500 if (!$audit->isInteresting()) { 502 501 // Don't send mail to uninteresting auditors, like packages which ··· 504 503 continue; 505 504 } 506 505 507 - if ($audit->getAuditStatus() != $status_resigned) { 506 + if (!$audit->isResigned()) { 508 507 $phids[] = $audit->getAuditorPHID(); 509 508 } 510 509 } 511 510 512 511 $phids[] = $this->getActingAsPHID(); 512 + 513 + return $phids; 514 + } 515 + 516 + protected function newMailUnexpandablePHIDs(PhabricatorLiskDAO $object) { 517 + $phids = array(); 518 + 519 + foreach ($object->getAudits() as $auditor) { 520 + if ($auditor->isResigned()) { 521 + $phids[] = $auditor->getAuditorPHID(); 522 + } 523 + } 513 524 514 525 return $phids; 515 526 }
+12
src/applications/differential/editor/DifferentialTransactionEditor.php
··· 644 644 return $phids; 645 645 } 646 646 647 + protected function newMailUnexpandablePHIDs(PhabricatorLiskDAO $object) { 648 + $phids = array(); 649 + 650 + foreach ($object->getReviewers() as $reviewer) { 651 + if ($reviewer->isResigned()) { 652 + $phids[] = $reviewer->getReviewerPHID(); 653 + } 654 + } 655 + 656 + return $phids; 657 + } 658 + 647 659 protected function getMailAction( 648 660 PhabricatorLiskDAO $object, 649 661 array $xactions) {
+8 -2
src/applications/differential/storage/DifferentialRevision.php
··· 820 820 } 821 821 822 822 foreach ($reviewers as $reviewer) { 823 - if ($reviewer->getReviewerPHID() == $phid) { 824 - return true; 823 + if ($reviewer->getReviewerPHID() !== $phid) { 824 + continue; 825 825 } 826 + 827 + if ($reviewer->isResigned()) { 828 + continue; 829 + } 830 + 831 + return true; 826 832 } 827 833 828 834 return false;
+30
src/applications/metamta/replyhandler/PhabricatorMailReplyHandler.php
··· 6 6 private $applicationEmail; 7 7 private $actor; 8 8 private $excludePHIDs = array(); 9 + private $unexpandablePHIDs = array(); 9 10 10 11 final public function setMailReceiver($mail_receiver) { 11 12 $this->validateMailReceiver($mail_receiver); ··· 43 44 44 45 final public function getExcludeMailRecipientPHIDs() { 45 46 return $this->excludePHIDs; 47 + } 48 + 49 + public function setUnexpandablePHIDs(array $phids) { 50 + $this->unexpandablePHIDs = $phids; 51 + return $this; 52 + } 53 + 54 + public function getUnexpandablePHIDs() { 55 + return $this->unexpandablePHIDs; 46 56 } 47 57 48 58 abstract public function validateMailReceiver($mail_receiver); ··· 297 307 $to_result = array(); 298 308 $cc_result = array(); 299 309 310 + // "Unexpandable" users have disengaged from an object (for example, 311 + // by resigning from a revision). 312 + 313 + // If such a user is still a direct recipient (for example, they're still 314 + // on the Subscribers list) they're fair game, but group targets (like 315 + // projects) will no longer include them when expanded. 316 + 317 + $unexpandable = $this->getUnexpandablePHIDs(); 318 + $unexpandable = array_fuse($unexpandable); 319 + 300 320 $all_phids = array_merge($to, $cc); 301 321 if ($all_phids) { 302 322 $map = id(new PhabricatorMetaMTAMemberQuery()) ··· 305 325 ->execute(); 306 326 foreach ($to as $phid) { 307 327 foreach ($map[$phid] as $expanded) { 328 + if ($expanded !== $phid) { 329 + if (isset($unexpandable[$expanded])) { 330 + continue; 331 + } 332 + } 308 333 $to_result[$expanded] = $expanded; 309 334 } 310 335 } 311 336 foreach ($cc as $phid) { 312 337 foreach ($map[$phid] as $expanded) { 338 + if ($expanded !== $phid) { 339 + if (isset($unexpandable[$expanded])) { 340 + continue; 341 + } 342 + } 313 343 $cc_result[$expanded] = $expanded; 314 344 } 315 345 }
+9
src/applications/repository/storage/PhabricatorRepositoryAuditRequest.php
··· 72 72 return true; 73 73 } 74 74 75 + public function isResigned() { 76 + switch ($this->getAuditStatus()) { 77 + case PhabricatorAuditStatusConstants::RESIGNED: 78 + return true; 79 + } 80 + 81 + return false; 82 + } 83 + 75 84 76 85 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 77 86
+2 -1
src/applications/repository/storage/PhabricatorRepositoryCommit.php
··· 657 657 public function isAutomaticallySubscribed($phid) { 658 658 659 659 // TODO: This should also list auditors, but handling that is a bit messy 660 - // right now because we are not guaranteed to have the data. 660 + // right now because we are not guaranteed to have the data. (It should not 661 + // include resigned auditors.) 661 662 662 663 return ($phid == $this->getAuthorPHID()); 663 664 }
+14
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 77 77 private $oldTo = array(); 78 78 private $oldCC = array(); 79 79 private $mailRemovedPHIDs = array(); 80 + private $mailUnexpandablePHIDs = array(); 80 81 81 82 private $transactionQueue = array(); 82 83 ··· 1204 1205 $this->mailShouldSend = true; 1205 1206 $this->mailToPHIDs = $this->getMailTo($object); 1206 1207 $this->mailCCPHIDs = $this->getMailCC($object); 1208 + $this->mailUnexpandablePHIDs = $this->newMailUnexpandablePHIDs($object); 1207 1209 1208 1210 // Add any recipients who were previously on the notification list 1209 1211 // but were removed by this change. ··· 2561 2563 $email_to = $this->mailToPHIDs; 2562 2564 $email_cc = $this->mailCCPHIDs; 2563 2565 $email_cc = array_merge($email_cc, $this->heraldEmailPHIDs); 2566 + 2567 + $unexpandable = $this->mailUnexpandablePHIDs; 2568 + if (!is_array($unexpandable)) { 2569 + $unexpandable = array(); 2570 + } 2564 2571 2565 2572 $targets = $this->buildReplyHandler($object) 2573 + ->setUnexpandablePHIDs($unexpandable) 2566 2574 ->getMailTargets($email_to, $email_cc); 2567 2575 2568 2576 // Set this explicitly before we start swapping out the effective actor. ··· 2814 2822 */ 2815 2823 protected function getMailTo(PhabricatorLiskDAO $object) { 2816 2824 throw new Exception(pht('Capability not supported.')); 2825 + } 2826 + 2827 + 2828 + protected function newMailUnexpandablePHIDs(PhabricatorLiskDAO $object) { 2829 + return array(); 2817 2830 } 2818 2831 2819 2832 ··· 3617 3630 'mailShouldSend', 3618 3631 'mustEncrypt', 3619 3632 'mailStamps', 3633 + 'mailUnexpandablePHIDs', 3620 3634 ); 3621 3635 } 3622 3636