|
| 1 | +<?php |
| 2 | + |
| 3 | +/* |
| 4 | + * Copyright 2012 Facebook, Inc. |
| 5 | + * |
| 6 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 7 | + * you may not use this file except in compliance with the License. |
| 8 | + * You may obtain a copy of the License at |
| 9 | + * |
| 10 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | + * |
| 12 | + * Unless required by applicable law or agreed to in writing, software |
| 13 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 14 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 15 | + * See the License for the specific language governing permissions and |
| 16 | + * limitations under the License. |
| 17 | + */ |
| 18 | + |
| 19 | +abstract class PackageMail { |
| 20 | + |
| 21 | + protected $package; |
| 22 | + protected $handles; |
| 23 | + protected $owners; |
| 24 | + protected $paths; |
| 25 | + protected $mailTo; |
| 26 | + |
| 27 | + public function __construct($package) { |
| 28 | + $this->package = $package; |
| 29 | + } |
| 30 | + |
| 31 | + abstract protected function getVerb(); |
| 32 | + |
| 33 | + abstract protected function isNewThread(); |
| 34 | + |
| 35 | + final protected function getPackage() { |
| 36 | + return $this->package; |
| 37 | + } |
| 38 | + |
| 39 | + final protected function getHandles() { |
| 40 | + return $this->handles; |
| 41 | + } |
| 42 | + |
| 43 | + final protected function getOwners() { |
| 44 | + return $this->owners; |
| 45 | + } |
| 46 | + |
| 47 | + final protected function getPaths() { |
| 48 | + return $this->paths; |
| 49 | + } |
| 50 | + |
| 51 | + final protected function getMailTo() { |
| 52 | + return $this->mailTo; |
| 53 | + } |
| 54 | + |
| 55 | + final protected function renderPackageTitle() { |
| 56 | + return $this->getPackage()->getName(); |
| 57 | + } |
| 58 | + |
| 59 | + final protected function renderRepoSubSection($repository_phid, $paths) { |
| 60 | + $handles = $this->getHandles(); |
| 61 | + $section = array(); |
| 62 | + $section[] = ' In repository '.$handles[$repository_phid]->getName(). |
| 63 | + ' - '. PhabricatorEnv::getProductionURI($handles[$repository_phid] |
| 64 | + ->getURI()); |
| 65 | + foreach ($paths as $path => $ignored) { |
| 66 | + $section[] = ' '.$path; |
| 67 | + } |
| 68 | + |
| 69 | + return implode("\n", $section); |
| 70 | + } |
| 71 | + |
| 72 | + protected function needSend() { |
| 73 | + return true; |
| 74 | + } |
| 75 | + |
| 76 | + protected function loadData() { |
| 77 | + $package = $this->getPackage(); |
| 78 | + $owners = $package->loadOwners(); |
| 79 | + $this->owners = $owners; |
| 80 | + |
| 81 | + $owner_phids = mpull($owners, 'getUserPHID'); |
| 82 | + $primary_owner_phid = $package->getPrimaryOwnerPHID(); |
| 83 | + $mail_to = $owner_phids; |
| 84 | + if (!in_array($primary_owner_phid, $owner_phids)) { |
| 85 | + $mail_to[] = $primary_owner_phid; |
| 86 | + } |
| 87 | + $this->mailTo = $mail_to; |
| 88 | + |
| 89 | + $paths = $package->loadPaths(); |
| 90 | + $this->paths = mgroup($paths, 'getRepositoryPHID', 'getPath'); |
| 91 | + |
| 92 | + $phids = array_mergev(array( |
| 93 | + $this->mailTo, |
| 94 | + array($package->getActorPHID()), |
| 95 | + array_keys($this->paths), |
| 96 | + )); |
| 97 | + $this->handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); |
| 98 | + } |
| 99 | + |
| 100 | + final protected function renderSummarySection() { |
| 101 | + $package = $this->getPackage(); |
| 102 | + $handles = $this->getHandles(); |
| 103 | + $section = array(); |
| 104 | + $section[] = $handles[$package->getActorPHID()]->getName().' '. |
| 105 | + strtolower($this->getVerb()).' '.$this->renderPackageTitle().'.'; |
| 106 | + $section[] = ''; |
| 107 | + |
| 108 | + $section[] = 'PACKAGE DETAIL'; |
| 109 | + $section[] = ' '.PhabricatorEnv::getProductionURI( |
| 110 | + '/owners/package/'.$package->getID().'/'); |
| 111 | + |
| 112 | + return implode("\n", $section); |
| 113 | + } |
| 114 | + |
| 115 | + protected function renderDescriptionSection() { |
| 116 | + return "PACKAGE DESCRIPTION\n". |
| 117 | + ' '.$this->getPackage()->getDescription(); |
| 118 | + } |
| 119 | + |
| 120 | + protected function renderPrimaryOwnerSection() { |
| 121 | + $handles = $this->getHandles(); |
| 122 | + return "PRIMARY OWNER\n". |
| 123 | + ' '.$handles[$this->getPackage()->getPrimaryOwnerPHID()]->getName(); |
| 124 | + } |
| 125 | + |
| 126 | + protected function renderOwnersSection() { |
| 127 | + $handles = $this->getHandles(); |
| 128 | + $owners = $this->getOwners(); |
| 129 | + if (!$owners) { |
| 130 | + return null; |
| 131 | + } |
| 132 | + |
| 133 | + $owners = mpull($owners, 'getUserPHID'); |
| 134 | + $owners = array_select_keys($handles, $owners); |
| 135 | + $owners = mpull($owners, 'getName'); |
| 136 | + return "OWNERS\n". |
| 137 | + ' '.implode(', ', $owners); |
| 138 | + } |
| 139 | + |
| 140 | + protected function renderAuditingEnabledSection() { |
| 141 | + return "AUDITING ENABLED STATUS\n". |
| 142 | + ' '.($this->getPackage()->getAuditingEnabled() ? 'Enabled' : 'Disabled'); |
| 143 | + } |
| 144 | + |
| 145 | + protected function renderPathsSection() { |
| 146 | + $section = array(); |
| 147 | + $section[] = 'PATHS'; |
| 148 | + foreach ($this->paths as $repository_phid => $paths) { |
| 149 | + $section[] = $this->renderRepoSubSection($repository_phid, $paths); |
| 150 | + } |
| 151 | + |
| 152 | + return implode("\n", $section); |
| 153 | + } |
| 154 | + |
| 155 | + final protected function renderBody() { |
| 156 | + $body = array(); |
| 157 | + $body[] = $this->renderSummarySection(); |
| 158 | + $body[] = $this->renderDescriptionSection(); |
| 159 | + $body[] = $this->renderPrimaryOwnerSection(); |
| 160 | + $body[] = $this->renderOwnersSection(); |
| 161 | + $body[] = $this->renderAuditingEnabledSection(); |
| 162 | + $body[] = $this->renderPathsSection(); |
| 163 | + $body = array_filter($body); |
| 164 | + return implode("\n\n", $body); |
| 165 | + } |
| 166 | + |
| 167 | + final public function send() { |
| 168 | + $mails = $this->prepareMails(); |
| 169 | + |
| 170 | + foreach ($mails as $mail) { |
| 171 | + $mail->saveAndSend(); |
| 172 | + } |
| 173 | + } |
| 174 | + |
| 175 | + final public function prepareMails() { |
| 176 | + if (!$this->needSend()) { |
| 177 | + return array(); |
| 178 | + } |
| 179 | + |
| 180 | + $this->loadData(); |
| 181 | + |
| 182 | + $package = $this->getPackage(); |
| 183 | + $prefix = PhabricatorEnv::getEnvConfig('metamta.package.subject-prefix'); |
| 184 | + $verb = $this->getVerb(); |
| 185 | + $package_title = $this->renderPackageTitle(); |
| 186 | + $subject = trim("{$prefix} {$package_title}"); |
| 187 | + $vary_subject = trim("{$prefix} [{$verb}] {$package_title}"); |
| 188 | + $threading = $this->getMailThreading(); |
| 189 | + list($thread_id, $thread_topic) = $threading; |
| 190 | + |
| 191 | + $template = id(new PhabricatorMetaMTAMail()) |
| 192 | + ->setSubject($subject) |
| 193 | + ->setVarySubject($vary_subject) |
| 194 | + ->setFrom($package->getActorPHID()) |
| 195 | + ->setThreadID($thread_id, $this->isNewThread()) |
| 196 | + ->addHeader('Thread-Topic', $thread_topic) |
| 197 | + ->setRelatedPHID($package->getPHID()) |
| 198 | + ->setIsBulk(true) |
| 199 | + ->setBody($this->renderBody()); |
| 200 | + |
| 201 | + $reply_handler = $this->newReplyHandler(); |
| 202 | + $mails = $reply_handler->multiplexMail( |
| 203 | + $template, |
| 204 | + array_select_keys($this->getHandles(), $this->getMailTo()), |
| 205 | + array()); |
| 206 | + return $mails; |
| 207 | + } |
| 208 | + |
| 209 | + private function getMailThreading() { |
| 210 | + return array( |
| 211 | + 'package-'.$this->getPackage()->getPHID(), |
| 212 | + 'package '.$this->getPackage()->getPHID(), |
| 213 | + ); |
| 214 | + } |
| 215 | + |
| 216 | + private function newReplyHandler() { |
| 217 | + $reply_handler = PhabricatorEnv::newObjectFromConfig( |
| 218 | + 'metamta.package.reply-handler'); |
| 219 | + $reply_handler->setMailReceiver($this->getPackage()); |
| 220 | + return $reply_handler; |
| 221 | + } |
| 222 | + |
| 223 | +} |
0 commit comments