protected static function getDecimalParseRegex(AgaviLocale $locale = null) { static $patternCache = array(); if ($locale) { $localeId = $locale->getIdentifier(); } else { $localeId = ''; } if (isset($patternCache[$localeId])) { return $patternCache[$localeId]; } if ($locale) { $decimalFormats = $locale->getDecimalFormats(); $groupingSeparator = $locale->getNumberSymbolGroup(); $decimalSeparator = $locale->getNumberSymbolDecimal(); $minusSign = $locale->getNumberSymbolMinusSign(); } else { $decimalFormats = array('#,##0.###'); $groupingSeparator = ','; $decimalSeparator = '.'; $minusSign = '-'; } $patterns = array(); foreach ($decimalFormats as $decimalFormatList) { $decimalFormatList = explode(';', $decimalFormatList, 2); if (count($decimalFormatList) == 1) { // no pattern for negative numbers // we need a copy of the format with a minus prefix $decimalFormatList[1] = '-' . $decimalFormatList[0]; } foreach (array(true, false) as $withFraction) { foreach ($decimalFormatList as $decimalFormat) { // we need to make three parts: number, decimal part and minus sign $decimalFormatChunks = preg_split('/([\\.\\-])/', $decimalFormat, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); // there is a minus sign at the beginning or end! find it! $pastDecimalSeparator = false; foreach ($decimalFormatChunks as &$decimalFormatChunk) { if ($decimalFormatChunk == '-') { // always allow "-" in addition to the minus sign supplied by the locale. we do this because some locales (e.g. da, fa, se, sv) have U+2212 (the "real" minus sign) defined in the locale data, but no human can really type that character on their keyboard. consider it lenient parsing ;) see ticket #1293 $decimalFormatChunk = '(?P<minus>' . preg_quote($minusSign, '#') . '|-)'; } elseif ($decimalFormatChunk == '.') { $pastDecimalSeparator = true; if ($withFraction) { $decimalFormatChunk = preg_quote($decimalSeparator, '#'); } else { $decimalFormatChunk = ''; } } else { $decimalFormatChunk = preg_replace('/[#0,]+/u', '[\\d' . preg_quote($groupingSeparator, '#') . ']*', $decimalFormatChunk); if (!$pastDecimalSeparator) { if ($withFraction) { $decimalFormatChunk = '(?P<num>(?=[\\d,]*\\d)' . $decimalFormatChunk . '(\\d|' . $decimalFormatChunk . '(?=\\.[\\d,]*\\d)))?'; } else { $decimalFormatChunk = '(?P<num>(?=[\\d,]*\\d)' . $decimalFormatChunk . '\\d)'; } } else { if ($withFraction) { $decimalFormatChunk = '(?P<dec>' . $decimalFormatChunk . '\\d)?'; } else { $decimalFormatChunk = ''; } } } } $patterns[] = implode('', $decimalFormatChunks); } } } return $patternCache[$localeId] = '#(?J)^(' . implode('|', $patterns) . ')#u'; }