PageRenderTime 70ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/application/libraries/PHPExcel/Classes/PHPExcel/Calculation/Functions.php

https://bitbucket.org/dipendrapkrl/excelapi
PHP | 813 lines | 394 code | 110 blank | 309 comment | 92 complexity | be77ea18e76da0b177a66b6e55d0fe12 MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /**
  3. * PHPExcel
  4. *
  5. * Copyright (c) 2006 - 2012 PHPExcel
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * @category PHPExcel
  22. * @package PHPExcel_Calculation
  23. * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
  24. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  25. * @version 1.7.7, 2012-05-19
  26. */
  27. /** PHPExcel root directory */
  28. if (!defined('PHPEXCEL_ROOT')) {
  29. /**
  30. * @ignore
  31. */
  32. define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
  33. require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  34. }
  35. /** MAX_VALUE */
  36. define('MAX_VALUE', 1.2e308);
  37. /** 2 / PI */
  38. define('M_2DIVPI', 0.63661977236758134307553505349006);
  39. /** MAX_ITERATIONS */
  40. define('MAX_ITERATIONS', 256);
  41. /** PRECISION */
  42. define('PRECISION', 8.88E-016);
  43. /**
  44. * PHPExcel_Calculation_Functions
  45. *
  46. * @category PHPExcel
  47. * @package PHPExcel_Calculation
  48. * @copyright Copyright (c) 2006 - 2012 PHPExcel (http://www.codeplex.com/PHPExcel)
  49. */
  50. class PHPExcel_Calculation_Functions {
  51. /** constants */
  52. const COMPATIBILITY_EXCEL = 'Excel';
  53. const COMPATIBILITY_GNUMERIC = 'Gnumeric';
  54. const COMPATIBILITY_OPENOFFICE = 'OpenOfficeCalc';
  55. const RETURNDATE_PHP_NUMERIC = 'P';
  56. const RETURNDATE_PHP_OBJECT = 'O';
  57. const RETURNDATE_EXCEL = 'E';
  58. /**
  59. * Compatibility mode to use for error checking and responses
  60. *
  61. * @access private
  62. * @var string
  63. */
  64. protected static $compatibilityMode = self::COMPATIBILITY_EXCEL;
  65. /**
  66. * Data Type to use when returning date values
  67. *
  68. * @access private
  69. * @var string
  70. */
  71. protected static $ReturnDateType = self::RETURNDATE_EXCEL;
  72. /**
  73. * List of error codes
  74. *
  75. * @access private
  76. * @var array
  77. */
  78. protected static $_errorCodes = array( 'null' => '#NULL!',
  79. 'divisionbyzero' => '#DIV/0!',
  80. 'value' => '#VALUE!',
  81. 'reference' => '#REF!',
  82. 'name' => '#NAME?',
  83. 'num' => '#NUM!',
  84. 'na' => '#N/A',
  85. 'gettingdata' => '#GETTING_DATA'
  86. );
  87. /**
  88. * Set the Compatibility Mode
  89. *
  90. * @access public
  91. * @category Function Configuration
  92. * @param string $compatibilityMode Compatibility Mode
  93. * Permitted values are:
  94. * PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL 'Excel'
  95. * PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC 'Gnumeric'
  96. * PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE 'OpenOfficeCalc'
  97. * @return boolean (Success or Failure)
  98. */
  99. public static function setCompatibilityMode($compatibilityMode) {
  100. if (($compatibilityMode == self::COMPATIBILITY_EXCEL) ||
  101. ($compatibilityMode == self::COMPATIBILITY_GNUMERIC) ||
  102. ($compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) {
  103. self::$compatibilityMode = $compatibilityMode;
  104. return True;
  105. }
  106. return False;
  107. } // function setCompatibilityMode()
  108. /**
  109. * Return the current Compatibility Mode
  110. *
  111. * @access public
  112. * @category Function Configuration
  113. * @return string Compatibility Mode
  114. * Possible Return values are:
  115. * PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL 'Excel'
  116. * PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC 'Gnumeric'
  117. * PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE 'OpenOfficeCalc'
  118. */
  119. public static function getCompatibilityMode() {
  120. return self::$compatibilityMode;
  121. } // function getCompatibilityMode()
  122. /**
  123. * Set the Return Date Format used by functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object)
  124. *
  125. * @access public
  126. * @category Function Configuration
  127. * @param string $returnDateType Return Date Format
  128. * Permitted values are:
  129. * PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC 'P'
  130. * PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT 'O'
  131. * PHPExcel_Calculation_Functions::RETURNDATE_EXCEL 'E'
  132. * @return boolean Success or failure
  133. */
  134. public static function setReturnDateType($returnDateType) {
  135. if (($returnDateType == self::RETURNDATE_PHP_NUMERIC) ||
  136. ($returnDateType == self::RETURNDATE_PHP_OBJECT) ||
  137. ($returnDateType == self::RETURNDATE_EXCEL)) {
  138. self::$ReturnDateType = $returnDateType;
  139. return True;
  140. }
  141. return False;
  142. } // function setReturnDateType()
  143. /**
  144. * Return the current Return Date Format for functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object)
  145. *
  146. * @access public
  147. * @category Function Configuration
  148. * @return string Return Date Format
  149. * Possible Return values are:
  150. * PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC 'P'
  151. * PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT 'O'
  152. * PHPExcel_Calculation_Functions::RETURNDATE_EXCEL 'E'
  153. */
  154. public static function getReturnDateType() {
  155. return self::$ReturnDateType;
  156. } // function getReturnDateType()
  157. /**
  158. * DUMMY
  159. *
  160. * @access public
  161. * @category Error Returns
  162. * @return string #Not Yet Implemented
  163. */
  164. public static function DUMMY() {
  165. return '#Not Yet Implemented';
  166. } // function DUMMY()
  167. /**
  168. * DIV0
  169. *
  170. * @access public
  171. * @category Error Returns
  172. * @return string #Not Yet Implemented
  173. */
  174. public static function DIV0() {
  175. return self::$_errorCodes['divisionbyzero'];
  176. } // function DIV0()
  177. /**
  178. * NA
  179. *
  180. * Excel Function:
  181. * =NA()
  182. *
  183. * Returns the error value #N/A
  184. * #N/A is the error value that means "no value is available."
  185. *
  186. * @access public
  187. * @category Logical Functions
  188. * @return string #N/A!
  189. */
  190. public static function NA() {
  191. return self::$_errorCodes['na'];
  192. } // function NA()
  193. /**
  194. * NaN
  195. *
  196. * Returns the error value #NUM!
  197. *
  198. * @access public
  199. * @category Error Returns
  200. * @return string #NUM!
  201. */
  202. public static function NaN() {
  203. return self::$_errorCodes['num'];
  204. } // function NaN()
  205. /**
  206. * NAME
  207. *
  208. * Returns the error value #NAME?
  209. *
  210. * @access public
  211. * @category Error Returns
  212. * @return string #NAME?
  213. */
  214. public static function NAME() {
  215. return self::$_errorCodes['name'];
  216. } // function NAME()
  217. /**
  218. * REF
  219. *
  220. * Returns the error value #REF!
  221. *
  222. * @access public
  223. * @category Error Returns
  224. * @return string #REF!
  225. */
  226. public static function REF() {
  227. return self::$_errorCodes['reference'];
  228. } // function REF()
  229. /**
  230. * NULL
  231. *
  232. * Returns the error value #NULL!
  233. *
  234. * @access public
  235. * @category Error Returns
  236. * @return string #REF!
  237. */
  238. public static function NULL() {
  239. return self::$_errorCodes['null'];
  240. } // function NULL()
  241. /**
  242. * VALUE
  243. *
  244. * Returns the error value #VALUE!
  245. *
  246. * @access public
  247. * @category Error Returns
  248. * @return string #VALUE!
  249. */
  250. public static function VALUE() {
  251. return self::$_errorCodes['value'];
  252. } // function VALUE()
  253. public static function isMatrixValue($idx) {
  254. return ((substr_count($idx,'.') <= 1) || (preg_match('/\.[A-Z]/',$idx) > 0));
  255. }
  256. public static function isValue($idx) {
  257. return (substr_count($idx,'.') == 0);
  258. }
  259. public static function isCellValue($idx) {
  260. return (substr_count($idx,'.') > 1);
  261. }
  262. public static function _ifCondition($condition) {
  263. $condition = PHPExcel_Calculation_Functions::flattenSingleValue($condition);
  264. if (!in_array($condition{0},array('>', '<', '='))) {
  265. if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::_wrapResult(strtoupper($condition)); }
  266. return '='.$condition;
  267. } else {
  268. preg_match('/([<>=]+)(.*)/',$condition,$matches);
  269. list(,$operator,$operand) = $matches;
  270. if (!is_numeric($operand)) { $operand = PHPExcel_Calculation::_wrapResult(strtoupper($operand)); }
  271. return $operator.$operand;
  272. }
  273. } // function _ifCondition()
  274. /**
  275. * ERROR_TYPE
  276. *
  277. * @param mixed $value Value to check
  278. * @return boolean
  279. */
  280. public static function ERROR_TYPE($value = '') {
  281. $value = self::flattenSingleValue($value);
  282. $i = 1;
  283. foreach(self::$_errorCodes as $errorCode) {
  284. if ($value === $errorCode) {
  285. return $i;
  286. }
  287. ++$i;
  288. }
  289. return self::NA();
  290. } // function ERROR_TYPE()
  291. /**
  292. * IS_BLANK
  293. *
  294. * @param mixed $value Value to check
  295. * @return boolean
  296. */
  297. public static function IS_BLANK($value = NULL) {
  298. if (!is_null($value)) {
  299. $value = self::flattenSingleValue($value);
  300. }
  301. return is_null($value);
  302. } // function IS_BLANK()
  303. /**
  304. * IS_ERR
  305. *
  306. * @param mixed $value Value to check
  307. * @return boolean
  308. */
  309. public static function IS_ERR($value = '') {
  310. $value = self::flattenSingleValue($value);
  311. return self::IS_ERROR($value) && (!self::IS_NA($value));
  312. } // function IS_ERR()
  313. /**
  314. * IS_ERROR
  315. *
  316. * @param mixed $value Value to check
  317. * @return boolean
  318. */
  319. public static function IS_ERROR($value = '') {
  320. $value = self::flattenSingleValue($value);
  321. if (!is_string($value))
  322. return false;
  323. return in_array($value, array_values(self::$_errorCodes));
  324. } // function IS_ERROR()
  325. /**
  326. * IS_NA
  327. *
  328. * @param mixed $value Value to check
  329. * @return boolean
  330. */
  331. public static function IS_NA($value = '') {
  332. $value = self::flattenSingleValue($value);
  333. return ($value === self::NA());
  334. } // function IS_NA()
  335. /**
  336. * IS_EVEN
  337. *
  338. * @param mixed $value Value to check
  339. * @return boolean
  340. */
  341. public static function IS_EVEN($value = NULL) {
  342. $value = self::flattenSingleValue($value);
  343. if ($value === NULL)
  344. return self::NAME();
  345. if ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value))))
  346. return self::VALUE();
  347. return ($value % 2 == 0);
  348. } // function IS_EVEN()
  349. /**
  350. * IS_ODD
  351. *
  352. * @param mixed $value Value to check
  353. * @return boolean
  354. */
  355. public static function IS_ODD($value = NULL) {
  356. $value = self::flattenSingleValue($value);
  357. if ($value === NULL)
  358. return self::NAME();
  359. if ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value))))
  360. return self::VALUE();
  361. return (abs($value) % 2 == 1);
  362. } // function IS_ODD()
  363. /**
  364. * IS_NUMBER
  365. *
  366. * @param mixed $value Value to check
  367. * @return boolean
  368. */
  369. public static function IS_NUMBER($value = NULL) {
  370. $value = self::flattenSingleValue($value);
  371. if (is_string($value)) {
  372. return False;
  373. }
  374. return is_numeric($value);
  375. } // function IS_NUMBER()
  376. /**
  377. * IS_LOGICAL
  378. *
  379. * @param mixed $value Value to check
  380. * @return boolean
  381. */
  382. public static function IS_LOGICAL($value = NULL) {
  383. $value = self::flattenSingleValue($value);
  384. return is_bool($value);
  385. } // function IS_LOGICAL()
  386. /**
  387. * IS_TEXT
  388. *
  389. * @param mixed $value Value to check
  390. * @return boolean
  391. */
  392. public static function IS_TEXT($value = NULL) {
  393. $value = self::flattenSingleValue($value);
  394. return (is_string($value) && !self::IS_ERROR($value));
  395. } // function IS_TEXT()
  396. /**
  397. * IS_NONTEXT
  398. *
  399. * @param mixed $value Value to check
  400. * @return boolean
  401. */
  402. public static function IS_NONTEXT($value = NULL) {
  403. return !self::IS_TEXT($value);
  404. } // function IS_NONTEXT()
  405. /**
  406. * VERSION
  407. *
  408. * @return string Version information
  409. */
  410. public static function VERSION() {
  411. return 'PHPExcel 1.7.7, 2012-05-19';
  412. } // function VERSION()
  413. /**
  414. * N
  415. *
  416. * Returns a value converted to a number
  417. *
  418. * @param value The value you want converted
  419. * @return number N converts values listed in the following table
  420. * If value is or refers to N returns
  421. * A number That number
  422. * A date The serial number of that date
  423. * TRUE 1
  424. * FALSE 0
  425. * An error value The error value
  426. * Anything else 0
  427. */
  428. public static function N($value = NULL) {
  429. while (is_array($value)) {
  430. $value = array_shift($value);
  431. }
  432. switch (gettype($value)) {
  433. case 'double' :
  434. case 'float' :
  435. case 'integer' :
  436. return $value;
  437. break;
  438. case 'boolean' :
  439. return (integer) $value;
  440. break;
  441. case 'string' :
  442. // Errors
  443. if ((strlen($value) > 0) && ($value{0} == '#')) {
  444. return $value;
  445. }
  446. break;
  447. }
  448. return 0;
  449. } // function N()
  450. /**
  451. * TYPE
  452. *
  453. * Returns a number that identifies the type of a value
  454. *
  455. * @param value The value you want tested
  456. * @return number N converts values listed in the following table
  457. * If value is or refers to N returns
  458. * A number 1
  459. * Text 2
  460. * Logical Value 4
  461. * An error value 16
  462. * Array or Matrix 64
  463. */
  464. public static function TYPE($value = NULL) {
  465. $value = self::flattenArrayIndexed($value);
  466. if (is_array($value) && (count($value) > 1)) {
  467. $a = array_keys($value);
  468. $a = array_pop($a);
  469. // Range of cells is an error
  470. if (self::isCellValue($a)) {
  471. return 16;
  472. // Test for Matrix
  473. } elseif (self::isMatrixValue($a)) {
  474. return 64;
  475. }
  476. } elseif(empty($value)) {
  477. // Empty Cell
  478. return 1;
  479. }
  480. $value = self::flattenSingleValue($value);
  481. if (($value === NULL) || (is_float($value)) || (is_int($value))) {
  482. return 1;
  483. } elseif(is_bool($value)) {
  484. return 4;
  485. } elseif(is_array($value)) {
  486. return 64;
  487. break;
  488. } elseif(is_string($value)) {
  489. // Errors
  490. if ((strlen($value) > 0) && ($value{0} == '#')) {
  491. return 16;
  492. }
  493. return 2;
  494. }
  495. return 0;
  496. } // function TYPE()
  497. /**
  498. * Convert a multi-dimensional array to a simple 1-dimensional array
  499. *
  500. * @param array $array Array to be flattened
  501. * @return array Flattened array
  502. */
  503. public static function flattenArray($array) {
  504. if (!is_array($array)) {
  505. return (array) $array;
  506. }
  507. $arrayValues = array();
  508. foreach ($array as $value) {
  509. if (is_array($value)) {
  510. foreach ($value as $val) {
  511. if (is_array($val)) {
  512. foreach ($val as $v) {
  513. $arrayValues[] = $v;
  514. }
  515. } else {
  516. $arrayValues[] = $val;
  517. }
  518. }
  519. } else {
  520. $arrayValues[] = $value;
  521. }
  522. }
  523. return $arrayValues;
  524. } // function flattenArray()
  525. /**
  526. * Convert a multi-dimensional array to a simple 1-dimensional array, but retain an element of indexing
  527. *
  528. * @param array $array Array to be flattened
  529. * @return array Flattened array
  530. */
  531. public static function flattenArrayIndexed($array) {
  532. if (!is_array($array)) {
  533. return (array) $array;
  534. }
  535. $arrayValues = array();
  536. foreach ($array as $k1 => $value) {
  537. if (is_array($value)) {
  538. foreach ($value as $k2 => $val) {
  539. if (is_array($val)) {
  540. foreach ($val as $k3 => $v) {
  541. $arrayValues[$k1.'.'.$k2.'.'.$k3] = $v;
  542. }
  543. } else {
  544. $arrayValues[$k1.'.'.$k2] = $val;
  545. }
  546. }
  547. } else {
  548. $arrayValues[$k1] = $value;
  549. }
  550. }
  551. return $arrayValues;
  552. } // function flattenArrayIndexed()
  553. /**
  554. * Convert an array to a single scalar value by extracting the first element
  555. *
  556. * @param mixed $value Array or scalar value
  557. * @return mixed
  558. */
  559. public static function flattenSingleValue($value = '') {
  560. while (is_array($value)) {
  561. $value = array_pop($value);
  562. }
  563. return $value;
  564. } // function flattenSingleValue()
  565. } // class PHPExcel_Calculation_Functions
  566. //
  567. // There are a few mathematical functions that aren't available on all versions of PHP for all platforms
  568. // These functions aren't available in Windows implementations of PHP prior to version 5.3.0
  569. // So we test if they do exist for this version of PHP/operating platform; and if not we create them
  570. //
  571. if (!function_exists('acosh')) {
  572. function acosh($x) {
  573. return 2 * log(sqrt(($x + 1) / 2) + sqrt(($x - 1) / 2));
  574. } // function acosh()
  575. }
  576. if (!function_exists('asinh')) {
  577. function asinh($x) {
  578. return log($x + sqrt(1 + $x * $x));
  579. } // function asinh()
  580. }
  581. if (!function_exists('atanh')) {
  582. function atanh($x) {
  583. return (log(1 + $x) - log(1 - $x)) / 2;
  584. } // function atanh()
  585. }
  586. if (!function_exists('money_format')) {
  587. function money_format($format, $number) {
  588. $regex = array( '/%((?:[\^!\-]|\+|\(|\=.)*)([0-9]+)?(?:#([0-9]+))?',
  589. '(?:\.([0-9]+))?([in%])/'
  590. );
  591. $regex = implode('', $regex);
  592. if (setlocale(LC_MONETARY, null) == '') {
  593. setlocale(LC_MONETARY, '');
  594. }
  595. $locale = localeconv();
  596. $number = floatval($number);
  597. if (!preg_match($regex, $format, $fmatch)) {
  598. trigger_error("No format specified or invalid format", E_USER_WARNING);
  599. return $number;
  600. }
  601. $flags = array( 'fillchar' => preg_match('/\=(.)/', $fmatch[1], $match) ? $match[1] : ' ',
  602. 'nogroup' => preg_match('/\^/', $fmatch[1]) > 0,
  603. 'usesignal' => preg_match('/\+|\(/', $fmatch[1], $match) ? $match[0] : '+',
  604. 'nosimbol' => preg_match('/\!/', $fmatch[1]) > 0,
  605. 'isleft' => preg_match('/\-/', $fmatch[1]) > 0
  606. );
  607. $width = trim($fmatch[2]) ? (int)$fmatch[2] : 0;
  608. $left = trim($fmatch[3]) ? (int)$fmatch[3] : 0;
  609. $right = trim($fmatch[4]) ? (int)$fmatch[4] : $locale['int_frac_digits'];
  610. $conversion = $fmatch[5];
  611. $positive = true;
  612. if ($number < 0) {
  613. $positive = false;
  614. $number *= -1;
  615. }
  616. $letter = $positive ? 'p' : 'n';
  617. $prefix = $suffix = $cprefix = $csuffix = $signal = '';
  618. if (!$positive) {
  619. $signal = $locale['negative_sign'];
  620. switch (true) {
  621. case $locale['n_sign_posn'] == 0 || $flags['usesignal'] == '(':
  622. $prefix = '(';
  623. $suffix = ')';
  624. break;
  625. case $locale['n_sign_posn'] == 1:
  626. $prefix = $signal;
  627. break;
  628. case $locale['n_sign_posn'] == 2:
  629. $suffix = $signal;
  630. break;
  631. case $locale['n_sign_posn'] == 3:
  632. $cprefix = $signal;
  633. break;
  634. case $locale['n_sign_posn'] == 4:
  635. $csuffix = $signal;
  636. break;
  637. }
  638. }
  639. if (!$flags['nosimbol']) {
  640. $currency = $cprefix;
  641. $currency .= ($conversion == 'i' ? $locale['int_curr_symbol'] : $locale['currency_symbol']);
  642. $currency .= $csuffix;
  643. $currency = iconv('ISO-8859-1','UTF-8',$currency);
  644. } else {
  645. $currency = '';
  646. }
  647. $space = $locale["{$letter}_sep_by_space"] ? ' ' : '';
  648. if (!isset($locale['mon_decimal_point']) || empty($locale['mon_decimal_point'])) {
  649. $locale['mon_decimal_point'] = (!isset($locale['decimal_point']) || empty($locale['decimal_point'])) ?
  650. $locale['decimal_point'] :
  651. '.';
  652. }
  653. $number = number_format($number, $right, $locale['mon_decimal_point'], $flags['nogroup'] ? '' : $locale['mon_thousands_sep'] );
  654. $number = explode($locale['mon_decimal_point'], $number);
  655. $n = strlen($prefix) + strlen($currency);
  656. if ($left > 0 && $left > $n) {
  657. if ($flags['isleft']) {
  658. $number[0] .= str_repeat($flags['fillchar'], $left - $n);
  659. } else {
  660. $number[0] = str_repeat($flags['fillchar'], $left - $n) . $number[0];
  661. }
  662. }
  663. $number = implode($locale['mon_decimal_point'], $number);
  664. if ($locale["{$letter}_cs_precedes"]) {
  665. $number = $prefix . $currency . $space . $number . $suffix;
  666. } else {
  667. $number = $prefix . $number . $space . $currency . $suffix;
  668. }
  669. if ($width > 0) {
  670. $number = str_pad($number, $width, $flags['fillchar'], $flags['isleft'] ? STR_PAD_RIGHT : STR_PAD_LEFT);
  671. }
  672. $format = str_replace($fmatch[0], $number, $format);
  673. return $format;
  674. } // function money_format()
  675. }
  676. //
  677. // Strangely, PHP doesn't have a mb_str_replace multibyte function
  678. // As we'll only ever use this function with UTF-8 characters, we can simply "hard-code" the character set
  679. //
  680. if ((!function_exists('mb_str_replace')) &&
  681. (function_exists('mb_substr')) && (function_exists('mb_strlen')) && (function_exists('mb_strpos'))) {
  682. function mb_str_replace($search, $replace, $subject) {
  683. if(is_array($subject)) {
  684. $ret = array();
  685. foreach($subject as $key => $val) {
  686. $ret[$key] = mb_str_replace($search, $replace, $val);
  687. }
  688. return $ret;
  689. }
  690. foreach((array) $search as $key => $s) {
  691. if($s == '') {
  692. continue;
  693. }
  694. $r = !is_array($replace) ? $replace : (array_key_exists($key, $replace) ? $replace[$key] : '');
  695. $pos = mb_strpos($subject, $s, 0, 'UTF-8');
  696. while($pos !== false) {
  697. $subject = mb_substr($subject, 0, $pos, 'UTF-8') . $r . mb_substr($subject, $pos + mb_strlen($s, 'UTF-8'), 65535, 'UTF-8');
  698. $pos = mb_strpos($subject, $s, $pos + mb_strlen($r, 'UTF-8'), 'UTF-8');
  699. }
  700. }
  701. return $subject;
  702. }
  703. }