Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F18471179
D10633.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
40 KB
Referenced Files
None
Subscribers
None
D10633.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Sep 3 2025, 6:54 PM (7 w, 3 d ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/3b/os/z65lerqikuy7a4nj
Default Alt Text
D10633.diff (40 KB)
Attached To
Mode
D10633: Make Currency a more formal type
Attached
Detach File
Event Timeline
Log In to Comment