summaryrefslogtreecommitdiff
path: root/framework/I18N/TNumberFormat.php
blob: 7940c785947796524a44013e4de4f61c9a79f8e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
<?php
/**
 * TNumberFromat component.
 *
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 * @link http://www.pradosoft.com/
 * @copyright Copyright &copy; 2005-2014 PradoSoft
 * @license http://www.pradosoft.com/license/
 * @package Prado\I18N
 */

namespace Prado\I18N;

/**
 * Get the NumberFormat class.
 */
Prado::using('System.I18N.core.NumberFormat');

/**
 * Get the parent control class.
 */
Prado::using('System.I18N.TI18NControl');

/**
  * To format numbers in locale sensitive manner use
  * <code>
  * <com:TNumberFormat Pattern="0.##" value="2.0" />
  * </code>
  *
  * Numbers can be formatted as currency, percentage, decimal or scientific
  * numbers by specifying the Type attribute. The known types are
  * "currency", "percentage", "decimal" and "scientific".
  *
  * If someone from US want to see sales figures from a store in
  * Germany (say using the EURO currency), formatted using the german
  * currency, you would need to use the attribute Culture="de_DE" to get
  * the currency right, e.g. 100,00. The decimal and grouping separator is
  * then also from the de_DE locale. This may lead to some confusion because
  * people from US know the "," as thousand separator. Therefore a "Currency"
  * attribute is available, so that the output from the following example
  * results in 100.00.
  * <code>
  * <com:TNumberFormat Type="currency" Culture="en_US" Currency="EUR" Value="100" />
  * </code>
  *
  * Namespace: System.I18N
  *
  * Properties
  * - <b>Value</b>, number,
  *   <br>Gets or sets the number to format. The tag content is used as Value
  *   if the Value property is not specified.
  * - <b>Type</b>, string,
  *   <br>Gets or sets the formatting type. The valid types are
  *    'decimal', 'currency', 'percentage' and 'scientific'.
  * - <b>Currency</b>, string,
  *   <br>Gets or sets the currency symbol for the currency format.
  *   The default is 'USD' if the Currency property is not specified.
  * - <b>Pattern</b>, string,
  *   <br>Gets or sets the custom number formatting pattern.
  * - <b>DefaultText</b>, string,
  * <br>Gets or sets the default text. If Value is not set, DefaultText will be
  * shown instead of the default currency Value/Pattern.
  *
  * @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com>
  * @package Prado\I18N
  */
class TNumberFormat extends TI18NControl implements \Prado\IDataRenderer
{
	/**
	 * Default NumberFormat, set to the application culture.
	 * @var NumberFormat
	 */
	protected static $formatter;

	/**
	 * Get the number formatting pattern.
	 * @return string format pattern.
	 */
	public function getPattern()
	{
		return $this->getViewState('Pattern','');
	}

	/**
	 * Set the number format pattern.
	 * @param string format pattern.
	 */
	public function setPattern($pattern)
	{
		$this->setViewState('Pattern',$pattern,'');
	}

	/**
	 * Get the numberic value for this control.
	 * @return string number
	 */
	public function getValue()
	{
		return $this->getViewState('Value','');
	}

	/**
	 * Set the numberic value for this control.
	 * @param string the number value
	 */
	public function setValue($value)
	{
		$this->setViewState('Value',$value,'');
	}

	/**
	 * Get the default text value for this control.
	 * @return string default text value
	 */
	public function getDefaultText()
	{
		return $this->getViewState('DefaultText','');
	}

	/**
	 * Set the default text value for this control.
	 * @param string default text value
	 */
	public function setDefaultText($value)
	{
		$this->setViewState('DefaultText',$value,'');
	}

	/**
	 * Get the numberic value for this control.
	 * This method is required by {@link \Prado\IDataRenderer}.
	 * It is the same as {@link getValue()}.
	 * @return string number
	 * @see getValue
	 * @since 3.1.2
	 */
	public function getData()
	{
		return $this->getValue();
	}

	/**
	 * Set the numberic value for this control.
	 * This method is required by {@link \Prado\IDataRenderer}.
	 * It is the same as {@link setValue()}.
	 * @param string the number value
	 * @see setValue
	 * @since 3.1.2
	 */
	public function setData($value)
	{
		$this->setValue($value);
	}

	/**
	 * Get the formatting type for this control.
	 * @return string formatting type.
	 */
	public function getType()
	{
		return $this->getViewState('Type','d');
	}

	/**
	 * Set the formatting type for this control.
	 * @param string formatting type, either "decimal", "currency","percentage"
	 * or "scientific"
	 * @throws TPropertyTypeInvalidException
	 */
	public function setType($type)
	{
		$type = strtolower($type);

		switch($type)
		{
			case 'decimal':
				$this->setViewState('Type','d',''); break;
			case 'currency':
				$this->setViewState('Type','c',''); break;
			case 'percentage':
				$this->setViewState('Type','p',''); break;
			case 'scientific':
				$this->setViewState('Type','e',''); break;
			default:
				throw new TInvalidDataValueException('numberformat_type_invalid',$type);
		}

	}

	/**
	 * @return string 3 letter currency code. Defaults to 'USD'.
	 */
	public function getCurrency()
	{
		return $this->getViewState('Currency','USD');
	}

	/**
	 * Set the 3-letter ISO 4217 code. For example, the code
	 * "USD" represents the US Dollar and "EUR" represents the Euro currency.
	 * @param string currency code.
	 */
	public function setCurrency($currency)
	{
		$this->setViewState('Currency', $currency,'');
	}

	/**
	 * Formats the localized number, be it currency or decimal, or percentage.
	 * If the culture is not specified, the default application
	 * culture will be used.
	 * @return string formatted number
	 */
	protected function getFormattedValue()
	{
		$value = $this->getValue();
		$defaultText = $this->getDefaultText();
		if(empty($value) && !empty($defaultText))
			return $this->getDefaultText();

		$app = $this->getApplication()->getGlobalization();
		//initialized the default class wide formatter
		if(self::$formatter===null)
			self::$formatter = new NumberFormat($app->getCulture());

		$pattern = strlen($this->getPattern()) > 0
						? $this->getPattern() : $this->getType();

		$culture = $this->getCulture();
		//return the specific cultural formatted number
		if(!empty($culture) && $app->getCulture() != $culture)
		{
			$formatter = new NumberFormat($culture);
			return $formatter->format($this->getValue(),$pattern,
									  $this->getCurrency(),
									  $this->getCharset());
		}

		//return the application wide culture formatted number.
		return self::$formatter->format($this->getValue(),$pattern,
										$this->getCurrency(),
										$this->getCharset());
	}

	public function render($writer)
	{
		$writer->write($this->getFormattedValue());
	}
}