Development

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

You must first sign up to be able to contribute.

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

Revision 6806, 16.4 kB (checked in by fabien, 7 years ago)

fixed phpdoc package/subpackage entries

  • 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 ICU data for date time formatting.
114    * @see getInstance()
115    */
116   function __construct($data = array(), $type = sfNumberFormatInfo::DECIMAL)
117   {
118     $this->properties = get_class_methods($this);
119
120     if (empty($data))
121     {
122       throw new sfException('Please provide the ICU data to initialize.');
123     }
124
125     $this->data = $data;
126
127     $this->setPattern($type);
128   }
129
130   /**
131    * Sets the pattern for a specific number pattern. The validate patterns
132    * sfNumberFormatInfo::DECIMAL, sfNumberFormatInfo::CURRENCY,
133    * sfNumberFormatInfo::PERCENTAGE, or sfNumberFormatInfo::SCIENTIFIC
134    *
135    * @param int pattern type.
136    */
137   function setPattern($type = sfNumberFormatInfo::DECIMAL)
138   {
139     if (is_int($type))
140     {
141       $this->pattern = $this->parsePattern($this->data['NumberPatterns'][$type]);
142     }
143     else
144     {
145       $this->pattern = $this->parsePattern($type);
146     }
147
148     $this->pattern['negInfty'] = $this->data['NumberElements'][6].$this->data['NumberElements'][9];
149
150     $this->pattern['posInfty'] = $this->data['NumberElements'][11].$this->data['NumberElements'][9];
151   }
152
153   function getPattern()
154   {
155     return $this->pattern;
156   }
157
158   /**
159    * Gets the default sfNumberFormatInfo that is culture-independent (invariant).
160    *
161    * @return sfNumberFormatInfo default sfNumberFormatInfo.
162    */
163   static public function getInvariantInfo($type = sfNumberFormatInfo::DECIMAL)
164   {
165     static $invariant;
166     if (is_null($invariant))
167     {
168       $culture = sfCultureInfo::getInvariantCulture();
169       $invariant = $culture->NumberFormat;
170       $invariant->setPattern($type);
171     }
172
173     return $invariant;
174   }
175
176   /**
177    * Returns the sfNumberFormatInfo associated with the specified culture.
178    *
179    * @param sfCultureInfo the culture that gets the sfNumberFormat property.
180    * @param int the number formatting type, it should be
181    * sfNumberFormatInfo::DECIMAL, sfNumberFormatInfo::CURRENCY,
182    * sfNumberFormatInfo::PERCENTAGE, or sfNumberFormatInfo::SCIENTIFIC
183    * @return sfNumberFormatInfo sfNumberFormatInfo for the specified culture.
184    * @see getCurrencyInstance();
185    * @see getPercentageInstance();
186    * @see getScientificInstance();
187    */
188   public static function getInstance($culture = null, $type = sfNumberFormatInfo::DECIMAL)
189   {
190     if ($culture instanceof sfCultureInfo)
191     {
192       $formatInfo = $culture->getNumberFormat();
193       $formatInfo->setPattern($type);
194
195       return $formatInfo;
196     }
197     else if (is_string($culture))
198     {
199       $sfCultureInfo = new sfCultureInfo($culture);
200       $formatInfo = $sfCultureInfo->getNumberFormat();
201       $formatInfo->setPattern($type);
202
203       return $formatInfo;
204     }
205     else
206     {
207       $sfCultureInfo = new sfCultureInfo();
208       $formatInfo = $sfCultureInfo->getNumberFormat();
209       $formatInfo->setPattern($type);
210
211       return $formatInfo;
212     }
213   }
214
215   /**
216    * Returns the currency format info associated with the specified culture.
217    *
218    * @param sfCultureInfo the culture that gets the NumberFormat property.
219    * @return sfNumberFormatInfo sfNumberFormatInfo for the specified culture.
220    */
221   public static function getCurrencyInstance($culture = null)
222   {
223     return self::getInstance($culture, self::CURRENCY);
224   }
225
226   /**
227    * Returns the percentage format info associated with the specified culture.
228    *
229    * @param sfCultureInfo the culture that gets the NumberFormat property.
230    * @return sfNumberFormatInfo sfNumberFormatInfo for the specified culture.
231    */
232   public static function getPercentageInstance($culture = null)
233   {
234     return self::getInstance($culture, self::PERCENTAGE);
235   }
236
237   /**
238    * Returns the scientific format info associated with the specified culture.
239    *
240    * @param sfCultureInfo the culture that gets the NumberFormat property.
241    * @return sfNumberFormatInfo sfNumberFormatInfo for the specified culture.
242    */
243   public static function getScientificInstance($culture = null)
244   {
245     return self::getInstance($culture, self::SCIENTIFIC);
246   }
247
248   /**
249    * Parses the given pattern and return a list of known properties.
250    *
251    * @param string a number pattern.
252    * @return array list of pattern properties.
253    */
254   protected function parsePattern($pattern)
255   {
256     $pattern = explode(';', $pattern);
257
258     $negative = null;
259     if (count($pattern) > 1)
260     {
261       $negative = $pattern[1];
262     }
263     $pattern = $pattern[0];
264
265     $comma = ',';
266     $dot = '.';
267     $digit = '0';
268     $hash = '#';
269
270     // find the first group point, and decimal point
271     $groupPos1 = strrpos($pattern, $comma);
272     $decimalPos = strrpos($pattern, $dot);
273
274     $groupPos2 = false;
275     $groupSize1 = false;
276     $groupSize2 = false;
277     $decimalPoints = is_int($decimalPos) ? -1 : false;
278
279     $info['negPref'] = $this->data['NumberElements'][6];
280     $info['negPost'] = '';
281
282     $info['negative'] = $negative;
283     $info['positive'] = $pattern;
284
285     // find the negative prefix and postfix
286     if ($negative)
287     {
288       $prefixPostfix = $this->getPrePostfix($negative);
289       $info['negPref'] = $prefixPostfix[0];
290       $info['negPost'] = $prefixPostfix[1];
291     }
292
293     $posfix = $this->getPrePostfix($pattern);
294     $info['posPref'] = $posfix[0];
295     $info['posPost'] = $posfix[1];
296
297     if (is_int($groupPos1))
298     {
299       // get the second group
300       $groupPos2 = strrpos(substr($pattern, 0, $groupPos1), $comma);
301
302       // get the number of decimal digits
303       if (is_int($decimalPos))
304       {
305         $groupSize1 = $decimalPos - $groupPos1 - 1;
306       }
307       else
308       {
309         // no decimal point, so traverse from the back
310         // to find the groupsize 1.
311         for ($i = strlen($pattern) - 1; $i >= 0; $i--)
312         {
313           if ($pattern{$i} == $digit || $pattern{$i} == $hash)
314           {
315             $groupSize1 = $i - $groupPos1;
316             break;
317           }
318         }
319       }
320
321       // get the second group size
322       if (is_int($groupPos2))
323       {
324         $groupSize2 = $groupPos1 - $groupPos2 - 1;
325       }
326     }
327
328     if (is_int($decimalPos))
329     {
330       for ($i = strlen($pattern) - 1; $i >= 0; $i--)
331       {
332         if ($pattern{$i} == $dot)
333         {
334           break;
335         }
336         if ($pattern{$i} == $digit)
337         {
338           $decimalPoints = $i - $decimalPos;
339           break;
340         }
341       }
342     }
343
344     $info['groupPos1']     = $groupPos1;
345     $info['groupSize1']    = $groupSize1;
346     $info['groupPos2']     = $groupPos2;
347     $info['groupSize2']    = $groupSize2;
348     $info['decimalPos']    = $decimalPos;
349     $info['decimalPoints'] = $decimalPoints;
350
351     return $info;
352   }
353
354   /**
355    * Gets the prefix and postfix of a pattern.
356    *
357    * @param string pattern
358    * @return array of prefix and postfix, array(prefix,postfix).
359    */
360   protected function getPrePostfix($pattern)
361   {
362     $regexp = '/[#,\.0]+/';
363     $result = preg_split($regexp, $pattern);
364
365     return array($result[0], $result[1]);
366   }
367
368   /**
369    * Indicates the number of decimal places.
370    *
371    * @return int number of decimal places.
372    */
373   function getDecimalDigits()
374   {
375     return $this->pattern['decimalPoints'];
376   }
377
378   /**
379    * Sets the number of decimal places.
380    *
381    * @param int number of decimal places.
382    */
383   function setDecimalDigits($value)
384   {
385     return $this->pattern['decimalPoints'] = $value;
386   }
387
388   /**
389    * Gets the string to use as the decimal separator.
390    *
391    * @return string decimal separator.
392    */
393   function getDecimalSeparator()
394   {
395     return $this->data['NumberElements'][0];
396   }
397
398   /**
399    * Sets the string to use as the decimal separator.
400    *
401    * @param string the decimal point
402    */
403   function setDecimalSeparator($value)
404   {
405     return $this->data['NumberElements'][0] = $value;
406   }
407
408   /**
409    * Gets the string that separates groups of digits to the left
410    * of the decimal in currency values.
411    *
412    * @param parameter
413    * @return string currency group separator.
414    */
415   function getGroupSeparator()
416   {
417     return $this->data['NumberElements'][1];
418   }
419
420   /**
421    * Sets the string to use as the group separator.
422    *
423    * @param string the group separator.
424    */
425   function setGroupSeparator($value)
426   {
427     return $this->data['NumberElements'][1] = $value;
428   }
429
430   /**
431    * Gets the number of digits in each group to the left of the decimal
432    * There can be two grouping sizes, this fucntion
433    * returns <b>array(group1, group2)</b>, if there is only 1 grouping size,
434    * group2 will be false.
435    *
436    * @return array grouping size(s).
437    */
438   function getGroupSizes()
439   {
440     $group1 = $this->pattern['groupSize1'];
441     $group2 = $this->pattern['groupSize2'];
442
443     return array($group1, $group2);
444   }
445
446   /**
447    * Sets the number of digits in each group to the left of the decimal.
448    * There can be two grouping sizes, the value should
449    * be an <b>array(group1, group2)</b>, if there is only 1 grouping size,
450    * group2 should be false.
451    *
452    * @param array grouping size(s).
453    */
454   function setGroupSizes($groupSize)
455   {
456     $this->pattern['groupSize1'] = $groupSize[0];
457     $this->pattern['groupSize2'] = $groupSize[1];
458   }
459
460   /**
461    * Gets the format pattern for negative values.
462    * The negative pattern is composed of a prefix, and postfix.
463    * This function returns <b>array(prefix, postfix)</b>.
464    *
465    * @return arary negative pattern.
466    */
467   function getNegativePattern()
468   {
469     $prefix = $this->pattern['negPref'];
470     $postfix = $this->pattern['negPost'];
471
472     return array($prefix, $postfix);
473   }
474
475   /**
476    * Sets the format pattern for negative values.
477    * The negative pattern is composed of a prefix, and postfix in the form
478    * <b>array(prefix, postfix)</b>.
479    *
480    * @param arary negative pattern.
481    */
482   function setNegativePattern($pattern)
483   {
484     $this->pattern['negPref'] = $pattern[0];
485     $this->pattern['negPost'] = $pattern[1];
486   }
487
488   /**
489    * Gets the format pattern for positive values.
490    * The positive pattern is composed of a prefix, and postfix.
491    * This function returns <b>array(prefix, postfix)</b>.
492    *
493    * @return arary positive pattern.
494    */
495   function getPositivePattern()
496   {
497     $prefix = $this->pattern['posPref'];
498     $postfix = $this->pattern['posPost'];
499
500     return array($prefix, $postfix);
501   }
502
503   /**
504    * Sets the format pattern for positive values.
505    * The positive pattern is composed of a prefix, and postfix in the form
506    * <b>array(prefix, postfix)</b>.
507    *
508    * @param arary positive pattern.
509    */
510   function setPositivePattern($pattern)
511   {
512     $this->pattern['posPref'] = $pattern[0];
513     $this->pattern['posPost'] = $pattern[1];
514   }
515
516   /**
517    * Gets the string to use as the currency symbol.
518    *
519    * @return string currency symbol.
520    */
521   function getCurrencySymbol($currency = 'USD')
522   {
523     if (isset($this->pattern['symbol']))
524     {
525       return $this->pattern['symbol'];
526     }
527     else
528     {
529       return $this->data['Currencies'][$currency][0];
530     }
531   }
532
533   /**
534    * Sets the string to use as the currency symbol.
535    *
536    * @param string currency symbol.
537    */
538   function setCurrencySymbol($symbol)
539   {
540     $this->pattern['symbol'] = $symbol;
541   }
542
543   /**
544    * Gets the string that represents negative infinity.
545    *
546    * @return string negative infinity.
547    */
548   function getNegativeInfinitySymbol()
549   {
550     return $this->pattern['negInfty'];
551   }
552
553   /**
554    * Sets the string that represents negative infinity.
555    *
556    * @param string negative infinity.
557    */
558   function setNegativeInfinitySymbol($value)
559   {
560     $this->pattern['negInfty'] = $value;
561   }
562
563   /**
564    * Gets the string that represents positive infinity.
565    *
566    * @return string positive infinity.
567    */
568   function getPositiveInfinitySymbol()
569   {
570     return $this->pattern['posInfty'];
571   }
572
573   /**
574    * Sets the string that represents positive infinity.
575    *
576    * @param string positive infinity.
577    */
578   function setPositiveInfinitySymbol($value)
579   {
580     $this->pattern['posInfty'] = $value;
581   }
582
583   /**
584    * Gets the string that denotes that the associated number is negative.
585    *
586    * @return string negative sign.
587    */
588   function getNegativeSign()
589   {
590     return $this->data['NumberElements'][6];
591   }
592
593   /**
594    * Sets the string that denotes that the associated number is negative.
595    *
596    * @param string negative sign.
597    */
598   function setNegativeSign($value)
599   {
600     $this->data['NumberElements'][6] = $value;
601   }
602
603   /**
604    * Gets the string that denotes that the associated number is positive.
605    *
606    * @return string positive sign.
607    */
608   function getPositiveSign()
609   {
610     return $this->data['NumberElements'][11];
611   }
612
613   /**
614    * Sets the string that denotes that the associated number is positive.
615    *
616    * @param string positive sign.
617    */
618   function setPositiveSign($value)
619   {
620     $this->data['NumberElements'][11] = $value;
621   }
622
623   /**
624    * Gets the string that represents the IEEE NaN (not a number) value.
625    *
626    * @return string NaN symbol.
627    */
628   function getNaNSymbol()
629   {
630     return $this->data['NumberElements'][10];
631   }
632
633   /**
634    * Sets the string that represents the IEEE NaN (not a number) value.
635    *
636    * @param string NaN symbol.
637    */
638   function setNaNSymbol($value)
639   {
640     $this->data['NumberElements'][10] = $value;
641   }
642
643   /**
644    * Gets the string to use as the percent symbol.
645    *
646    * @return string percent symbol.
647    */
648   function getPercentSymbol()
649   {
650     return $this->data['NumberElements'][3];
651   }
652
653   /**
654    * Sets the string to use as the percent symbol.
655    *
656    * @param string percent symbol.
657    */
658   function setPercentSymbol($value)
659   {
660     $this->data['NumberElements'][3] = $value;
661   }
662
663   /**
664    * Gets the string to use as the per mille symbol.
665    *
666    * @return string percent symbol.
667    */
668   function getPerMilleSymbol()
669   {
670     return $this->data['NumberElements'][8];
671   }
672
673   /**
674    * Sets the string to use as the per mille symbol.
675    *
676    * @param string percent symbol.
677    */
678   function setPerMilleSymbol($value)
679   {
680     $this->data['NumberElements'][8] = $value;
681   }
682 }
683
Note: See TracBrowser for help on using the browser.