Number.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. <?php
  2. namespace Tools\Utility;
  3. use Cake\Core\Configure;
  4. use Cake\I18n\Number as CakeNumber;
  5. /**
  6. * Extend CakeNumber with a few important improvements:
  7. * - config setting for format()
  8. * - spacer char for currency (initially from https://github.com/cakephp/cakephp/pull/1148)
  9. * - signed values possible
  10. */
  11. class Number extends CakeNumber {
  12. protected static $_currency = 'EUR';
  13. protected static $_symbolRight = '€';
  14. protected static $_symbolLeft = '';
  15. protected static $_decimals = ',';
  16. protected static $_thousands = '.';
  17. /**
  18. * Correct the default values according to localization
  19. *
  20. * @param array $options
  21. * @return void
  22. * @deprecated Should not be used anymore with 3.x functionality?
  23. */
  24. public static function setConfig($options = []) {
  25. $config = $options + (array)Configure::read('Localization');
  26. foreach ($config as $key => $value) {
  27. $key = '_' . $key;
  28. if (!isset(static::${$key})) {
  29. continue;
  30. }
  31. static::${$key} = $value;
  32. }
  33. }
  34. /**
  35. * Convenience method to display the default currency
  36. *
  37. * @param float $amount
  38. * @param array $formatOptions
  39. * @return string
  40. */
  41. public static function money($amount, array $formatOptions = []) {
  42. return static::currency($amount, null, $formatOptions);
  43. }
  44. /**
  45. * Format numeric values
  46. * should not be used for currencies
  47. * //TODO: automize per localeconv() ?
  48. *
  49. * @param float $number
  50. * @param array $formatOptions Format options: currency=true/false, ... (leave empty for no special treatment)
  51. * @return string
  52. */
  53. public static function _format($number, array $formatOptions = []) {
  54. if (!is_numeric($number)) {
  55. $default = '---';
  56. if (!empty($options['default'])) {
  57. $default = $options['default'];
  58. }
  59. return $default;
  60. }
  61. if ($formatOptions === false) {
  62. $formatOptions = [];
  63. } elseif (!is_array($formatOptions)) {
  64. $formatOptions = ['places' => $formatOptions];
  65. }
  66. $options = ['before' => '', 'after' => '', 'places' => 2, 'thousands' => static::$_thousands, 'decimals' => static::$_decimals, 'escape' => false];
  67. $options = $formatOptions + $options;
  68. if (!empty($options['currency'])) {
  69. if (!empty(static::$_symbolRight)) {
  70. $options['after'] = ' ' . static::$_symbolRight;
  71. } elseif (!empty(static::$_symbolLeft)) {
  72. $options['before'] = static::$_symbolLeft . ' ';
  73. }
  74. }
  75. /*
  76. if ($spacer !== false) {
  77. $spacer = ($spacer === true) ? ' ' : $spacer;
  78. if ((string)$before !== '') {
  79. $before .= $spacer;
  80. }
  81. if ((string)$after !== '') {
  82. $after = $spacer . $after;
  83. }
  84. }
  85. */
  86. if ($options['places'] < 0) {
  87. $number = round($number, $options['places']);
  88. }
  89. $sign = '';
  90. if ($number > 0 && !empty($options['signed'])) {
  91. $sign = '+';
  92. }
  93. if (isset($options['signed'])) {
  94. unset($options['signed']);
  95. }
  96. return $sign . parent::format($number, $options);
  97. }
  98. /**
  99. * Format
  100. *
  101. * Additional options
  102. * - signed
  103. * - positive
  104. *
  105. * @param float $number
  106. * @param array $options
  107. * @return string
  108. */
  109. public static function format($number, array $options = []) {
  110. $defaults = [
  111. 'positive' => '+', 'signed' => false
  112. ];
  113. $options += $defaults;
  114. $sign = '';
  115. if ($number > 0 && !empty($options['signed'])) {
  116. $sign = '+';
  117. }
  118. if (isset($options['signed'])) {
  119. unset($options['signed']);
  120. }
  121. return $sign . parent::format($number, $options);
  122. }
  123. /**
  124. * Overwrite to allow
  125. *
  126. * - signed: true/false
  127. *
  128. * @param float $number
  129. * @param string|null $currency
  130. * @param array $options
  131. * @return string
  132. */
  133. public static function currency($number, $currency = null, array $options = []) {
  134. $defaults = [
  135. 'positive' => '+', 'signed' => false
  136. ];
  137. $options += $defaults;
  138. $sign = '';
  139. if ($number > 0 && !empty($options['signed'])) {
  140. $sign = $options['positive'];
  141. }
  142. return $sign . parent::currency($number, $currency, $options);
  143. }
  144. /**
  145. * Returns a formatted-for-humans file size.
  146. *
  147. * @param int $size Size in bytes
  148. * @param string $decimals
  149. * @return string Human readable size
  150. * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/number.html#NumberHelper::toReadableSize
  151. */
  152. public static function _toReadableSize($size, $decimals = '.') {
  153. $size = parent::toReadableSize($size);
  154. if ($decimals !== '.') {
  155. $size = str_replace('.', $decimals, $size);
  156. }
  157. return $size;
  158. }
  159. /**
  160. * Get the rounded average.
  161. *
  162. * @param array $values Values: int or float values
  163. * @param int $precision
  164. * @return float Average
  165. */
  166. public static function average($values, $precision = 0) {
  167. if (empty($values)) {
  168. return 0.0;
  169. }
  170. return round(array_sum($values) / count($values), $precision);
  171. }
  172. /**
  173. * Round value.
  174. *
  175. * @param float $number
  176. * @param float $increment
  177. * @return float result
  178. */
  179. public static function roundTo($number, $increment = 1.0) {
  180. $precision = static::getDecimalPlaces($increment);
  181. $res = round($number, $precision);
  182. if ($precision <= 0) {
  183. $res = (int)$res;
  184. }
  185. return $res;
  186. }
  187. /**
  188. * Round value up.
  189. *
  190. * @param float $number
  191. * @param int $increment
  192. * @return float result
  193. */
  194. public static function roundUpTo($number, $increment = 1) {
  195. return ceil($number / $increment) * $increment;
  196. }
  197. /**
  198. * Round value down.
  199. *
  200. * @param float $number
  201. * @param int $increment
  202. * @return float result
  203. */
  204. public static function roundDownTo($number, $increment = 1) {
  205. return floor($number / $increment) * $increment;
  206. }
  207. /**
  208. * Get decimal places
  209. *
  210. * @param float $number
  211. * @return int decimalPlaces
  212. */
  213. public static function getDecimalPlaces($number) {
  214. $decimalPlaces = 0;
  215. while ($number > 1 && $number != 0) {
  216. $number /= 10;
  217. $decimalPlaces -= 1;
  218. }
  219. while ($number < 1 && $number != 0) {
  220. $number *= 10;
  221. $decimalPlaces += 1;
  222. }
  223. return $decimalPlaces;
  224. }
  225. /**
  226. * Can compare two float values
  227. *
  228. * @link http://php.net/manual/en/language.types.float.php
  229. * @param float $x
  230. * @param float $y
  231. * @param float $precision
  232. * @return bool
  233. */
  234. public static function isFloatEqual($x, $y, $precision = 0.0000001) {
  235. return ($x + $precision >= $y) && ($x - $precision <= $y);
  236. }
  237. /**
  238. * Get the settings for a specific formatName
  239. *
  240. * @param string $formatName (EUR, ...)
  241. * @return array currencySettings
  242. */
  243. public static function getFormat($formatName) {
  244. if (!isset(static::$_currencies[$formatName])) {
  245. return [];
  246. }
  247. return static::$_currencies[$formatName];
  248. }
  249. }