<?php
/**
* @version	$Id: formatter.php 14241 2011-03-16 20:24:35Z alex $
* @package	In-Portal
* @copyright	Copyright (C) 1997 - 2009 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.
*/

class kFormatter extends kBase {

	/**
	 * Reference to category helper
	 *
	 * @var CategoryHelper
	 */
	var $_categoryHelper = null;

	function kFormatter()
	{
		parent::kBase();

		$this->_categoryHelper =& $this->Application->recallObject('CategoryHelper');
	}

	/**
	 * Replace FCK links like "@@ID@@" to real page urls, when "using_fck" option is set.
	 *
	 * @param string $text
	 * @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)
	{
		$ret = true;
		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';
			}
			$type_ok = preg_match('#int|integer|double|float|real|numeric|string#', $field_type);
			if ($field_type == 'string') {
				if (!$this->Application->isAdmin && isset($options['allow_html']) && $options['allow_html']) {
					// this allows to revert htmlspecialchars call for each field submitted on front-end
					$value = unhtmlentities($value);
				}
				return $value;
			}

			static $comma = null;
			static $thousands = null;
			if (is_null($comma) || is_null($thousands)) {
				$lang =& $this->Application->recallObject('lang.current');
				$comma = $lang->GetDBField('DecimalPoint');
				$thousands = $lang->GetDBField('ThousandSep');
			}

			$value = str_replace($thousands, '', $value);
			$value = str_replace($comma, '.', $value);

			if ($value != '' && $type_ok)
			{
				$ret = is_numeric($value);
				if($ret)
				{
					$f = 'is_'.$field_type;
					settype($value, $field_type);
					$ret = $f($value);
				}
			}
		}

		return $ret ? $value : false;
	}

	function TypeCastArray($src, &$object)
	{
		$dst = array();
		foreach ($src as $id => $row) {
			$tmp_row = array();
			foreach ($row as $fld => $value) {
				$tmp_row[$fld] = $this->TypeCast($value, $object->Fields[$fld]);
			}
			$dst[$id] = $tmp_row;
		}
		return $dst;
	}

//function Format($value, $options, &$errors)
	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) {
			$value = sprintf($format, $value);
		}

		if (preg_match('#int|integer|double|float|real|numeric#', $options['type'])) {
			$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 $object
	 * @return mixed
	 */
	function Parse($value, $field_name, &$object)
	{
		if ($value == '') {
			return NULL;
		}

		$options = $object->GetFieldOptions($field_name);
		$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 unknown_type $field
	 * @param unknown_type $value
	 * @param unknown_type $options
	 * @param unknown_type $object
	 */
	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 $object
	 */
	function UpdateMasterFields($field, $value, &$options, &$object)
	{

	}

/*	function GetErrorMsg($pseudo_error, $options)
	{
		if ( isset($options['error_msgs'][$pseudo_error]) ) {
			return $options['error_msgs'][$pseudo_error];
		}
		else {
			return $this->ErrorMsgs[$pseudo_error];
		}
	}*/

	function GetSample($field, &$options, &$object)
	{
		if (isset($options['sample_value'])) return $options['sample_value'];
	}

}