FEATURE Added MoneyField as a form field to edit Money values

ENHANCEMENT Using MoneyField in Money->scaffoldFormField()
BUGFIX Fixed Money->setValue() to respect $value parameter over $record to avoid wrongly updated values from stale $record values instead of new $value

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@77772 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Ingo Schommer 2009-05-25 22:21:02 +00:00
parent 75ba6a1ab9
commit b478c8be34
3 changed files with 198 additions and 23 deletions

View File

@ -101,16 +101,16 @@ class Money extends DBField implements CompositeDBField {
}
function setValue($value,$record=null) {
if($record && isset($record[$this->name . 'Currency']) && isset($record[$this->name . 'Amount'])) {
if ($value instanceof Money) {
$this->setCurrency($value->getCurrency());
$this->setAmount($value->getAmount());
} else if($record && isset($record[$this->name . 'Currency']) && isset($record[$this->name . 'Amount'])) {
if($record[$this->name . 'Currency'] && $record[$this->name . 'Amount']) {
$this->setCurrency($record[$this->name . 'Currency']);
$this->setAmount($record[$this->name . 'Amount']);
} else {
$this->value = $this->nullValue();
}
} elseif ($value instanceof Money) {
$this->setCurrency($value->getCurrency());
$this->setAmount($value->getAmount());
} else if (is_array($value)) {
if (array_key_exists('Currency', $value)) {
$this->setCurrency($value['Currency']);
@ -266,25 +266,8 @@ class Money extends DBField implements CompositeDBField {
* @return FormField
*/
public function scaffoldFormField($title = null) {
$fieldAmount = new NumericField($this->name."Amount", 'Amount');
$allowedCurrencies = $this->getAllowedCurrencies();
if($allowedCurrencies) {
$fieldCurrency = new DropdownField(
$this->name."Currency",
'Currency',
array_combine($allowedCurrencies,$allowedCurrencies)
);
} else {
$fieldCurrency = new TextField($this->name."Currency", 'Currency');
}
$field = new FieldGroup(
$fieldAmount,
$fieldCurrency
);
$field->setID ($this->name);
$field = new MoneyField($this->name);
$field->setAllowedCurrencies($this->getAllowedCurrencies());
return $field;
}

139
forms/MoneyField.php Normal file
View File

@ -0,0 +1,139 @@
<?php
/**
* @author Ingo Schommer, SilverStripe Ltd. (<firstname>@silverstripe.com)
*
* @package sapphire
* @subpackage fields-formattedinput
*/
class MoneyField extends FormField {
/**
* @var string $_locale
*/
protected $_locale;
/**
* Limit the currencies
* @var array $allowedCurrencies
*/
protected $allowedCurrencies;
/**
* @var FormField
*/
protected $fieldAmount = null;
/**
* @var FormField
*/
protected $fieldCurrency = null;
function __construct($name, $title = null, $value = "", $form = null) {
parent::__construct($name, $title, $value, $form);
// naming with underscores to prevent values from actually being saved somewhere
$this->fieldAmount = new NumericField("{$name}[Amount]", _t('MoneyField.FIELDLABELAMOUNT', 'Amount'));
$this->fieldCurrency = $this->FieldCurrency();
$this->setValue($value);
}
/**
* @return string
*/
function Field() {
return "<div class=\"fieldgroup\">" .
"<div class=\"fieldgroupField\">" . $this->fieldCurrency->SmallFieldHolder() . "</div>" .
"<div class=\"fieldgroupField\">" . $this->fieldAmount->SmallFieldHolder() . "</div>" .
"</div>";
}
/**
* @return FormField
*/
protected function FieldCurrency() {
$allowedCurrencies = $this->getAllowedCurrencies();
if($allowedCurrencies) {
$field = new DropdownField(
"{$this->name}[Currency]",
_t('MoneyField.FIELDLABELCURRENCY', 'Currency'),
array_combine($allowedCurrencies,$allowedCurrencies)
);
} else {
$field = new TextField(
"{$this->name}[Currency]",
_t('MoneyField.FIELDLABELCURRENCY', 'Currency')
);
}
return $field;
}
function setValue($val) {
$this->value = $val;
if(is_array($val)) {
$this->fieldCurrency->setValue($val['Currency']);
$this->fieldAmount->setValue($val['Amount']);
} elseif($val instanceof Money) {
$this->fieldCurrency->setValue($val->getCurrency());
$this->fieldAmount->setValue($val->getAmount());
}
}
function saveInto($dataObject) {
$fieldName = $this->name;
$dataObject->$fieldName->setCurrency($this->fieldCurrency->Value());
$dataObject->$fieldName->setAmount($this->fieldAmount->Value());
}
/**
* Returns a readonly version of this field.
*/
function performReadonlyTransformation() {
$clone = clone $this;
$clone->setReadonly(true);
return $clone;
}
/**
* @todo Implement removal of readonly state with $bool=false
* @todo Set readonly state whenever field is recreated, e.g. in setAllowedCurrencies()
*/
function setReadonly($bool) {
parent::setReadonly($bool);
if($bool) {
$this->fieldAmount = $this->fieldAmount->performReadonlyTransformation();
$this->fieldCurrency = $this->fieldCurrency->performReadonlyTransformation();
}
}
/**
* @param array $arr
*/
function setAllowedCurrencies($arr) {
$this->allowedCurrencies = $arr;
// @todo Has to be done twice in case allowed currencies changed since construction
$oldVal = $this->fieldCurrency->Value();
$this->fieldCurrency = $this->FieldCurrency();
$this->fieldCurrency->setValue($oldVal);
}
/**
* @return array
*/
function getAllowedCurrencies() {
return $this->allowedCurrencies;
}
function setLocale($locale) {
$this->_locale = $locale;
$this->fieldAmount->setLocale($locale);
}
function getLocale() {
return $this->_locale;
}
}
?>

View File

@ -0,0 +1,53 @@
<?php
/**
* @package sapphire
* @subpackage tests
*/
class MoneyFieldTest extends SapphireTest {
function testSaveInto() {
$o = new MoneyFieldTest_Object();
$m = new Money();
$m->setAmount(1.23);
$m->setCurrency('EUR');
$f = new MoneyField('MyMoney', 'MyMoney', $m);
$f->saveInto($o);
$this->assertEquals($o->MyMoney->getAmount(), 1.23);
$this->assertEquals($o->MyMoney->getCurrency(), 'EUR');
}
function testSetValueAsMoney() {
$o = new MoneyFieldTest_Object();
$f = new MoneyField('MyMoney', 'MyMoney');
$m = new Money();
$m->setAmount(1.23);
$m->setCurrency('EUR');
$f->setValue($m);
$f->saveInto($o);
$this->assertEquals($o->MyMoney->getAmount(), 1.23);
$this->assertEquals($o->MyMoney->getCurrency(), 'EUR');
}
function testSetValueAsArray() {
$o = new MoneyFieldTest_Object();
$f = new MoneyField('MyMoney', 'MyMoney');
$f->setValue(array('Currency'=>'EUR','Amount'=>1.23));
$f->saveInto($o);
$this->assertEquals($o->MyMoney->getAmount(), 1.23);
$this->assertEquals($o->MyMoney->getCurrency(), 'EUR');
}
}
class MoneyFieldTest_Object extends DataObject implements TestOnly {
static $db = array(
'MyMoney' => 'Money',
);
}
?>