mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 08:42:41 +01:00
Phortune Carts and Purchases
Summary: Ref T2787. Make carts and purchases real objects, with storage, that kind-of work. Roughly, the idea here is that applications create "purchases" (like "1 large t-shirt") and add them to "carts" (a user can have a lot of different carts at the same time), then hand things off to Phortune to deal with actualy charging a card. Roughly this works like Paypal or other similar systems do, except Phortune is the thing the user gets handed off to. This doesn't do anything interesting/useful yet. Also fix some bugs and update some UI. Test Plan: Added a product to a cart, saw it in cart screen. Reviewers: btrahan, chad Reviewed By: chad Subscribers: epriestley Maniphest Tasks: T2787 Differential Revision: https://secure.phabricator.com/D10001
This commit is contained in:
parent
e561a5fe73
commit
6ec1f35870
16 changed files with 1336 additions and 985 deletions
File diff suppressed because it is too large
Load diff
11
resources/sql/autopatches/20140721.phortune.1.cart.sql
Normal file
11
resources/sql/autopatches/20140721.phortune.1.cart.sql
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
CREATE TABLE {$NAMESPACE}_phortune.phortune_cart (
|
||||||
|
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
phid VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
accountPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
authorPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
metadata LONGTEXT NOT NULL COLLATE utf8_bin,
|
||||||
|
dateCreated INT UNSIGNED NOT NULL,
|
||||||
|
dateModified INT UNSIGNED NOT NULL,
|
||||||
|
UNIQUE KEY `key_phid` (phid),
|
||||||
|
KEY `key_account` (accountPHID)
|
||||||
|
) ENGINE=InnoDB, COLLATE utf8_general_ci;
|
17
resources/sql/autopatches/20140721.phortune.2.purchase.sql
Normal file
17
resources/sql/autopatches/20140721.phortune.2.purchase.sql
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
CREATE TABLE {$NAMESPACE}_phortune.phortune_purchase (
|
||||||
|
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
phid VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
productPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
accountPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
authorPHID VARCHAR(64) NOT NULL COLLATE utf8_bin,
|
||||||
|
cartPHID VARCHAR(64) COLLATE utf8_bin,
|
||||||
|
basePriceInCents INT NOT NULL,
|
||||||
|
quantity INT UNSIGNED NOT NULL,
|
||||||
|
totalPriceInCents INT NOT NULL,
|
||||||
|
status VARCHAR(32) NOT NULL COLLATE utf8_bin,
|
||||||
|
metadata LONGTEXT NOT NULL COLLATE utf8_bin,
|
||||||
|
dateCreated INT UNSIGNED NOT NULL,
|
||||||
|
dateModified INT UNSIGNED NOT NULL,
|
||||||
|
UNIQUE KEY `key_phid` (phid),
|
||||||
|
KEY `key_cart` (cartPHID)
|
||||||
|
) ENGINE=InnoDB, COLLATE utf8_general_ci;
|
|
@ -2496,6 +2496,7 @@ phutil_register_library_map(array(
|
||||||
'PhortuneAccountViewController' => 'applications/phortune/controller/PhortuneAccountViewController.php',
|
'PhortuneAccountViewController' => 'applications/phortune/controller/PhortuneAccountViewController.php',
|
||||||
'PhortuneBalancedPaymentProvider' => 'applications/phortune/provider/PhortuneBalancedPaymentProvider.php',
|
'PhortuneBalancedPaymentProvider' => 'applications/phortune/provider/PhortuneBalancedPaymentProvider.php',
|
||||||
'PhortuneCart' => 'applications/phortune/storage/PhortuneCart.php',
|
'PhortuneCart' => 'applications/phortune/storage/PhortuneCart.php',
|
||||||
|
'PhortuneCartQuery' => 'applications/phortune/query/PhortuneCartQuery.php',
|
||||||
'PhortuneCharge' => 'applications/phortune/storage/PhortuneCharge.php',
|
'PhortuneCharge' => 'applications/phortune/storage/PhortuneCharge.php',
|
||||||
'PhortuneConstants' => 'applications/phortune/constants/PhortuneConstants.php',
|
'PhortuneConstants' => 'applications/phortune/constants/PhortuneConstants.php',
|
||||||
'PhortuneController' => 'applications/phortune/controller/PhortuneController.php',
|
'PhortuneController' => 'applications/phortune/controller/PhortuneController.php',
|
||||||
|
@ -2521,12 +2522,14 @@ phutil_register_library_map(array(
|
||||||
'PhortuneProductEditController' => 'applications/phortune/controller/PhortuneProductEditController.php',
|
'PhortuneProductEditController' => 'applications/phortune/controller/PhortuneProductEditController.php',
|
||||||
'PhortuneProductEditor' => 'applications/phortune/editor/PhortuneProductEditor.php',
|
'PhortuneProductEditor' => 'applications/phortune/editor/PhortuneProductEditor.php',
|
||||||
'PhortuneProductListController' => 'applications/phortune/controller/PhortuneProductListController.php',
|
'PhortuneProductListController' => 'applications/phortune/controller/PhortuneProductListController.php',
|
||||||
|
'PhortuneProductPurchaseController' => 'applications/phortune/controller/PhortuneProductPurchaseController.php',
|
||||||
'PhortuneProductQuery' => 'applications/phortune/query/PhortuneProductQuery.php',
|
'PhortuneProductQuery' => 'applications/phortune/query/PhortuneProductQuery.php',
|
||||||
'PhortuneProductTransaction' => 'applications/phortune/storage/PhortuneProductTransaction.php',
|
'PhortuneProductTransaction' => 'applications/phortune/storage/PhortuneProductTransaction.php',
|
||||||
'PhortuneProductTransactionQuery' => 'applications/phortune/query/PhortuneProductTransactionQuery.php',
|
'PhortuneProductTransactionQuery' => 'applications/phortune/query/PhortuneProductTransactionQuery.php',
|
||||||
'PhortuneProductViewController' => 'applications/phortune/controller/PhortuneProductViewController.php',
|
'PhortuneProductViewController' => 'applications/phortune/controller/PhortuneProductViewController.php',
|
||||||
'PhortuneProviderController' => 'applications/phortune/controller/PhortuneProviderController.php',
|
'PhortuneProviderController' => 'applications/phortune/controller/PhortuneProviderController.php',
|
||||||
'PhortunePurchase' => 'applications/phortune/storage/PhortunePurchase.php',
|
'PhortunePurchase' => 'applications/phortune/storage/PhortunePurchase.php',
|
||||||
|
'PhortunePurchaseQuery' => 'applications/phortune/query/PhortunePurchaseQuery.php',
|
||||||
'PhortuneStripePaymentProvider' => 'applications/phortune/provider/PhortuneStripePaymentProvider.php',
|
'PhortuneStripePaymentProvider' => 'applications/phortune/provider/PhortuneStripePaymentProvider.php',
|
||||||
'PhortuneTestExtraPaymentProvider' => 'applications/phortune/provider/__tests__/PhortuneTestExtraPaymentProvider.php',
|
'PhortuneTestExtraPaymentProvider' => 'applications/phortune/provider/__tests__/PhortuneTestExtraPaymentProvider.php',
|
||||||
'PhortuneTestPaymentProvider' => 'applications/phortune/provider/PhortuneTestPaymentProvider.php',
|
'PhortuneTestPaymentProvider' => 'applications/phortune/provider/PhortuneTestPaymentProvider.php',
|
||||||
|
@ -5374,7 +5377,11 @@ phutil_register_library_map(array(
|
||||||
'PhortuneAccountTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
'PhortuneAccountTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
'PhortuneAccountViewController' => 'PhortuneController',
|
'PhortuneAccountViewController' => 'PhortuneController',
|
||||||
'PhortuneBalancedPaymentProvider' => 'PhortunePaymentProvider',
|
'PhortuneBalancedPaymentProvider' => 'PhortunePaymentProvider',
|
||||||
'PhortuneCart' => 'PhortuneDAO',
|
'PhortuneCart' => array(
|
||||||
|
'PhortuneDAO',
|
||||||
|
'PhabricatorPolicyInterface',
|
||||||
|
),
|
||||||
|
'PhortuneCartQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhortuneCharge' => 'PhortuneDAO',
|
'PhortuneCharge' => 'PhortuneDAO',
|
||||||
'PhortuneController' => 'PhabricatorController',
|
'PhortuneController' => 'PhabricatorController',
|
||||||
'PhortuneCurrencyTestCase' => 'PhabricatorTestCase',
|
'PhortuneCurrencyTestCase' => 'PhabricatorTestCase',
|
||||||
|
@ -5402,12 +5409,17 @@ phutil_register_library_map(array(
|
||||||
'PhortuneProductEditController' => 'PhabricatorController',
|
'PhortuneProductEditController' => 'PhabricatorController',
|
||||||
'PhortuneProductEditor' => 'PhabricatorApplicationTransactionEditor',
|
'PhortuneProductEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
'PhortuneProductListController' => 'PhabricatorController',
|
'PhortuneProductListController' => 'PhabricatorController',
|
||||||
|
'PhortuneProductPurchaseController' => 'PhortuneController',
|
||||||
'PhortuneProductQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhortuneProductQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhortuneProductTransaction' => 'PhabricatorApplicationTransaction',
|
'PhortuneProductTransaction' => 'PhabricatorApplicationTransaction',
|
||||||
'PhortuneProductTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
'PhortuneProductTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
'PhortuneProductViewController' => 'PhortuneController',
|
'PhortuneProductViewController' => 'PhortuneController',
|
||||||
'PhortuneProviderController' => 'PhortuneController',
|
'PhortuneProviderController' => 'PhortuneController',
|
||||||
'PhortunePurchase' => 'PhortuneDAO',
|
'PhortunePurchase' => array(
|
||||||
|
'PhortuneDAO',
|
||||||
|
'PhabricatorPolicyInterface',
|
||||||
|
),
|
||||||
|
'PhortunePurchaseQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhortuneStripePaymentProvider' => 'PhortunePaymentProvider',
|
'PhortuneStripePaymentProvider' => 'PhortunePaymentProvider',
|
||||||
'PhortuneTestExtraPaymentProvider' => 'PhortunePaymentProvider',
|
'PhortuneTestExtraPaymentProvider' => 'PhortunePaymentProvider',
|
||||||
'PhortuneTestPaymentProvider' => 'PhortunePaymentProvider',
|
'PhortuneTestPaymentProvider' => 'PhortunePaymentProvider',
|
||||||
|
|
|
@ -39,8 +39,9 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication {
|
||||||
'paymentmethod/' => array(
|
'paymentmethod/' => array(
|
||||||
'edit/' => 'PhortunePaymentMethodEditController',
|
'edit/' => 'PhortunePaymentMethodEditController',
|
||||||
),
|
),
|
||||||
'buy/(?P<id>\d+)/' => 'PhortuneAccountBuyController',
|
'buy/(?P<productID>\d+)/' => 'PhortuneProductPurchaseController',
|
||||||
),
|
),
|
||||||
|
'cart/(?P<id>\d+)/' => 'PhortuneAccountBuyController',
|
||||||
'account/' => array(
|
'account/' => array(
|
||||||
'' => 'PhortuneAccountListController',
|
'' => 'PhortuneAccountListController',
|
||||||
'edit/(?:(?P<id>\d+)/)?' => 'PhortuneAccountEditController',
|
'edit/(?:(?P<id>\d+)/)?' => 'PhortuneAccountEditController',
|
||||||
|
|
|
@ -3,11 +3,9 @@
|
||||||
final class PhortuneAccountBuyController
|
final class PhortuneAccountBuyController
|
||||||
extends PhortuneController {
|
extends PhortuneController {
|
||||||
|
|
||||||
private $accountID;
|
|
||||||
private $id;
|
private $id;
|
||||||
|
|
||||||
public function willProcessRequest(array $data) {
|
public function willProcessRequest(array $data) {
|
||||||
$this->accountID = $data['accountID'];
|
|
||||||
$this->id = $data['id'];
|
$this->id = $data['id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,47 +13,23 @@ final class PhortuneAccountBuyController
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$user = $request->getUser();
|
$user = $request->getUser();
|
||||||
|
|
||||||
$account = id(new PhortuneAccountQuery())
|
$cart = id(new PhortuneCartQuery())
|
||||||
->setViewer($user)
|
|
||||||
->withIDs(array($this->accountID))
|
|
||||||
->executeOne();
|
|
||||||
if (!$account) {
|
|
||||||
return new Aphront404Response();
|
|
||||||
}
|
|
||||||
|
|
||||||
$account_uri = $this->getApplicationURI($account->getID().'/');
|
|
||||||
|
|
||||||
$product = id(new PhortuneProductQuery())
|
|
||||||
->setViewer($user)
|
->setViewer($user)
|
||||||
->withIDs(array($this->id))
|
->withIDs(array($this->id))
|
||||||
|
->needPurchases(true)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
if (!$product) {
|
if (!$cart) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$purchase = new PhortunePurchase();
|
$account = $cart->getAccount();
|
||||||
$purchase->setProductPHID($product->getPHID());
|
$account_uri = $this->getApplicationURI($account->getID().'/');
|
||||||
$purchase->setAccountPHID($account->getPHID());
|
|
||||||
$purchase->setPurchaseName($product->getProductName());
|
|
||||||
$purchase->setBasePriceInCents($product->getPriceInCents());
|
|
||||||
$purchase->setQuantity(1);
|
|
||||||
$purchase->setTotalPriceInCents(
|
|
||||||
$purchase->getBasePriceInCents() * $purchase->getQuantity());
|
|
||||||
$purchase->setStatus(PhortunePurchase::STATUS_PENDING);
|
|
||||||
|
|
||||||
$cart = new PhortuneCart();
|
|
||||||
$cart->setAccountPHID($account->getPHID());
|
|
||||||
$cart->setOwnerPHID($user->getPHID());
|
|
||||||
$cart->attachPurchases(
|
|
||||||
array(
|
|
||||||
$purchase,
|
|
||||||
));
|
|
||||||
|
|
||||||
$rows = array();
|
$rows = array();
|
||||||
$total = 0;
|
$total = 0;
|
||||||
foreach ($cart->getPurchases() as $purchase) {
|
foreach ($cart->getPurchases() as $purchase) {
|
||||||
$rows[] = array(
|
$rows[] = array(
|
||||||
$purchase->getPurchaseName(),
|
pht('A Purchase'),
|
||||||
PhortuneCurrency::newFromUSDCents($purchase->getBasePriceInCents())
|
PhortuneCurrency::newFromUSDCents($purchase->getBasePriceInCents())
|
||||||
->formatForDisplay(),
|
->formatForDisplay(),
|
||||||
$purchase->getQuantity(),
|
$purchase->getQuantity(),
|
||||||
|
|
|
@ -211,7 +211,8 @@ final class PhortunePaymentMethodEditController
|
||||||
'as a payment method.');
|
'as a payment method.');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$message = $provider->getCreatePaymentErrorMessage($client_error);
|
$message = $provider->getCreatePaymentMethodErrorMessage(
|
||||||
|
$client_error);
|
||||||
if (!$message) {
|
if (!$message) {
|
||||||
$message = pht(
|
$message = pht(
|
||||||
"There was an unexpected error ('%s') processing payment ".
|
"There was an unexpected error ('%s') processing payment ".
|
||||||
|
|
|
@ -142,15 +142,14 @@ final class PhortuneProductEditController extends PhabricatorController {
|
||||||
$is_create ? pht('Create') : pht('Edit'),
|
$is_create ? pht('Create') : pht('Edit'),
|
||||||
$request->getRequestURI());
|
$request->getRequestURI());
|
||||||
|
|
||||||
$header = id(new PHUIHeaderView())
|
$box = id(new PHUIObjectBoxView())
|
||||||
->setHeader(pht('Edit Product'));
|
->setHeaderText(pht('Edit Product'))
|
||||||
|
->appendChild($form);
|
||||||
|
|
||||||
return $this->buildApplicationPage(
|
return $this->buildApplicationPage(
|
||||||
array(
|
array(
|
||||||
$crumbs,
|
$crumbs,
|
||||||
$header,
|
$box,
|
||||||
$errors,
|
|
||||||
$form,
|
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhortuneProductPurchaseController
|
||||||
|
extends PhortuneController {
|
||||||
|
|
||||||
|
private $accountID;
|
||||||
|
private $productID;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->accountID = $data['accountID'];
|
||||||
|
$this->productID = $data['productID'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
|
$account = id(new PhortuneAccountQuery())
|
||||||
|
->setViewer($user)
|
||||||
|
->withIDs(array($this->accountID))
|
||||||
|
->executeOne();
|
||||||
|
if (!$account) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$account_uri = $this->getApplicationURI($account->getID().'/');
|
||||||
|
|
||||||
|
$product = id(new PhortuneProductQuery())
|
||||||
|
->setViewer($user)
|
||||||
|
->withIDs(array($this->productID))
|
||||||
|
->executeOne();
|
||||||
|
if (!$product) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->isFormPost()) {
|
||||||
|
// TODO: Use ApplicationTransations.
|
||||||
|
|
||||||
|
$cart = new PhortuneCart();
|
||||||
|
$cart->openTransaction();
|
||||||
|
|
||||||
|
$cart->setAccountPHID($account->getPHID());
|
||||||
|
$cart->setAuthorPHID($user->getPHID());
|
||||||
|
$cart->save();
|
||||||
|
|
||||||
|
$purchase = new PhortunePurchase();
|
||||||
|
$purchase->setProductPHID($product->getPHID());
|
||||||
|
$purchase->setAccountPHID($account->getPHID());
|
||||||
|
$purchase->setAuthorPHID($user->getPHID());
|
||||||
|
$purchase->setCartPHID($cart->getPHID());
|
||||||
|
$purchase->setBasePriceInCents($product->getPriceInCents());
|
||||||
|
$purchase->setQuantity(1);
|
||||||
|
$purchase->setTotalPriceInCents(
|
||||||
|
$purchase->getBasePriceInCents() * $purchase->getQuantity());
|
||||||
|
$purchase->setStatus(PhortunePurchase::STATUS_PENDING);
|
||||||
|
$purchase->save();
|
||||||
|
|
||||||
|
$cart->saveTransaction();
|
||||||
|
|
||||||
|
$cart_uri = $this->getApplicationURI('/cart/'.$cart->getID().'/');
|
||||||
|
return id(new AphrontRedirectResponse())->setURI($cart_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->newDialog()
|
||||||
|
->setTitle(pht('Purchase Product'))
|
||||||
|
->appendParagraph(pht('Really purchase this stuff?'))
|
||||||
|
->addSubmitButton(pht('Checkout'))
|
||||||
|
->addCancelButton($account_uri);
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,7 +46,7 @@ final class PhortuneProductViewController extends PhortuneController {
|
||||||
->setName(pht('Purchase'))
|
->setName(pht('Purchase'))
|
||||||
->setHref($cart_uri)
|
->setHref($cart_uri)
|
||||||
->setIcon('fa-shopping-cart')
|
->setIcon('fa-shopping-cart')
|
||||||
->setRenderAsForm(true));
|
->setWorkflow(true));
|
||||||
|
|
||||||
$crumbs = $this->buildApplicationCrumbs();
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
$crumbs->setActionList($actions);
|
$crumbs->setActionList($actions);
|
||||||
|
|
|
@ -54,7 +54,8 @@ final class PhortuneCurrency {
|
||||||
|
|
||||||
public static function newFromUSDCents($cents) {
|
public static function newFromUSDCents($cents) {
|
||||||
if (!is_int($cents)) {
|
if (!is_int($cents)) {
|
||||||
throw new Exception('USDCents value is not an integer!');
|
throw new Exception(
|
||||||
|
pht('USDCents value "%s" is not an integer!', $cents));
|
||||||
}
|
}
|
||||||
|
|
||||||
$obj = new PhortuneCurrency();
|
$obj = new PhortuneCurrency();
|
||||||
|
|
|
@ -110,8 +110,9 @@ final class PhortuneStripePaymentProvider extends PhortunePaymentProvider {
|
||||||
$customer = Stripe_Customer::create($params, $secret_key);
|
$customer = Stripe_Customer::create($params, $secret_key);
|
||||||
|
|
||||||
$card = $info->card;
|
$card = $info->card;
|
||||||
|
|
||||||
$method
|
$method
|
||||||
->setBrand($card->type)
|
->setBrand($card->brand)
|
||||||
->setLastFourDigits($card->last4)
|
->setLastFourDigits($card->last4)
|
||||||
->setExpires($card->exp_year, $card->exp_month)
|
->setExpires($card->exp_year, $card->exp_month)
|
||||||
->setMetadata(
|
->setMetadata(
|
||||||
|
|
102
src/applications/phortune/query/PhortuneCartQuery.php
Normal file
102
src/applications/phortune/query/PhortuneCartQuery.php
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhortuneCartQuery
|
||||||
|
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
|
|
||||||
|
private $ids;
|
||||||
|
private $phids;
|
||||||
|
|
||||||
|
private $needPurchases;
|
||||||
|
|
||||||
|
public function withIDs(array $ids) {
|
||||||
|
$this->ids = $ids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withPHIDs(array $phids) {
|
||||||
|
$this->phids = $phids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function needPurchases($need_purchases) {
|
||||||
|
$this->needPurchases = $need_purchases;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function loadPage() {
|
||||||
|
$table = new PhortuneCart();
|
||||||
|
$conn = $table->establishConnection('r');
|
||||||
|
|
||||||
|
$rows = queryfx_all(
|
||||||
|
$conn,
|
||||||
|
'SELECT cart.* FROM %T cart %Q %Q %Q',
|
||||||
|
$table->getTableName(),
|
||||||
|
$this->buildWhereClause($conn),
|
||||||
|
$this->buildOrderClause($conn),
|
||||||
|
$this->buildLimitClause($conn));
|
||||||
|
|
||||||
|
return $table->loadAllFromArray($rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function willFilterPage(array $carts) {
|
||||||
|
$accounts = id(new PhortuneAccountQuery())
|
||||||
|
->setViewer($this->getViewer())
|
||||||
|
->withPHIDs(mpull($carts, 'getAccountPHID'))
|
||||||
|
->execute();
|
||||||
|
$accounts = mpull($accounts, null, 'getPHID');
|
||||||
|
|
||||||
|
foreach ($carts as $key => $cart) {
|
||||||
|
$account = idx($accounts, $cart->getAccountPHID());
|
||||||
|
if (!$account) {
|
||||||
|
unset($carts[$key]);
|
||||||
|
}
|
||||||
|
$cart->attachAccount($account);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $carts;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function didFilterPage(array $carts) {
|
||||||
|
if ($this->needPurchases) {
|
||||||
|
$purchases = id(new PhortunePurchaseQuery())
|
||||||
|
->setViewer($this->getViewer())
|
||||||
|
->setParentQuery($this)
|
||||||
|
->withCartPHIDs(mpull($carts, 'getPHID'))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$purchases = mgroup($purchases, 'getCartPHID');
|
||||||
|
foreach ($carts as $cart) {
|
||||||
|
$cart->attachPurchases(idx($purchases, $cart->getPHID(), array()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $carts;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildWhereClause(AphrontDatabaseConnection $conn) {
|
||||||
|
$where = array();
|
||||||
|
|
||||||
|
$where[] = $this->buildPagingClause($conn);
|
||||||
|
|
||||||
|
if ($this->ids !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'cart.id IN (%Ld)',
|
||||||
|
$this->ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->phids !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'cart.phid IN (%Ls)',
|
||||||
|
$this->phids);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->formatWhereClause($where);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryApplicationClass() {
|
||||||
|
return 'PhabricatorApplicationPhortune';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
91
src/applications/phortune/query/PhortunePurchaseQuery.php
Normal file
91
src/applications/phortune/query/PhortunePurchaseQuery.php
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhortunePurchaseQuery
|
||||||
|
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
|
|
||||||
|
private $ids;
|
||||||
|
private $phids;
|
||||||
|
private $cartPHIDs;
|
||||||
|
|
||||||
|
public function withIDs(array $ids) {
|
||||||
|
$this->ids = $ids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withPHIDs(array $phids) {
|
||||||
|
$this->phids = $phids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withCartPHIDs(array $cart_phids) {
|
||||||
|
$this->cartPHIDs = $cart_phids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function loadPage() {
|
||||||
|
$table = new PhortunePurchase();
|
||||||
|
$conn = $table->establishConnection('r');
|
||||||
|
|
||||||
|
$rows = queryfx_all(
|
||||||
|
$conn,
|
||||||
|
'SELECT purchase.* FROM %T purchase %Q %Q %Q',
|
||||||
|
$table->getTableName(),
|
||||||
|
$this->buildWhereClause($conn),
|
||||||
|
$this->buildOrderClause($conn),
|
||||||
|
$this->buildLimitClause($conn));
|
||||||
|
|
||||||
|
return $table->loadAllFromArray($rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function willFilterPage(array $purchases) {
|
||||||
|
$carts = id(new PhabricatorObjectQuery())
|
||||||
|
->setViewer($this->getViewer())
|
||||||
|
->setParentQuery($this)
|
||||||
|
->withPHIDs(mpull($purchases, 'getCartPHID'))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
foreach ($purchases as $key => $purchase) {
|
||||||
|
$cart = idx($carts, $purchase->getCartPHID());
|
||||||
|
if (!$cart) {
|
||||||
|
unset($purchases[$key]);
|
||||||
|
}
|
||||||
|
$purchase->attachCart($cart);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $purchases;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildWhereClause(AphrontDatabaseConnection $conn) {
|
||||||
|
$where = array();
|
||||||
|
|
||||||
|
$where[] = $this->buildPagingClause($conn);
|
||||||
|
|
||||||
|
if ($this->ids !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'purchase.id IN (%Ld)',
|
||||||
|
$this->ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->phids !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'purchase.phid IN (%Ls)',
|
||||||
|
$this->phids);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->cartPHIDs !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'purchase.cartPHID IN (%Ls)',
|
||||||
|
$this->cartPHIDs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->formatWhereClause($where);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQueryApplicationClass() {
|
||||||
|
return 'PhabricatorApplicationPhortune';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,11 +1,13 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class PhortuneCart extends PhortuneDAO {
|
final class PhortuneCart extends PhortuneDAO
|
||||||
|
implements PhabricatorPolicyInterface {
|
||||||
|
|
||||||
protected $accountPHID;
|
protected $accountPHID;
|
||||||
protected $ownerPHID;
|
protected $authorPHID;
|
||||||
protected $metadata;
|
protected $metadata;
|
||||||
|
|
||||||
|
private $account = self::ATTACHABLE;
|
||||||
private $purchases = self::ATTACHABLE;
|
private $purchases = self::ATTACHABLE;
|
||||||
|
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
|
@ -22,18 +24,50 @@ final class PhortuneCart extends PhortuneDAO {
|
||||||
PhabricatorPHIDConstants::PHID_TYPE_CART);
|
PhabricatorPHIDConstants::PHID_TYPE_CART);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getTotalInCents() {
|
||||||
|
return 123;
|
||||||
|
}
|
||||||
|
|
||||||
public function attachPurchases(array $purchases) {
|
public function attachPurchases(array $purchases) {
|
||||||
assert_instances_of($purchases, 'PhortunePurchase');
|
assert_instances_of($purchases, 'PhortunePurchase');
|
||||||
$this->purchases = $purchases;
|
$this->purchases = $purchases;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTotalInCents() {
|
|
||||||
return 123;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPurchases() {
|
public function getPurchases() {
|
||||||
return $this->assertAttached($this->purchases);
|
return $this->assertAttached($this->purchases);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function attachAccount(PhortuneAccount $account) {
|
||||||
|
$this->account = $account;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAccount() {
|
||||||
|
return $this->assertAttached($this->account);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function getCapabilities() {
|
||||||
|
return array(
|
||||||
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPolicy($capability) {
|
||||||
|
return $this->getAccount()->getPolicy($capability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||||
|
return $this->getAccount()->hasAutomaticCapability($capability, $viewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function describeAutomaticCapability($capability) {
|
||||||
|
return pht('Carts inherit the policies of the associated account.');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
/**
|
/**
|
||||||
* A purchase represents a user buying something or a subscription to a plan.
|
* A purchase represents a user buying something or a subscription to a plan.
|
||||||
*/
|
*/
|
||||||
final class PhortunePurchase extends PhortuneDAO {
|
final class PhortunePurchase extends PhortuneDAO
|
||||||
|
implements PhabricatorPolicyInterface {
|
||||||
|
|
||||||
const STATUS_PENDING = 'purchase:pending';
|
const STATUS_PENDING = 'purchase:pending';
|
||||||
const STATUS_PROCESSING = 'purchase:processing';
|
const STATUS_PROCESSING = 'purchase:processing';
|
||||||
|
@ -15,17 +16,15 @@ final class PhortunePurchase extends PhortuneDAO {
|
||||||
protected $productPHID;
|
protected $productPHID;
|
||||||
protected $accountPHID;
|
protected $accountPHID;
|
||||||
protected $authorPHID;
|
protected $authorPHID;
|
||||||
protected $purchaseName;
|
protected $cartPHID;
|
||||||
protected $purchaseURI;
|
|
||||||
protected $paymentMethodPHID;
|
|
||||||
protected $basePriceInCents;
|
protected $basePriceInCents;
|
||||||
protected $priceAdjustmentInCents;
|
|
||||||
protected $finalPriceInCents;
|
|
||||||
protected $quantity;
|
protected $quantity;
|
||||||
protected $totalPriceInCents;
|
protected $totalPriceInCents;
|
||||||
protected $status;
|
protected $status;
|
||||||
protected $metadata;
|
protected $metadata;
|
||||||
|
|
||||||
|
private $cart = self::ATTACHABLE;
|
||||||
|
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
self::CONFIG_AUX_PHID => true,
|
self::CONFIG_AUX_PHID => true,
|
||||||
|
@ -40,4 +39,42 @@ final class PhortunePurchase extends PhortuneDAO {
|
||||||
PhabricatorPHIDConstants::PHID_TYPE_PRCH);
|
PhabricatorPHIDConstants::PHID_TYPE_PRCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function attachCart(PhortuneCart $cart) {
|
||||||
|
$this->cart = $cart;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCart() {
|
||||||
|
return $this->assertAttached($this->cart);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function didReadData() {
|
||||||
|
// The payment processing code is strict about types.
|
||||||
|
$this->basePriceInCents = (int)$this->basePriceInCents;
|
||||||
|
$this->totalPriceInCents = (int)$this->totalPriceInCents;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function getCapabilities() {
|
||||||
|
return array(
|
||||||
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPolicy($capability) {
|
||||||
|
return $this->getCart()->getPolicy($capability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||||
|
return $this->getCart()->hasAutomaticCapability($capability, $viewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function describeAutomaticCapability($capability) {
|
||||||
|
return pht('Purchases have the policies of their cart.');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue