Completed
Push — 3.7 ( 11b87a...bb5701 )
by
unknown
09:09 queued 01:14
created

Money   F

Complexity

Total Complexity 60

Size/Duplication

Total Lines 291
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
dl 0
loc 291
rs 3.6
c 0
b 0
f 0
wmc 60
lcom 1
cbo 6

26 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A compositeDatabaseFields() 0 3 1
A requireField() 0 6 3
A writeToManipulation() 0 15 3
A addToQuery() 0 5 1
C setValue() 0 37 16
A Nice() 0 9 5
A NiceWithShortname() 0 4 1
A NiceWithName() 0 4 1
A getCurrency() 0 3 1
A setCurrency() 0 4 2
A getAmount() 0 3 1
A setAmount() 0 4 2
A exists() 0 3 2
A hasAmount() 0 4 2
A isChanged() 0 3 1
A setLocale() 0 4 1
A getLocale() 0 3 2
A getSymbol() 0 7 3
A getShortName() 0 6 3
A getName() 0 6 3
A setAllowedCurrencies() 0 3 1
A getAllowedCurrencies() 0 3 1
A scaffoldFormField() 0 7 1
A __toString() 0 3 1
A scalarValueOnly() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Money often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Money, and based on these observations, apply Extract Interface, too.

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 25 and the first side effect is on line 10.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Partially based on Zend_Currency.
4
 *
5
 * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
6
 * @license   http://framework.zend.com/license/new-bsd	 New BSD License
7
 * @version   $Id: Currency.php 6137 2007-08-19 14:55:27Z shreef $
8
 */
9
10
require_once 'Zend/Currency.php';
11
12
/**
13
 * Implements the "Money" pattern.
14
 *
15
 * @see http://www.martinfowler.com/eaaCatalog/money.html
16
 *
17
 * @todo Support different ways of rounding
18
 * @todo Equality operators
19
 * @todo Addition, substraction and allocation of values
20
 * @todo Model validation for $allowedCurrencies
21
 *
22
 * @package framework
23
 * @subpackage model
24
 */
25
class Money extends DBField implements CompositeDBField {
26
27
	/**
28
	 * @var string $getCurrency()
29
	 */
30
	protected $currency;
31
32
	/**
33
	 * @var float $currencyAmount
34
	 */
35
	protected $amount;
36
37
	/**
38
	 * @var boolean $isChanged
39
	 */
40
	protected $isChanged = false;
41
42
	/**
43
	 * @var string $locale
44
	 */
45
	protected $locale = null;
46
47
	/**
48
	 * @var Zend_Currency
49
	 */
50
	protected $currencyLib;
51
52
	/**
53
	 * Limit the currencies
54
	 * @var array $allowedCurrencies
55
	 */
56
	protected $allowedCurrencies;
57
58
	/**
59
	 * @param array
60
	 */
61
	private static $composite_db = array(
62
		"Currency" => "Varchar(3)",
63
		"Amount" => 'Decimal(19,4)'
64
	);
65
66
	public function __construct($name = null) {
67
		$this->currencyLib = new Zend_Currency(null, i18n::get_locale());
68
69
		parent::__construct($name);
70
	}
71
72
	public function compositeDatabaseFields() {
73
		return self::$composite_db;
74
	}
75
76
	public function requireField() {
77
		$fields = $this->compositeDatabaseFields();
78
		if($fields) foreach($fields as $name => $type){
0 ignored issues
show
Bug Best Practice introduced by
The expression $fields of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
79
			DB::require_field($this->tableName, $this->name.$name, $type);
80
		}
81
	}
82
83
	public function writeToManipulation(&$manipulation) {
84
		if($this->getCurrency()) {
85
			$manipulation['fields'][$this->name.'Currency'] = $this->prepValueForDB($this->getCurrency());
86
		} else {
87
			$manipulation['fields'][$this->name.'Currency']
88
				= DBField::create_field('Varchar', $this->getCurrency())->nullValue();
89
		}
90
91
		if($this->getAmount()) {
92
			$manipulation['fields'][$this->name.'Amount'] = $this->getAmount();
93
		} else {
94
			$manipulation['fields'][$this->name.'Amount']
95
				= DBField::create_field('Decimal', $this->getAmount())->nullValue();
96
		}
97
	}
98
99
	public function addToQuery(&$query) {
100
		parent::addToQuery($query);
101
		$query->selectField(sprintf('"%sAmount"', $this->name));
102
		$query->selectField(sprintf('"%sCurrency"', $this->name));
103
	}
104
105
	public function setValue($value, $record = null, $markChanged = true) {
106
		// Convert an object to an array
107
		if($record && $record instanceof DataObject) {
108
			$record = $record->getQueriedDatabaseFields();
109
		}
110
111
		// @todo Allow resetting value to NULL through Money $value field
112
		if ($value instanceof Money && $value->exists()) {
113
			$this->setCurrency($value->getCurrency(), $markChanged);
114
			$this->setAmount($value->getAmount(), $markChanged);
115
			if($markChanged) $this->isChanged = true;
116
		} else if($record && isset($record[$this->name . 'Amount'])) {
117
			if($record[$this->name . 'Amount']) {
118
				if(!empty($record[$this->name . 'Currency'])) {
119
					$this->setCurrency($record[$this->name . 'Currency'], $markChanged);
120
				} else if($currency = (string)$this->config()->default_currency) {
121
					$this->setCurrency($currency, $markChanged);
122
				}
123
124
				$this->setAmount($record[$this->name . 'Amount'], $markChanged);
125
			} else {
126
				$this->value = $this->nullValue();
127
			}
128
			if($markChanged) $this->isChanged = true;
129
		} else if (is_array($value)) {
130
			if (array_key_exists('Currency', $value)) {
131
				$this->setCurrency($value['Currency'], $markChanged);
132
			}
133
			if (array_key_exists('Amount', $value)) {
134
				$this->setAmount($value['Amount'], $markChanged);
135
			}
136
			if($markChanged) $this->isChanged = true;
137
		} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
138
			// @todo Allow to reset a money value by passing in NULL
139
			//user_error('Invalid value in Money->setValue()', E_USER_ERROR);
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
140
		}
141
	}
142
143
	/**
144
	 * @return string
145
	 */
146
	public function Nice($options = array()) {
147
		$amount = $this->getAmount();
148
		if(!isset($options['display'])) $options['display'] = Zend_Currency::USE_SYMBOL;
149
		if(!isset($options['currency'])) $options['currency'] = $this->getCurrency();
150
		if(!isset($options['symbol'])) {
151
			$options['symbol'] = $this->currencyLib->getSymbol($this->getCurrency(), $this->getLocale());
152
		}
153
		return (is_numeric($amount)) ? $this->currencyLib->toCurrency($amount, $options) : '';
154
	}
155
156
	/**
157
	 * @return string
158
	 */
159
	public function NiceWithShortname($options = array()){
160
		$options['display'] = Zend_Currency::USE_SHORTNAME;
161
		return $this->Nice($options);
162
	}
163
164
	/**
165
	 * @return string
166
	 */
167
	public function NiceWithName($options = array()){
168
		$options['display'] = Zend_Currency::USE_NAME;
169
		return $this->Nice($options);
170
	}
171
172
	/**
173
	 * @return string
174
	 */
175
	public function getCurrency() {
176
		return $this->currency;
177
	}
178
179
	/**
180
	 * @param string
181
	 */
182
	public function setCurrency($currency, $markChanged = true) {
183
		$this->currency = $currency;
184
		if($markChanged) $this->isChanged = true;
185
	}
186
187
	/**
188
	 * @todo Return casted Float DBField?
189
	 *
190
	 * @return float
191
	 */
192
	public function getAmount() {
193
		return $this->amount;
194
	}
195
196
	/**
197
	 * @param float $amount
198
	 */
199
	public function setAmount($amount, $markChanged = true) {
200
		$this->amount = (float)$amount;
201
		if($markChanged) $this->isChanged = true;
202
	}
203
204
	/**
205
	 * @return boolean
206
	 */
207
	public function exists() {
208
		return ($this->getCurrency() && is_numeric($this->getAmount()));
209
	}
210
211
	/**
212
	 * @return boolean
213
	 */
214
	public function hasAmount() {
215
		$a = $this->getAmount();
216
		return (!empty($a) && is_numeric($a));
217
	}
218
219
	public function isChanged() {
220
		return $this->isChanged;
221
	}
222
223
	/**
224
	 * @param string $locale
225
	 */
226
	public function setLocale($locale) {
227
		$this->locale = $locale;
228
		$this->currencyLib->setLocale($locale);
229
	}
230
231
	/**
232
	 * @return string
233
	 */
234
	public function getLocale() {
235
		return ($this->locale) ? $this->locale : i18n::get_locale();
236
	}
237
238
	/**
239
	 * @return string
240
	 */
241
	public function getSymbol($currency = null, $locale = null) {
242
243
		if($locale === null) $locale = $this->getLocale();
244
		if($currency === null) $currency = $this->getCurrency();
245
246
		return $this->currencyLib->getSymbol($currency, $locale);
247
	}
248
249
	/**
250
	 * @return string
251
	 */
252
	public function getShortName($currency = null, $locale = null) {
253
		if($locale === null) $locale = $this->getLocale();
254
		if($currency === null) $currency = $this->getCurrency();
255
256
		return $this->currencyLib->getShortName($currency, $locale);
257
	}
258
259
	/**
260
	 * @return string
261
	 */
262
	public function getName($currency = null, $locale = null) {
263
		if($locale === null) $locale = $this->getLocale();
264
		if($currency === null) $currency = $this->getCurrency();
265
266
		return $this->currencyLib->getName($currency, $locale);
267
	}
268
269
	/**
270
	 * @param array $arr
271
	 */
272
	public function setAllowedCurrencies($arr) {
273
		$this->allowedCurrencies = $arr;
274
	}
275
276
	/**
277
	 * @return array
278
	 */
279
	public function getAllowedCurrencies() {
280
		return $this->allowedCurrencies;
281
	}
282
283
	/**
284
	 * Returns a CompositeField instance used as a default
285
	 * for form scaffolding.
286
	 *
287
	 * Used by {@link SearchContext}, {@link ModelAdmin}, {@link DataObject::scaffoldFormFields()}
288
	 *
289
	 * @param string $title Optional. Localized title of the generated instance
290
	 * @return FormField
291
	 */
292
	public function scaffoldFormField($title = null) {
293
		$field = new MoneyField($this->name);
294
		$field->setAllowedCurrencies($this->getAllowedCurrencies());
295
		$field->setLocale($this->getLocale());
296
297
		return $field;
298
	}
299
300
	/**
301
	 * For backwards compatibility reasons
302
	 * (mainly with ecommerce module),
303
	 * this returns the amount value of the field,
304
	 * rather than a {@link Nice()} formatting.
305
	 */
306
	public function __toString() {
307
		return (string)$this->getAmount();
308
	}
309
310
    public function scalarValueOnly()
311
    {
312
        return false;
313
    }
314
315
}
316