PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/include/fields/CurrencyField.php

https://bitbucket.org/yousef_fadila/vtiger
PHP | 342 lines | 185 code | 36 blank | 121 comment | 36 complexity | 3b9261bd3394d312cc9a77cae4d12785 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0
  1. <?php
  2. /*+**********************************************************************************
  3. * The contents of this file are subject to the vtiger CRM Public License Version 1.0
  4. * ("License"); You may not use this file except in compliance with the License
  5. * The Original Code is: vtiger CRM Open Source
  6. * The Initial Developer of the Original Code is vtiger.
  7. * Portions created by vtiger are Copyright (C) vtiger.
  8. * All Rights Reserved.
  9. ************************************************************************************/
  10. class CurrencyField {
  11. private $CURRENCY_PATTERN_PLAIN = '123456789';
  12. private $CURRENCY_PATTERN_SINGLE_GROUPING = '123456,789';
  13. private $CURRENCY_PATTERN_THOUSAND_GROUPING = '123,456,789';
  14. private $CURRENCY_PATTERN_MIXED_GROUPING = '12,34,56,789';
  15. /**
  16. * Currency Format(3,3,3) or (2,2,3)
  17. * @var String
  18. */
  19. var $currencyFormat = '123,456,789';
  20. /**
  21. * Currency Separator for example (comma, dot, hash)
  22. * @var String
  23. */
  24. var $currencySeparator = ',';
  25. /**
  26. * Decimal Separator for example (dot, comma, space)
  27. * @var <type>
  28. */
  29. var $decimalSeparator = '.';
  30. /**
  31. * Number of Decimal Numbers
  32. * @var Integer
  33. */
  34. var $numberOfDecimal = 3;
  35. /**
  36. * Currency Id
  37. * @var Integer
  38. */
  39. var $currencyId = 1;
  40. /**
  41. * Currency Symbol
  42. * @var String
  43. */
  44. var $currencySymbol;
  45. /**
  46. * Currency Symbol Placement
  47. */
  48. var $currencySymbolPlacement;
  49. /**
  50. * Currency Conversion Rate
  51. * @var Number
  52. */
  53. var $conversionRate = 1;
  54. /**
  55. * Value to be converted
  56. * @param Number $value
  57. */
  58. var $value = null;
  59. /**
  60. * Constructor
  61. * @param Number $value
  62. */
  63. public function __construct($value) {
  64. $this->value = $value;
  65. }
  66. /**
  67. * Initializes the User's Currency Details
  68. * @global Users $current_user
  69. * @param Users $user
  70. */
  71. public function initialize($user=null) {
  72. global $current_user,$default_charset;
  73. if(empty($user)) {
  74. $user = $current_user;
  75. }
  76. if(!empty($user->currency_grouping_pattern)) {
  77. $this->currencyFormat = html_entity_decode($user->currency_grouping_pattern, ENT_QUOTES, $default_charset);
  78. $this->currencySeparator = html_entity_decode($user->currency_grouping_separator, ENT_QUOTES, $default_charset);
  79. $this->decimalSeparator = html_entity_decode($user->currency_decimal_separator, ENT_QUOTES, $default_charset);
  80. }
  81. if(!empty($user->currency_id)) {
  82. $this->currencyId = $user->currency_id;
  83. } else {
  84. $this->currencyId = self::getDBCurrencyId();
  85. }
  86. $currencyRateAndSymbol = getCurrencySymbolandCRate($this->currencyId);
  87. $this->currencySymbol = $currencyRateAndSymbol['symbol'];
  88. $this->conversionRate = $currencyRateAndSymbol['rate'];
  89. $this->currencySymbolPlacement = $user->currency_symbol_placement;
  90. }
  91. public function getCurrencySymbol() {
  92. return $this->currencySymbol;
  93. }
  94. public function setNumberofDecimals($numberOfDecimals) {
  95. $this->numberOfDecimal = $numberOfDecimals;
  96. }
  97. /**
  98. * Returns the Formatted Currency value for the User
  99. * @global Users $current_user
  100. * @param Users $user
  101. * @param Boolean $skipConversion
  102. * @return String - Formatted Currency
  103. */
  104. public static function convertToUserFormat($value, $user=null, $skipConversion=false) {
  105. $self = new self($value);
  106. return $self->getDisplayValue($user,$skipConversion);
  107. }
  108. /**
  109. * Function that converts the Number into Users Currency
  110. * @param Users $user
  111. * @param Boolean $skipConversion
  112. * @return Formatted Currency
  113. */
  114. public function getDisplayValue($user=null, $skipConversion=false) {
  115. global $current_user;
  116. if(empty($user)) {
  117. $user = $current_user;
  118. }
  119. $this->initialize($user);
  120. $value = $this->value;
  121. if($skipConversion == false) {
  122. $value = convertFromDollar($value,$this->conversionRate);
  123. }
  124. $number = $this->_formatCurrencyValue($value);
  125. return $number;
  126. }
  127. /**
  128. * Function that converts the Number into Users Currency along with currency symbol
  129. * @param Users $user
  130. * @param Boolean $skipConversion
  131. * @return Formatted Currency
  132. */
  133. public function getDisplayValueWithSymbol($user=null, $skipConversion=false) {
  134. $formattedValue = $this->getDisplayValue($user, $skipConversion);
  135. return self::appendCurrencySymbol($formattedValue, $this->currencySymbol, $this->currencySymbolPlacement);
  136. }
  137. /**
  138. * Static Function that appends the currency symbol to a given currency value, based on the preferred symbol placement
  139. * @param Number $currencyValue
  140. * @param String $currencySymbol
  141. * @param String $currencySymbolPlacement
  142. * @return Currency value appended with the currency symbol
  143. */
  144. public static function appendCurrencySymbol($currencyValue, $currencySymbol, $currencySymbolPlacement='') {
  145. global $current_user;
  146. if(empty($currencySymbolPlacement)) {
  147. $currencySymbolPlacement = $current_user->currency_symbol_placement;
  148. }
  149. switch($currencySymbolPlacement) {
  150. case '1.0$' : $returnValue = $currencyValue . $currencySymbol;
  151. break;
  152. case '$1.0' :
  153. default : $returnValue = $currencySymbol . $currencyValue;
  154. }
  155. return $returnValue;
  156. }
  157. /**
  158. * Function that formats the Number based on the User configured Pattern, Currency separator and Decimal separator
  159. * @param Number $value
  160. * @return Formatted Currency
  161. */
  162. private function _formatCurrencyValue($value) {
  163. $currencyPattern = $this->currencyFormat;
  164. $currencySeparator = $this->currencySeparator;
  165. $decimalSeparator = $this->decimalSeparator;
  166. if(empty($currencySeparator)) $currencySeparator = ' ';
  167. if(empty($decimalSeparator)) $decimalSeparator = ' ';
  168. if($currencyPattern == $this->CURRENCY_PATTERN_PLAIN) {
  169. // Replace '.' with Decimal Separator
  170. $number = str_replace('.', $decimalSeparator, $value);
  171. return $number;
  172. }
  173. if($currencyPattern == $this->CURRENCY_PATTERN_SINGLE_GROUPING) {
  174. // Separate the numeric and decimal parts
  175. $numericParts = explode('.', $value);
  176. $wholeNumber = $numericParts[0];
  177. // First part of the number which remains intact
  178. if(strlen($wholeNumber) > 3) {
  179. $wholeNumberFirstPart = substr($wholeNumber,0,strlen($wholeNumber)-3);
  180. }
  181. // Second Part of the number (last 3 digits) which should be separated from the First part using Currency Separator
  182. $wholeNumberLastPart = substr($wholeNumber,-3);
  183. // Re-create the whole number with user's configured currency separator
  184. if(!empty($wholeNumberFirstPart)) {
  185. $numericParts[0] = $wholeNumberFirstPart.$currencySeparator.$wholeNumberLastPart;
  186. } else {
  187. $numericParts[0] = $wholeNumberLastPart;
  188. }
  189. // Re-create the currency value combining the whole number and the decimal part using Decimal separator
  190. $number = implode($decimalSeparator, $numericParts);
  191. return $number;
  192. }
  193. if($currencyPattern == $this->CURRENCY_PATTERN_THOUSAND_GROUPING) {
  194. // Separate the numeric and decimal parts
  195. $numericParts = explode('.', $value);
  196. $wholeNumber = $numericParts[0];
  197. // Pad the rest of the length in the number string with Leading 0, to get it to the multiples of 3
  198. $numberLength = strlen($wholeNumber);
  199. // First grouping digits length
  200. $OddGroupLength = $numberLength%3;
  201. $gapsToBeFilled = 0;
  202. if($OddGroupLength > 0) $gapsToBeFilled = 3 - $OddGroupLength;
  203. $wholeNumber = str_pad($wholeNumber, $numberLength+$gapsToBeFilled, '0', STR_PAD_LEFT);
  204. // Split the whole number into chunks of 3 digits
  205. $wholeNumberParts = str_split($wholeNumber,3);
  206. // Re-create the whole number with user's configured currency separator
  207. $numericParts[0] = $wholeNumber = implode($currencySeparator, $wholeNumberParts);
  208. if($wholeNumber > 0) {
  209. $numericParts[0] = ltrim($wholeNumber, '0');
  210. } else {
  211. $numericParts[0] = 0;
  212. }
  213. // Re-create the currency value combining the whole number and the decimal part using Decimal separator
  214. $number = implode($decimalSeparator, $numericParts);
  215. return $number;
  216. }
  217. if($currencyPattern == $this->CURRENCY_PATTERN_MIXED_GROUPING) {
  218. // Separate the numeric and decimal parts
  219. $numericParts = explode('.', $value);
  220. $wholeNumber = $numericParts[0];
  221. // First part of the number which needs separate division
  222. if(strlen($wholeNumber) > 3) {
  223. $wholeNumberFirstPart = substr($wholeNumber,0,strlen($wholeNumber)-3);
  224. }
  225. // Second Part of the number (last 3 digits) which should be separated from the First part using Currency Separator
  226. $wholeNumberLastPart = substr($wholeNumber,-3);
  227. if(!empty($wholeNumberFirstPart)) {
  228. // Pad the rest of the length in the number string with Leading 0, to get it to the multiples of 2
  229. $numberLength = strlen($wholeNumberFirstPart);
  230. // First grouping digits length
  231. $OddGroupLength = $numberLength%2;
  232. $gapsToBeFilled = 0;
  233. if($OddGroupLength > 0) $gapsToBeFilled = 2 - $OddGroupLength;
  234. $wholeNumberFirstPart = str_pad($wholeNumberFirstPart, $numberLength+$gapsToBeFilled, '0', STR_PAD_LEFT);
  235. // Split the first part of tne number into chunks of 2 digits
  236. $wholeNumberFirstPartElements = str_split($wholeNumberFirstPart,2);
  237. $wholeNumberFirstPart = ltrim(implode($currencySeparator, $wholeNumberFirstPartElements), '0');
  238. $wholeNumberFirstPart = implode($currencySeparator, $wholeNumberFirstPartElements);
  239. if($wholeNumberFirstPart > 0) {
  240. $wholeNumberFirstPart = ltrim($wholeNumberFirstPart, '0');
  241. } else {
  242. $wholeNumberFirstPart = 0;
  243. }
  244. // Re-create the whole number with user's configured currency separator
  245. $numericParts[0] = $wholeNumberFirstPart.$currencySeparator.$wholeNumberLastPart;
  246. } else {
  247. $numericParts[0] = $wholeNumberLastPart;
  248. }
  249. // Re-create the currency value combining the whole number and the decimal part using Decimal separator
  250. $number = implode($decimalSeparator, $numericParts);
  251. return $number;
  252. }
  253. return $number;
  254. }
  255. /**
  256. * Returns the Currency value without formatting for DB Operations
  257. * @global Users $current_user
  258. * @param Users $user
  259. * @param Boolean $skipConversion
  260. * @return Number
  261. */
  262. public function getDBInsertedValue($user=null, $skipConversion=false) {
  263. global $current_user;
  264. if(empty($user)) {
  265. $user = $current_user;
  266. }
  267. $this->initialize($user);
  268. $value = $this->value;
  269. $currencySeparator = $this->currencySeparator;
  270. $decimalSeparator = $this->decimalSeparator;
  271. if(empty($currencySeparator)) $currencySeparator = ' ';
  272. if(empty($decimalSeparator)) $decimalSeparator = ' ';
  273. $value = str_replace("$currencySeparator", "", $value);
  274. $value = str_replace("$decimalSeparator", ".", $value);
  275. if($skipConversion == false) {
  276. $value = convertToDollar($value,$this->conversionRate);
  277. }
  278. $value = round($value, $this->numberOfDecimal);
  279. return $value;
  280. }
  281. /**
  282. * Returns the Currency value without formatting for DB Operations
  283. * @param Number $value
  284. * @param Users $user
  285. * @param Boolean $skipConversion
  286. * @return Number
  287. */
  288. public static function convertToDBFormat($value, $user=null, $skipConversion=false) {
  289. $self = new self($value);
  290. return $self->getDBInsertedValue($user, $skipConversion);
  291. }
  292. /**
  293. * Function to get the default CRM currency
  294. * @return Integer Default system currency id
  295. */
  296. public static function getDBCurrencyId() {
  297. $adb = PearDatabase::getInstance();
  298. $result = $adb->pquery('SELECT id FROM vtiger_currency_info WHERE defaultid < 0', array());
  299. $noOfRows = $adb->num_rows($result);
  300. if($noOfRows > 0) {
  301. return $adb->query_result($result, 0, 'id');
  302. }
  303. return null;
  304. }
  305. }
  306. ?>