Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Fri, Feb 21, 11:58 PM

in-portal

Index: branches/5.2.x/core/kernel/utility/formatters/formatter.php
===================================================================
--- branches/5.2.x/core/kernel/utility/formatters/formatter.php (revision 16762)
+++ branches/5.2.x/core/kernel/utility/formatters/formatter.php (revision 16763)
@@ -1,305 +1,317 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2011 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kFormatter extends kBase {
/**
* Reference to category helper
*
* @var CategoryHelper
*/
var $_categoryHelper = null;
/**
* Creates formatter instance
*
* @access public
*/
public function __construct()
{
parent::__construct();
$this->_categoryHelper = $this->Application->recallObject('CategoryHelper');
}
/**
* Replace FCK links like "@@ID@@" to real page urls, when "using_fck" option is set.
*
* @param string $value
* @param Array $options
* @param string $format
* @return string
*/
function _replaceFCKLinks(&$value, $options, $format = null)
{
if ((isset($format) && strpos($format, 'fck_ready') !== false) || (!array_key_exists('using_fck', $options) || !$options['using_fck'])) {
// in textarea, where fck will be used OR not using fck
return $value;
}
return $this->_categoryHelper->replacePageIds($value);
}
/**
* Convert's value to match type from config
*
* @param mixed $value
* @param Array $options
* @return mixed
* @access protected
*/
function TypeCast($value, $options)
{
if ( isset($options['type']) ) {
$field_type = $options['type'];
if ($field_type == 'numeric') {
trigger_error('Invalid field type <strong>' . $field_type . '</strong> (in TypeCast method), please use <strong>float</strong> instead', E_USER_NOTICE);
$field_type = 'float';
}
elseif ( $field_type == 'string' ) {
if ( isset($options['allow_html']) && $options['allow_html'] ) {
$value = $this->Application->unescapeRequestVariable($value);
}
return $value;
}
$value = $this->formatNumber($value);
$is_numeric_type = preg_match('#int|integer|double|float|real#', $field_type);
if ( $value != '' && $is_numeric_type ) {
$tc_value = $value;
settype($tc_value, $field_type);
// Type casing is considered a success only, when type casted value visually looks the same.
return (string)$value === (string)$tc_value ? $tc_value : false;
}
}
return $value;
}
/**
* Formats number, according to regional settings
*
* @param string $number
* @return float
*/
function formatNumber($number)
{
static $comma = null, $thousands = null;
if ( !isset($comma) || !isset($thousands) ) {
/** @var LanguagesItem $lang */
$lang = $this->Application->recallObject('lang.current');
$comma = $lang->GetDBField('DecimalPoint');
$thousands = $lang->GetDBField('ThousandSep');
}
$number = str_replace($thousands, '', $number);
$number = str_replace($comma, '.', $number);
return $number;
}
/**
* Applies type casting on each array element
* @param Array $src
* @param kDBItem|kDBList|kDBBase $object
* @return Array
* @access public
*/
public function TypeCastArray($src, &$object)
{
$dst = array ();
foreach ($src as $id => $row) {
$tmp_row = array ();
foreach ($row as $fld => $value) {
$field_options = $object->GetFieldOptions($fld);
$tmp_row[$fld] = $this->TypeCast($value, $field_options);
}
$dst[$id] = $tmp_row;
}
return $dst;
}
/**
* Formats value of a given field
*
* @param string $value
* @param string $field_name
* @param kDBItem|kDBList|kDBBase $object
* @param string $format
* @return string
*/
function Format($value, $field_name, &$object, $format = null)
{
if ( is_null($value) ) {
return '';
}
$options = $object->GetFieldOptions($field_name);
if (!isset($format) && array_key_exists('format', $options)) {
$format = $options['format'];
}
if ($value === false) {
// used ?
return $value; // for leaving badly formatted date on the form
}
$original_format = $format;
if (isset($format)) {
if (strpos($format, 'fck_ready') !== false) {
$format = trim(str_replace('fck_ready', '', $format), ';');
}
}
if (isset($format) && $format) {
if ( substr($format, -1) === 'f' ) {
// High precision formats (e.g. '%01.20f') are not supported to keep code below as fast as possible.
$value = round($value, substr($format, -2, 1));
}
$value = sprintf($format, $value);
- if ( isset($options['cut_zeros']) && $options['cut_zeros'] ) {
+ if ( isset($options['keep_cents']) && $options['keep_cents'] ) {
+ preg_match('/(\d+\.\d{' . $options['keep_cents'] . '})(\d+)?/', $value, $regs);
+
+ // When "keep_cents" option matches format's precision, there will be an "Undefined index: 2" notice.
+ if ( rtrim($regs[2], '0') === '' ) {
+ $value = $regs[1];
+ }
+ else {
+ // Remove trailing zeros in decimal part.
+ $value = preg_replace('/(\.\d+?)0+$/', '$1', $value);
+ }
+ }
+ elseif ( isset($options['cut_zeros']) && $options['cut_zeros'] ) {
// Remove trailing zeros in decimal part (including "." if any left at the end).
$value = preg_replace('/\.0+$/', '', $value);
$value = preg_replace('/(\.\d+?)0+$/', '$1', $value);
}
}
if (preg_match('#int|integer|double|float|real|numeric#', $options['type'])) {
/** @var LanguagesItem $lang */
$lang = $this->Application->recallObject('lang.current');
return $lang->formatNumber($value);
}
elseif ($options['type'] == 'string') {
$value = $this->_replaceFCKLinks($value, $options, $original_format);
}
return $value;
}
/**
* Performs basic type validation on form field value
*
* @param mixed $value
* @param string $field_name
* @param kDBItem|kDBList|kDBBase $object
* @return mixed
* @access public
*/
public function Parse($value, $field_name, &$object)
{
$options = $object->GetFieldOptions($field_name);
if ($value == '') {
return $options['type'] == 'string' ? $value : null;
}
$tc_value = $this->TypeCast($value, $options);
if ($tc_value === false) {
return $value; // for leaving badly formatted date on the form
}
if(isset($options['type'])) {
if (preg_match('#double|float|real|numeric#', $options['type'])) {
$tc_value = str_replace(',', '.', $tc_value);
}
}
if (isset($options['regexp'])) {
if (!preg_match($options['regexp'], $value)) {
$object->SetError($field_name, 'invalid_format');
}
}
return $tc_value;
}
function HumanFormat($format)
{
return $format;
}
/**
* The method is supposed to alter config options or cofigure object in some way based on its usage of formatters
* The methods is called for every field with formatter defined when configuring item.
* Could be used for adding additional VirtualFields to an object required by some special Formatter
*
* @param string $field_name
* @param array $field_options
* @param kDBBase $object
*/
function PrepareOptions($field_name, &$field_options, &$object)
{
}
/**
* Used for split fields like timestamp -> date, time
* Called from DBItem to update sub fields values after loading item
*
* @param string $field
* @param string $value
* @param Array $options
* @param kDBItem|kDBList|kDBBase $object
* @return void
* @access public
*/
public function UpdateSubFields($field, $value, &$options, &$object)
{
}
/**
* Used for split fields like timestamp -> date, time
* Called from DBItem Validate (before validation) to get back master field value from its sub_fields
*
* @param string $field
* @param mixed $value
* @param Array $options
* @param kDBItem|kDBList|kDBBase $object
*/
function UpdateMasterFields($field, $value, &$options, &$object)
{
}
/**
* Return sample value, that can be entered in this field
*
* @param string $field
* @param Array $options
* @param kDBItem|kDBList|kDBBase $object
* @return string
* @access public
*/
public function GetSample($field, &$options, &$object)
{
return isset($options['sample_value']) ? $options['sample_value'] : '';
}
}
Index: branches/5.2.x/core/tests/kernel/utility/formatters/kFormatterTest.php
===================================================================
--- branches/5.2.x/core/tests/kernel/utility/formatters/kFormatterTest.php (nonexistent)
+++ branches/5.2.x/core/tests/kernel/utility/formatters/kFormatterTest.php (revision 16763)
@@ -0,0 +1,63 @@
+<?php
+
+
+final class kFormatterTest extends AbstractTestCase
+{
+
+ /**
+ * @dataProvider cutZerosDataProvider
+ */
+ public function testCutZeros($raw_number, $formatted_number, array $field_options)
+ {
+ $formatter = new kFormatter();
+
+ $item_prophecy = $this->prophesize('kDBItem');
+ $item_prophecy->GetFieldOptions('FieldName')->willReturn(array(
+ 'type' => 'float',
+ 'format' => '%01.6f',
+ ) + $field_options);
+ $item = $item_prophecy->reveal();
+
+ $this->assertSame($formatted_number, $formatter->Format($raw_number, 'FieldName', $item));
+ }
+
+ public function cutZerosDataProvider()
+ {
+ return array(
+ 'long' => array('12.345000', '12.345', array('cut_zeros' => 1)),
+ 'short' => array('12.300000', '12.3', array('cut_zeros' => 1)),
+ 'exact+leading_zero' => array('12.030000', '12.03', array('cut_zeros' => 1)),
+ 'very_long' => array('12.030050', '12.03005', array('cut_zeros' => 1)),
+ 'no_decimals' => array('12.000000', '12', array('cut_zeros' => 1)),
+ );
+ }
+
+ /**
+ * @dataProvider keepCentsDataProvider
+ */
+ public function testKeepCents($raw_number, $formatted_number, array $field_options)
+ {
+ $formatter = new kFormatter();
+
+ $item_prophecy = $this->prophesize('kDBItem');
+ $item_prophecy->GetFieldOptions('FieldName')->willReturn(array(
+ 'type' => 'float',
+ 'format' => '%01.6f',
+ ) + $field_options);
+ $item = $item_prophecy->reveal();
+
+ $this->assertSame($formatted_number, $formatter->Format($raw_number, 'FieldName', $item));
+ }
+
+ public function keepCentsDataProvider()
+ {
+ return array(
+ 'long' => array('12.345000', '12.345', array('keep_cents' => 2)),
+ 'short' => array('12.300000', '12.30', array('keep_cents' => 2)),
+ 'exact+leading_zero' => array('12.030000', '12.03', array('keep_cents' => 2)),
+ 'very_long' => array('12.030050', '12.03005', array('keep_cents' => 2)),
+ 'no_decimals' => array('12.000000', '12.00', array('keep_cents' => 2)),
+ );
+ }
+
+}
Property changes on: branches/5.2.x/core/tests/kernel/utility/formatters/kFormatterTest.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+LF
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id
\ No newline at end of property

Event Timeline