package = $package; } abstract protected function getVerb(); abstract protected function isNewThread(); final protected function getPackage() { return $this->package; } final protected function getHandles() { return $this->handles; } final protected function getOwners() { return $this->owners; } final protected function getPaths() { return $this->paths; } final protected function getMailTo() { return $this->mailTo; } final protected function renderPackageTitle() { return $this->getPackage()->getName(); } final protected function renderRepoSubSection($repository_phid, $paths) { $handles = $this->getHandles(); $section = array(); $section[] = ' In repository '.$handles[$repository_phid]->getName(). ' - '.PhabricatorEnv::getProductionURI($handles[$repository_phid] ->getURI()); foreach ($paths as $path => $excluded) { $section[] = ' '.($excluded ? 'Excluded' : 'Included').' '.$path; } return implode("\n", $section); } protected function needSend() { return true; } protected function loadData() { $package = $this->getPackage(); $owners = $package->loadOwners(); $this->owners = $owners; $owner_phids = mpull($owners, 'getUserPHID'); $primary_owner_phid = $package->getPrimaryOwnerPHID(); $mail_to = $owner_phids; if (!in_array($primary_owner_phid, $owner_phids)) { $mail_to[] = $primary_owner_phid; } $this->mailTo = $mail_to; $this->paths = array(); $repository_paths = mgroup($package->loadPaths(), 'getRepositoryPHID'); foreach ($repository_paths as $repository_phid => $paths) { $this->paths[$repository_phid] = mpull($paths, 'getExcluded', 'getPath'); } $phids = array_merge( $this->mailTo, array($package->getActorPHID()), array_keys($this->paths)); $this->handles = id(new PhabricatorHandleQuery()) ->setViewer($this->getActor()) ->withPHIDs($phids) ->execute(); } final protected function renderSummarySection() { $package = $this->getPackage(); $handles = $this->getHandles(); $section = array(); $section[] = $handles[$package->getActorPHID()]->getName().' '. strtolower($this->getVerb()).' '.$this->renderPackageTitle().'.'; $section[] = ''; $section[] = 'PACKAGE DETAIL'; $section[] = ' '.PhabricatorEnv::getProductionURI( '/owners/package/'.$package->getID().'/'); return implode("\n", $section); } protected function renderDescriptionSection() { return "PACKAGE DESCRIPTION\n". ' '.$this->getPackage()->getDescription(); } protected function renderPrimaryOwnerSection() { $handles = $this->getHandles(); return "PRIMARY OWNER\n". ' '.$handles[$this->getPackage()->getPrimaryOwnerPHID()]->getName(); } protected function renderOwnersSection() { $handles = $this->getHandles(); $owners = $this->getOwners(); if (!$owners) { return null; } $owners = mpull($owners, 'getUserPHID'); $owners = array_select_keys($handles, $owners); $owners = mpull($owners, 'getName'); return "OWNERS\n". ' '.implode(', ', $owners); } protected function renderAuditingEnabledSection() { return "AUDITING ENABLED STATUS\n". ' '.($this->getPackage()->getAuditingEnabled() ? 'Enabled' : 'Disabled'); } protected function renderPathsSection() { $section = array(); $section[] = 'PATHS'; foreach ($this->paths as $repository_phid => $paths) { $section[] = $this->renderRepoSubSection($repository_phid, $paths); } return implode("\n", $section); } final protected function renderBody() { $body = array(); $body[] = $this->renderSummarySection(); $body[] = $this->renderDescriptionSection(); $body[] = $this->renderPrimaryOwnerSection(); $body[] = $this->renderOwnersSection(); $body[] = $this->renderAuditingEnabledSection(); $body[] = $this->renderPathsSection(); $body = array_filter($body); return implode("\n\n", $body)."\n"; } final public function send() { $mails = $this->prepareMails(); foreach ($mails as $mail) { $mail->saveAndSend(); } } final public function prepareMails() { if (!$this->needSend()) { return array(); } $this->loadData(); $package = $this->getPackage(); $prefix = PhabricatorEnv::getEnvConfig('metamta.package.subject-prefix'); $verb = $this->getVerb(); $threading = $this->getMailThreading(); list($thread_id, $thread_topic) = $threading; $template = id(new PhabricatorMetaMTAMail()) ->setSubject($this->renderPackageTitle()) ->setSubjectPrefix($prefix) ->setVarySubjectPrefix("[{$verb}]") ->setFrom($package->getActorPHID()) ->setThreadID($thread_id, $this->isNewThread()) ->addHeader('Thread-Topic', $thread_topic) ->setRelatedPHID($package->getPHID()) ->setIsBulk(true) ->setBody($this->renderBody()); $reply_handler = $this->newReplyHandler(); $mails = $reply_handler->multiplexMail( $template, array_select_keys($this->getHandles(), $this->getMailTo()), array()); return $mails; } private function getMailThreading() { return array( 'package-'.$this->getPackage()->getPHID(), 'Package '.$this->getPackage()->getOriginalName(), ); } private function newReplyHandler() { $reply_handler = PhabricatorEnv::newObjectFromConfig( 'metamta.package.reply-handler'); $reply_handler->setMailReceiver($this->getPackage()); return $reply_handler; } }