Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 29 | class Money |
||
| 30 | { |
||
| 31 | |||
| 32 | /** |
||
| 33 | * number of decimal places to be added to currencies for internal computations, |
||
| 34 | * but removed before any output or formatting is applied. |
||
| 35 | * This allows us to avoid rounding errors during calculations. |
||
| 36 | */ |
||
| 37 | const EXTRA_PRECISION = 3; |
||
| 38 | |||
| 39 | /** |
||
| 40 | * @var int $amount |
||
| 41 | */ |
||
| 42 | private $amount; |
||
| 43 | |||
| 44 | /** |
||
| 45 | * @var Currency $currency |
||
| 46 | */ |
||
| 47 | private $currency; |
||
| 48 | |||
| 49 | /** |
||
| 50 | * @var Calculator $calculator |
||
| 51 | */ |
||
| 52 | protected static $calculator; |
||
| 53 | |||
| 54 | /** |
||
| 55 | * @var MoneyFormatter[] $formatters |
||
| 56 | */ |
||
| 57 | protected static $formatters; |
||
| 58 | |||
| 59 | |||
| 60 | |||
| 61 | /** |
||
| 62 | * Money constructor. |
||
| 63 | * |
||
| 64 | * @param float|int|string $amount money amount IN THE STANDARD UNIT FOR THE CURRENCY ie: dollars, Euros, etc |
||
| 65 | * example: $12.5 USD would equate to a value amount of 12.50 |
||
| 66 | * @param Currency $currency |
||
| 67 | * @throws InvalidDataTypeException |
||
| 68 | */ |
||
| 69 | public function __construct($amount, Currency $currency) |
||
| 74 | |||
| 75 | |||
| 76 | |||
| 77 | /** |
||
| 78 | * factory method that returns a Money object using the currency corresponding to the site's country |
||
| 79 | * example: Money::forSite(12.5) |
||
| 80 | * |
||
| 81 | * @param float|int|string $amount money amount IN THE STANDARD UNIT FOR THE CURRENCY ie: dollars, Euros, etc |
||
| 82 | * example: $12.5 USD would equate to a value amount of 12.50 |
||
| 83 | * @return Money |
||
| 84 | * @throws InvalidArgumentException |
||
| 85 | */ |
||
| 86 | public static function forSite($amount) |
||
| 94 | |||
| 95 | |||
| 96 | |||
| 97 | /** |
||
| 98 | * factory method that returns a Money object using the currency as specified by the supplied ISO country code |
||
| 99 | * example: Money::forCountry(12.5,'US') |
||
| 100 | * |
||
| 101 | * @param float|int|string $amount money amount IN THE STANDARD UNIT FOR THE CURRENCY ie: dollars, Euros, etc |
||
| 102 | * example: $12.5 USD would equate to a value amount of 12.50 |
||
| 103 | * @param string $CNT_ISO |
||
| 104 | * @return Money |
||
| 105 | * @throws InvalidArgumentException |
||
| 106 | */ |
||
| 107 | public static function forCountry($amount, $CNT_ISO) |
||
| 111 | |||
| 112 | |||
| 113 | |||
| 114 | /** |
||
| 115 | * factory method that returns a Money object using the currency as specified by the supplied currency code |
||
| 116 | * example: Money::forCurrency(12.5, 'USD') |
||
| 117 | * |
||
| 118 | * @param float|int|string $amount money amount IN THE STANDARD UNIT FOR THE CURRENCY ie: dollars, Euros, etc |
||
| 119 | * example: $12.5 USD would equate to a value amount of 12.50 |
||
| 120 | * @param string $currency_code |
||
| 121 | * @return Money |
||
| 122 | * @throws InvalidDataTypeException |
||
| 123 | * @throws EE_Error |
||
| 124 | * @throws InvalidArgumentException |
||
| 125 | */ |
||
| 126 | public static function forCurrency($amount, $currency_code) |
||
| 130 | |||
| 131 | |||
| 132 | |||
| 133 | /** |
||
| 134 | * factory method that returns a Money object for the currency specified as if it were a class method |
||
| 135 | * example: Money::USD(12.5); |
||
| 136 | * money amount IN THE STANDARD UNIT FOR THE CURRENCY ie: dollars, Euros, etc |
||
| 137 | * example: $12.5 USD would equate to a value amount of 12.50 |
||
| 138 | * |
||
| 139 | * @param string $currency_code |
||
| 140 | * @param array $arguments |
||
| 141 | * @return Money |
||
| 142 | * @throws InvalidDataTypeException |
||
| 143 | * @throws EE_Error |
||
| 144 | * @throws InvalidArgumentException |
||
| 145 | */ |
||
| 146 | public static function __callStatic($currency_code, $arguments) |
||
| 150 | |||
| 151 | |||
| 152 | |||
| 153 | /** |
||
| 154 | * @param float|int|string $amount money amount IN THE STANDARD UNIT FOR THE CURRENCY ie: dollars, Euros, etc |
||
| 155 | * example: $12.5 USD would equate to a value amount of 12.50 |
||
| 156 | * @return float|int|number|string |
||
| 157 | * @throws InvalidDataTypeException |
||
| 158 | */ |
||
| 159 | private function parseAmount($amount) |
||
| 182 | |||
| 183 | |||
| 184 | |||
| 185 | /** |
||
| 186 | * adds or subtracts additional decimal places based on the value of the Money::EXTRA_PRECISION constant |
||
| 187 | * |
||
| 188 | * @param bool $positive |
||
| 189 | * @return int |
||
| 190 | */ |
||
| 191 | private function precision($positive = true) |
||
| 196 | |||
| 197 | |||
| 198 | |||
| 199 | /** |
||
| 200 | * Returns the money amount as an unformatted string |
||
| 201 | * IF YOU REQUIRE A FORMATTED STRING, THEN USE Money::format() |
||
| 202 | * |
||
| 203 | * @return string |
||
| 204 | */ |
||
| 205 | public function amount() |
||
| 214 | |||
| 215 | |||
| 216 | |||
| 217 | /** |
||
| 218 | * applies formatting based on the specified formatting level |
||
| 219 | * corresponding to one of the constants on \EventEspresso\core\services\currency\MoneyFormatter |
||
| 220 | * |
||
| 221 | * @param int $formatting_level |
||
| 222 | * @return string |
||
| 223 | */ |
||
| 224 | public function format($formatting_level = MoneyFormatter::ADD_THOUSANDS) |
||
| 240 | |||
| 241 | |||
| 242 | |||
| 243 | /** |
||
| 244 | * Returns the Currency object for this money |
||
| 245 | * |
||
| 246 | * @return Currency |
||
| 247 | */ |
||
| 248 | public function currency() |
||
| 252 | |||
| 253 | |||
| 254 | |||
| 255 | /** |
||
| 256 | * adds the supplied Money amount to this Money amount |
||
| 257 | * and returns a new Money object |
||
| 258 | * |
||
| 259 | * @param Money $other |
||
| 260 | * @return Money |
||
| 261 | * @throws InvalidArgumentException |
||
| 262 | */ |
||
| 263 | View Code Duplication | public function add(Money $other) |
|
| 274 | |||
| 275 | |||
| 276 | |||
| 277 | /** |
||
| 278 | * subtracts the supplied Money amount from this Money amount |
||
| 279 | * and returns a new Money object |
||
| 280 | * |
||
| 281 | * @param Money $other |
||
| 282 | * @return Money |
||
| 283 | * @throws InvalidArgumentException |
||
| 284 | */ |
||
| 285 | View Code Duplication | public function subtract(Money $other) |
|
| 296 | |||
| 297 | |||
| 298 | |||
| 299 | /** |
||
| 300 | * multiplies this Money amount by the supplied $multiplier |
||
| 301 | * and returns a new Money object |
||
| 302 | * |
||
| 303 | * @param float|int|string $multiplier |
||
| 304 | * @param int $rounding_mode |
||
| 305 | * @return Money |
||
| 306 | * @throws InvalidDataTypeException |
||
| 307 | */ |
||
| 308 | View Code Duplication | public function multiply($multiplier, $rounding_mode = Calculator::ROUND_HALF_UP) |
|
| 320 | |||
| 321 | |||
| 322 | |||
| 323 | /** |
||
| 324 | * divides this Money amount by the supplied $divisor |
||
| 325 | * and returns a new Money object |
||
| 326 | * |
||
| 327 | * @param float|int|string $divisor |
||
| 328 | * @param int $rounding_mode |
||
| 329 | * @return Money |
||
| 330 | * @throws InvalidDataTypeException |
||
| 331 | */ |
||
| 332 | View Code Duplication | public function divide($divisor, $rounding_mode = Calculator::ROUND_HALF_UP) |
|
| 344 | |||
| 345 | |||
| 346 | |||
| 347 | /** |
||
| 348 | * @param Currency $other_currency |
||
| 349 | * @throws InvalidArgumentException |
||
| 350 | */ |
||
| 351 | public function verifySameCurrency(Currency $other_currency) |
||
| 362 | |||
| 363 | |||
| 364 | |||
| 365 | /** |
||
| 366 | * @return Calculator |
||
| 367 | */ |
||
| 368 | protected function calculator() |
||
| 373 | |||
| 374 | |||
| 375 | |||
| 376 | /** |
||
| 377 | * loops through a filterable array of Calculator services |
||
| 378 | * and selects the first one that is supported by the current server |
||
| 379 | */ |
||
| 380 | protected function initializeCalculators() |
||
| 402 | |||
| 403 | |||
| 404 | |||
| 405 | /** |
||
| 406 | * @return MoneyFormatter[] |
||
| 407 | */ |
||
| 408 | protected function formatters() |
||
| 413 | |||
| 414 | |||
| 415 | |||
| 416 | /** |
||
| 417 | * initializes a filterable array of MoneyFormatter services |
||
| 418 | */ |
||
| 419 | protected function initializeFormatters() |
||
| 434 | |||
| 435 | |||
| 436 | |||
| 437 | /** |
||
| 438 | * @return string |
||
| 439 | */ |
||
| 440 | public function __toString() |
||
| 444 | |||
| 445 | |||
| 446 | |||
| 447 | |||
| 448 | } |
||
| 449 | // End of file Money.php |
||
| 450 | // Location: core/entities/money/Money.php |
This check looks for assignments to scalar types that may be of the wrong type.
To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.