diff --git a/core/model/fieldtypes/Money.php b/core/model/fieldtypes/Money.php index 1097985c1..9f0b4aea8 100644 --- a/core/model/fieldtypes/Money.php +++ b/core/model/fieldtypes/Money.php @@ -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; } diff --git a/forms/MoneyField.php b/forms/MoneyField.php new file mode 100644 index 000000000..88df1fab5 --- /dev/null +++ b/forms/MoneyField.php @@ -0,0 +1,139 @@ +@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 "
" . + "
" . $this->fieldCurrency->SmallFieldHolder() . "
" . + "
" . $this->fieldAmount->SmallFieldHolder() . "
" . + "
"; + } + + /** + * @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; + } +} +?> \ No newline at end of file diff --git a/tests/forms/MoneyFieldTest.php b/tests/forms/MoneyFieldTest.php new file mode 100644 index 000000000..87f2391de --- /dev/null +++ b/tests/forms/MoneyFieldTest.php @@ -0,0 +1,53 @@ +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', + ); +} +?> \ No newline at end of file