Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15419385
D10673.id25632.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
17 KB
Referenced Files
None
Subscribers
None
D10673.id25632.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2547,7 +2547,9 @@
'PholioTransactionView' => 'applications/pholio/view/PholioTransactionView.php',
'PholioUploadedImageView' => 'applications/pholio/view/PholioUploadedImageView.php',
'PhortuneAccount' => 'applications/phortune/storage/PhortuneAccount.php',
+ 'PhortuneAccountEditController' => 'applications/phortune/controller/PhortuneAccountEditController.php',
'PhortuneAccountEditor' => 'applications/phortune/editor/PhortuneAccountEditor.php',
+ 'PhortuneAccountListController' => 'applications/phortune/controller/PhortuneAccountListController.php',
'PhortuneAccountPHIDType' => 'applications/phortune/phid/PhortuneAccountPHIDType.php',
'PhortuneAccountQuery' => 'applications/phortune/query/PhortuneAccountQuery.php',
'PhortuneAccountTransaction' => 'applications/phortune/storage/PhortuneAccountTransaction.php',
@@ -5601,7 +5603,9 @@
'PhortuneDAO',
'PhabricatorPolicyInterface',
),
+ 'PhortuneAccountEditController' => 'PhortuneController',
'PhortuneAccountEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'PhortuneAccountListController' => 'PhortuneController',
'PhortuneAccountPHIDType' => 'PhabricatorPHIDType',
'PhortuneAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhortuneAccountTransaction' => 'PhabricatorApplicationTransaction',
diff --git a/src/applications/fund/controller/FundInitiativeBackController.php b/src/applications/fund/controller/FundInitiativeBackController.php
--- a/src/applications/fund/controller/FundInitiativeBackController.php
+++ b/src/applications/fund/controller/FundInitiativeBackController.php
@@ -39,11 +39,25 @@
->addCancelButton($initiative_uri);
}
+ $accounts = PhortuneAccountQuery::loadAccountsForUser(
+ $viewer,
+ PhabricatorContentSource::newFromRequest($request));
+
$v_amount = null;
$e_amount = true;
+
+ $v_account = head($accounts)->getPHID();
+
$errors = array();
if ($request->isFormPost()) {
$v_amount = $request->getStr('amount');
+ $v_account = $request->getStr('accountPHID');
+
+ if (empty($accounts[$v_account])) {
+ $errors[] = pht('You must specify an account.');
+ } else {
+ $account = $accounts[$v_account];
+ }
if (!strlen($v_amount)) {
$errors[] = pht(
@@ -74,10 +88,6 @@
->withClassAndRef('FundBackerProduct', $initiative->getPHID())
->executeOne();
- $account = PhortuneAccountQuery::loadActiveAccountForUser(
- $viewer,
- PhabricatorContentSource::newFromRequest($request));
-
$cart_implementation = id(new FundBackerCart())
->setInitiative($initiative);
@@ -111,6 +121,12 @@
$form = id(new AphrontFormView())
->setUser($viewer)
->appendChild(
+ id(new AphrontFormSelectControl())
+ ->setName('accountPHID')
+ ->setLabel(pht('Account'))
+ ->setValue($v_account)
+ ->setOptions(mpull($accounts, 'getName', 'getPHID')))
+ ->appendChild(
id(new AphrontFormTextControl())
->setName('amount')
->setLabel(pht('Amount'))
diff --git a/src/applications/fund/phortune/FundBackerProduct.php b/src/applications/fund/phortune/FundBackerProduct.php
--- a/src/applications/fund/phortune/FundBackerProduct.php
+++ b/src/applications/fund/phortune/FundBackerProduct.php
@@ -79,8 +79,6 @@
public function didPurchaseProduct(
PhortuneProduct $product,
PhortunePurchase $purchase) {
- // TODO: This viewer may be wrong if the purchase completes after a hold
- // we should load the backer explicitly.
$viewer = $this->getViewer();
$backer = id(new FundBackerQuery())
@@ -91,25 +89,33 @@
throw new Exception(pht('Unable to load FundBacker!'));
}
+ // Load the actual backing user --they may not be the curent viewer if this
+ // product purchase is completing from a background worker or a merchant
+ // action.
+
+ $actor = id(new PhabricatorPeopleQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($backer->getBackerPHID()))
+ ->executeOne();
+
$xactions = array();
$xactions[] = id(new FundBackerTransaction())
->setTransactionType(FundBackerTransaction::TYPE_STATUS)
->setNewValue(FundBacker::STATUS_PURCHASED);
$editor = id(new FundBackerEditor())
- ->setActor($viewer)
+ ->setActor($actor)
->setContentSource($this->getContentSource());
$editor->applyTransactions($backer, $xactions);
-
$xactions = array();
$xactions[] = id(new FundInitiativeTransaction())
->setTransactionType(FundInitiativeTransaction::TYPE_BACKER)
->setNewValue($backer->getPHID());
$editor = id(new FundInitiativeEditor())
- ->setActor($viewer)
+ ->setActor($actor)
->setContentSource($this->getContentSource());
$editor->applyTransactions($this->getInitiative(), $xactions);
diff --git a/src/applications/phortune/controller/PhortuneAccountEditController.php b/src/applications/phortune/controller/PhortuneAccountEditController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/phortune/controller/PhortuneAccountEditController.php
@@ -0,0 +1,122 @@
+<?php
+
+final class PhortuneAccountEditController extends PhortuneController {
+
+ private $id;
+
+ public function willProcessRequest(array $data) {
+ $this->id = idx($data, 'id');
+ }
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ if ($this->id) {
+ $account = id(new PhortuneAccountQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($this->id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$account) {
+ return new Aphront404Response();
+ }
+ $is_new = false;
+ } else {
+ $account = PhortuneAccount::initializeNewAccount($viewer);
+ $is_new = true;
+ }
+
+ $v_name = $account->getName();
+ $e_name = true;
+ $validation_exception = null;
+
+ if ($request->isFormPost()) {
+ $v_name = $request->getStr('name');
+
+ $type_name = PhortuneAccountTransaction::TYPE_NAME;
+
+ $xactions = array();
+ $xactions[] = id(new PhortuneAccountTransaction())
+ ->setTransactionType($type_name)
+ ->setNewValue($v_name);
+
+ if ($is_new) {
+ $xactions[] = id(new PhortuneAccountTransaction())
+ ->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
+ ->setMetadataValue(
+ 'edge:type',
+ PhabricatorEdgeConfig::TYPE_ACCOUNT_HAS_MEMBER)
+ ->setNewValue(
+ array(
+ '=' => array($viewer->getPHID() => $viewer->getPHID()),
+ ));
+ }
+
+ $editor = id(new PhortuneAccountEditor())
+ ->setActor($viewer)
+ ->setContentSourceFromRequest($request)
+ ->setContinueOnNoEffect(true);
+
+ try {
+ $editor->applyTransactions($account, $xactions);
+
+ $account_uri = $this->getApplicationURI($account->getID().'/');
+ return id(new AphrontRedirectResponse())->setURI($account_uri);
+ } catch (PhabricatorApplicationTransactionValidationException $ex) {
+ $validation_exception = $ex;
+ $e_name = $ex->getShortMessage($type_name);
+ }
+ }
+
+ $crumbs = $this->buildApplicationCrumbs();
+
+ if ($is_new) {
+ $cancel_uri = $this->getApplicationURI('account/');
+ $crumbs->addTextCrumb(pht('Accounts'), $cancel_uri);
+ $crumbs->addTextCrumb(pht('Create Account'));
+
+ $title = pht('Create Payment Account');
+ $submit_button = pht('Create Account');
+ } else {
+ $cancel_uri = $this->getApplicationURI($account->getID().'/');
+ $crumbs->addTextCrumb($account->getName(), $cancel_uri);
+ $crumbs->addTextCrumb(pht('Edit'));
+
+ $title = pht('Edit %s', $account->getName());
+ $submit_button = pht('Save Changes');
+ }
+
+ $form = id(new AphrontFormView())
+ ->setUser($viewer)
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setName('name')
+ ->setLabel(pht('Name'))
+ ->setValue($v_name)
+ ->setError($e_name))
+ ->appendChild(
+ id(new AphrontFormSubmitControl())
+ ->setValue($submit_button)
+ ->addCancelButton($cancel_uri));
+
+ $box = id(new PHUIObjectBoxView())
+ ->setHeaderText($title)
+ ->setValidationException($validation_exception)
+ ->appendChild($form);
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $box,
+ ),
+ array(
+ 'title' => $title,
+ ));
+ }
+
+}
diff --git a/src/applications/phortune/controller/PhortuneAccountListController.php b/src/applications/phortune/controller/PhortuneAccountListController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/phortune/controller/PhortuneAccountListController.php
@@ -0,0 +1,108 @@
+<?php
+
+final class PhortuneAccountListController extends PhortuneController {
+
+ public function processRequest() {
+ $request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $accounts = id(new PhortuneAccountQuery())
+ ->setViewer($viewer)
+ ->withMemberPHIDs(array($viewer->getPHID()))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->execute();
+
+ $merchants = id(new PhortuneMerchantQuery())
+ ->setViewer($viewer)
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->execute();
+
+ $title = pht('Accounts');
+
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb(pht('Accounts'));
+
+ $payment_list = id(new PHUIObjectItemListView())
+ ->setUser($viewer)
+ ->setNoDataString(
+ pht(
+ 'You are not a member of any payment accounts. Payment '.
+ 'accounts are used to make purchases.'));
+
+ foreach ($accounts as $account) {
+ $item = id(new PHUIObjectItemView())
+ ->setObjectName(pht('Account %d', $account->getID()))
+ ->setHeader($account->getName())
+ ->setHref($this->getApplicationURI($account->getID().'/'))
+ ->setObject($account);
+
+ $payment_list->addItem($item);
+ }
+
+ $payment_header = id(new PHUIHeaderView())
+ ->setHeader(pht('Payment Accounts'))
+ ->addActionLink(
+ id(new PHUIButtonView())
+ ->setTag('a')
+ ->setHref($this->getApplicationURI('account/edit/'))
+ ->setIcon(
+ id(new PHUIIconView())
+ ->setIconFont('fa-plus'))
+ ->setText(pht('Create Account')));
+
+ $payment_box = id(new PHUIObjectBoxView())
+ ->setHeader($payment_header)
+ ->appendChild($payment_list);
+
+ $merchant_list = id(new PHUIObjectItemListView())
+ ->setUser($viewer)
+ ->setNoDataString(
+ pht(
+ 'You do not control any merchant accounts. Merchant accounts are '.
+ 'used to receive payments.'));
+
+ foreach ($merchants as $merchant) {
+ $item = id(new PHUIObjectItemView())
+ ->setObjectName(pht('Merchant %d', $merchant->getID()))
+ ->setHeader($merchant->getName())
+ ->setHref($this->getApplicationURI('/merchant/'.$merchant->getID().'/'))
+ ->setObject($merchant);
+
+ $merchant_list->addItem($item);
+ }
+
+ $merchant_header = id(new PHUIHeaderView())
+ ->setHeader(pht('Merchant Accounts'))
+ ->addActionLink(
+ id(new PHUIButtonView())
+ ->setTag('a')
+ ->setHref($this->getApplicationURI('merchant/'))
+ ->setIcon(
+ id(new PHUIIconView())
+ ->setIconFont('fa-folder-open'))
+ ->setText(pht('Browse Merchants')));
+
+ $merchant_box = id(new PHUIObjectBoxView())
+ ->setHeader($merchant_header)
+ ->appendChild($merchant_list);
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $payment_box,
+ $merchant_box,
+ ),
+ array(
+ 'title' => $title,
+ ));
+ }
+
+}
diff --git a/src/applications/phortune/controller/PhortuneAccountViewController.php b/src/applications/phortune/controller/PhortuneAccountViewController.php
--- a/src/applications/phortune/controller/PhortuneAccountViewController.php
+++ b/src/applications/phortune/controller/PhortuneAccountViewController.php
@@ -17,6 +17,7 @@
// process orders but merchants should not be able to see all the details
// of an account. Ideally this page should be visible to merchants, too,
// just with less information.
+ $can_edit = true;
$account = id(new PhortuneAccountQuery())
->setViewer($user)
@@ -27,7 +28,6 @@
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
-
if (!$account) {
return new Aphront404Response();
}
@@ -35,11 +35,15 @@
$title = $account->getName();
$crumbs = $this->buildApplicationCrumbs();
- $crumbs->addTextCrumb(pht('Account'), $request->getRequestURI());
+ $crumbs->addTextCrumb(
+ $account->getName(),
+ $request->getRequestURI());
$header = id(new PHUIHeaderView())
->setHeader($title);
+ $edit_uri = $this->getApplicationURI('account/edit/'.$account->getID().'/');
+
$actions = id(new PhabricatorActionListView())
->setUser($user)
->setObjectURI($request->getRequestURI())
@@ -47,8 +51,9 @@
id(new PhabricatorActionView())
->setName(pht('Edit Account'))
->setIcon('fa-pencil')
- ->setHref('#')
- ->setDisabled(true))
+ ->setHref($edit_uri)
+ ->setDisabled(!$can_edit)
+ ->setWorkflow(!$can_edit))
->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Members'))
@@ -291,4 +296,17 @@
return $xaction_view;
}
+ protected function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ $crumbs->addAction(
+ id(new PHUIListItemView())
+ ->setIcon('fa-exchange')
+ ->setHref($this->getApplicationURI('account/'))
+ ->setName(pht('Switch Accounts')));
+
+ return $crumbs;
+ }
+
+
}
diff --git a/src/applications/phortune/controller/PhortuneCartCheckoutController.php b/src/applications/phortune/controller/PhortuneCartCheckoutController.php
--- a/src/applications/phortune/controller/PhortuneCartCheckoutController.php
+++ b/src/applications/phortune/controller/PhortuneCartCheckoutController.php
@@ -114,7 +114,7 @@
->setHeaderText(pht('Cart Contents'))
->appendChild($cart_table);
- $title = pht('Buy Stuff');
+ $title = $cart->getName();
if (!$methods) {
$method_control = id(new AphrontFormStaticControl())
@@ -210,6 +210,7 @@
->appendChild($provider_form);
$crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb(pht('Checkout'));
$crumbs->addTextCrumb($title);
return $this->buildApplicationPage(
diff --git a/src/applications/phortune/editor/PhortuneAccountEditor.php b/src/applications/phortune/editor/PhortuneAccountEditor.php
--- a/src/applications/phortune/editor/PhortuneAccountEditor.php
+++ b/src/applications/phortune/editor/PhortuneAccountEditor.php
@@ -67,4 +67,32 @@
return parent::applyCustomExternalTransaction($object, $xaction);
}
+ protected function validateTransaction(
+ PhabricatorLiskDAO $object,
+ $type,
+ array $xactions) {
+
+ $errors = parent::validateTransaction($object, $type, $xactions);
+
+ switch ($type) {
+ case PhortuneAccountTransaction::TYPE_NAME:
+ $missing = $this->validateIsEmptyTextField(
+ $object->getName(),
+ $xactions);
+
+ if ($missing) {
+ $error = new PhabricatorApplicationTransactionValidationError(
+ $type,
+ pht('Required'),
+ pht('Account name is required.'),
+ nonempty(last($xactions), null));
+
+ $error->setIsMissingFieldError(true);
+ $errors[] = $error;
+ }
+ break;
+ }
+
+ return $errors;
+ }
}
diff --git a/src/applications/phortune/query/PhortuneAccountQuery.php b/src/applications/phortune/query/PhortuneAccountQuery.php
--- a/src/applications/phortune/query/PhortuneAccountQuery.php
+++ b/src/applications/phortune/query/PhortuneAccountQuery.php
@@ -7,6 +7,26 @@
private $phids;
private $memberPHIDs;
+ public static function loadAccountsForUser(
+ PhabricatorUser $user,
+ PhabricatorContentSource $content_source) {
+
+ $accounts = id(new PhortuneAccountQuery())
+ ->setViewer($user)
+ ->withMemberPHIDs(array($user->getPHID()))
+ ->execute();
+
+ if (!$accounts) {
+ $accounts = array(
+ PhortuneAccount::createNewAccount($user, $content_source),
+ );
+ }
+
+ $accounts = mpull($accounts, null, 'getPHID');
+
+ return $accounts;
+ }
+
public static function loadActiveAccountForUser(
PhabricatorUser $user,
PhabricatorContentSource $content_source) {
diff --git a/src/applications/phortune/storage/PhortuneAccount.php b/src/applications/phortune/storage/PhortuneAccount.php
--- a/src/applications/phortune/storage/PhortuneAccount.php
+++ b/src/applications/phortune/storage/PhortuneAccount.php
@@ -30,7 +30,7 @@
$xactions = array();
$xactions[] = id(new PhortuneAccountTransaction())
->setTransactionType(PhortuneAccountTransaction::TYPE_NAME)
- ->setNewValue(pht('Account (%s)', $actor->getUserName()));
+ ->setNewValue(pht('Personal Account'));
$xactions[] = id(new PhortuneAccountTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 22, 5:52 AM (1 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7572160
Default Alt Text
D10673.id25632.diff (17 KB)
Attached To
Mode
D10673: Support multiple payment accounts and account switching in Phortune
Attached
Detach File
Event Timeline
Log In to Comment