mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-29 10:12:41 +01:00
Detect package change and send out email
Summary: For package creation and deletion, send email to all the owners For package modification, detect important fields such as owners and paths, and then send out emails to all owners (including deleted owners and current owners) Also start using transaction for package creation/deletion/modification. Test Plan: - tested mail creation and deletion - tested modification to auditing enabled, primary owners, owners, paths Reviewers: epriestley, nh, vrana Reviewed By: epriestley CC: prithvi, aran, Koolvin Differential Revision: https://secure.phabricator.com/D2470
This commit is contained in:
parent
bb96115fa6
commit
67d4f1ef4c
17 changed files with 680 additions and 2 deletions
|
@ -356,6 +356,14 @@ return array(
|
|||
// affects Diffusion.
|
||||
'metamta.diffusion.reply-handler' => 'PhabricatorAuditReplyHandler',
|
||||
|
||||
// Prefix prepended to mail sent by Package.
|
||||
'metamta.package.subject-prefix' => '[Package]',
|
||||
|
||||
// See 'metamta.maniphest.reply-handler'. This does similar thing for package
|
||||
// except that it only supports sending out mail and doesn't handle incoming
|
||||
// email.
|
||||
'metamta.package.reply-handler' => 'OwnersPackageReplyHandler',
|
||||
|
||||
// By default, Phabricator generates unique reply-to addresses and sends a
|
||||
// separate email to each recipient when you enable reply handling. This is
|
||||
// more secure than using "From" to establish user identity, but can mean
|
||||
|
|
|
@ -516,6 +516,11 @@ phutil_register_library_map(array(
|
|||
'ManiphestView' => 'applications/maniphest/view/base',
|
||||
'MetaMTAConstants' => 'applications/metamta/constants/base',
|
||||
'MetaMTANotificationType' => 'applications/metamta/constants/notificationtype',
|
||||
'OwnersPackageReplyHandler' => 'applications/owners/replyhandler',
|
||||
'PackageCreateMail' => 'applications/owners/mail/create',
|
||||
'PackageDeleteMail' => 'applications/owners/mail/delete',
|
||||
'PackageMail' => 'applications/owners/mail/base',
|
||||
'PackageModifyMail' => 'applications/owners/mail/modify',
|
||||
'Phabricator404Controller' => 'applications/base/controller/404',
|
||||
'PhabricatorAccessLog' => 'infrastructure/accesslog',
|
||||
'PhabricatorAphlictTestPageController' => 'applications/notifications/controller/test',
|
||||
|
@ -1470,6 +1475,10 @@ phutil_register_library_map(array(
|
|||
'ManiphestTransactionType' => 'ManiphestConstants',
|
||||
'ManiphestView' => 'AphrontView',
|
||||
'MetaMTANotificationType' => 'MetaMTAConstants',
|
||||
'OwnersPackageReplyHandler' => 'PhabricatorMailReplyHandler',
|
||||
'PackageCreateMail' => 'PackageMail',
|
||||
'PackageDeleteMail' => 'PackageMail',
|
||||
'PackageModifyMail' => 'PackageMail',
|
||||
'Phabricator404Controller' => 'PhabricatorController',
|
||||
'PhabricatorAphlictTestPageController' => 'PhabricatorNotificationsController',
|
||||
'PhabricatorAuditAddCommentController' => 'PhabricatorAuditController',
|
||||
|
|
|
@ -35,6 +35,7 @@ final class PhabricatorOwnersDeleteController
|
|||
}
|
||||
|
||||
if ($request->isDialogFormPost()) {
|
||||
$package->attachActorPHID($user->getPHID());
|
||||
$package->delete();
|
||||
return id(new AphrontRedirectResponse())->setURI('/owners/');
|
||||
}
|
||||
|
|
|
@ -47,10 +47,12 @@ final class PhabricatorOwnersEditController
|
|||
if ($request->isFormPost()) {
|
||||
$package->setName($request->getStr('name'));
|
||||
$package->setDescription($request->getStr('description'));
|
||||
$old_auditing_enabled = $package->getAuditingEnabled();
|
||||
$package->setAuditingEnabled($request->getStr('auditing') === 'enabled');
|
||||
|
||||
$primary = $request->getArr('primary');
|
||||
$primary = reset($primary);
|
||||
$old_primary = $package->getPrimaryOwnerPHID();
|
||||
$package->setPrimaryOwnerPHID($primary);
|
||||
|
||||
$owners = $request->getArr('owners');
|
||||
|
@ -94,6 +96,9 @@ final class PhabricatorOwnersEditController
|
|||
if (!$errors) {
|
||||
$package->attachUnsavedOwners($owners);
|
||||
$package->attachUnsavedPaths($path_refs);
|
||||
$package->attachOldAuditingEnabled($old_auditing_enabled);
|
||||
$package->attachOldPrimaryOwnerPHID($old_primary);
|
||||
$package->attachActorPHID($user->getPHID());
|
||||
try {
|
||||
$package->save();
|
||||
return id(new AphrontRedirectResponse())
|
||||
|
|
223
src/applications/owners/mail/base/PackageMail.php
Normal file
223
src/applications/owners/mail/base/PackageMail.php
Normal file
|
@ -0,0 +1,223 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
abstract class PackageMail {
|
||||
|
||||
protected $package;
|
||||
protected $handles;
|
||||
protected $owners;
|
||||
protected $paths;
|
||||
protected $mailTo;
|
||||
|
||||
public function __construct($package) {
|
||||
$this->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 => $ignored) {
|
||||
$section[] = ' '.$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;
|
||||
|
||||
$paths = $package->loadPaths();
|
||||
$this->paths = mgroup($paths, 'getRepositoryPHID', 'getPath');
|
||||
|
||||
$phids = array_mergev(array(
|
||||
$this->mailTo,
|
||||
array($package->getActorPHID()),
|
||||
array_keys($this->paths),
|
||||
));
|
||||
$this->handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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();
|
||||
$package_title = $this->renderPackageTitle();
|
||||
$subject = trim("{$prefix} {$package_title}");
|
||||
$vary_subject = trim("{$prefix} [{$verb}] {$package_title}");
|
||||
$threading = $this->getMailThreading();
|
||||
list($thread_id, $thread_topic) = $threading;
|
||||
|
||||
$template = id(new PhabricatorMetaMTAMail())
|
||||
->setSubject($subject)
|
||||
->setVarySubject($vary_subject)
|
||||
->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()->getPHID(),
|
||||
);
|
||||
}
|
||||
|
||||
private function newReplyHandler() {
|
||||
$reply_handler = PhabricatorEnv::newObjectFromConfig(
|
||||
'metamta.package.reply-handler');
|
||||
$reply_handler->setMailReceiver($this->getPackage());
|
||||
return $reply_handler;
|
||||
}
|
||||
|
||||
}
|
16
src/applications/owners/mail/base/__init__.php
Normal file
16
src/applications/owners/mail/base/__init__.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/metamta/storage/mail');
|
||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PackageMail.php');
|
28
src/applications/owners/mail/create/PackageCreateMail.php
Normal file
28
src/applications/owners/mail/create/PackageCreateMail.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PackageCreateMail extends PackageMail {
|
||||
|
||||
protected function isNewThread() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function getVerb() {
|
||||
return 'Created';
|
||||
}
|
||||
}
|
12
src/applications/owners/mail/create/__init__.php
Normal file
12
src/applications/owners/mail/create/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/owners/mail/base');
|
||||
|
||||
|
||||
phutil_require_source('PackageCreateMail.php');
|
29
src/applications/owners/mail/delete/PackageDeleteMail.php
Normal file
29
src/applications/owners/mail/delete/PackageDeleteMail.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PackageDeleteMail extends PackageMail {
|
||||
|
||||
protected function getVerb() {
|
||||
return "Deleted";
|
||||
}
|
||||
|
||||
protected function isNewThread() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
12
src/applications/owners/mail/delete/__init__.php
Normal file
12
src/applications/owners/mail/delete/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/owners/mail/base');
|
||||
|
||||
|
||||
phutil_require_source('PackageDeleteMail.php');
|
175
src/applications/owners/mail/modify/PackageModifyMail.php
Normal file
175
src/applications/owners/mail/modify/PackageModifyMail.php
Normal file
|
@ -0,0 +1,175 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PackageModifyMail extends PackageMail {
|
||||
|
||||
protected $addOwners;
|
||||
protected $removeOwners;
|
||||
protected $allOwners;
|
||||
protected $touchedRepos;
|
||||
protected $addPaths;
|
||||
protected $removePaths;
|
||||
|
||||
public function __construct(
|
||||
PhabricatorOwnersPackage $package,
|
||||
$add_owners,
|
||||
$remove_owners,
|
||||
$all_owners,
|
||||
$touched_repos,
|
||||
$add_paths,
|
||||
$remove_paths) {
|
||||
|
||||
$this->package = $package;
|
||||
|
||||
$this->addOwners = $add_owners;
|
||||
$this->removeOwners = $remove_owners;
|
||||
$this->allOwners = $all_owners;
|
||||
$this->touchedRepos = $touched_repos;
|
||||
$this->addPaths = $add_paths;
|
||||
$this->removePaths = $remove_paths;
|
||||
}
|
||||
|
||||
protected function getVerb() {
|
||||
return 'Modified';
|
||||
}
|
||||
|
||||
protected function isNewThread() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function needSend() {
|
||||
$package = $this->getPackage();
|
||||
if ($package->getOldPrimaryOwnerPHID() !== $package->getPrimaryOwnerPHID()
|
||||
|| $package->getOldAuditingEnabled() != $package->getAuditingEnabled()
|
||||
|| $this->addOwners
|
||||
|| $this->removeOwners
|
||||
|| $this->addPaths
|
||||
|| $this->removePaths) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function loadData() {
|
||||
$this->mailTo = $this->allOwners;
|
||||
|
||||
$phids = array_mergev(array(
|
||||
$this->allOwners,
|
||||
$this->touchedRepos,
|
||||
array(
|
||||
$this->getPackage()->getActorPHID(),
|
||||
),
|
||||
));
|
||||
$this->handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
|
||||
}
|
||||
|
||||
protected function renderDescriptionSection() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function renderPrimaryOwnerSection() {
|
||||
$package = $this->getPackage();
|
||||
$handles = $this->getHandles();
|
||||
|
||||
$old_primary_owner_phid = $package->getOldPrimaryOwnerPHID();
|
||||
$primary_owner_phid = $package->getPrimaryOwnerPHID();
|
||||
if ($old_primary_owner_phid == $primary_owner_phid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$section = array();
|
||||
$section[] = 'PRIMARY OWNER CHANGE';
|
||||
$section[] = ' Old owner: ' .
|
||||
$handles[$old_primary_owner_phid]->getName();
|
||||
$section[] = ' New owner: ' .
|
||||
$handles[$primary_owner_phid]->getName();
|
||||
$section[] = '';
|
||||
|
||||
return implode("\n", $section);
|
||||
}
|
||||
|
||||
protected function renderOwnersSection() {
|
||||
$section = array();
|
||||
$add_owners = $this->addOwners;
|
||||
$remove_owners = $this->removeOwners;
|
||||
$handles = $this->getHandles();
|
||||
|
||||
if ($add_owners) {
|
||||
$add_owners = array_select_keys($handles, $add_owners);
|
||||
$add_owners = mpull($add_owners, 'getName');
|
||||
$section[] = 'ADDED OWNERS';
|
||||
$section[] = ' '.implode(', ', $add_owners);
|
||||
}
|
||||
|
||||
if ($remove_owners) {
|
||||
if ($add_owners) {
|
||||
$section[] = '';
|
||||
}
|
||||
$remove_owners = array_select_keys($handles, $remove_owners);
|
||||
$remove_owners = mpull($remove_owners, 'getName');
|
||||
$section[] = 'REMOVED OWNERS';
|
||||
$section[] = ' '.implode(', ', $remove_owners);
|
||||
}
|
||||
|
||||
if ($section) {
|
||||
return implode("\n", $section);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function renderAuditingEnabledSection() {
|
||||
$package = $this->getPackage();
|
||||
$old_auditing_enabled = $package->getOldAuditingEnabled();
|
||||
$auditing_enabled = $package->getAuditingEnabled();
|
||||
if ($old_auditing_enabled == $auditing_enabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$section = array();
|
||||
$section[] = 'AUDITING ENABLED STATUS CHANGE';
|
||||
$section[] = ' Old value: '.
|
||||
($old_auditing_enabled ? 'Enabled' : 'Disabled');
|
||||
$section[] = ' New value: '.
|
||||
($auditing_enabled ? 'Enabled' : 'Disabled');
|
||||
return implode("\n", $section);
|
||||
}
|
||||
|
||||
protected function renderPathsSection() {
|
||||
$section = array();
|
||||
if ($this->addPaths) {
|
||||
$section[] = 'ADDED PATHS';
|
||||
foreach ($this->addPaths as $repository_phid => $paths) {
|
||||
$section[] = $this->renderRepoSubSection($repository_phid, $paths);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->removePaths) {
|
||||
if ($this->addPaths) {
|
||||
$section[] = '';
|
||||
}
|
||||
$section[] = 'REMOVED PATHS';
|
||||
foreach ($this->removePaths as $repository_phid => $paths) {
|
||||
$section[] = $this->renderRepoSubSection($repository_phid, $paths);
|
||||
}
|
||||
}
|
||||
return implode("\n", $section);
|
||||
}
|
||||
|
||||
}
|
15
src/applications/owners/mail/modify/__init__.php
Normal file
15
src/applications/owners/mail/modify/__init__.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/owners/mail/base');
|
||||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PackageModifyMail.php');
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class OwnersPackageReplyHandler extends PhabricatorMailReplyHandler {
|
||||
public function validateMailReceiver($mail_receiver) {
|
||||
if (!($mail_receiver instanceof PhabricatorOwnersPackage)) {
|
||||
throw new Exception("Receiver is not a PhabricatorOwnersPackage!");
|
||||
}
|
||||
}
|
||||
|
||||
public function getPrivateReplyHandlerEmailAddress(
|
||||
PhabricatorObjectHandle $handle) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getPublicReplyHandlerEmailAddress() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getReplyHandlerDomain() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getReplyHandlerInstructions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
12
src/applications/owners/replyhandler/__init__.php
Normal file
12
src/applications/owners/replyhandler/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/metamta/replyhandler/base');
|
||||
|
||||
|
||||
phutil_require_source('OwnersPackageReplyHandler.php');
|
|
@ -26,6 +26,9 @@ final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO {
|
|||
|
||||
private $unsavedOwners;
|
||||
private $unsavedPaths;
|
||||
private $actorPHID;
|
||||
private $oldPrimaryOwnerPHID;
|
||||
private $oldAuditingEnabled;
|
||||
|
||||
public function getConfiguration() {
|
||||
return array(
|
||||
|
@ -49,6 +52,33 @@ final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function attachActorPHID($actor_phid) {
|
||||
$this->actorPHID = $actor_phid;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getActorPHID() {
|
||||
return $this->actorPHID;
|
||||
}
|
||||
|
||||
public function attachOldPrimaryOwnerPHID($old_primary) {
|
||||
$this->oldPrimaryOwnerPHID = $old_primary;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOldPrimaryOwnerPHID() {
|
||||
return $this->oldPrimaryOwnerPHID;
|
||||
}
|
||||
|
||||
public function attachOldAuditingEnabled($auditing_enabled) {
|
||||
$this->oldAuditingEnabled = $auditing_enabled;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOldAuditingEnabled() {
|
||||
return $this->oldAuditingEnabled;
|
||||
}
|
||||
|
||||
public function loadOwners() {
|
||||
if (!$this->getID()) {
|
||||
return array();
|
||||
|
@ -143,21 +173,36 @@ final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO {
|
|||
|
||||
public function save() {
|
||||
|
||||
// TODO: Transactions!
|
||||
if ($this->getID()) {
|
||||
$is_new = false;
|
||||
} else {
|
||||
$is_new = true;
|
||||
}
|
||||
|
||||
$this->openTransaction();
|
||||
|
||||
$ret = parent::save();
|
||||
|
||||
$add_owners = array();
|
||||
$remove_owners = array();
|
||||
$all_owners = array();
|
||||
if ($this->unsavedOwners) {
|
||||
$new_owners = array_fill_keys($this->unsavedOwners, true);
|
||||
$cur_owners = array();
|
||||
foreach ($this->loadOwners() as $owner) {
|
||||
if (empty($new_owners[$owner->getUserPHID()])) {
|
||||
$remove_owners[$owner->getUserPHID()] = true;
|
||||
$owner->delete();
|
||||
continue;
|
||||
}
|
||||
$cur_owners[$owner->getUserPHID()] = true;
|
||||
}
|
||||
|
||||
$add_owners = array_diff_key($new_owners, $cur_owners);
|
||||
$all_owners = array_mergev(array(
|
||||
array($this->getPrimaryOwnerPHID() => true),
|
||||
$new_owners,
|
||||
$remove_owners));
|
||||
foreach ($add_owners as $phid => $ignored) {
|
||||
$owner = new PhabricatorOwnersOwner();
|
||||
$owner->setPackageID($this->getID());
|
||||
|
@ -167,15 +212,21 @@ final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO {
|
|||
unset($this->unsavedOwners);
|
||||
}
|
||||
|
||||
$add_paths = array();
|
||||
$remove_paths = array();
|
||||
$touched_repos = array();
|
||||
if ($this->unsavedPaths) {
|
||||
$new_paths = igroup($this->unsavedPaths, 'repositoryPHID', 'path');
|
||||
$cur_paths = $this->loadPaths();
|
||||
foreach ($cur_paths as $key => $path) {
|
||||
if (empty($new_paths[$path->getRepositoryPHID()][$path->getPath()])) {
|
||||
$touched_repos[$path->getRepositoryPHID()] = true;
|
||||
$remove_paths[$path->getRepositoryPHID()][$path->getPath()] = true;
|
||||
$path->delete();
|
||||
unset($cur_paths[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$cur_paths = mgroup($cur_paths, 'getRepositoryPHID', 'getPath');
|
||||
foreach ($new_paths as $repository_phid => $paths) {
|
||||
// get repository object for path validation
|
||||
|
@ -215,6 +266,8 @@ final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO {
|
|||
$path = '/'.$path;
|
||||
}
|
||||
if (empty($cur_paths[$repository_phid][$path]) && $valid) {
|
||||
$touched_repos[$repository_phid] = true;
|
||||
$add_paths[$repository_phid][$path] = true;
|
||||
$obj = new PhabricatorOwnersPath();
|
||||
$obj->setPackageID($this->getID());
|
||||
$obj->setRepositoryPHID($repository_phid);
|
||||
|
@ -226,17 +279,45 @@ final class PhabricatorOwnersPackage extends PhabricatorOwnersDAO {
|
|||
unset($this->unsavedPaths);
|
||||
}
|
||||
|
||||
$this->saveTransaction();
|
||||
|
||||
if ($is_new) {
|
||||
$mail = new PackageCreateMail($this);
|
||||
} else {
|
||||
$mail = new PackageModifyMail(
|
||||
$this,
|
||||
array_keys($add_owners),
|
||||
array_keys($remove_owners),
|
||||
array_keys($all_owners),
|
||||
array_keys($touched_repos),
|
||||
$add_paths,
|
||||
$remove_paths);
|
||||
}
|
||||
$mail->send();
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function delete() {
|
||||
$mails = id(new PackageDeleteMail($this))->prepareMails();
|
||||
|
||||
$this->openTransaction();
|
||||
foreach ($this->loadOwners() as $owner) {
|
||||
$owner->delete();
|
||||
}
|
||||
foreach ($this->loadPaths() as $path) {
|
||||
$path->delete();
|
||||
}
|
||||
return parent::delete();
|
||||
|
||||
$ret = parent::delete();
|
||||
|
||||
$this->saveTransaction();
|
||||
|
||||
foreach ($mails as $mail) {
|
||||
$mail->saveAndSend();
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
private static function splitPath($path) {
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
phutil_require_module('phabricator', 'applications/diffusion/query/browse/base');
|
||||
phutil_require_module('phabricator', 'applications/diffusion/request/base');
|
||||
phutil_require_module('phabricator', 'applications/owners/mail/create');
|
||||
phutil_require_module('phabricator', 'applications/owners/mail/delete');
|
||||
phutil_require_module('phabricator', 'applications/owners/mail/modify');
|
||||
phutil_require_module('phabricator', 'applications/owners/storage/base');
|
||||
phutil_require_module('phabricator', 'applications/owners/storage/owner');
|
||||
phutil_require_module('phabricator', 'applications/owners/storage/path');
|
||||
|
|
1
src/infrastructure/env/PhabricatorEnv.php
vendored
1
src/infrastructure/env/PhabricatorEnv.php
vendored
|
@ -303,6 +303,7 @@ final class PhabricatorEnv {
|
|||
'metamta.maniphest.reply-handler' => 'PhabricatorMailReplyHandler',
|
||||
'metamta.differential.reply-handler' => 'PhabricatorMailReplyHandler',
|
||||
'metamta.diffusion.reply-handler' => 'PhabricatorMailReplyHandler',
|
||||
'metamta.package.reply-handler' => 'OwnersPackageReplyHandler',
|
||||
'storage.engine-selector' => 'PhabricatorFileStorageEngineSelector',
|
||||
'search.engine-selector' => 'PhabricatorSearchEngineSelector',
|
||||
'differential.field-selector' => 'DifferentialFieldSelector',
|
||||
|
|
Loading…
Reference in a new issue