@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<?php
2
3abstract class PhabricatorApplicationTransactionReplyHandler
4 extends PhabricatorMailReplyHandler {
5
6 abstract public function getObjectPrefix();
7
8 public function getPrivateReplyHandlerEmailAddress(
9 PhabricatorUser $user) {
10 return $this->getDefaultPrivateReplyHandlerEmailAddress(
11 $user,
12 $this->getObjectPrefix());
13 }
14
15 public function getPublicReplyHandlerEmailAddress() {
16 return $this->getDefaultPublicReplyHandlerEmailAddress(
17 $this->getObjectPrefix());
18 }
19
20 private function newEditor(PhabricatorMetaMTAReceivedMail $mail) {
21 $content_source = $mail->newContentSource();
22
23 $editor = $this->getMailReceiver()
24 ->getApplicationTransactionEditor()
25 ->setActor($this->getActor())
26 ->setContentSource($content_source)
27 ->setContinueOnMissingFields(true)
28 ->setParentMessageID($mail->getMessageID())
29 ->setExcludeMailRecipientPHIDs($this->getExcludeMailRecipientPHIDs());
30
31 if ($this->getApplicationEmail()) {
32 $editor->setApplicationEmail($this->getApplicationEmail());
33 }
34
35 return $editor;
36 }
37
38 protected function newTransaction() {
39 return $this->getMailReceiver()->getApplicationTransactionTemplate();
40 }
41
42 protected function didReceiveMail(
43 PhabricatorMetaMTAReceivedMail $mail,
44 $body) {
45 return array();
46 }
47
48 protected function shouldCreateCommentFromMailBody() {
49 return (bool)$this->getMailReceiver()->getID();
50 }
51
52 final protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) {
53 $viewer = $this->getActor();
54 $object = $this->getMailReceiver();
55 $app_email = $this->getApplicationEmail();
56
57 $is_new = !$object->getID();
58
59 // If this is a new object which implements the Spaces interface and was
60 // created by sending mail to an ApplicationEmail address, put the object
61 // in the same Space the address is in.
62 if ($is_new) {
63 if ($object instanceof PhabricatorSpacesInterface) {
64 if ($app_email) {
65 $space_phid = PhabricatorSpacesNamespaceQuery::getObjectSpacePHID(
66 $app_email);
67 $object->setSpacePHID($space_phid);
68 }
69 }
70 }
71
72 $body_data = $mail->parseBody();
73 $body = $body_data['body'];
74 $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments());
75
76 $xactions = $this->didReceiveMail($mail, $body);
77
78 // If this object is subscribable, subscribe all the users who were
79 // recipients on the message.
80 if ($object instanceof PhabricatorSubscribableInterface) {
81 $subscriber_phids = $mail->loadAllRecipientPHIDs();
82 if ($subscriber_phids) {
83 $xactions[] = $this->newTransaction()
84 ->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
85 ->setNewValue(
86 array(
87 '+' => $subscriber_phids,
88 ));
89 }
90 }
91
92 $command_xactions = $this->processMailCommands(
93 $mail,
94 $body_data['commands']);
95 foreach ($command_xactions as $xaction) {
96 $xactions[] = $xaction;
97 }
98
99 if ($this->shouldCreateCommentFromMailBody()) {
100 $comment = $this
101 ->newTransaction()
102 ->getApplicationTransactionCommentObject()
103 ->setContent($body);
104
105 $xactions[] = $this->newTransaction()
106 ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
107 ->attachComment($comment);
108 }
109
110 $this->newEditor($mail)
111 ->setContinueOnNoEffect(true)
112 ->applyTransactions($object, $xactions);
113 }
114
115 private function processMailCommands(
116 PhabricatorMetaMTAReceivedMail $mail,
117 array $command_list) {
118
119 $viewer = $this->getActor();
120 $object = $this->getMailReceiver();
121
122 $list = MetaMTAEmailTransactionCommand::getAllCommandsForObject($object);
123 $map = MetaMTAEmailTransactionCommand::getCommandMap($list);
124
125 $xactions = array();
126 foreach ($command_list as $command_argv) {
127 $command = head($command_argv);
128 $argv = array_slice($command_argv, 1);
129
130 $handler = idx($map, phutil_utf8_strtolower($command));
131 if ($handler) {
132 $results = $handler->buildTransactions(
133 $viewer,
134 $object,
135 $mail,
136 $command,
137 $argv);
138 foreach ($results as $result) {
139 $xactions[] = $result;
140 }
141 } else {
142 $valid_commands = array();
143 foreach ($list as $valid_command) {
144 $aliases = $valid_command->getCommandAliases();
145 if ($aliases) {
146 foreach ($aliases as $key => $alias) {
147 $aliases[$key] = '!'.$alias;
148 }
149 $aliases = implode(', ', $aliases);
150 $valid_commands[] = pht(
151 '!%s (or %s)',
152 $valid_command->getCommand(),
153 $aliases);
154 } else {
155 $valid_commands[] = '!'.$valid_command->getCommand();
156 }
157 }
158
159 throw new Exception(
160 pht(
161 'The command "!%s" is not a supported mail command. Valid '.
162 'commands for this object are: %s.',
163 $command,
164 implode(', ', $valid_commands)));
165 }
166 }
167
168 return $xactions;
169 }
170
171}