Page MenuHomePhabricator

D10633.id25546.diff
No OneTemporary

D10633.id25546.diff

diff --git a/resources/sql/autopatches/20140902.almanacdevice.1.sql b/resources/sql/autopatches/20140902.almanacdevice.1.sql
--- a/resources/sql/autopatches/20140902.almanacdevice.1.sql
+++ b/resources/sql/autopatches/20140902.almanacdevice.1.sql
@@ -1,18 +1,18 @@
CREATE TABLE {$NAMESPACE}_almanac.almanac_device (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
phid VARBINARY(64) NOT NULL,
- name VARCHAR(255) NOT NULL COLLATE {$COLLATE_TEXT},
+ name VARCHAR(255) NOT NULL COLLATE utf8_bin,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
UNIQUE KEY `key_phid` (phid)
-) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+) ENGINE=InnoDB, COLLATE utf8_bin;
CREATE TABLE {$NAMESPACE}_almanac.almanac_deviceproperty (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
devicePHID VARBINARY(64) NOT NULL,
- `key` VARCHAR(128) NOT NULL COLLATE {$COLLATE_TEXT},
+ `key` VARCHAR(128) NOT NULL COLLATE utf8_bin,
value LONGTEXT NOT NULL,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
KEY `key_device` (devicePHID, `key`)
-) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+) ENGINE=InnoDB, COLLATE utf8_bin;
diff --git a/resources/sql/autopatches/20141004.harborliskcounter.sql b/resources/sql/autopatches/20141004.harborliskcounter.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20141004.harborliskcounter.sql
@@ -0,0 +1,4 @@
+CREATE TABLE `{$NAMESPACE}_harbormaster`.`lisk_counter` (
+ counterName VARCHAR(64) COLLATE utf8_bin PRIMARY KEY,
+ counterValue BIGINT UNSIGNED NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/resources/sql/autopatches/20141004.currency.01.sql b/resources/sql/autopatches/20141004.currency.01.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20141004.currency.01.sql
@@ -0,0 +1,4 @@
+TRUNCATE TABLE {$NAMESPACE}_fund.fund_backer;
+
+ALTER TABLE {$NAMESPACE}_fund.fund_backer
+ CHANGE amountInCents amountAsCurrency VARCHAR(64) NOT NULL COLLATE utf8_bin;
diff --git a/resources/sql/autopatches/20141004.currency.02.sql b/resources/sql/autopatches/20141004.currency.02.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20141004.currency.02.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_phortune.phortune_account
+ DROP balanceInCents;
diff --git a/resources/sql/autopatches/20141004.currency.03.sql b/resources/sql/autopatches/20141004.currency.03.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20141004.currency.03.sql
@@ -0,0 +1,4 @@
+TRUNCATE {$NAMESPACE}_phortune.phortune_charge;
+
+ALTER TABLE {$NAMESPACE}_phortune.phortune_charge
+ CHANGE amountInCents amountAsCurrency VARCHAR(64) NOT NULL COLLATE utf8_bin;
diff --git a/resources/sql/autopatches/20141004.currency.04.sql b/resources/sql/autopatches/20141004.currency.04.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20141004.currency.04.sql
@@ -0,0 +1,13 @@
+TRUNCATE {$NAMESPACE}_phortune.phortune_product;
+
+ALTER TABLE {$NAMESPACE}_phortune.phortune_product
+ DROP status;
+
+ALTER TABLE {$NAMESPACE}_phortune.phortune_product
+ DROP billingIntervalInMonths;
+
+ALTER TABLE {$NAMESPACE}_phortune.phortune_product
+ DROP trialPeriodInDays;
+
+ALTER TABLE {$NAMESPACE}_phortune.phortune_product
+ CHANGE priceInCents priceAsCurrency VARCHAR(64) NOT NULL collate utf8_bin;
diff --git a/resources/sql/autopatches/20141004.currency.05.sql b/resources/sql/autopatches/20141004.currency.05.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20141004.currency.05.sql
@@ -0,0 +1,8 @@
+TRUNCATE {$NAMESPACE}_phortune.phortune_purchase;
+
+ALTER TABLE {$NAMESPACE}_phortune.phortune_purchase
+ DROP totalPriceInCents;
+
+ALTER TABLE {$NAMESPACE}_phortune.phortune_purchase
+ CHANGE basePriceInCents basePriceAsCurrency VARCHAR(64)
+ NOT NULL collate utf8_bin;
diff --git a/resources/sql/autopatches/20141004.currency.06.sql b/resources/sql/autopatches/20141004.currency.06.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20141004.currency.06.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_phortune.phortune_product
+ DROP productType;
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
@@ -1716,6 +1716,7 @@
'PhabricatorLipsumManagementWorkflow' => 'applications/lipsum/management/PhabricatorLipsumManagementWorkflow.php',
'PhabricatorLipsumMondrianArtist' => 'applications/lipsum/image/PhabricatorLipsumMondrianArtist.php',
'PhabricatorLiskDAO' => 'infrastructure/storage/lisk/PhabricatorLiskDAO.php',
+ 'PhabricatorLiskSerializer' => 'infrastructure/storage/lisk/PhabricatorLiskSerializer.php',
'PhabricatorLocalDiskFileStorageEngine' => 'applications/files/engine/PhabricatorLocalDiskFileStorageEngine.php',
'PhabricatorLocalTimeTestCase' => 'view/__tests__/PhabricatorLocalTimeTestCase.php',
'PhabricatorLogoutController' => 'applications/auth/controller/PhabricatorLogoutController.php',
@@ -2561,6 +2562,7 @@
'PhortuneController' => 'applications/phortune/controller/PhortuneController.php',
'PhortuneCreditCardForm' => 'applications/phortune/view/PhortuneCreditCardForm.php',
'PhortuneCurrency' => 'applications/phortune/currency/PhortuneCurrency.php',
+ 'PhortuneCurrencySerializer' => 'applications/phortune/currency/PhortuneCurrencySerializer.php',
'PhortuneCurrencyTestCase' => 'applications/phortune/currency/__tests__/PhortuneCurrencyTestCase.php',
'PhortuneDAO' => 'applications/phortune/storage/PhortuneDAO.php',
'PhortuneErrCode' => 'applications/phortune/constants/PhortuneErrCode.php',
@@ -5591,6 +5593,7 @@
'PhortuneChargeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhortuneController' => 'PhabricatorController',
'PhortuneCurrency' => 'Phobject',
+ 'PhortuneCurrencySerializer' => 'PhabricatorLiskSerializer',
'PhortuneCurrencyTestCase' => 'PhabricatorTestCase',
'PhortuneDAO' => 'PhabricatorLiskDAO',
'PhortuneErrCode' => 'PhortuneConstants',
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
@@ -57,7 +57,7 @@
$backer = FundBacker::initializeNewBacker($viewer)
->setInitiativePHID($initiative->getPHID())
->attachInitiative($initiative)
- ->setAmountInCents($currency->getValue())
+ ->setAmountAsCurrency($currency)
->save();
// TODO: Here, we'd create a purchase and cart.
diff --git a/src/applications/fund/query/FundBackerSearchEngine.php b/src/applications/fund/query/FundBackerSearchEngine.php
--- a/src/applications/fund/query/FundBackerSearchEngine.php
+++ b/src/applications/fund/query/FundBackerSearchEngine.php
@@ -128,8 +128,7 @@
foreach ($backers as $backer) {
$backer_handle = $handles[$backer->getBackerPHID()];
- $currency = PhortuneCurrency::newFromUSDCents(
- $backer->getAmountInCents());
+ $currency = $backer->getAmount();
$header = pht(
'%s for %s',
diff --git a/src/applications/fund/storage/FundBacker.php b/src/applications/fund/storage/FundBacker.php
--- a/src/applications/fund/storage/FundBacker.php
+++ b/src/applications/fund/storage/FundBacker.php
@@ -7,7 +7,7 @@
protected $initiativePHID;
protected $backerPHID;
- protected $amountInCents;
+ protected $amountAsCurrency;
protected $status;
protected $properties = array();
@@ -28,9 +28,12 @@
self::CONFIG_SERIALIZATION => array(
'properties' => self::SERIALIZATION_JSON,
),
+ self::CONFIG_APPLICATION_SERIALIZERS => array(
+ 'amountAsCurrency' => new PhortuneCurrencySerializer(),
+ ),
self::CONFIG_COLUMN_SCHEMA => array(
'status' => 'text32',
- 'amountInCents' => 'uint32',
+ 'amountAsCurrency' => 'text64',
),
self::CONFIG_KEY_SCHEMA => array(
'key_initiative' => array(
@@ -47,11 +50,6 @@
return PhabricatorPHID::generateNewPHID(FundBackerPHIDType::TYPECONST);
}
- protected function didReadData() {
- // The payment processing code is strict about types.
- $this->amountInCents = (int)$this->amountInCents;
- }
-
public function getProperty($key, $default = null) {
return idx($this->properties, $key, $default);
}
diff --git a/src/applications/harbormaster/storage/HarbormasterSchemaSpec.php b/src/applications/harbormaster/storage/HarbormasterSchemaSpec.php
--- a/src/applications/harbormaster/storage/HarbormasterSchemaSpec.php
+++ b/src/applications/harbormaster/storage/HarbormasterSchemaSpec.php
@@ -5,6 +5,23 @@
public function buildSchemata() {
$this->buildEdgeSchemata(new HarbormasterBuildable());
+ // NOTE: This table is not used by any Harbormaster objects, but is used
+ // by unit tests.
+ $this->buildRawSchema(
+ id(new HarbormasterObject())->getApplicationName(),
+ PhabricatorLiskDAO::COUNTER_TABLE_NAME,
+ array(
+ 'counterName' => 'text32',
+ 'counterValue' => 'id64',
+ ),
+ array(
+ 'PRIMARY' => array(
+ 'columns' => array('counterName'),
+ 'unique' => true,
+ ),
+ ));
+
+
$this->buildRawSchema(
id(new HarbormasterBuildable())->getApplicationName(),
'harbormaster_buildlogchunk',
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
@@ -51,7 +51,7 @@
->setObject($account)
->setUser($user);
- $properties->addProperty(pht('Balance'), $account->getBalanceInCents());
+ $properties->addProperty(pht('Balance'), '-');
$properties->setActionList($actions);
$payment_methods = $this->buildPaymentMethodsSection($account);
@@ -189,8 +189,7 @@
foreach ($cart->getPurchases() as $purchase) {
$id = $purchase->getID();
- $price = $purchase->getTotalPriceInCents();
- $price = PhortuneCurrency::newFromUSDCents($price)->formatForDisplay();
+ $price = $purchase->getTotalPriceAsCurrency()->formatForDisplay();
$purchase_link = phutil_tag(
'a',
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
@@ -59,7 +59,7 @@
->setAuthorPHID($viewer->getPHID())
->setPaymentProviderKey($provider->getProviderKey())
->setPaymentMethodPHID($method->getPHID())
- ->setAmountInCents($cart->getTotalPriceInCents())
+ ->setAmountAsCurrency($cart->getTotalPriceAsCurrency())
->setStatus(PhortuneCharge::STATUS_PENDING);
$charge->openTransaction();
diff --git a/src/applications/phortune/controller/PhortuneCartController.php b/src/applications/phortune/controller/PhortuneCartController.php
--- a/src/applications/phortune/controller/PhortuneCartController.php
+++ b/src/applications/phortune/controller/PhortuneCartController.php
@@ -6,18 +6,13 @@
protected function buildCartContents(PhortuneCart $cart) {
$rows = array();
- $total = 0;
foreach ($cart->getPurchases() as $purchase) {
$rows[] = array(
$purchase->getFullDisplayName(),
- PhortuneCurrency::newFromUSDCents($purchase->getBasePriceInCents())
- ->formatForDisplay(),
+ $purchase->getBasePriceAsCurrency()->formatForDisplay(),
$purchase->getQuantity(),
- PhortuneCurrency::newFromUSDCents($purchase->getTotalPriceInCents())
- ->formatForDisplay(),
+ $purchase->getTotalPriceAsCurrency()->formatForDisplay(),
);
-
- $total += $purchase->getTotalPriceInCents();
}
$rows[] = array(
@@ -25,7 +20,7 @@
'',
'',
phutil_tag('strong', array(),
- PhortuneCurrency::newFromUSDCents($total)->formatForDisplay()),
+ $cart->getTotalPriceAsCurrency()->formatForDisplay()),
);
$table = new AphrontTableView($rows);
diff --git a/src/applications/phortune/controller/PhortuneController.php b/src/applications/phortune/controller/PhortuneController.php
--- a/src/applications/phortune/controller/PhortuneController.php
+++ b/src/applications/phortune/controller/PhortuneController.php
@@ -73,8 +73,7 @@
$cart_href,
$charge->getPaymentProviderKey(),
$charge->getPaymentMethodPHID(),
- PhortuneCurrency::newFromUSDCents($charge->getAmountInCents())
- ->formatForDisplay(),
+ $charge->getAmountAsCurrency()->formatForDisplay(),
$charge->getStatus(),
phabricator_datetime($charge->getDateCreated(), $viewer),
);
diff --git a/src/applications/phortune/controller/PhortuneProductEditController.php b/src/applications/phortune/controller/PhortuneProductEditController.php
--- a/src/applications/phortune/controller/PhortuneProductEditController.php
+++ b/src/applications/phortune/controller/PhortuneProductEditController.php
@@ -25,19 +25,16 @@
$cancel_uri = $this->getApplicationURI(
'product/view/'.$this->productID.'/');
} else {
- $product = new PhortuneProduct();
+ $product = PhortuneProduct::initializeNewProduct();
$is_create = true;
$cancel_uri = $this->getApplicationURI('product/');
}
$v_name = $product->getProductName();
- $v_type = $product->getProductType();
- $v_price = (int)$product->getPriceInCents();
- $display_price = PhortuneCurrency::newFromUSDCents($v_price)
- ->formatForDisplay();
+ $v_price = $product->getPriceAsCurrency()->formatForDisplay();
+ $display_price = $v_price;
$e_name = true;
- $e_type = null;
$e_price = true;
$errors = array();
@@ -50,21 +47,10 @@
$e_name = null;
}
- if ($is_create) {
- $v_type = $request->getStr('type');
- $type_map = PhortuneProduct::getTypeMap();
- if (empty($type_map[$v_type])) {
- $e_type = pht('Invalid');
- $errors[] = pht('Product type is invalid.');
- } else {
- $e_type = null;
- }
- }
-
$display_price = $request->getStr('price');
try {
$v_price = PhortuneCurrency::newFromUserInput($user, $display_price)
- ->getValue();
+ ->serializeForStorage();
$e_price = null;
} catch (Exception $ex) {
$errors[] = pht('Price should be formatted as: $1.23');
@@ -79,10 +65,6 @@
->setNewValue($v_name);
$xactions[] = id(new PhortuneProductTransaction())
- ->setTransactionType(PhortuneProductTransaction::TYPE_TYPE)
- ->setNewValue($v_type);
-
- $xactions[] = id(new PhortuneProductTransaction())
->setTransactionType(PhortuneProductTransaction::TYPE_PRICE)
->setNewValue($v_price);
@@ -112,14 +94,6 @@
->setValue($v_name)
->setError($e_name))
->appendChild(
- id(new AphrontFormSelectControl())
- ->setLabel(pht('Type'))
- ->setName('type')
- ->setValue($v_type)
- ->setError($e_type)
- ->setOptions(PhortuneProduct::getTypeMap())
- ->setDisabled(!$is_create))
- ->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Price'))
->setName('price')
diff --git a/src/applications/phortune/controller/PhortuneProductListController.php b/src/applications/phortune/controller/PhortuneProductListController.php
--- a/src/applications/phortune/controller/PhortuneProductListController.php
+++ b/src/applications/phortune/controller/PhortuneProductListController.php
@@ -32,15 +32,13 @@
$view_uri = $this->getApplicationURI(
'product/view/'.$product->getID().'/');
- $price = $product->getPriceInCents();
+ $price = $product->getPriceAsCurrency();
$item = id(new PHUIObjectItemView())
->setObjectName($product->getID())
->setHeader($product->getProductName())
->setHref($view_uri)
- ->addAttribute(
- PhortuneCurrency::newFromUSDCents($price)->formatForDisplay())
- ->addAttribute($product->getTypeName());
+ ->addAttribute($price->formatForDisplay());
$product_list->addItem($item);
}
diff --git a/src/applications/phortune/controller/PhortuneProductPurchaseController.php b/src/applications/phortune/controller/PhortuneProductPurchaseController.php
--- a/src/applications/phortune/controller/PhortuneProductPurchaseController.php
+++ b/src/applications/phortune/controller/PhortuneProductPurchaseController.php
@@ -49,10 +49,9 @@
$purchase->setAccountPHID($account->getPHID());
$purchase->setAuthorPHID($user->getPHID());
$purchase->setCartPHID($cart->getPHID());
- $purchase->setBasePriceInCents($product->getPriceInCents());
+ $purchase->setBasePriceAsCurrency($product->getPriceAsCurrency());
$purchase->setQuantity(1);
- $purchase->setTotalPriceInCents(
- $purchase->getBasePriceInCents() * $purchase->getQuantity());
+
$purchase->setStatus(PhortunePurchase::STATUS_PENDING);
$purchase->save();
diff --git a/src/applications/phortune/controller/PhortuneProductViewController.php b/src/applications/phortune/controller/PhortuneProductViewController.php
--- a/src/applications/phortune/controller/PhortuneProductViewController.php
+++ b/src/applications/phortune/controller/PhortuneProductViewController.php
@@ -60,11 +60,9 @@
$properties = id(new PHUIPropertyListView())
->setUser($user)
->setActionList($actions)
- ->addProperty(pht('Type'), $product->getTypeName())
->addProperty(
pht('Price'),
- PhortuneCurrency::newFromUSDCents($product->getPriceInCents())
- ->formatForDisplay());
+ $product->getPriceAsCurrency()->formatForDisplay());
$xactions = id(new PhortuneProductTransactionQuery())
->setViewer($user)
diff --git a/src/applications/phortune/currency/PhortuneCurrency.php b/src/applications/phortune/currency/PhortuneCurrency.php
--- a/src/applications/phortune/currency/PhortuneCurrency.php
+++ b/src/applications/phortune/currency/PhortuneCurrency.php
@@ -9,7 +9,20 @@
// Intentionally private.
}
+ public static function getDefaultCurrency() {
+ return 'USD';
+ }
+
+ public static function newEmptyCurrency() {
+ return self::newFromString('0.00 USD');
+ }
+
public static function newFromUserInput(PhabricatorUser $user, $string) {
+ // Eventually, this might select a default currency based on user settings.
+ return self::newFromString($string, self::getDefaultCurrency());
+ }
+
+ public static function newFromString($string, $default = null) {
$matches = null;
$ok = preg_match(
'/^([-$]*(?:\d+)?(?:[.]\d{0,2})?)(?:\s+([A-Z]+))?$/',
@@ -34,7 +47,7 @@
$value = (float)$value;
$value = (int)round(100 * $value);
- $currency = idx($matches, 2, 'USD');
+ $currency = idx($matches, 2, $default);
if ($currency) {
switch ($currency) {
case 'USD':
@@ -44,6 +57,10 @@
}
}
+ return self::newFromValueAndCurrency($value, $currency);
+ }
+
+ public static function newFromValueAndCurrency($value, $currency) {
$obj = new PhortuneCurrency();
$obj->value = $value;
@@ -56,31 +73,34 @@
assert_instances_of($list, 'PhortuneCurrency');
$total = 0;
+ $currency = null;
foreach ($list as $item) {
+ if ($currency === null) {
+ $currency = $item->getCurrency();
+ } else if ($currency === $item->getCurrency()) {
+ // Adding a value denominated in the same currency, which is
+ // fine.
+ } else {
+ throw new Exception(
+ pht('Trying to sum a list of unlike currencies.'));
+ }
+
// TODO: This should check for integer overflows, etc.
$total += $item->getValue();
}
- return PhortuneCurrency::newFromUSDCents($total);
- }
-
- public static function newFromUSDCents($cents) {
- if (!is_int($cents)) {
- throw new Exception(
- pht('USDCents value "%s" is not an integer!', $cents));
- }
-
- $obj = new PhortuneCurrency();
-
- $obj->value = $cents;
- $obj->currency = 'USD';
-
- return $obj;
+ return PhortuneCurrency::newFromValueAndCurrency(
+ $total,
+ self::getDefaultCurrency());
}
public function formatForDisplay() {
$bare = $this->formatBareValue();
- return '$'.$bare.' USD';
+ return '$'.$bare.' '.$this->currency;
+ }
+
+ public function serializeForStorage() {
+ return $this->formatBareValue().' '.$this->currency;
}
public function formatBareValue() {
@@ -88,8 +108,8 @@
case 'USD':
return sprintf('%.02f', $this->value / 100);
default:
- throw new Exception('Unsupported currency!');
-
+ throw new Exception(
+ pht('Unsupported currency ("%s")!', $this->currency));
}
}
@@ -105,4 +125,6 @@
throw new Exception("Invalid currency format ('{$string}').");
}
+
+
}
diff --git a/src/applications/phortune/currency/PhortuneCurrencySerializer.php b/src/applications/phortune/currency/PhortuneCurrencySerializer.php
new file mode 100644
--- /dev/null
+++ b/src/applications/phortune/currency/PhortuneCurrencySerializer.php
@@ -0,0 +1,20 @@
+<?php
+
+final class PhortuneCurrencySerializer extends PhabricatorLiskSerializer {
+
+ public function willReadValue($value) {
+ return PhortuneCurrency::newFromString($value);
+ }
+
+ public function willWriteValue($value) {
+ if (!($value instanceof PhortuneCurrency)) {
+ throw new Exception(
+ pht(
+ 'Trying to save object with a currency column, but the column '.
+ 'value is not a PhortuneCurrency object.'));
+ }
+
+ return $value->serializeForStorage();
+ }
+
+}
diff --git a/src/applications/phortune/currency/__tests__/PhortuneCurrencyTestCase.php b/src/applications/phortune/currency/__tests__/PhortuneCurrencyTestCase.php
--- a/src/applications/phortune/currency/__tests__/PhortuneCurrencyTestCase.php
+++ b/src/applications/phortune/currency/__tests__/PhortuneCurrencyTestCase.php
@@ -4,18 +4,18 @@
public function testCurrencyFormatForDisplay() {
$map = array(
- 0 => '$0.00 USD',
- 1 => '$0.01 USD',
- 100 => '$1.00 USD',
- -123 => '$-1.23 USD',
- 5000000 => '$50000.00 USD',
+ '0' => '$0.00 USD',
+ '.01' => '$0.01 USD',
+ '1.00' => '$1.00 USD',
+ '-1.23' => '$-1.23 USD',
+ '50000.00' => '$50000.00 USD',
);
foreach ($map as $input => $expect) {
$this->assertEqual(
$expect,
- PhortuneCurrency::newFromUSDCents($input)->formatForDisplay(),
- "formatForDisplay({$input})");
+ PhortuneCurrency::newFromString($input, 'USD')->formatForDisplay(),
+ "newFromString({$input})->formatForDisplay()");
}
}
@@ -25,22 +25,22 @@
// NOTE: The PayPal API depends on the behavior of the bare value format!
$map = array(
- 0 => '0.00',
- 1 => '0.01',
- 100 => '1.00',
- -123 => '-1.23',
- 5000000 => '50000.00',
+ '0' => '0.00',
+ '.01' => '0.01',
+ '1.00' => '1.00',
+ '-1.23' => '-1.23',
+ '50000.00' => '50000.00',
);
foreach ($map as $input => $expect) {
$this->assertEqual(
$expect,
- PhortuneCurrency::newFromUSDCents($input)->formatBareValue(),
- "formatBareValue({$input})");
+ PhortuneCurrency::newFromString($input, 'USD')->formatBareValue(),
+ "newFromString({$input})->formatBareValue()");
}
}
- public function testCurrencyFromUserInput() {
+ public function testCurrencyFromString() {
$map = array(
'1.00' => 100,
@@ -57,17 +57,15 @@
'$.99 USD' => 99,
);
- $user = new PhabricatorUser();
-
foreach ($map as $input => $expect) {
$this->assertEqual(
$expect,
- PhortuneCurrency::newFromUserInput($user, $input)->getValue(),
- "newFromUserInput({$input})->getValue()");
+ PhortuneCurrency::newFromString($input, 'USD')->getValue(),
+ "newFromString({$input})->getValue()");
}
}
- public function testInvalidCurrencyFromUserInput() {
+ public function testInvalidCurrencyFromString() {
$map = array(
'--1',
'$$1',
@@ -77,12 +75,10 @@
'1 dollar',
);
- $user = new PhabricatorUser();
-
foreach ($map as $input) {
$caught = null;
try {
- PhortuneCurrency::newFromUserInput($user, $input);
+ PhortuneCurrency::newFromString($input, 'USD');
} catch (Exception $ex) {
$caught = $ex;
}
diff --git a/src/applications/phortune/editor/PhortuneProductEditor.php b/src/applications/phortune/editor/PhortuneProductEditor.php
--- a/src/applications/phortune/editor/PhortuneProductEditor.php
+++ b/src/applications/phortune/editor/PhortuneProductEditor.php
@@ -16,7 +16,6 @@
$types = parent::getTransactionTypes();
$types[] = PhortuneProductTransaction::TYPE_NAME;
- $types[] = PhortuneProductTransaction::TYPE_TYPE;
$types[] = PhortuneProductTransaction::TYPE_PRICE;
return $types;
@@ -29,10 +28,8 @@
switch ($xaction->getTransactionType()) {
case PhortuneProductTransaction::TYPE_NAME:
return $object->getProductName();
- case PhortuneProductTransaction::TYPE_TYPE:
- return $object->getProductType();
case PhortuneProductTransaction::TYPE_PRICE:
- return $object->getPriceInCents();
+ return $object->getPriceAsCurrency()->serializeForStorage();
}
return parent::getCustomTransactionOldValue($object, $xaction);
}
@@ -42,7 +39,6 @@
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhortuneProductTransaction::TYPE_NAME:
- case PhortuneProductTransaction::TYPE_TYPE:
case PhortuneProductTransaction::TYPE_PRICE:
return $xaction->getNewValue();
}
@@ -56,11 +52,9 @@
case PhortuneProductTransaction::TYPE_NAME:
$object->setProductName($xaction->getNewValue());
return;
- case PhortuneProductTransaction::TYPE_TYPE:
- $object->setProductType($xaction->getNewValue());
- return;
case PhortuneProductTransaction::TYPE_PRICE:
- $object->setPriceInCents($xaction->getNewValue());
+ $object->setPriceAsCurrency(
+ PhortuneCurrency::newFromString($xaction->getNewValue()));
return;
}
return parent::applyCustomInternalTransaction($object, $xaction);
@@ -71,7 +65,6 @@
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
case PhortuneProductTransaction::TYPE_NAME:
- case PhortuneProductTransaction::TYPE_TYPE:
case PhortuneProductTransaction::TYPE_PRICE:
return;
}
diff --git a/src/applications/phortune/provider/PhortunePaypalPaymentProvider.php b/src/applications/phortune/provider/PhortunePaypalPaymentProvider.php
--- a/src/applications/phortune/provider/PhortunePaypalPaymentProvider.php
+++ b/src/applications/phortune/provider/PhortunePaypalPaymentProvider.php
@@ -93,8 +93,7 @@
'cartID' => $cart->getID(),
));
- $total_in_cents = $cart->getTotalPriceInCents();
- $price = PhortuneCurrency::newFromUSDCents($total_in_cents);
+ $price = $cart->getTotalPriceAsCurrency();
$result = $this
->newPaypalAPICall()
diff --git a/src/applications/phortune/provider/PhortuneStripePaymentProvider.php b/src/applications/phortune/provider/PhortuneStripePaymentProvider.php
--- a/src/applications/phortune/provider/PhortuneStripePaymentProvider.php
+++ b/src/applications/phortune/provider/PhortuneStripePaymentProvider.php
@@ -47,10 +47,12 @@
$root = dirname(phutil_get_library_root('phabricator'));
require_once $root.'/externals/stripe-php/lib/Stripe.php';
+ $price = $charge->getAmountAsCurrency();
+
$secret_key = $this->getSecretKey();
$params = array(
- 'amount' => $charge->getAmountInCents(),
- 'currency' => 'usd',
+ 'amount' => $price->getValue(),
+ 'currency' => $price->getCurrency(),
'customer' => $method->getMetadataValue('stripe.customerID'),
'description' => $charge->getPHID(),
'capture' => true,
diff --git a/src/applications/phortune/provider/PhortuneWePayPaymentProvider.php b/src/applications/phortune/provider/PhortuneWePayPaymentProvider.php
--- a/src/applications/phortune/provider/PhortuneWePayPaymentProvider.php
+++ b/src/applications/phortune/provider/PhortuneWePayPaymentProvider.php
@@ -116,8 +116,7 @@
'cartID' => $cart->getID(),
));
- $total_in_cents = $cart->getTotalPriceInCents();
- $price = PhortuneCurrency::newFromUSDCents($total_in_cents);
+ $price = $cart->getTotalPriceAsCurrency();
$params = array(
'account_id' => $this->getWePayAccountID(),
@@ -176,10 +175,12 @@
$result->state));
}
+ $currency = PhortuneCurrency::newFromString($checkout->gross, 'USD');
+
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$charge = id(new PhortuneCharge())
- ->setAmountInCents((int)$checkout->gross * 100)
+ ->setAmountAsCurrency($currency)
->setAccountPHID($cart->getAccount()->getPHID())
->setAuthorPHID($viewer->getPHID())
->setPaymentProviderKey($this->getProviderKey())
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
@@ -10,7 +10,6 @@
implements PhabricatorPolicyInterface {
protected $name;
- protected $balanceInCents = 0;
private $memberPHIDs = self::ATTACHABLE;
@@ -19,7 +18,6 @@
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'text255',
- 'balanceInCents' => 'sint64',
),
) + parent::getConfiguration();
}
diff --git a/src/applications/phortune/storage/PhortuneCart.php b/src/applications/phortune/storage/PhortuneCart.php
--- a/src/applications/phortune/storage/PhortuneCart.php
+++ b/src/applications/phortune/storage/PhortuneCart.php
@@ -56,14 +56,13 @@
return $this->assertAttached($this->account);
}
- public function getTotalPriceInCents() {
+ public function getTotalPriceAsCurrency() {
$prices = array();
foreach ($this->getPurchases() as $purchase) {
- $prices[] = PhortuneCurrency::newFromUSDCents(
- $purchase->getTotalPriceInCents());
+ $prices[] = $purchase->getTotalPriceAsCurrency();
}
- return PhortuneCurrency::newFromList($prices)->getValue();
+ return PhortuneCurrency::newFromList($prices);
}
diff --git a/src/applications/phortune/storage/PhortuneCharge.php b/src/applications/phortune/storage/PhortuneCharge.php
--- a/src/applications/phortune/storage/PhortuneCharge.php
+++ b/src/applications/phortune/storage/PhortuneCharge.php
@@ -20,7 +20,7 @@
protected $cartPHID;
protected $paymentProviderKey;
protected $paymentMethodPHID;
- protected $amountInCents;
+ protected $amountAsCurrency;
protected $status;
protected $metadata = array();
@@ -33,10 +33,13 @@
self::CONFIG_SERIALIZATION => array(
'metadata' => self::SERIALIZATION_JSON,
),
+ self::CONFIG_APPLICATION_SERIALIZERS => array(
+ 'amountAsCurrency' => new PhortuneCurrencySerializer(),
+ ),
self::CONFIG_COLUMN_SCHEMA => array(
'paymentProviderKey' => 'text128',
'paymentMethodPHID' => 'phid?',
- 'amountInCents' => 'sint32',
+ 'amountAsCurrency' => 'text64',
'status' => 'text32',
),
self::CONFIG_KEY_SCHEMA => array(
@@ -55,11 +58,6 @@
PhabricatorPHIDConstants::PHID_TYPE_CHRG);
}
- protected function didReadData() {
- // The payment processing code is strict about types.
- $this->amountInCents = (int)$this->amountInCents;
- }
-
public function getMetadataValue($key, $default = null) {
return idx($this->metadata, $key, $default);
}
diff --git a/src/applications/phortune/storage/PhortuneProduct.php b/src/applications/phortune/storage/PhortuneProduct.php
--- a/src/applications/phortune/storage/PhortuneProduct.php
+++ b/src/applications/phortune/storage/PhortuneProduct.php
@@ -1,24 +1,13 @@
<?php
/**
- * A product is something users can purchase. It may be a one-time purchase,
- * or a plan which is billed monthly.
+ * A product is something users can purchase.
*/
final class PhortuneProduct extends PhortuneDAO
implements PhabricatorPolicyInterface {
- const TYPE_BILL_ONCE = 'phortune:thing';
- const TYPE_BILL_PLAN = 'phortune:plan';
-
- const STATUS_ACTIVE = 'product:active';
- const STATUS_DISABLED = 'product:disabled';
-
protected $productName;
- protected $productType;
- protected $status = self::STATUS_ACTIVE;
- protected $priceInCents;
- protected $billingIntervalInMonths;
- protected $trialPeriodInDays;
+ protected $priceAsCurrency;
protected $metadata;
public function getConfiguration() {
@@ -27,19 +16,16 @@
self::CONFIG_SERIALIZATION => array(
'metadata' => self::SERIALIZATION_JSON,
),
+ self::CONFIG_APPLICATION_SERIALIZERS => array(
+ 'priceAsCurrency' => new PhortuneCurrencySerializer(),
+ ),
self::CONFIG_COLUMN_SCHEMA => array(
'productName' => 'text255',
- 'productType' => 'text64',
'status' => 'text64',
- 'priceInCents' => 'sint64',
+ 'priceAsCurrency' => 'text64',
'billingIntervalInMonths' => 'uint32?',
'trialPeriodInDays' => 'uint32?',
),
- self::CONFIG_KEY_SCHEMA => array(
- 'key_status' => array(
- 'columns' => array('status'),
- ),
- ),
) + parent::getConfiguration();
}
@@ -48,24 +34,9 @@
PhabricatorPHIDConstants::PHID_TYPE_PDCT);
}
- public static function getTypeMap() {
- return array(
- self::TYPE_BILL_ONCE => pht('Product (Charged Once)'),
- self::TYPE_BILL_PLAN => pht('Flat Rate Plan (Charged Monthly)'),
- );
- }
-
- public function getTypeName() {
- return idx(self::getTypeMap(), $this->getProductType());
- }
-
- public function getPriceInCents() {
- $price = parent::getPriceInCents();
- if ($price === null) {
- return $price;
- } else {
- return (int)parent::getPriceInCents();
- }
+ public static function initializeNewProduct() {
+ return id(new PhortuneProduct())
+ ->setPriceAsCurrency(PhortuneCurrency::newEmptyCurrency());
}
diff --git a/src/applications/phortune/storage/PhortuneProductTransaction.php b/src/applications/phortune/storage/PhortuneProductTransaction.php
--- a/src/applications/phortune/storage/PhortuneProductTransaction.php
+++ b/src/applications/phortune/storage/PhortuneProductTransaction.php
@@ -4,7 +4,6 @@
extends PhabricatorApplicationTransaction {
const TYPE_NAME = 'product:name';
- const TYPE_TYPE = 'product:type';
const TYPE_PRICE = 'product:price';
public function getApplicationName() {
@@ -44,33 +43,18 @@
return pht(
'%s set product price to %s.',
$this->renderHandleLink($author_phid),
- PhortuneCurrency::newFromUSDCents($new)
+ PhortuneCurrency::newFromString($new)
->formatForDisplay());
} else {
return pht(
'%s changed product price from %s to %s.',
$this->renderHandleLink($author_phid),
- PhortuneCurrency::newFromUSDCents($old)
+ PhortuneCurrency::newFromString($old)
->formatForDisplay(),
- PhortuneCurrency::newFromUSDCents($new)
+ PhortuneCurrency::newFromString($new)
->formatForDisplay());
}
break;
- case self::TYPE_TYPE:
- $map = PhortuneProduct::getTypeMap();
- if ($old === null) {
- return pht(
- '%s set product type to "%s".',
- $this->renderHandleLink($author_phid),
- $map[$new]);
- } else {
- return pht(
- '%s changed product type from "%s" to "%s".',
- $this->renderHandleLink($author_phid),
- $map[$old],
- $map[$new]);
- }
- break;
}
return parent::getTitle();
diff --git a/src/applications/phortune/storage/PhortunePurchase.php b/src/applications/phortune/storage/PhortunePurchase.php
--- a/src/applications/phortune/storage/PhortunePurchase.php
+++ b/src/applications/phortune/storage/PhortunePurchase.php
@@ -17,9 +17,8 @@
protected $accountPHID;
protected $authorPHID;
protected $cartPHID;
- protected $basePriceInCents;
+ protected $basePriceAsCurrency;
protected $quantity;
- protected $totalPriceInCents;
protected $status;
protected $metadata;
@@ -31,11 +30,13 @@
self::CONFIG_SERIALIZATION => array(
'metadata' => self::SERIALIZATION_JSON,
),
+ self::CONFIG_APPLICATION_SERIALIZERS => array(
+ 'basePriceAsCurrency' => new PhortuneCurrencySerializer(),
+ ),
self::CONFIG_COLUMN_SCHEMA => array(
'cartPHID' => 'phid?',
- 'basePriceInCents' => 'sint32',
+ 'basePriceAsCurrency' => 'text64',
'quantity' => 'uint32',
- 'totalPriceInCents' => 'sint32',
'status' => 'text32',
),
self::CONFIG_KEY_SCHEMA => array(
@@ -60,16 +61,14 @@
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;
- }
-
public function getFullDisplayName() {
return pht('Goods and/or Services');
}
+ public function getTotalPriceAsCurrency() {
+ return $this->getBasePriceAsCurrency();
+ }
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
diff --git a/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php b/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php
--- a/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php
+++ b/src/infrastructure/storage/lisk/PhabricatorLiskDAO.php
@@ -8,6 +8,7 @@
private static $namespaceStack = array();
const ATTACHABLE = '<attachable>';
+ const CONFIG_APPLICATION_SERIALIZERS = 'phabricator/serializers';
/* -( Configuring Storage )------------------------------------------------ */
@@ -209,14 +210,35 @@
return phutil_utf8ize($string);
}
- public function delete() {
+ protected function willReadData(array &$data) {
+ parent::willReadData($data);
- // TODO: We should make some reasonable effort to destroy related
- // infrastructure objects here, like edges, transactions, custom field
- // storage, flags, Phrequent tracking, tokens, etc. This doesn't need to
- // be exhaustive, but we can get a lot of it pretty easily.
+ static $custom;
+ if ($custom === null) {
+ $custom = $this->getConfigOption(self::CONFIG_APPLICATION_SERIALIZERS);
+ }
- return parent::delete();
+ if ($custom) {
+ foreach ($custom as $key => $serializer) {
+ $data[$key] = $serializer->willReadValue($data[$key]);
+ }
+ }
}
+ protected function willWriteData(array &$data) {
+ static $custom;
+ if ($custom === null) {
+ $custom = $this->getConfigOption(self::CONFIG_APPLICATION_SERIALIZERS);
+ }
+
+ if ($custom) {
+ foreach ($custom as $key => $serializer) {
+ $data[$key] = $serializer->willWriteValue($data[$key]);
+ }
+ }
+
+ parent::willWriteData($data);
+ }
+
+
}
diff --git a/src/infrastructure/storage/lisk/PhabricatorLiskSerializer.php b/src/infrastructure/storage/lisk/PhabricatorLiskSerializer.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/storage/lisk/PhabricatorLiskSerializer.php
@@ -0,0 +1,8 @@
+<?php
+
+abstract class PhabricatorLiskSerializer {
+
+ abstract public function willReadValue($value);
+ abstract public function willWriteValue($value);
+
+}

File Metadata

Mime Type
text/plain
Expires
Thu, May 8, 2:48 PM (1 d, 20 h ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/tc/p7/x3vuqhu33nzcdpfw
Default Alt Text
D10633.id25546.diff (40 KB)

Event Timeline