Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15462064
D12868.id30952.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
D12868.id30952.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -3101,6 +3101,7 @@
'ProjectQueryConduitAPIMethod' => 'applications/project/conduit/ProjectQueryConduitAPIMethod.php',
'ProjectRemarkupRule' => 'applications/project/remarkup/ProjectRemarkupRule.php',
'ProjectRemarkupRuleTestCase' => 'applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php',
+ 'ProjectReplyHandler' => 'applications/project/mail/ProjectReplyHandler.php',
'QueryFormattingTestCase' => 'infrastructure/storage/__tests__/QueryFormattingTestCase.php',
'ReleephAuthorFieldSpecification' => 'applications/releeph/field/specification/ReleephAuthorFieldSpecification.php',
'ReleephBranch' => 'applications/releeph/storage/ReleephBranch.php',
@@ -6670,6 +6671,7 @@
'ProjectQueryConduitAPIMethod' => 'ProjectConduitAPIMethod',
'ProjectRemarkupRule' => 'PhabricatorObjectRemarkupRule',
'ProjectRemarkupRuleTestCase' => 'PhabricatorTestCase',
+ 'ProjectReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
'QueryFormattingTestCase' => 'PhabricatorTestCase',
'ReleephAuthorFieldSpecification' => 'ReleephFieldSpecification',
'ReleephBranch' => array(
diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
--- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
+++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
@@ -41,7 +41,7 @@
$slugs = $object->getSlugs();
$slugs = mpull($slugs, 'getSlug', 'getSlug');
unset($slugs[$object->getPrimarySlug()]);
- return $slugs;
+ return array_keys($slugs);
case PhabricatorProjectTransaction::TYPE_STATUS:
return $object->getStatus();
case PhabricatorProjectTransaction::TYPE_IMAGE:
@@ -403,11 +403,74 @@
return parent::requireCapabilities($object, $xaction);
}
- /**
- * Note: this is implemented for Feed purposes.
- */
+ protected function loadEdges(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+
+ $member_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
+ $object->getPHID(),
+ PhabricatorProjectProjectHasMemberEdgeType::EDGECONST);
+ $object->attachMemberPHIDs($member_phids);
+ }
+
+ protected function shouldSendMail(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+ return true;
+ }
+
+ protected function getMailSubjectPrefix() {
+ return pht('[Project]');
+ }
+
protected function getMailTo(PhabricatorLiskDAO $object) {
- return array();
+ return $object->getMemberPHIDs();
+ }
+
+ protected function getMailCC(PhabricatorLiskDAO $object) {
+ $all = parent::getMailCC($object);
+ return array_diff($all, $object->getMemberPHIDs());
+ }
+
+ public function getMailTagsMap() {
+ return array(
+ PhabricatorProjectTransaction::MAILTAG_METADATA =>
+ pht('Project name, hashtags, icon, image, or color changes.'),
+ PhabricatorProjectTransaction::MAILTAG_MEMBERS =>
+ pht('Project membership changes.'),
+ PhabricatorProjectTransaction::MAILTAG_WATCHERS =>
+ pht('Project watcher list changes.'),
+ PhabricatorProjectTransaction::MAILTAG_OTHER =>
+ pht('Other project activity not listed above occurs.'),
+ );
+ }
+
+ protected function buildReplyHandler(PhabricatorLiskDAO $object) {
+ return id(new ProjectReplyHandler())
+ ->setMailReceiver($object);
+ }
+
+ protected function buildMailTemplate(PhabricatorLiskDAO $object) {
+ $id = $object->getID();
+ $name = $object->getName();
+
+ return id(new PhabricatorMetaMTAMail())
+ ->setSubject("{$name}")
+ ->addHeader('Thread-Topic', "Project {$id}");
+ }
+
+ protected function buildMailBody(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+
+ $body = parent::buildMailBody($object, $xactions);
+
+ $uri = '/project/profile/'.$object->getID().'/';
+ $body->addLinkSection(
+ pht('PROJECT DETAIL'),
+ PhabricatorEnv::getProductionURI($uri));
+
+ return $body;
}
protected function shouldPublishFeedStory(
diff --git a/src/applications/project/mail/ProjectReplyHandler.php b/src/applications/project/mail/ProjectReplyHandler.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/mail/ProjectReplyHandler.php
@@ -0,0 +1,20 @@
+<?php
+
+final class ProjectReplyHandler
+ extends PhabricatorApplicationTransactionReplyHandler {
+
+ public function validateMailReceiver($mail_receiver) {
+ if (!($mail_receiver instanceof PhabricatorProject)) {
+ throw new Exception('Mail receiver is not a PhabricatorProject.');
+ }
+ }
+
+ public function getObjectPrefix() {
+ return PhabricatorProjectProjectPHIDType::TYPECONST;
+ }
+
+ protected function shouldCreateCommentFromMailBody() {
+ return false;
+ }
+
+}
diff --git a/src/applications/project/storage/PhabricatorProjectTransaction.php b/src/applications/project/storage/PhabricatorProjectTransaction.php
--- a/src/applications/project/storage/PhabricatorProjectTransaction.php
+++ b/src/applications/project/storage/PhabricatorProjectTransaction.php
@@ -14,6 +14,11 @@
// NOTE: This is deprecated, members are just a normal edge now.
const TYPE_MEMBERS = 'project:members';
+ const MAILTAG_METADATA = 'project-metadata';
+ const MAILTAG_MEMBERS = 'project-members';
+ const MAILTAG_WATCHERS = 'project-watchers';
+ const MAILTAG_OTHER = 'project-other';
+
public function getApplicationName() {
return 'project';
}
@@ -106,6 +111,8 @@
$old,
$new);
}
+ break;
+
case self::TYPE_STATUS:
if ($old == 0) {
return pht(
@@ -116,6 +123,8 @@
'%s activated this project.',
$author_handle);
}
+ break;
+
case self::TYPE_IMAGE:
// TODO: Some day, it would be nice to show the images.
if (!$old) {
@@ -134,18 +143,21 @@
$this->renderHandleLink($old),
$this->renderHandleLink($new));
}
+ break;
case self::TYPE_ICON:
return pht(
'%s set this project\'s icon to %s.',
$author_handle,
PhabricatorProjectIcon::getLabel($new));
+ break;
case self::TYPE_COLOR:
return pht(
'%s set this project\'s color to %s.',
$author_handle,
PHUITagView::getShadeName($new));
+ break;
case self::TYPE_LOCKED:
if ($new) {
@@ -157,6 +169,7 @@
'%s unlocked this project\'s membership.',
$author_handle);
}
+ break;
case self::TYPE_SLUGS:
$add = array_diff($new, $old);
@@ -183,6 +196,7 @@
count($rem),
$this->renderSlugList($rem));
}
+ break;
case self::TYPE_MEMBERS:
$add = array_diff($new, $old);
@@ -221,6 +235,7 @@
$this->renderHandleList($rem));
}
}
+ break;
}
return parent::getTitle();
@@ -339,12 +354,43 @@
$object_handle,
$this->renderSlugList($rem));
}
-
}
return parent::getTitleForFeed();
}
+ public function getMailTags() {
+ $tags = array();
+ switch ($this->getTransactionType()) {
+ case self::TYPE_NAME:
+ case self::TYPE_SLUGS:
+ case self::TYPE_IMAGE:
+ case self::TYPE_ICON:
+ case self::TYPE_COLOR:
+ $tags[] = self::MAILTAG_METADATA;
+ break;
+ case PhabricatorTransactions::TYPE_EDGE:
+ $type = $this->getMetadata('edge:type');
+ $type = head($type);
+ $type_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST;
+ $type_watcher = PhabricatorObjectHasWatcherEdgeType::EDGECONST;
+ if ($type == $type_member) {
+ $tags[] = self::MAILTAG_MEMBERS;
+ } else if ($type == $type_watcher) {
+ $tags[] = self::MAILTAG_WATCHERS;
+ } else {
+ $tags[] = self::MAILTAG_OTHER;
+ }
+ break;
+ case self::TYPE_STATUS:
+ case self::TYPE_LOCKED:
+ default:
+ $tags[] = self::MAILTAG_OTHER;
+ break;
+ }
+ return $tags;
+ }
+
private function renderSlugList($slugs) {
return implode(', ', $slugs);
}
diff --git a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
--- a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
+++ b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
@@ -840,6 +840,8 @@
// subscribers to pick up changes caused by Herald (or by other side effects
// in various transaction phases).
$this->loadSubscribers($object);
+ // Hook for other edges that may need (re-)loading
+ $this->loadEdges($object, $xactions);
$this->loadHandles($xactions);
@@ -965,6 +967,12 @@
}
}
+ protected function loadEdges(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+ return;
+ }
+
private function validateEditParameters(
PhabricatorLiskDAO $object,
array $xactions) {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 2, 12:47 PM (5 d, 20 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7711939
Default Alt Text
D12868.id30952.diff (9 KB)
Attached To
Mode
D12868: Projects - add mail to project updates
Attached
Detach File
Event Timeline
Log In to Comment