Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 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: sfNumberFormatInfo.class.php 28725 2010-03-23 16:56:48Z FabianLange $
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 (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['negative'] = $negative;
281
    $info['positive'] = $pattern;
282
 
283
    $posfix = $this->getPrePostfix($pattern);
284
    $info['posPref'] = $posfix[0];
285
    $info['posPost'] = $posfix[1];
286
 
287
    if ($negative)
288
    {
289
      // find the negative prefix and postfix
290
      $prefixPostfix = $this->getPrePostfix($negative);
291
      $info['negPref'] = $prefixPostfix[0];
292
      $info['negPost'] = $prefixPostfix[1];
293
    }
294
    else
295
    {
296
      // use the positive prefix and postfix and add the NegativeSign
297
      // http://www.unicode.org/reports/tr35/tr35-15.html#Number_Format_Patterns
298
      // If there is no explicit negative subpattern, the negative subpattern is the localized minus sign prefixed to the positive subpattern.
299
      $info['negPref'] = $this->getNegativeSign().$info['posPref'];
300
      $info['negPost'] = $info['posPost'];
301
    }
302
 
303
    if (is_int($groupPos1))
304
    {
305
      // get the second group
306
      $groupPos2 = strrpos(substr($pattern, 0, $groupPos1), $comma);
307
 
308
      // get the number of decimal digits
309
      if (is_int($decimalPos))
310
      {
311
        $groupSize1 = $decimalPos - $groupPos1 - 1;
312
      }
313
      else
314
      {
315
        // no decimal point, so traverse from the back
316
        // to find the groupsize 1.
317
        for ($i = strlen($pattern) - 1; $i >= 0; $i--)
318
        {
319
          if ($pattern{$i} == $digit || $pattern{$i} == $hash)
320
          {
321
            $groupSize1 = $i - $groupPos1;
322
            break;
323
          }
324
        }
325
      }
326
 
327
      // get the second group size
328
      if (is_int($groupPos2))
329
      {
330
        $groupSize2 = $groupPos1 - $groupPos2 - 1;
331
      }
332
    }
333
 
334
    if (is_int($decimalPos))
335
    {
336
      for ($i = strlen($pattern) - 1; $i >= 0; $i--)
337
      {
338
        if ($pattern{$i} == $dot)
339
        {
340
          break;
341
        }
342
        if ($pattern{$i} == $digit)
343
        {
344
          $decimalPoints = $i - $decimalPos;
345
          break;
346
        }
347
      }
348
    }
349
 
350
    $digitPattern = is_int($decimalPos) ? substr($pattern, 0, $decimalPos) : $pattern;
351
    $digitPattern  = preg_replace('/[^0]/', '', $digitPattern);
352
 
353
    $info['groupPos1']     = $groupPos1;
354
    $info['groupSize1']    = $groupSize1;
355
    $info['groupPos2']     = $groupPos2;
356
    $info['groupSize2']    = $groupSize2;
357
    $info['decimalPos']    = $decimalPos;
358
    $info['decimalPoints'] = $decimalPoints;
359
    $info['digitSize']     = strlen($digitPattern);
360
 
361
    return $info;
362
  }
363
 
364
  /**
365
   * Gets the prefix and postfix of a pattern.
366
   *
367
   * @param string $pattern pattern
368
   * @return array of prefix and postfix, array(prefix,postfix).
369
   */
370
  protected function getPrePostfix($pattern)
371
  {
372
    $regexp = '/[#,\.0]+/';
373
    $result = preg_split($regexp, $pattern);
374
 
375
    return array($result[0], $result[1]);
376
  }
377
 
378
  /**
379
   * Indicates the number of decimal places.
380
   *
381
   * @return int number of decimal places.
382
   */
383
  function getDecimalDigits()
384
  {
385
    return $this->pattern['decimalPoints'];
386
  }
387
 
388
  /**
389
   * Sets the number of decimal places.
390
   *
391
   * @param int $value number of decimal places.
392
   */
393
  function setDecimalDigits($value)
394
  {
395
    return $this->pattern['decimalPoints'] = $value;
396
  }
397
 
398
  /**
399
   * Indicates the digit size.
400
   *
401
   * @return int digit size.
402
   */
403
  function getDigitSize()
404
  {
405
    return $this->pattern['digitSize'];
406
  }
407
 
408
  /**
409
   * Sets the digit size.
410
   *
411
   * @param int $value digit size.
412
   */
413
  function setDigitSize($value)
414
  {
415
    $this->pattern['digitSize'] = $value;
416
  }
417
 
418
  /**
419
   * Gets the string to use as the decimal separator.
420
   *
421
   * @return string decimal separator.
422
   */
423
  function getDecimalSeparator()
424
  {
425
    return $this->data['NumberElements'][0];
426
  }
427
 
428
  /**
429
   * Sets the string to use as the decimal separator.
430
   *
431
   * @param string $value the decimal point
432
   */
433
  function setDecimalSeparator($value)
434
  {
435
    return $this->data['NumberElements'][0] = $value;
436
  }
437
 
438
  /**
439
   * Gets the string that separates groups of digits to the left
440
   * of the decimal in currency values.
441
   *
442
   * @return string currency group separator.
443
   */
444
  function getGroupSeparator()
445
  {
446
    return $this->data['NumberElements'][1];
447
  }
448
 
449
  /**
450
   * Sets the string to use as the group separator.
451
   *
452
   * @param string $value the group separator.
453
   */
454
  function setGroupSeparator($value)
455
  {
456
    return $this->data['NumberElements'][1] = $value;
457
  }
458
 
459
  /**
460
   * Gets the number of digits in each group to the left of the decimal
461
   * There can be two grouping sizes, this fucntion
462
   * returns <b>array(group1, group2)</b>, if there is only 1 grouping size,
463
   * group2 will be false.
464
   *
465
   * @return array grouping size(s).
466
   */
467
  function getGroupSizes()
468
  {
469
    $group1 = $this->pattern['groupSize1'];
470
    $group2 = $this->pattern['groupSize2'];
471
 
472
    return array($group1, $group2);
473
  }
474
 
475
  /**
476
   * Sets the number of digits in each group to the left of the decimal.
477
   * There can be two grouping sizes, the value should
478
   * be an <b>array(group1, group2)</b>, if there is only 1 grouping size,
479
   * group2 should be false.
480
   *
481
   * @param array $groupSize grouping size(s).
482
   */
483
  function setGroupSizes($groupSize)
484
  {
485
    $this->pattern['groupSize1'] = $groupSize[0];
486
    $this->pattern['groupSize2'] = $groupSize[1];
487
  }
488
 
489
  /**
490
   * Gets the format pattern for negative values.
491
   * The negative pattern is composed of a prefix, and postfix.
492
   * This function returns <b>array(prefix, postfix)</b>.
493
   *
494
   * @return arary negative pattern.
495
   */
496
  function getNegativePattern()
497
  {
498
    $prefix = $this->pattern['negPref'];
499
    $postfix = $this->pattern['negPost'];
500
 
501
    return array($prefix, $postfix);
502
  }
503
 
504
  /**
505
   * Sets the format pattern for negative values.
506
   * The negative pattern is composed of a prefix, and postfix in the form
507
   * <b>array(prefix, postfix)</b>.
508
   *
509
   * @param arary $pattern negative pattern.
510
   */
511
  function setNegativePattern($pattern)
512
  {
513
    $this->pattern['negPref'] = $pattern[0];
514
    $this->pattern['negPost'] = $pattern[1];
515
  }
516
 
517
  /**
518
   * Gets the format pattern for positive values.
519
   * The positive pattern is composed of a prefix, and postfix.
520
   * This function returns <b>array(prefix, postfix)</b>.
521
   *
522
   * @return arary positive pattern.
523
   */
524
  function getPositivePattern()
525
  {
526
    $prefix = $this->pattern['posPref'];
527
    $postfix = $this->pattern['posPost'];
528
 
529
    return array($prefix, $postfix);
530
  }
531
 
532
  /**
533
   * Sets the format pattern for positive values.
534
   * The positive pattern is composed of a prefix, and postfix in the form
535
   * <b>array(prefix, postfix)</b>.
536
   *
537
   * @param arary $pattern positive pattern.
538
   */
539
  function setPositivePattern($pattern)
540
  {
541
    $this->pattern['posPref'] = $pattern[0];
542
    $this->pattern['posPost'] = $pattern[1];
543
  }
544
 
545
  /**
546
   * Gets the string to use as the currency symbol.
547
   *
548
   * @return string $currency currency symbol.
549
   */
550
  function getCurrencySymbol($currency = 'USD')
551
  {
552
    if (isset($this->pattern['symbol']))
553
    {
554
      return $this->pattern['symbol'];
555
    }
556
    else
557
    {
558
      return $this->data['Currencies'][$currency][0];
559
    }
560
  }
561
 
562
  /**
563
   * Sets the string to use as the currency symbol.
564
   *
565
   * @param string $symbol currency symbol.
566
   */
567
  function setCurrencySymbol($symbol)
568
  {
569
    $this->pattern['symbol'] = $symbol;
570
  }
571
 
572
  /**
573
   * Gets the string that represents negative infinity.
574
   *
575
   * @return string negative infinity.
576
   */
577
  function getNegativeInfinitySymbol()
578
  {
579
    return $this->pattern['negInfty'];
580
  }
581
 
582
  /**
583
   * Sets the string that represents negative infinity.
584
   *
585
   * @param string $value negative infinity.
586
   */
587
  function setNegativeInfinitySymbol($value)
588
  {
589
    $this->pattern['negInfty'] = $value;
590
  }
591
 
592
  /**
593
   * Gets the string that represents positive infinity.
594
   *
595
   * @return string positive infinity.
596
   */
597
  function getPositiveInfinitySymbol()
598
  {
599
    return $this->pattern['posInfty'];
600
  }
601
 
602
  /**
603
   * Sets the string that represents positive infinity.
604
   *
605
   * @param string $value positive infinity.
606
   */
607
  function setPositiveInfinitySymbol($value)
608
  {
609
    $this->pattern['posInfty'] = $value;
610
  }
611
 
612
  /**
613
   * Gets the string that denotes that the associated number is negative.
614
   *
615
   * @return string negative sign.
616
   */
617
  function getNegativeSign()
618
  {
619
    return $this->data['NumberElements'][6];
620
  }
621
 
622
  /**
623
   * Sets the string that denotes that the associated number is negative.
624
   *
625
   * @param string $value negative sign.
626
   */
627
  function setNegativeSign($value)
628
  {
629
    $this->data['NumberElements'][6] = $value;
630
  }
631
 
632
  /**
633
   * Gets the string that denotes that the associated number is positive.
634
   *
635
   * @return string positive sign.
636
   */
637
  function getPositiveSign()
638
  {
639
    return $this->data['NumberElements'][11];
640
  }
641
 
642
  /**
643
   * Sets the string that denotes that the associated number is positive.
644
   *
645
   * @param string $value positive sign.
646
   */
647
  function setPositiveSign($value)
648
  {
649
    $this->data['NumberElements'][11] = $value;
650
  }
651
 
652
  /**
653
   * Gets the string that represents the IEEE NaN (not a number) value.
654
   *
655
   * @return string NaN symbol.
656
   */
657
  function getNaNSymbol()
658
  {
659
    return $this->data['NumberElements'][10];
660
  }
661
 
662
  /**
663
   * Sets the string that represents the IEEE NaN (not a number) value.
664
   *
665
   * @param string $value NaN symbol.
666
   */
667
  function setNaNSymbol($value)
668
  {
669
    $this->data['NumberElements'][10] = $value;
670
  }
671
 
672
  /**
673
   * Gets the string to use as the percent symbol.
674
   *
675
   * @return string percent symbol.
676
   */
677
  function getPercentSymbol()
678
  {
679
    return $this->data['NumberElements'][3];
680
  }
681
 
682
  /**
683
   * Sets the string to use as the percent symbol.
684
   *
685
   * @param string $value percent symbol.
686
   */
687
  function setPercentSymbol($value)
688
  {
689
    $this->data['NumberElements'][3] = $value;
690
  }
691
 
692
  /**
693
   * Gets the string to use as the per mille symbol.
694
   *
695
   * @return string percent symbol.
696
   */
697
  function getPerMilleSymbol()
698
  {
699
    return $this->data['NumberElements'][8];
700
  }
701
 
702
  /**
703
   * Sets the string to use as the per mille symbol.
704
   *
705
   * @param string $value percent symbol.
706
   */
707
  function setPerMilleSymbol($value)
708
  {
709
    $this->data['NumberElements'][8] = $value;
710
  }
711
}