CFormatter.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. <?php
  2. /**
  3. * CFormatter class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CFormatter provides a set of commonly used data formatting methods.
  12. *
  13. * The formatting methods provided by CFormatter are all named in the form of <code>formatXyz</code>.
  14. * The behavior of some of them may be configured via the properties of CFormatter. For example,
  15. * by configuring {@link dateFormat}, one may control how {@link formatDate} formats the value into a date string.
  16. *
  17. * For convenience, CFormatter also implements the mechanism of calling formatting methods with their shortcuts (called types).
  18. * In particular, if a formatting method is named <code>formatXyz</code>, then its shortcut method is <code>xyz</code>
  19. * (case-insensitive). For example, calling <code>$formatter->date($value)</code> is equivalent to calling
  20. * <code>$formatter->formatDate($value)</code>.
  21. *
  22. * Currently, the following types are recognizable:
  23. * <ul>
  24. * <li>raw: the attribute value will not be changed at all.</li>
  25. * <li>text: the attribute value will be HTML-encoded when rendering.</li>
  26. * <li>ntext: the {@link formatNtext} method will be called to format the attribute value as a HTML-encoded plain text with newlines converted as the HTML &lt;br /&gt; or &lt;p&gt;&lt;/p&gt; tags.</li>
  27. * <li>html: the attribute value will be purified and then returned.</li>
  28. * <li>date: the {@link formatDate} method will be called to format the attribute value as a date.</li>
  29. * <li>time: the {@link formatTime} method will be called to format the attribute value as a time.</li>
  30. * <li>datetime: the {@link formatDatetime} method will be called to format the attribute value as a date with time.</li>
  31. * <li>boolean: the {@link formatBoolean} method will be called to format the attribute value as a boolean display.</li>
  32. * <li>number: the {@link formatNumber} method will be called to format the attribute value as a number display.</li>
  33. * <li>email: the {@link formatEmail} method will be called to format the attribute value as a mailto link.</li>
  34. * <li>image: the {@link formatImage} method will be called to format the attribute value as an image tag where the attribute value is the image URL.</li>
  35. * <li>url: the {@link formatUrl} method will be called to format the attribute value as a hyperlink where the attribute value is the URL.</li>
  36. * <li>size: the {@link formatSize} method will be called to format the attribute value, interpreted as a number of bytes, as a size in human readable form.</li>
  37. * </ul>
  38. *
  39. * By default, {@link CApplication} registers {@link CFormatter} as an application component whose ID is 'format'.
  40. * Therefore, one may call <code>Yii::app()->format->boolean(1)</code>.
  41. * You might want to replace this component with {@link CLocalizedFormatter} to enable formatting based on the
  42. * current locale settings.
  43. *
  44. * @property CHtmlPurifier $htmlPurifier The HTML purifier instance.
  45. *
  46. * @author Qiang Xue <qiang.xue@gmail.com>
  47. * @package system.utils
  48. * @since 1.1.0
  49. */
  50. class CFormatter extends CApplicationComponent
  51. {
  52. /**
  53. * @var CHtmlPurifier
  54. */
  55. private $_htmlPurifier;
  56. /**
  57. * @var string the format string to be used to format a date using PHP date() function. Defaults to 'Y/m/d'.
  58. */
  59. public $dateFormat='Y/m/d';
  60. /**
  61. * @var string the format string to be used to format a time using PHP date() function. Defaults to 'h:i:s A'.
  62. */
  63. public $timeFormat='h:i:s A';
  64. /**
  65. * @var string the format string to be used to format a date and time using PHP date() function. Defaults to 'Y/m/d h:i:s A'.
  66. */
  67. public $datetimeFormat='Y/m/d h:i:s A';
  68. /**
  69. * @var array the format used to format a number with PHP number_format() function.
  70. * Three elements may be specified: "decimals", "decimalSeparator" and "thousandSeparator".
  71. * They correspond to the number of digits after the decimal point, the character displayed as the decimal point
  72. * and the thousands separator character.
  73. */
  74. public $numberFormat=array('decimals'=>null, 'decimalSeparator'=>null, 'thousandSeparator'=>null);
  75. /**
  76. * @var array the text to be displayed when formatting a boolean value. The first element corresponds
  77. * to the text display for false, the second element for true. Defaults to <code>array('No', 'Yes')</code>.
  78. */
  79. public $booleanFormat=array('No','Yes');
  80. /**
  81. * @var array the options to be passed to CHtmlPurifier instance used in this class. CHtmlPurifier is used
  82. * in {@link formatHtml} method, so this property could be useful to customize HTML filtering behavior.
  83. * @since 1.1.13
  84. */
  85. public $htmlPurifierOptions=array();
  86. /**
  87. * @var array the format used to format size (bytes). Three elements may be specified: "base", "decimals" and "decimalSeparator".
  88. * They correspond to the base at which a kilobyte is calculated (1000 or 1024 bytes per kilobyte, defaults to 1024),
  89. * the number of digits after the decimal point (defaults to 2) and the character displayed as the decimal point.
  90. * "decimalSeparator" is available since version 1.1.13
  91. * @since 1.1.11
  92. */
  93. public $sizeFormat=array(
  94. 'base'=>1024,
  95. 'decimals'=>2,
  96. 'decimalSeparator'=>null,
  97. );
  98. /**
  99. * Calls the format method when its shortcut is invoked.
  100. * This is a PHP magic method that we override to implement the shortcut format methods.
  101. * @param string $name the method name
  102. * @param array $parameters method parameters
  103. * @return mixed the method return value
  104. */
  105. public function __call($name,$parameters)
  106. {
  107. if(method_exists($this,'format'.$name))
  108. return call_user_func_array(array($this,'format'.$name),$parameters);
  109. else
  110. return parent::__call($name,$parameters);
  111. }
  112. /**
  113. * Formats a value based on the given type.
  114. * @param mixed $value the value to be formatted
  115. * @param string $type the data type. This must correspond to a format method available in CFormatter.
  116. * For example, we can use 'text' here because there is method named {@link formatText}.
  117. * @throws CException if given type is unknown
  118. * @return string the formatted data
  119. */
  120. public function format($value,$type)
  121. {
  122. $method='format'.$type;
  123. if(method_exists($this,$method))
  124. return $this->$method($value);
  125. else
  126. throw new CException(Yii::t('yii','Unknown type "{type}".',array('{type}'=>$type)));
  127. }
  128. /**
  129. * Formats the value as is without any formatting.
  130. * This method simply returns back the parameter without any format.
  131. * @param mixed $value the value to be formatted
  132. * @return string the formatted result
  133. */
  134. public function formatRaw($value)
  135. {
  136. return $value;
  137. }
  138. /**
  139. * Formats the value as a HTML-encoded plain text.
  140. * @param mixed $value the value to be formatted
  141. * @return string the formatted result
  142. */
  143. public function formatText($value)
  144. {
  145. return CHtml::encode($value);
  146. }
  147. /**
  148. * Formats the value as a HTML-encoded plain text and converts newlines with HTML &lt;br /&gt; or
  149. * &lt;p&gt;&lt;/p&gt; tags.
  150. * @param mixed $value the value to be formatted
  151. * @param boolean $paragraphs whether newlines should be converted to HTML &lt;p&gt;&lt;/p&gt; tags,
  152. * false by default meaning that HTML &lt;br /&gt; tags will be used
  153. * @param boolean $removeEmptyParagraphs whether empty paragraphs should be removed, defaults to true;
  154. * makes sense only when $paragraphs parameter is true
  155. * @return string the formatted result
  156. */
  157. public function formatNtext($value,$paragraphs=false,$removeEmptyParagraphs=true)
  158. {
  159. $value=CHtml::encode($value);
  160. if($paragraphs)
  161. {
  162. $value='<p>'.str_replace(array("\r\n", "\n", "\r"), '</p><p>',$value).'</p>';
  163. if($removeEmptyParagraphs)
  164. $value=preg_replace('/(<\/p><p>){2,}/i','</p><p>',$value);
  165. return $value;
  166. }
  167. else
  168. {
  169. return nl2br($value);
  170. }
  171. }
  172. /**
  173. * Formats the value as HTML text without any encoding.
  174. * @param mixed $value the value to be formatted
  175. * @return string the formatted result
  176. */
  177. public function formatHtml($value)
  178. {
  179. return $this->getHtmlPurifier()->purify($value);
  180. }
  181. /**
  182. * Formats the value as a date.
  183. * @param mixed $value the value to be formatted
  184. * @return string the formatted result
  185. * @see dateFormat
  186. */
  187. public function formatDate($value)
  188. {
  189. return date($this->dateFormat,$this->normalizeDateValue($value));
  190. }
  191. /**
  192. * Formats the value as a time.
  193. * @param mixed $value the value to be formatted
  194. * @return string the formatted result
  195. * @see timeFormat
  196. */
  197. public function formatTime($value)
  198. {
  199. return date($this->timeFormat,$this->normalizeDateValue($value));
  200. }
  201. /**
  202. * Formats the value as a date and time.
  203. * @param mixed $value the value to be formatted
  204. * @return string the formatted result
  205. * @see datetimeFormat
  206. */
  207. public function formatDatetime($value)
  208. {
  209. return date($this->datetimeFormat,$this->normalizeDateValue($value));
  210. }
  211. /**
  212. * Normalizes an expression as a timestamp.
  213. * @param mixed $time the time expression to be normalized
  214. * @return int the normalized result as a UNIX timestamp
  215. */
  216. protected function normalizeDateValue($time)
  217. {
  218. if(is_string($time))
  219. {
  220. if(ctype_digit($time) || ($time{0}=='-' && ctype_digit(substr($time, 1))))
  221. return (int)$time;
  222. else
  223. return strtotime($time);
  224. }
  225. elseif (class_exists('DateTime', false) && $time instanceof DateTime)
  226. return $time->getTimestamp();
  227. else
  228. return (int)$time;
  229. }
  230. /**
  231. * Formats the value as a boolean.
  232. * @param mixed $value the value to be formatted
  233. * @return string the formatted result
  234. * @see booleanFormat
  235. */
  236. public function formatBoolean($value)
  237. {
  238. return $value ? $this->booleanFormat[1] : $this->booleanFormat[0];
  239. }
  240. /**
  241. * Formats the value as a mailto link.
  242. * @param mixed $value the value to be formatted
  243. * @return string the formatted result
  244. */
  245. public function formatEmail($value)
  246. {
  247. return CHtml::mailto($value);
  248. }
  249. /**
  250. * Formats the value as an image tag.
  251. * @param mixed $value the value to be formatted
  252. * @return string the formatted result
  253. */
  254. public function formatImage($value)
  255. {
  256. return CHtml::image($value);
  257. }
  258. /**
  259. * Formats the value as a hyperlink.
  260. * @param mixed $value the value to be formatted
  261. * @return string the formatted result
  262. */
  263. public function formatUrl($value)
  264. {
  265. $url=$value;
  266. if(strpos($url,'http://')!==0 && strpos($url,'https://')!==0)
  267. $url='http://'.$url;
  268. return CHtml::link(CHtml::encode($value),$url);
  269. }
  270. /**
  271. * Formats the value as a number using PHP number_format() function.
  272. * @param mixed $value the value to be formatted
  273. * @return string the formatted result
  274. * @see numberFormat
  275. */
  276. public function formatNumber($value)
  277. {
  278. return number_format($value,$this->numberFormat['decimals'],$this->numberFormat['decimalSeparator'],$this->numberFormat['thousandSeparator']);
  279. }
  280. /**
  281. * @return CHtmlPurifier the HTML purifier instance
  282. */
  283. public function getHtmlPurifier()
  284. {
  285. if($this->_htmlPurifier===null)
  286. $this->_htmlPurifier=new CHtmlPurifier;
  287. $this->_htmlPurifier->options=$this->htmlPurifierOptions;
  288. return $this->_htmlPurifier;
  289. }
  290. /**
  291. * Formats the value in bytes as a size in human readable form.
  292. * @param integer $value value in bytes to be formatted
  293. * @param boolean $verbose if full names should be used (e.g. bytes, kilobytes, ...).
  294. * Defaults to false meaning that short names will be used (e.g. B, KB, ...).
  295. * @return string the formatted result
  296. * @see sizeFormat
  297. * @since 1.1.11
  298. */
  299. public function formatSize($value,$verbose=false)
  300. {
  301. $base=$this->sizeFormat['base'];
  302. for($i=0; $base<=$value && $i<5; $i++)
  303. $value=$value/$base;
  304. $value=round($value, $this->sizeFormat['decimals']);
  305. $formattedValue=isset($this->sizeFormat['decimalSeparator']) ? str_replace('.',$this->sizeFormat['decimalSeparator'],$value) : $value;
  306. $params=array($value,'{n}'=>$formattedValue);
  307. switch($i)
  308. {
  309. case 0:
  310. return $verbose ? Yii::t('yii','{n} byte|{n} bytes',$params) : Yii::t('yii', '{n} B',$params);
  311. case 1:
  312. return $verbose ? Yii::t('yii','{n} kilobyte|{n} kilobytes',$params) : Yii::t('yii','{n} KB',$params);
  313. case 2:
  314. return $verbose ? Yii::t('yii','{n} megabyte|{n} megabytes',$params) : Yii::t('yii','{n} MB',$params);
  315. case 3:
  316. return $verbose ? Yii::t('yii','{n} gigabyte|{n} gigabytes',$params) : Yii::t('yii','{n} GB',$params);
  317. default:
  318. return $verbose ? Yii::t('yii','{n} terabyte|{n} terabytes',$params) : Yii::t('yii','{n} TB',$params);
  319. }
  320. }
  321. }