2009-05-05 10:10:51 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Partially based on Zend_Currency.
|
|
|
|
*
|
|
|
|
* @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
|
|
|
|
* @license http://framework.zend.com/license/new-bsd New BSD License
|
|
|
|
* @version $Id: Currency.php 6137 2007-08-19 14:55:27Z shreef $
|
|
|
|
*/
|
|
|
|
|
|
|
|
require_once 'Zend/Currency.php';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implements the "Money" pattern.
|
|
|
|
*
|
|
|
|
* @see http://www.martinfowler.com/eaaCatalog/money.html
|
|
|
|
*
|
|
|
|
* @todo Support different ways of rounding
|
|
|
|
* @todo Equality operators
|
|
|
|
* @todo Addition, substraction and allocation of values
|
|
|
|
* @todo Model validation for $allowedCurrencies
|
|
|
|
*
|
|
|
|
* @package sapphire
|
|
|
|
* @subpackage model
|
|
|
|
*/
|
|
|
|
class Money extends DBField implements CompositeDBField {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string $getCurrency()
|
|
|
|
*/
|
|
|
|
protected $currency;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var float $currencyAmount
|
|
|
|
*/
|
|
|
|
protected $amount;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var boolean $isChanged
|
|
|
|
*/
|
|
|
|
protected $isChanged = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string $locale
|
|
|
|
*/
|
|
|
|
protected $locale = null;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var Zend_Currency
|
|
|
|
*/
|
|
|
|
protected $currencyLib;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Limit the currencies
|
|
|
|
* @var array $allowedCurrencies
|
|
|
|
*/
|
|
|
|
protected $allowedCurrencies;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param array
|
|
|
|
*/
|
|
|
|
static $composite_db = array(
|
2009-06-02 05:41:26 +02:00
|
|
|
"Currency" => "Varchar(3)",
|
|
|
|
"Amount" => 'Decimal(19,4)'
|
2009-05-05 10:10:51 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
function __construct($name = null) {
|
2009-05-07 01:32:57 +02:00
|
|
|
$this->currencyLib = new Zend_Currency(null, i18n::default_locale());
|
2009-05-05 10:10:51 +02:00
|
|
|
|
|
|
|
parent::__construct($name);
|
|
|
|
}
|
2009-05-27 02:09:23 +02:00
|
|
|
|
|
|
|
function compositeDatabaseFields() {
|
2009-05-05 10:10:51 +02:00
|
|
|
return self::$composite_db;
|
|
|
|
}
|
|
|
|
|
|
|
|
function requireField() {
|
2009-05-27 02:09:23 +02:00
|
|
|
$fields = $this->compositeDatabaseFields();
|
|
|
|
if($fields) foreach($fields as $name => $type){
|
2009-05-05 10:10:51 +02:00
|
|
|
DB::requireField($this->tableName, $this->name.$name, $type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function writeToManipulation(&$manipulation) {
|
2009-05-21 06:46:58 +02:00
|
|
|
if($this->getCurrency()) {
|
|
|
|
$manipulation['fields'][$this->name.'Currency'] = $this->prepValueForDB($this->getCurrency());
|
|
|
|
} else {
|
|
|
|
$manipulation['fields'][$this->name.'Currency'] = DBField::create('Varchar', $this->getCurrency())->nullValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
if($this->getAmount()) {
|
|
|
|
$manipulation['fields'][$this->name.'Amount'] = $this->getAmount();
|
|
|
|
} else {
|
|
|
|
$manipulation['fields'][$this->name.'Amount'] = DBField::create('Decimal', $this->getAmount())->nullValue();
|
|
|
|
}
|
2009-05-05 10:10:51 +02:00
|
|
|
}
|
2009-05-12 07:29:59 +02:00
|
|
|
|
|
|
|
function addToQuery(&$query) {
|
|
|
|
parent::addToQuery($query);
|
2009-05-19 03:58:29 +02:00
|
|
|
$query->select[] = sprintf('"%sAmount"', $this->name);
|
|
|
|
$query->select[] = sprintf('"%sCurrency"', $this->name);
|
2009-05-12 07:29:59 +02:00
|
|
|
}
|
2009-05-05 10:10:51 +02:00
|
|
|
|
2009-05-27 02:09:23 +02:00
|
|
|
function setValue($value, $record = null, $markChanged = true) {
|
2009-05-26 03:08:27 +02:00
|
|
|
// @todo Allow resetting value to NULL through Money $value field
|
|
|
|
if ($value instanceof Money && $value->hasValue()) {
|
2009-05-27 02:09:23 +02:00
|
|
|
$this->setCurrency($value->getCurrency(), $markChanged);
|
|
|
|
$this->setAmount($value->getAmount(), $markChanged);
|
|
|
|
if($markChanged) $this->isChanged = true;
|
2009-05-26 00:21:02 +02:00
|
|
|
} else if($record && isset($record[$this->name . 'Currency']) && isset($record[$this->name . 'Amount'])) {
|
2009-05-05 10:10:51 +02:00
|
|
|
if($record[$this->name . 'Currency'] && $record[$this->name . 'Amount']) {
|
2009-05-27 02:09:23 +02:00
|
|
|
$this->setCurrency($record[$this->name . 'Currency'], $markChanged);
|
|
|
|
$this->setAmount($record[$this->name . 'Amount'], $markChanged);
|
2009-05-05 10:10:51 +02:00
|
|
|
} else {
|
|
|
|
$this->value = $this->nullValue();
|
|
|
|
}
|
2009-05-27 02:09:23 +02:00
|
|
|
if($markChanged) $this->isChanged = true;
|
2009-05-05 10:10:51 +02:00
|
|
|
} else if (is_array($value)) {
|
|
|
|
if (array_key_exists('Currency', $value)) {
|
2009-05-27 02:09:23 +02:00
|
|
|
$this->setCurrency($value['Currency'], $markChanged);
|
2009-05-05 10:10:51 +02:00
|
|
|
}
|
|
|
|
if (array_key_exists('Amount', $value)) {
|
2009-05-27 02:09:23 +02:00
|
|
|
$this->setAmount($value['Amount'], $markChanged);
|
2009-05-05 10:10:51 +02:00
|
|
|
}
|
2009-05-27 02:09:23 +02:00
|
|
|
if($markChanged) $this->isChanged = true;
|
2009-05-05 10:10:51 +02:00
|
|
|
} else {
|
2009-05-21 06:46:58 +02:00
|
|
|
// @todo Allow to reset a money value by passing in NULL
|
|
|
|
//user_error('Invalid value in Money->setValue()', E_USER_ERROR);
|
2009-05-05 10:10:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function Nice($options = array()) {
|
2009-05-21 06:46:58 +02:00
|
|
|
$amount = $this->getAmount();
|
2009-05-25 08:03:06 +02:00
|
|
|
if(!isset($options['display'])) $options['display'] = Zend_Currency::USE_SYMBOL;
|
|
|
|
if(!isset($options['currency'])) $options['currency'] = $this->getCurrency();
|
|
|
|
if(!isset($options['symbol'])) $options['symbol'] = $this->currencyLib->getSymbol($this->getCurrency(), $this->getLocale());
|
2009-05-21 06:46:58 +02:00
|
|
|
return (is_numeric($amount)) ? $this->currencyLib->toCurrency($amount, $options) : '';
|
2009-05-05 10:10:51 +02:00
|
|
|
}
|
2009-05-07 01:32:57 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function NiceWithShortname($options = array()){
|
2009-05-21 06:46:58 +02:00
|
|
|
$options['display'] = Zend_Currency::USE_SHORTNAME;
|
|
|
|
return $this->Nice($options);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function NiceWithName($options = array()){
|
|
|
|
$options['display'] = Zend_Currency::USE_NAME;
|
|
|
|
return $this->Nice($options);
|
2009-05-07 01:32:57 +02:00
|
|
|
}
|
2009-05-05 10:10:51 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function getCurrency() {
|
|
|
|
return $this->currency;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string
|
|
|
|
*/
|
2009-05-27 02:09:23 +02:00
|
|
|
function setCurrency($currency, $markChanged = true) {
|
2009-05-05 10:10:51 +02:00
|
|
|
$this->currency = $currency;
|
2009-05-27 02:09:23 +02:00
|
|
|
if($markChanged) $this->isChanged = true;
|
2009-05-05 10:10:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @todo Return casted Float DBField?
|
|
|
|
*
|
|
|
|
* @return float
|
|
|
|
*/
|
|
|
|
function getAmount() {
|
|
|
|
return $this->amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param float $amount
|
|
|
|
*/
|
2009-05-27 02:09:23 +02:00
|
|
|
function setAmount($amount, $markChanged = true) {
|
2009-05-05 10:10:51 +02:00
|
|
|
$this->amount = (float)$amount;
|
2009-05-27 02:09:23 +02:00
|
|
|
if($markChanged) $this->isChanged = true;
|
2009-05-05 10:10:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
function hasValue() {
|
|
|
|
return ($this->getCurrency() && is_numeric($this->getAmount()));
|
|
|
|
}
|
|
|
|
|
2009-07-24 05:16:20 +02:00
|
|
|
/**
|
|
|
|
* @return boolean
|
|
|
|
*/
|
|
|
|
function hasAmount() {
|
|
|
|
return (int)$this->getAmount() != '0';
|
|
|
|
}
|
|
|
|
|
2009-05-05 10:10:51 +02:00
|
|
|
function isChanged() {
|
|
|
|
return $this->isChanged;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $locale
|
|
|
|
*/
|
|
|
|
function setLocale($locale) {
|
|
|
|
$this->locale = $locale;
|
|
|
|
$this->currencyLib->setLocale($locale);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function getLocale() {
|
|
|
|
return ($this->locale) ? $this->locale : i18n::get_locale();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function getSymbol($currency = null, $locale = null) {
|
|
|
|
|
|
|
|
if($locale === null) $locale = $this->getLocale();
|
|
|
|
if($currency === null) $currency = $this->getCurrency();
|
|
|
|
|
|
|
|
return $this->currencyLib->getSymbol($currency, $locale);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function getShortName($currency = null, $locale = null) {
|
|
|
|
if($locale === null) $locale = $this->getLocale();
|
|
|
|
if($currency === null) $currency = $this->getCurrency();
|
|
|
|
|
|
|
|
return $this->currencyLib->getShortName($currency, $locale);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function getName($currency = null, $locale = null) {
|
|
|
|
if($locale === null) $locale = $this->getLocale();
|
|
|
|
if($currency === null) $currency = $this->getCurrency();
|
|
|
|
|
|
|
|
return $this->currencyLib->getName($currency, $locale);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param array $arr
|
|
|
|
*/
|
|
|
|
function setAllowedCurrencies($arr) {
|
|
|
|
$this->allowedCurrencies = $arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
function getAllowedCurrencies() {
|
|
|
|
return $this->allowedCurrencies;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a CompositeField instance used as a default
|
|
|
|
* for form scaffolding.
|
|
|
|
*
|
|
|
|
* Used by {@link SearchContext}, {@link ModelAdmin}, {@link DataObject::scaffoldFormFields()}
|
|
|
|
*
|
|
|
|
* @param string $title Optional. Localized title of the generated instance
|
|
|
|
* @return FormField
|
|
|
|
*/
|
|
|
|
public function scaffoldFormField($title = null) {
|
2009-05-26 00:21:02 +02:00
|
|
|
$field = new MoneyField($this->name);
|
|
|
|
$field->setAllowedCurrencies($this->getAllowedCurrencies());
|
2009-05-26 03:08:27 +02:00
|
|
|
$field->setLocale($this->getLocale());
|
2009-05-06 07:50:18 +02:00
|
|
|
|
2009-05-05 10:10:51 +02:00
|
|
|
return $field;
|
|
|
|
}
|
2009-05-21 06:46:58 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* For backwards compatibility reasons
|
|
|
|
* (mainly with ecommerce module),
|
|
|
|
* this returns the amount value of the field,
|
|
|
|
* rather than a {@link Nice()} formatting.
|
|
|
|
*/
|
|
|
|
function __toString() {
|
2009-05-27 02:09:23 +02:00
|
|
|
return (string)$this->getAmount();
|
2009-05-21 06:46:58 +02:00
|
|
|
}
|
2009-05-05 10:10:51 +02:00
|
|
|
}
|
|
|
|
?>
|