mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-01 19:22:42 +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',
|
'PhortuneAccountEditController' => 'applications/phortune/controller/account/PhortuneAccountEditController.php',
|
||||||
'PhortuneAccountEditEngine' => 'applications/phortune/editor/PhortuneAccountEditEngine.php',
|
'PhortuneAccountEditEngine' => 'applications/phortune/editor/PhortuneAccountEditEngine.php',
|
||||||
'PhortuneAccountEditor' => 'applications/phortune/editor/PhortuneAccountEditor.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',
|
'PhortuneAccountHasMemberEdgeType' => 'applications/phortune/edge/PhortuneAccountHasMemberEdgeType.php',
|
||||||
'PhortuneAccountListController' => 'applications/phortune/controller/account/PhortuneAccountListController.php',
|
'PhortuneAccountListController' => 'applications/phortune/controller/account/PhortuneAccountListController.php',
|
||||||
'PhortuneAccountManagersController' => 'applications/phortune/controller/account/PhortuneAccountManagersController.php',
|
'PhortuneAccountManagersController' => 'applications/phortune/controller/account/PhortuneAccountManagersController.php',
|
||||||
|
@ -11764,6 +11777,24 @@ phutil_register_library_map(array(
|
||||||
'PhortuneAccountEditController' => 'PhortuneController',
|
'PhortuneAccountEditController' => 'PhortuneController',
|
||||||
'PhortuneAccountEditEngine' => 'PhabricatorEditEngine',
|
'PhortuneAccountEditEngine' => 'PhabricatorEditEngine',
|
||||||
'PhortuneAccountEditor' => 'PhabricatorApplicationTransactionEditor',
|
'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',
|
'PhortuneAccountHasMemberEdgeType' => 'PhabricatorEdgeType',
|
||||||
'PhortuneAccountListController' => 'PhortuneController',
|
'PhortuneAccountListController' => 'PhortuneController',
|
||||||
'PhortuneAccountManagersController' => 'PhortuneAccountProfileController',
|
'PhortuneAccountManagersController' => 'PhortuneAccountProfileController',
|
||||||
|
|
|
@ -80,8 +80,18 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
|
||||||
'' => 'PhortuneAccountManagersController',
|
'' => 'PhortuneAccountManagersController',
|
||||||
'add/' => 'PhortuneAccountAddManagerController',
|
'add/' => 'PhortuneAccountAddManagerController',
|
||||||
),
|
),
|
||||||
|
'addresses/' => array(
|
||||||
|
'' => 'PhortuneAccountEmailAddressesController',
|
||||||
|
$this->getEditRoutePattern('edit/')
|
||||||
|
=> 'PhortuneAccountEmailEditController',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
'address/' => array(
|
||||||
|
'(?P<id>\d+)/' => 'PhortuneAccountEmailViewController',
|
||||||
|
$this->getEditRoutePattern('edit/')
|
||||||
|
=> 'PhortuneAccountEmailEditController',
|
||||||
|
),
|
||||||
'product/' => array(
|
'product/' => array(
|
||||||
'' => 'PhortuneProductListController',
|
'' => 'PhortuneProductListController',
|
||||||
'view/(?P<id>\d+)/' => 'PhortuneProductViewController',
|
'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;
|
return $this->account;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function setAccount(PhortuneAccount $account) {
|
||||||
|
$this->account = $account;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
protected function buildApplicationCrumbs() {
|
protected function buildApplicationCrumbs() {
|
||||||
$crumbs = parent::buildApplicationCrumbs();
|
$crumbs = parent::buildApplicationCrumbs();
|
||||||
|
|
||||||
|
@ -29,7 +34,6 @@ abstract class PhortuneAccountController
|
||||||
return $this->loadAccountForEdit();
|
return $this->loadAccountForEdit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected function loadAccountForEdit() {
|
protected function loadAccountForEdit() {
|
||||||
$viewer = $this->getViewer();
|
$viewer = $this->getViewer();
|
||||||
$request = $this->getRequest();
|
$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/"),
|
$this->getApplicationURI("/account/{$id}/managers/"),
|
||||||
'fa-group');
|
'fa-group');
|
||||||
|
|
||||||
|
$nav->addFilter(
|
||||||
|
'addresses',
|
||||||
|
pht('Email Addresses'),
|
||||||
|
$this->getApplicationURI("/account/{$id}/addresses/"),
|
||||||
|
'fa-envelope-o');
|
||||||
|
|
||||||
$nav->selectFilter($filter);
|
$nav->selectFilter($filter);
|
||||||
|
|
||||||
return $nav;
|
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());
|
$this->getID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEmailAddressesURI() {
|
||||||
|
return urisprintf(
|
||||||
|
'/phortune/account/%d/addresses/',
|
||||||
|
$this->getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
/* -( 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