Development

/branches/1.1/lib/i18n/sfNumberFormatInfo.class.php

You must first sign up to be able to contribute.

root/branches/1.1/lib/i18n/sfNumberFormatInfo.class.php

Revision 11700, 17.2 kB (checked in by fabien, 6 years ago)

[1.1, 1.2] changed internal classes to always use the sfCultureInfo singleton

  • Property svn:mime-type set to text/x-php
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Rev Date
Line 
1 <?php
2
3 /**
4  * sfNumberFormatInfo class file.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the BSD License.
8  *
9  * Copyright(c) 2004 by Qiang Xue. All rights reserved.
10  *
11  * To contact the author write to {@link mailto:qiang.xue@gmail.com Qiang Xue}
12  * The latest version of PRADO can be obtained from:
13  * {@link http://prado.sourceforge.net/}
14  *
15  * @author     Wei Zhuo <weizhuo[at]gmail[dot]com>
16  * @version    $Id$
17  * @package    symfony
18  * @subpackage i18n
19  */
20  
21 /**
22  * sfNumberFormatInfo class
23  *
24  * Defines how numeric values are formatted and displayed,
25  * depending on the culture. Numeric values are formatted using
26  * standard or custom patterns stored in the properties of a
27  * sfNumberFormatInfo.
28  *
29  * This class contains information, such as currency, decimal
30  * separators, and other numeric symbols.
31  *
32  * To create a sfNumberFormatInfo for a specific culture,
33  * create a sfCultureInfo for that culture and retrieve the
34  * sfCultureInfo->NumberFormat property. Or use
35  * sfNumberFormatInfo::getInstance($culture).
36  * To create a sfNumberFormatInfo for the invariant culture, use the
37  * InvariantInfo::getInvariantInfo().
38  *
39  *
40  * @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com>
41  * @version v1.0, last update on Sun Dec 05 14:48:26 EST 2004
42  * @package    symfony
43  * @subpackage i18n
44  */
45 class sfNumberFormatInfo
46 {
47   /**
48    * ICU number formatting data.
49    * @var array
50    */
51   protected $data = array();
52
53   /**
54    * A list of properties that are accessable/writable.
55    * @var array
56    */
57   protected $properties = array();
58
59   /**
60    * The number pattern.
61    * @var array
62    */
63   protected $pattern = array();
64
65   const DECIMAL = 0;
66   const CURRENCY = 1;
67   const PERCENTAGE = 2;
68   const SCIENTIFIC = 3;
69
70   /**
71    * Allows functions that begins with 'set' to be called directly
72    * as an attribute/property to retrieve the value.
73    *
74    * @return mixed
75    */
76   function __get($name)
77   {
78     $getProperty = 'get'.$name;
79     if (in_array($getProperty, $this->properties))
80     {
81       return $this->$getProperty();
82     }
83     else
84     {
85       throw new sfException(sprintf('Property %s does not exists.', $name));
86     }
87   }
88
89   /**
90    * Allows functions that begins with 'set' to be called directly
91    * as an attribute/property to set the value.
92    */
93   function __set($name, $value)
94   {
95     $setProperty = 'set'.$name;
96     if (in_array($setProperty, $this->properties))
97     {
98       $this->$setProperty($value);
99     }
100     else
101     {
102       throw new sfException(sprintf('Property %s can not be set.', $name));
103     }
104   }
105
106   /**
107    * Initializes a new writable instance of the sfNumberFormatInfo class
108    * that is dependent on the ICU data for number, decimal, and currency
109    * formatting information. <b>N.B.</b>You should not initialize this
110    * class directly unless you know what you are doing. Please use use
111    * sfNumberFormatInfo::getInstance() to create an instance.
112    *
113    * @param array $data ICU data for date time formatting.
114    * @param int   $type The sfNumberFormatInfo type
115    * @see getInstance()
116    */
117   function __construct($data = array(), $type = sfNumberFormatInfo::DECIMAL)
118   {
119     $this->properties = get_class_methods($this);
120
121     if (empty($data))
122     {
123       throw new sfException('Please provide the ICU data to initialize.');
124     }
125
126     $this->data = $data;
127
128     $this->setPattern($type);
129   }
130
131   /**
132    * Sets the pattern for a specific number pattern. The validate patterns
133    * sfNumberFormatInfo::DECIMAL, sfNumberFormatInfo::CURRENCY,
134    * sfNumberFormatInfo::PERCENTAGE, or sfNumberFormatInfo::SCIENTIFIC
135    *
136    * @param int $type pattern type.
137    */
138   function setPattern($type = sfNumberFormatInfo::DECIMAL)
139   {
140     if (is_int($type))
141     {
142       $this->pattern = $this->parsePattern($this->data['NumberPatterns'][$type]);
143     }
144     else
145     {
146       $this->pattern = $this->parsePattern($type);
147     }
148
149     $this->pattern['negInfty'] = $this->data['NumberElements'][6].$this->data['NumberElements'][9];
150
151     $this->pattern['posInfty'] = $this->data['NumberElements'][11].$this->data['NumberElements'][9];
152   }
153
154   function getPattern()
155   {
156     return $this->pattern;
157   }
158
159   /**
160    * Gets the default sfNumberFormatInfo that is culture-independent (invariant).
161    *
162    * @return sfNumberFormatInfo default sfNumberFormatInfo.
163    */
164   static public function getInvariantInfo($type = sfNumberFormatInfo::DECIMAL)
165   {
166     static $invariant;
167     if (is_null($invariant))
168     {
169       $culture = sfCultureInfo::getInvariantCulture();
170       $invariant = $culture->NumberFormat;
171       $invariant->setPattern($type);
172     }
173
174     return $invariant;
175   }
176
177   /**
178    * Returns the sfNumberFormatInfo associated with the specified culture.
179    *
180    * @param sfCultureInfo $culture  the culture that gets the sfNumberFormat property.
181    * @param int           $type     the number formatting type, it should be
182    * sfNumberFormatInfo::DECIMAL, sfNumberFormatInfo::CURRENCY,
183    * sfNumberFormatInfo::PERCENTAGE, or sfNumberFormatInfo::SCIENTIFIC
184    * @return sfNumberFormatInfo sfNumberFormatInfo for the specified culture.
185    * @see getCurrencyInstance();
186    * @see getPercentageInstance();
187    * @see getScientificInstance();
188    */
189   public static function getInstance($culture = null, $type = sfNumberFormatInfo::DECIMAL)
190   {
191     if ($culture instanceof sfCultureInfo)
192     {
193       $formatInfo = $culture->getNumberFormat();
194       $formatInfo->setPattern($type);
195
196       return $formatInfo;
197     }
198     else if (is_string($culture))
199     {
200       $sfCultureInfo = sfCultureInfo::getInstance($culture);
201       $formatInfo = $sfCultureInfo->getNumberFormat();
202       $formatInfo->setPattern($type);
203
204       return $formatInfo;
205     }
206     else
207     {
208       $sfCultureInfo = sfCultureInfo::getInstance();
209       $formatInfo = $sfCultureInfo->getNumberFormat();
210       $formatInfo->setPattern($type);
211
212       return $formatInfo;
213     }
214   }
215
216   /**
217    * Returns the currency format info associated with the specified culture.
218    *
219    * @param sfCultureInfo $culture the culture that gets the NumberFormat property.
220    * @return sfNumberFormatInfo sfNumberFormatInfo for the specified culture.
221    */
222   public static function getCurrencyInstance($culture = null)
223   {
224     return self::getInstance($culture, self::CURRENCY);
225   }
226
227   /**
228    * Returns the percentage format info associated with the specified culture.
229    *
230    * @param sfCultureInfo $culture the culture that gets the NumberFormat property.
231    * @return sfNumberFormatInfo sfNumberFormatInfo for the specified culture.
232    */
233   public static function getPercentageInstance($culture = null)
234   {
235     return self::getInstance($culture, self::PERCENTAGE);
236   }
237
238   /**
239    * Returns the scientific format info associated with the specified culture.
240    *
241    * @param sfCultureInfo $culture the culture that gets the NumberFormat property.
242    * @return sfNumberFormatInfo sfNumberFormatInfo for the specified culture.
243    */
244   public static function getScientificInstance($culture = null)
245   {
246     return self::getInstance($culture, self::SCIENTIFIC);
247   }
248
249   /**
250    * Parses the given pattern and return a list of known properties.
251    *
252    * @param string $pattern a number pattern.
253    * @return array list of pattern properties.
254    */
255   protected function parsePattern($pattern)
256   {
257     $pattern = explode(';', $pattern);
258
259     $negative = null;
260     if (count($pattern) > 1)
261     {
262       $negative = $pattern[1];
263     }
264     $pattern = $pattern[0];
265
266     $comma = ',';
267     $dot = '.';
268     $digit = '0';
269     $hash = '#';
270
271     // find the first group point, and decimal point
272     $groupPos1 = strrpos($pattern, $comma);
273     $decimalPos = strrpos($pattern, $dot);
274
275     $groupPos2 = false;
276     $groupSize1 = false;
277     $groupSize2 = false;
278     $decimalPoints = is_int($decimalPos) ? -1 : false;
279
280     $info['negPref'] = $this->data['NumberElements'][6];
281     $info['negPost'] = '';
282
283     $info['negative'] = $negative;
284     $info['positive'] = $pattern;
285
286     // find the negative prefix and postfix
287     if ($negative)
288     {
289       $prefixPostfix = $this->getPrePostfix($negative);
290       $info['negPref'] = $prefixPostfix[0];
291       $info['negPost'] = $prefixPostfix[1];
292     }
293
294     $posfix = $this->getPrePostfix($pattern);
295     $info['posPref'] = $posfix[0];
296     $info['posPost'] = $posfix[1];
297
298     if (is_int($groupPos1))
299     {
300       // get the second group
301       $groupPos2 = strrpos(substr($pattern, 0, $groupPos1), $comma);
302
303       // get the number of decimal digits
304       if (is_int($decimalPos))
305       {
306         $groupSize1 = $decimalPos - $groupPos1 - 1;
307       }
308       else
309       {
310         // no decimal point, so traverse from the back
311         // to find the groupsize 1.
312         for ($i = strlen($pattern) - 1; $i >= 0; $i--)
313         {
314           if ($pattern{$i} == $digit || $pattern{$i} == $hash)
315           {
316             $groupSize1 = $i - $groupPos1;
317             break;
318           }
319         }
320       }
321
322       // get the second group size
323       if (is_int($groupPos2))
324       {
325         $groupSize2 = $groupPos1 - $groupPos2 - 1;
326       }
327     }
328
329     if (is_int($decimalPos))
330     {
331       for ($i = strlen($pattern) - 1; $i >= 0; $i--)
332       {
333         if ($pattern{$i} == $dot)
334         {
335           break;
336         }
337         if ($pattern{$i} == $digit)
338         {
339           $decimalPoints = $i - $decimalPos;
340           break;
341         }
342       }
343     }
344
345     $digitPattern = is_int($decimalPos) ? substr($pattern, 0, $decimalPos) : $pattern;
346     $digitPattern  = preg_replace('/[^0]/', '', $digitPattern);
347
348     $info['groupPos1']     = $groupPos1;
349     $info['groupSize1']    = $groupSize1;
350     $info['groupPos2']     = $groupPos2;
351     $info['groupSize2']    = $groupSize2;
352     $info['decimalPos']    = $decimalPos;
353     $info['decimalPoints'] = $decimalPoints;
354     $info['digitSize']     = strlen($digitPattern);
355
356     return $info;
357   }
358
359   /**
360    * Gets the prefix and postfix of a pattern.
361    *
362    * @param string $pattern pattern
363    * @return array of prefix and postfix, array(prefix,postfix).
364    */
365   protected function getPrePostfix($pattern)
366   {
367     $regexp = '/[#,\.0]+/';
368     $result = preg_split($regexp, $pattern);
369
370     return array($result[0], $result[1]);
371   }
372
373   /**
374    * Indicates the number of decimal places.
375    *
376    * @return int number of decimal places.
377    */
378   function getDecimalDigits()
379   {
380     return $this->pattern['decimalPoints'];
381   }
382
383   /**
384    * Sets the number of decimal places.
385    *
386    * @param int $value number of decimal places.
387    */
388   function setDecimalDigits($value)
389   {
390     return $this->pattern['decimalPoints'] = $value;
391   }
392
393   /**
394    * Indicates the digit size.
395    *
396    * @return int digit size.
397    */
398   function getDigitSize()
399   {
400     return $this->pattern['digitSize'];
401   }
402
403   /**
404    * Sets the digit size.
405    *
406    * @param int $value digit size.
407    */
408   function setDigitSize($value)
409   {
410     $this->pattern['digitSize'] = $value;
411   }
412
413   /**
414    * Gets the string to use as the decimal separator.
415    *
416    * @return string decimal separator.
417    */
418   function getDecimalSeparator()
419   {
420     return $this->data['NumberElements'][0];
421   }
422
423   /**
424    * Sets the string to use as the decimal separator.
425    *
426    * @param string $value the decimal point
427    */
428   function setDecimalSeparator($value)
429   {
430     return $this->data['NumberElements'][0] = $value;
431   }
432
433   /**
434    * Gets the string that separates groups of digits to the left
435    * of the decimal in currency values.
436    *
437    * @return string currency group separator.
438    */
439   function getGroupSeparator()
440   {
441     return $this->data['NumberElements'][1];
442   }
443
444   /**
445    * Sets the string to use as the group separator.
446    *
447    * @param string $value the group separator.
448    */
449   function setGroupSeparator($value)
450   {
451     return $this->data['NumberElements'][1] = $value;
452   }
453
454   /**
455    * Gets the number of digits in each group to the left of the decimal
456    * There can be two grouping sizes, this fucntion
457    * returns <b>array(group1, group2)</b>, if there is only 1 grouping size,
458    * group2 will be false.
459    *
460    * @return array grouping size(s).
461    */
462   function getGroupSizes()
463   {
464     $group1 = $this->pattern['groupSize1'];
465     $group2 = $this->pattern['groupSize2'];
466
467     return array($group1, $group2);
468   }
469
470   /**
471    * Sets the number of digits in each group to the left of the decimal.
472    * There can be two grouping sizes, the value should
473    * be an <b>array(group1, group2)</b>, if there is only 1 grouping size,
474    * group2 should be false.
475    *
476    * @param array $groupSize grouping size(s).
477    */
478   function setGroupSizes($groupSize)
479   {
480     $this->pattern['groupSize1'] = $groupSize[0];
481     $this->pattern['groupSize2'] = $groupSize[1];
482   }
483
484   /**
485    * Gets the format pattern for negative values.
486    * The negative pattern is composed of a prefix, and postfix.
487    * This function returns <b>array(prefix, postfix)</b>.
488    *
489    * @return arary negative pattern.
490    */
491   function getNegativePattern()
492   {
493     $prefix = $this->pattern['negPref'];
494     $postfix = $this->pattern['negPost'];
495
496     return array($prefix, $postfix);
497   }
498
499   /**
500    * Sets the format pattern for negative values.
501    * The negative pattern is composed of a prefix, and postfix in the form
502    * <b>array(prefix, postfix)</b>.
503    *
504    * @param arary $pattern negative pattern.
505    */
506   function setNegativePattern($pattern)
507   {
508     $this->pattern['negPref'] = $pattern[0];
509     $this->pattern['negPost'] = $pattern[1];
510   }
511
512   /**
513    * Gets the format pattern for positive values.
514    * The positive pattern is composed of a prefix, and postfix.
515    * This function returns <b>array(prefix, postfix)</b>.
516    *
517    * @return arary positive pattern.
518    */
519   function getPositivePattern()
520   {
521     $prefix = $this->pattern['posPref'];
522     $postfix = $this->pattern['posPost'];
523
524     return array($prefix, $postfix);
525   }
526
527   /**
528    * Sets the format pattern for positive values.
529    * The positive pattern is composed of a prefix, and postfix in the form
530    * <b>array(prefix, postfix)</b>.
531    *
532    * @param arary $pattern positive pattern.
533    */
534   function setPositivePattern($pattern)
535   {
536     $this->pattern['posPref'] = $pattern[0];
537     $this->pattern['posPost'] = $pattern[1];
538   }
539
540   /**
541    * Gets the string to use as the currency symbol.
542    *
543    * @return string $currency currency symbol.
544    */
545   function getCurrencySymbol($currency = 'USD')
546   {
547     if (isset($this->pattern['symbol']))
548     {
549       return $this->pattern['symbol'];
550     }
551     else
552     {
553       return $this->data['Currencies'][$currency][0];
554     }
555   }
556
557   /**
558    * Sets the string to use as the currency symbol.
559    *
560    * @param string $symbol currency symbol.
561    */
562   function setCurrencySymbol($symbol)
563   {
564     $this->pattern['symbol'] = $symbol;
565   }
566
567   /**
568    * Gets the string that represents negative infinity.
569    *
570    * @return string negative infinity.
571    */
572   function getNegativeInfinitySymbol()
573   {
574     return $this->pattern['negInfty'];
575   }
576
577   /**
578    * Sets the string that represents negative infinity.
579    *
580    * @param string $value negative infinity.
581    */
582   function setNegativeInfinitySymbol($value)
583   {
584     $this->pattern['negInfty'] = $value;
585   }
586
587   /**
588    * Gets the string that represents positive infinity.
589    *
590    * @return string positive infinity.
591    */
592   function getPositiveInfinitySymbol()
593   {
594     return $this->pattern['posInfty'];
595   }
596
597   /**
598    * Sets the string that represents positive infinity.
599    *
600    * @param string $value positive infinity.
601    */
602   function setPositiveInfinitySymbol($value)
603   {
604     $this->pattern['posInfty'] = $value;
605   }
606
607   /**
608    * Gets the string that denotes that the associated number is negative.
609    *
610    * @return string negative sign.
611    */
612   function getNegativeSign()
613   {
614     return $this->data['NumberElements'][6];
615   }
616
617   /**
618    * Sets the string that denotes that the associated number is negative.
619    *
620    * @param string $value negative sign.
621    */
622   function setNegativeSign($value)
623   {
624     $this->data['NumberElements'][6] = $value;
625   }
626
627   /**
628    * Gets the string that denotes that the associated number is positive.
629    *
630    * @return string positive sign.
631    */
632   function getPositiveSign()
633   {
634     return $this->data['NumberElements'][11];
635   }
636
637   /**
638    * Sets the string that denotes that the associated number is positive.
639    *
640    * @param string $value positive sign.
641    */
642   function setPositiveSign($value)
643   {
644     $this->data['NumberElements'][11] = $value;
645   }
646
647   /**
648    * Gets the string that represents the IEEE NaN (not a number) value.
649    *
650    * @return string NaN symbol.
651    */
652   function getNaNSymbol()
653   {
654     return $this->data['NumberElements'][10];
655   }
656
657   /**
658    * Sets the string that represents the IEEE NaN (not a number) value.
659    *
660    * @param string $value NaN symbol.
661    */
662   function setNaNSymbol($value)
663   {
664     $this->data['NumberElements'][10] = $value;
665   }
666
667   /**
668    * Gets the string to use as the percent symbol.
669    *
670    * @return string percent symbol.
671    */
672   function getPercentSymbol()
673   {
674     return $this->data['NumberElements'][3];
675   }
676
677   /**
678    * Sets the string to use as the percent symbol.
679    *
680    * @param string $value percent symbol.
681    */
682   function setPercentSymbol($value)
683   {
684     $this->data['NumberElements'][3] = $value;
685   }
686
687   /**
688    * Gets the string to use as the per mille symbol.
689    *
690    * @return string percent symbol.
691    */
692   function getPerMilleSymbol()
693   {
694     return $this->data['NumberElements'][8];
695   }
696
697   /**
698    * Sets the string to use as the per mille symbol.
699    *
700    * @param string $value percent symbol.
701    */
702   function setPerMilleSymbol($value)
703   {
704     $this->data['NumberElements'][8] = $value;
705   }
706 }
707
Note: See TracBrowser for help on using the browser.