mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-29 10:12:41 +01:00
Add scaffolding for ad-hoc email addresses associated with Phortune accounts
Summary: Depends on D20697. Ref T8389. Add support for adding "billing@enterprise.com" and similar to Phortune accounts. Test Plan: Added and edited email addresses for a payment account. Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam Maniphest Tasks: T8389 Differential Revision: https://secure.phabricator.com/D20713
This commit is contained in:
parent
719a7d82c5
commit
e3ba53078e
20 changed files with 829 additions and 1 deletions
12
resources/sql/autopatches/20190802.email.01.storage.sql
Normal file
12
resources/sql/autopatches/20190802.email.01.storage.sql
Normal file
|
@ -0,0 +1,12 @@
|
|||
CREATE TABLE {$NAMESPACE}_phortune.phortune_accountemail (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
phid VARBINARY(64) NOT NULL,
|
||||
accountPHID VARBINARY(64) NOT NULL,
|
||||
authorPHID VARBINARY(64) NOT NULL,
|
||||
address VARCHAR(128) NOT NULL COLLATE {$COLLATE_SORT},
|
||||
status VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
addressKey VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
accessKey VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE {$COLLATE_TEXT};
|
19
resources/sql/autopatches/20190802.email.02.xaction.sql
Normal file
19
resources/sql/autopatches/20190802.email.02.xaction.sql
Normal file
|
@ -0,0 +1,19 @@
|
|||
CREATE TABLE {$NAMESPACE}_phortune.phortune_accountemailtransaction (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
phid VARBINARY(64) NOT NULL,
|
||||
authorPHID VARBINARY(64) NOT NULL,
|
||||
objectPHID VARBINARY(64) NOT NULL,
|
||||
viewPolicy VARBINARY(64) NOT NULL,
|
||||
editPolicy VARBINARY(64) NOT NULL,
|
||||
commentPHID VARBINARY(64) DEFAULT NULL,
|
||||
commentVersion INT UNSIGNED NOT NULL,
|
||||
transactionType VARCHAR(32) NOT NULL,
|
||||
oldValue LONGTEXT NOT NULL,
|
||||
newValue LONGTEXT NOT NULL,
|
||||
contentSource LONGTEXT NOT NULL,
|
||||
metadata LONGTEXT NOT NULL,
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL,
|
||||
UNIQUE KEY `key_phid` (`phid`),
|
||||
KEY `key_object` (`objectPHID`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE {$COLLATE_TEXT};
|
|
@ -5229,6 +5229,19 @@ phutil_register_library_map(array(
|
|||
'PhortuneAccountEditController' => 'applications/phortune/controller/account/PhortuneAccountEditController.php',
|
||||
'PhortuneAccountEditEngine' => 'applications/phortune/editor/PhortuneAccountEditEngine.php',
|
||||
'PhortuneAccountEditor' => 'applications/phortune/editor/PhortuneAccountEditor.php',
|
||||
'PhortuneAccountEmail' => 'applications/phortune/storage/PhortuneAccountEmail.php',
|
||||
'PhortuneAccountEmailAddressTransaction' => 'applications/phortune/xaction/PhortuneAccountEmailAddressTransaction.php',
|
||||
'PhortuneAccountEmailAddressesController' => 'applications/phortune/controller/account/PhortuneAccountEmailAddressesController.php',
|
||||
'PhortuneAccountEmailEditController' => 'applications/phortune/controller/account/PhortuneAccountEmailEditController.php',
|
||||
'PhortuneAccountEmailEditEngine' => 'applications/phortune/editor/PhortuneAccountEmailEditEngine.php',
|
||||
'PhortuneAccountEmailEditor' => 'applications/phortune/editor/PhortuneAccountEmailEditor.php',
|
||||
'PhortuneAccountEmailPHIDType' => 'applications/phortune/phid/PhortuneAccountEmailPHIDType.php',
|
||||
'PhortuneAccountEmailQuery' => 'applications/phortune/query/PhortuneAccountEmailQuery.php',
|
||||
'PhortuneAccountEmailStatus' => 'applications/phortune/constants/PhortuneAccountEmailStatus.php',
|
||||
'PhortuneAccountEmailTransaction' => 'applications/phortune/storage/PhortuneAccountEmailTransaction.php',
|
||||
'PhortuneAccountEmailTransactionQuery' => 'applications/phortune/query/PhortuneAccountEmailTransactionQuery.php',
|
||||
'PhortuneAccountEmailTransactionType' => 'applications/phortune/xaction/PhortuneAccountEmailTransactionType.php',
|
||||
'PhortuneAccountEmailViewController' => 'applications/phortune/controller/account/PhortuneAccountEmailViewController.php',
|
||||
'PhortuneAccountHasMemberEdgeType' => 'applications/phortune/edge/PhortuneAccountHasMemberEdgeType.php',
|
||||
'PhortuneAccountListController' => 'applications/phortune/controller/account/PhortuneAccountListController.php',
|
||||
'PhortuneAccountManagersController' => 'applications/phortune/controller/account/PhortuneAccountManagersController.php',
|
||||
|
@ -11764,6 +11777,24 @@ phutil_register_library_map(array(
|
|||
'PhortuneAccountEditController' => 'PhortuneController',
|
||||
'PhortuneAccountEditEngine' => 'PhabricatorEditEngine',
|
||||
'PhortuneAccountEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'PhortuneAccountEmail' => array(
|
||||
'PhortuneDAO',
|
||||
'PhabricatorApplicationTransactionInterface',
|
||||
'PhabricatorPolicyInterface',
|
||||
'PhabricatorExtendedPolicyInterface',
|
||||
),
|
||||
'PhortuneAccountEmailAddressTransaction' => 'PhortuneAccountEmailTransactionType',
|
||||
'PhortuneAccountEmailAddressesController' => 'PhortuneAccountProfileController',
|
||||
'PhortuneAccountEmailEditController' => 'PhortuneAccountController',
|
||||
'PhortuneAccountEmailEditEngine' => 'PhabricatorEditEngine',
|
||||
'PhortuneAccountEmailEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'PhortuneAccountEmailPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhortuneAccountEmailQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhortuneAccountEmailStatus' => 'Phobject',
|
||||
'PhortuneAccountEmailTransaction' => 'PhabricatorModularTransaction',
|
||||
'PhortuneAccountEmailTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'PhortuneAccountEmailTransactionType' => 'PhabricatorModularTransactionType',
|
||||
'PhortuneAccountEmailViewController' => 'PhortuneAccountController',
|
||||
'PhortuneAccountHasMemberEdgeType' => 'PhabricatorEdgeType',
|
||||
'PhortuneAccountListController' => 'PhortuneController',
|
||||
'PhortuneAccountManagersController' => 'PhortuneAccountProfileController',
|
||||
|
|
|
@ -80,8 +80,18 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
|
|||
'' => 'PhortuneAccountManagersController',
|
||||
'add/' => 'PhortuneAccountAddManagerController',
|
||||
),
|
||||
'addresses/' => array(
|
||||
'' => 'PhortuneAccountEmailAddressesController',
|
||||
$this->getEditRoutePattern('edit/')
|
||||
=> 'PhortuneAccountEmailEditController',
|
||||
),
|
||||
),
|
||||
),
|
||||
'address/' => array(
|
||||
'(?P<id>\d+)/' => 'PhortuneAccountEmailViewController',
|
||||
$this->getEditRoutePattern('edit/')
|
||||
=> 'PhortuneAccountEmailEditController',
|
||||
),
|
||||
'product/' => array(
|
||||
'' => 'PhortuneProductListController',
|
||||
'view/(?P<id>\d+)/' => 'PhortuneProductViewController',
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneAccountEmailStatus
|
||||
extends Phobject {
|
||||
|
||||
const STATUS_ACTIVE = 'active';
|
||||
const STATUS_DISABLED = 'disabled';
|
||||
const STATUS_UNSUBSCRIBED = 'unsubscribed';
|
||||
|
||||
public static function getDefaultStatusConstant() {
|
||||
return self::STATUS_ACTIVE;
|
||||
}
|
||||
|
||||
private static function getMap() {
|
||||
return array(
|
||||
self::STATUS_ACTIVE => array(
|
||||
'name' => pht('Active'),
|
||||
'closed' => false,
|
||||
),
|
||||
self::STATUS_DISABLED => array(
|
||||
'name' => pht('Disabled'),
|
||||
'closed' => true,
|
||||
),
|
||||
self::STATUS_UNSUBSCRIBED => array(
|
||||
'name' => pht('Unsubscribed'),
|
||||
'closed' => true,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,11 @@ abstract class PhortuneAccountController
|
|||
return $this->account;
|
||||
}
|
||||
|
||||
protected function setAccount(PhortuneAccount $account) {
|
||||
$this->account = $account;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function buildApplicationCrumbs() {
|
||||
$crumbs = parent::buildApplicationCrumbs();
|
||||
|
||||
|
@ -29,7 +34,6 @@ abstract class PhortuneAccountController
|
|||
return $this->loadAccountForEdit();
|
||||
}
|
||||
|
||||
|
||||
protected function loadAccountForEdit() {
|
||||
$viewer = $this->getViewer();
|
||||
$request = $this->getRequest();
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneAccountEmailAddressesController
|
||||
extends PhortuneAccountProfileController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$response = $this->loadAccount();
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$account = $this->getAccount();
|
||||
$title = $account->getName();
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Email Addresses'));
|
||||
|
||||
$header = $this->buildHeaderView();
|
||||
$addresses = $this->buildAddressesSection($account);
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter(
|
||||
array(
|
||||
$addresses,
|
||||
));
|
||||
|
||||
$navigation = $this->buildSideNavView('addresses');
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->setNavigation($navigation)
|
||||
->appendChild($view);
|
||||
}
|
||||
|
||||
private function buildAddressesSection(PhortuneAccount $account) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$account,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$id = $account->getID();
|
||||
|
||||
$add = id(new PHUIButtonView())
|
||||
->setTag('a')
|
||||
->setText(pht('Add Address'))
|
||||
->setIcon('fa-plus')
|
||||
->setWorkflow(!$can_edit)
|
||||
->setDisabled(!$can_edit)
|
||||
->setHref("/phortune/account/{$id}/addresses/edit/");
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Billing Email Addresses'))
|
||||
->addActionLink($add);
|
||||
|
||||
$addresses = id(new PhortuneAccountEmailQuery())
|
||||
->setViewer($viewer)
|
||||
->withAccountPHIDs(array($account->getPHID()))
|
||||
->execute();
|
||||
|
||||
$list = id(new PHUIObjectItemListView())
|
||||
->setUser($viewer)
|
||||
->setNoDataString(
|
||||
pht(
|
||||
'There are no billing email addresses associated '.
|
||||
'with this account.'));
|
||||
|
||||
$addresses = id(new PhortuneAccountEmailQuery())
|
||||
->setViewer($viewer)
|
||||
->withAccountPHIDs(array($account->getPHID()))
|
||||
->execute();
|
||||
foreach ($addresses as $address) {
|
||||
$item = id(new PHUIObjectItemView())
|
||||
->setObjectName($address->getObjectName())
|
||||
->setHeader($address->getAddress())
|
||||
->setHref($address->getURI());
|
||||
|
||||
$list->addItem($item);
|
||||
}
|
||||
|
||||
return id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->setObjectList($list);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneAccountEmailEditController
|
||||
extends PhortuneAccountController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$engine = id(new PhortuneAccountEmailEditEngine())
|
||||
->setController($this);
|
||||
|
||||
if (!$request->getURIData('id')) {
|
||||
|
||||
if (!$request->getURIData('accountID')) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$response = $this->loadAccount();
|
||||
if ($response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$account = $this->getAccount();
|
||||
|
||||
$engine->setAccount($account);
|
||||
}
|
||||
|
||||
return $engine->buildResponse();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneAccountEmailViewController
|
||||
extends PhortuneAccountController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$address = id(new PhortuneAccountEmailQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($request->getURIData('id')))
|
||||
->executeOne();
|
||||
if (!$address) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$account = $address->getAccount();
|
||||
$this->setAccount($account);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs()
|
||||
->addTextCrumb(pht('Email Addresses'), $account->getEmailAddressesURI())
|
||||
->addTextCrumb($address->getObjectName())
|
||||
->setBorder(true);
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Account Email: %s', $address->getAddress()));
|
||||
|
||||
$details = $this->newDetailsView($address);
|
||||
|
||||
$timeline = $this->buildTransactionTimeline(
|
||||
$address,
|
||||
new PhortuneAccountEmailTransactionQuery());
|
||||
$timeline->setShouldTerminate(true);
|
||||
|
||||
$curtain = $this->buildCurtainView($address);
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setCurtain($curtain)
|
||||
->setMainColumn(
|
||||
array(
|
||||
$details,
|
||||
$timeline,
|
||||
));
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($address->getObjectName())
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild($view);
|
||||
|
||||
}
|
||||
|
||||
private function buildCurtainView(PhortuneAccountEmail $address) {
|
||||
$viewer = $this->getViewer();
|
||||
$account = $address->getAccount();
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$address,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$edit_uri = $this->getApplicationURI(
|
||||
urisprintf(
|
||||
'address/edit/%d/',
|
||||
$address->getID()));
|
||||
|
||||
$curtain = $this->newCurtainView($account);
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Edit Address'))
|
||||
->setIcon('fa-pencil')
|
||||
->setHref($edit_uri)
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
return $curtain;
|
||||
}
|
||||
|
||||
private function newDetailsView(PhortuneAccountEmail $address) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$view = id(new PHUIPropertyListView())
|
||||
->setUser($viewer);
|
||||
|
||||
$view->addProperty(pht('Email Address'), $address->getAddress());
|
||||
|
||||
return id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Email Address Details'))
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->addPropertyList($view);
|
||||
}
|
||||
}
|
|
@ -82,6 +82,12 @@ abstract class PhortuneAccountProfileController
|
|||
$this->getApplicationURI("/account/{$id}/managers/"),
|
||||
'fa-group');
|
||||
|
||||
$nav->addFilter(
|
||||
'addresses',
|
||||
pht('Email Addresses'),
|
||||
$this->getApplicationURI("/account/{$id}/addresses/"),
|
||||
'fa-envelope-o');
|
||||
|
||||
$nav->selectFilter($filter);
|
||||
|
||||
return $nav;
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneAccountEmailEditEngine
|
||||
extends PhabricatorEditEngine {
|
||||
|
||||
const ENGINECONST = 'phortune.account.email';
|
||||
|
||||
private $account;
|
||||
|
||||
public function setAccount(PhortuneAccount $account) {
|
||||
$this->account = $account;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAccount() {
|
||||
return $this->account;
|
||||
}
|
||||
|
||||
public function getEngineName() {
|
||||
return pht('Phortune Account Emails');
|
||||
}
|
||||
|
||||
public function getEngineApplicationClass() {
|
||||
return 'PhabricatorPhortuneApplication';
|
||||
}
|
||||
|
||||
public function getSummaryHeader() {
|
||||
return pht('Configure Phortune Account Email Forms');
|
||||
}
|
||||
|
||||
public function getSummaryText() {
|
||||
return pht(
|
||||
'Configure creation and editing forms for Phortune Account '.
|
||||
'Email Addresses.');
|
||||
}
|
||||
|
||||
public function isEngineConfigurable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function newEditableObject() {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$account = $this->getAccount();
|
||||
if (!$account) {
|
||||
$account = new PhortuneAccount();
|
||||
}
|
||||
|
||||
return PhortuneAccountEmail::initializeNewAddress(
|
||||
$account,
|
||||
$viewer->getPHID());
|
||||
}
|
||||
|
||||
protected function newObjectQuery() {
|
||||
return new PhortuneAccountEmailQuery();
|
||||
}
|
||||
|
||||
protected function getObjectCreateTitleText($object) {
|
||||
return pht('Add Email Address');
|
||||
}
|
||||
|
||||
protected function getObjectEditTitleText($object) {
|
||||
return pht('Edit Account Email: %s', $object->getAddress());
|
||||
}
|
||||
|
||||
protected function getObjectEditShortText($object) {
|
||||
return pht('%s', $object->getAddress());
|
||||
}
|
||||
|
||||
protected function getObjectCreateShortText() {
|
||||
return pht('Add Email Address');
|
||||
}
|
||||
|
||||
protected function getObjectName() {
|
||||
return pht('Account Email');
|
||||
}
|
||||
|
||||
protected function getObjectCreateCancelURI($object) {
|
||||
return $this->getAccount()->getEmailAddressesURI();
|
||||
}
|
||||
|
||||
protected function getEditorURI() {
|
||||
return $this->getApplication()->getApplicationURI('address/edit/');
|
||||
}
|
||||
|
||||
protected function getObjectViewURI($object) {
|
||||
return $object->getURI();
|
||||
}
|
||||
|
||||
protected function buildCustomEditFields($object) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
if ($this->getIsCreate()) {
|
||||
$address_field = id(new PhabricatorTextEditField())
|
||||
->setTransactionType(
|
||||
PhortuneAccountEmailAddressTransaction::TRANSACTIONTYPE)
|
||||
->setIsRequired(true);
|
||||
} else {
|
||||
$address_field = new PhabricatorStaticEditField();
|
||||
}
|
||||
|
||||
$address_field
|
||||
->setKey('address')
|
||||
->setLabel(pht('Email Address'))
|
||||
->setDescription(pht('Email address.'))
|
||||
->setConduitTypeDescription(pht('New email address.'))
|
||||
->setValue($object->getAddress());
|
||||
|
||||
return array(
|
||||
$address_field,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneAccountEmailEditor
|
||||
extends PhabricatorApplicationTransactionEditor {
|
||||
|
||||
public function getEditorApplicationClass() {
|
||||
return 'PhabricatorPhortuneApplication';
|
||||
}
|
||||
|
||||
public function getEditorObjectsDescription() {
|
||||
return pht('Phortune Account Emails');
|
||||
}
|
||||
|
||||
public function getCreateObjectTitle($author, $object) {
|
||||
return pht('%s created this account email.', $author);
|
||||
}
|
||||
|
||||
protected function didCatchDuplicateKeyException(
|
||||
PhabricatorLiskDAO $object,
|
||||
array $xactions,
|
||||
Exception $ex) {
|
||||
|
||||
$errors = array();
|
||||
|
||||
$errors[] = new PhabricatorApplicationTransactionValidationError(
|
||||
PhortuneAccountEmailAddressTransaction::TRANSACTIONTYPE,
|
||||
pht('Duplicate'),
|
||||
pht(
|
||||
'The email address "%s" is already attached to this account.',
|
||||
$object->getAddress()),
|
||||
null);
|
||||
|
||||
throw new PhabricatorApplicationTransactionValidationException($errors);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneAccountEmailPHIDType extends PhabricatorPHIDType {
|
||||
|
||||
const TYPECONST = 'AEML';
|
||||
|
||||
public function getTypeName() {
|
||||
return pht('Phortune Account Email');
|
||||
}
|
||||
|
||||
public function newObject() {
|
||||
return new PhortuneAccountEmail();
|
||||
}
|
||||
|
||||
public function getPHIDTypeApplicationClass() {
|
||||
return 'PhabricatorPhortuneApplication';
|
||||
}
|
||||
|
||||
protected function buildQueryForObjects(
|
||||
PhabricatorObjectQuery $query,
|
||||
array $phids) {
|
||||
|
||||
return id(new PhortuneAccountEmailQuery())
|
||||
->withPHIDs($phids);
|
||||
}
|
||||
|
||||
public function loadHandles(
|
||||
PhabricatorHandleQuery $query,
|
||||
array $handles,
|
||||
array $objects) {
|
||||
|
||||
foreach ($handles as $phid => $handle) {
|
||||
$email = $objects[$phid];
|
||||
|
||||
$id = $email->getID();
|
||||
|
||||
$handle->setName($email->getObjectName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneAccountEmailQuery
|
||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
|
||||
private $ids;
|
||||
private $phids;
|
||||
private $accountPHIDs;
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withPHIDs(array $phids) {
|
||||
$this->phids = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withAccountPHIDs(array $phids) {
|
||||
$this->accountPHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function newResultObject() {
|
||||
return new PhortuneAccountEmail();
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
return $this->loadStandardPage($this->newResultObject());
|
||||
}
|
||||
|
||||
protected function willFilterPage(array $addresses) {
|
||||
$accounts = id(new PhortuneAccountQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->setParentQuery($this)
|
||||
->withPHIDs(mpull($addresses, 'getAccountPHID'))
|
||||
->execute();
|
||||
$accounts = mpull($accounts, null, 'getPHID');
|
||||
|
||||
foreach ($addresses as $key => $address) {
|
||||
$account = idx($accounts, $address->getAccountPHID());
|
||||
|
||||
if (!$account) {
|
||||
$this->didRejectResult($addresses[$key]);
|
||||
unset($addresses[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$address->attachAccount($account);
|
||||
}
|
||||
|
||||
return $addresses;
|
||||
}
|
||||
|
||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||
$where = parent::buildWhereClauseParts($conn);
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'address.id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
if ($this->phids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'address.phid IN (%Ls)',
|
||||
$this->phids);
|
||||
}
|
||||
|
||||
if ($this->accountPHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn,
|
||||
'address.accountPHID IN (%Ls)',
|
||||
$this->accountPHIDs);
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
return 'PhabricatorPhortuneApplication';
|
||||
}
|
||||
|
||||
protected function getPrimaryTableAlias() {
|
||||
return 'address';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneAccountEmailTransactionQuery
|
||||
extends PhabricatorApplicationTransactionQuery {
|
||||
|
||||
public function getTemplateApplicationTransaction() {
|
||||
return new PhortuneAccountEmailTransaction();
|
||||
}
|
||||
|
||||
}
|
|
@ -109,6 +109,12 @@ final class PhortuneAccount extends PhortuneDAO
|
|||
$this->getID());
|
||||
}
|
||||
|
||||
public function getEmailAddressesURI() {
|
||||
return urisprintf(
|
||||
'/phortune/account/%d/addresses/',
|
||||
$this->getID());
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
||||
|
||||
|
|
121
src/applications/phortune/storage/PhortuneAccountEmail.php
Normal file
121
src/applications/phortune/storage/PhortuneAccountEmail.php
Normal file
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneAccountEmail
|
||||
extends PhortuneDAO
|
||||
implements
|
||||
PhabricatorApplicationTransactionInterface,
|
||||
PhabricatorPolicyInterface,
|
||||
PhabricatorExtendedPolicyInterface {
|
||||
|
||||
protected $accountPHID;
|
||||
protected $authorPHID;
|
||||
protected $address;
|
||||
protected $status;
|
||||
protected $addressKey;
|
||||
protected $accessKey;
|
||||
|
||||
private $account = self::ATTACHABLE;
|
||||
|
||||
protected function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_AUX_PHID => true,
|
||||
self::CONFIG_COLUMN_SCHEMA => array(
|
||||
'address' => 'sort128',
|
||||
'status' => 'text32',
|
||||
'addressKey' => 'text32',
|
||||
'accessKey' => 'text32',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'key_account' => array(
|
||||
'columns' => array('accountPHID', 'address'),
|
||||
'unique' => true,
|
||||
),
|
||||
'key_address' => array(
|
||||
'columns' => array('addressKey'),
|
||||
),
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function getPHIDType() {
|
||||
return PhortuneAccountEmailPHIDType::TYPECONST;
|
||||
}
|
||||
|
||||
public static function initializeNewAddress(
|
||||
PhortuneAccount $account,
|
||||
$author_phid) {
|
||||
|
||||
$address_key = Filesystem::readRandomCharacters(16);
|
||||
$access_key = Filesystem::readRandomCharacters(16);
|
||||
$default_status = PhortuneAccountEmailStatus::getDefaultStatusConstant();
|
||||
|
||||
return id(new self())
|
||||
->setAuthorPHID($author_phid)
|
||||
->setAccountPHID($account->getPHID())
|
||||
->setStatus($default_status)
|
||||
->attachAccount($account)
|
||||
->setAddressKey($address_key)
|
||||
->setAccessKey($access_key);
|
||||
}
|
||||
|
||||
public function attachAccount(PhortuneAccount $account) {
|
||||
$this->account = $account;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAccount() {
|
||||
return $this->assertAttached($this->account);
|
||||
}
|
||||
|
||||
public function getObjectName() {
|
||||
return pht('Account Email %d', $this->getID());
|
||||
}
|
||||
|
||||
public function getURI() {
|
||||
return urisprintf(
|
||||
'/phortune/address/%d/',
|
||||
$this->getID());
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
||||
public function getCapabilities() {
|
||||
return array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
);
|
||||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
return PhabricatorPolicies::getMostOpenPolicy();
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
|
||||
|
||||
|
||||
public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
|
||||
return array(
|
||||
array($this->getAccount(), $capability),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
||||
|
||||
|
||||
public function getApplicationTransactionEditor() {
|
||||
return new PhortuneAccountEmailEditor();
|
||||
}
|
||||
|
||||
public function getApplicationTransactionTemplate() {
|
||||
return new PhortuneAccountEmailTransaction();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneAccountEmailTransaction
|
||||
extends PhabricatorModularTransaction {
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'phortune';
|
||||
}
|
||||
|
||||
public function getApplicationTransactionType() {
|
||||
return PhortuneAccountEmailPHIDType::TYPECONST;
|
||||
}
|
||||
|
||||
public function getBaseTransactionClass() {
|
||||
return 'PhortuneAccountEmailTransactionType';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
final class PhortuneAccountEmailAddressTransaction
|
||||
extends PhortuneAccountEmailTransactionType {
|
||||
|
||||
const TRANSACTIONTYPE = 'address';
|
||||
|
||||
public function generateOldValue($object) {
|
||||
return $object->getAddress();
|
||||
}
|
||||
|
||||
public function applyInternalEffects($object, $value) {
|
||||
$object->setAddress($value);
|
||||
}
|
||||
|
||||
public function validateTransactions($object, array $xactions) {
|
||||
$errors = array();
|
||||
|
||||
if ($this->isEmptyTextTransaction($object->getAddress(), $xactions)) {
|
||||
$errors[] = $this->newRequiredError(
|
||||
pht('You must provide an email address.'));
|
||||
}
|
||||
|
||||
$max_length = $object->getColumnMaximumByteLength('address');
|
||||
foreach ($xactions as $xaction) {
|
||||
$old_value = $xaction->getOldValue();
|
||||
$new_value = $xaction->getNewValue();
|
||||
|
||||
$new_length = strlen($new_value);
|
||||
if ($new_length > $max_length) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht(
|
||||
'The address can be no longer than %s characters.',
|
||||
new PhutilNumber($max_length)),
|
||||
$xaction);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!PhabricatorUserEmail::isValidAddress($new_value)) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
PhabricatorUserEmail::describeValidAddresses(),
|
||||
$xaction);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($new_value !== $old_value) {
|
||||
if (!$this->isNewObject()) {
|
||||
$errors[] = $this->newInvalidError(
|
||||
pht(
|
||||
'Account email addresses can not be edited once they are '.
|
||||
'created. To change the billing address for an account, '.
|
||||
'disable the old address and then add a new address.'),
|
||||
$xaction);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
abstract class PhortuneAccountEmailTransactionType
|
||||
extends PhabricatorModularTransactionType {}
|
Loading…
Reference in a new issue