<?php
/** class Is4NaC
 * @author: Jörg Reinholz, fastix WebDesign & Consult, Kassel (Germany), https://www.fastix.org
 * @License: GPL, LGPL or MPL. Show https://code.fastix.org/lizenz.php
 * 
 * This class try to become a float for input-strings in a row of international formats:
 * - Many peoples using the point as as decimal-delimiter a few of chars as thousender-delimiter.
 * - Germans use using the komma (",") as decimal-delimiter an the pooint as thousender-delimiter.
 * - minus sign at the beginning, minus sign at the end
 * 
 * Public-Propertys:
 * 
 * @$outputFormat: String. Show http://php.net/manual/function.sprintf.php
 * 
 * Methods: 
 * 
 * @setValue(string)		: input the string, save the number, returns the formatet number or false
 * @setDecimals(integer)	: Set the number of digits after the decimal point.
 * @setRoundMethod(const)	: Show http://php.net/manual/function.round.php
 * 
 * @getValue				: returns the formatet number or false 
 * @getValueRounded()		: Get the safed number rounded
 * @getFormated()			: Get the safed number rounded and formated.
*/ 

class Is4NaC {
	# Input-speculator for Numbers & Currency
	
	public  $outputFormat = '€ %01.2f';
	private $decimals     = 2;
	private $input         = '';
	private $value        = 0;
	private $arCommata    = array( '.', ',' );
	private $roundMethod  = PHP_ROUND_HALF_EVEN;
	private $maxDecimals  = 14;
		
	function __construct() {
		
		/*
		 * I think only Germans use the ',' as decimal-separator
		*/
		
		if ( isset ( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) {
			list( $FirstLang, $dummy ) = explode( ',', $_SERVER['HTTP_ACCEPT_LANGUAGE'], 2 );
			if ('de' == strtolower( $FirstLang ) ) {
				$this -> arCommata=[','];
			} else {
				$this -> arCommata=['.'];
			}
		}
		return true;
	}
		
	function setValue( $s ) {
		$s = trim( preg_replace( '/^[^0-9,.-]*/', '', $s ) );
		if ( '' == $s ) {
			$this -> value = false;
			return false;
		}
		$mPos = strpos( $s, '-' );
		if ( 0 === $mPos or ( strlen( $s ) -1 ) == $mPos ) {
				$prefix = -1;
		} else {
				$prefix = 1;
		}

		$kommata = false;
		if ( false !== strpos( $s, '.' ) and false !== strpos( $s, ',' ) ) {
			$arCommata = [ '.', ',' ];
		} else {
			$arCommata = $this -> arCommata;
		}
		#print_r( $arCommata ); echo "<br>";
		$posMin  = PHP_INT_MAX;
		$sRevers = strrev( $s );
		if ( count ( $arCommata ) ) {
			foreach ( $arCommata as $d ) {
				if ( 1 == substr_count( $s, $d ) ) {
					$pos = strpos( $sRevers, $d );
					if ( false !== $pos && $pos < $posMin ) {
						$posMin  = $pos;
						$kommata = $d;
					}
				}
			}
		}
		if ( $kommata ) {
			list ( $intPart, $decPart ) = explode ( $kommata, $s, 2 );
			$intPart = preg_replace( '/[^0-9]/', '' , $intPart );
			$decPart = preg_replace( '/[^0-9]/', '' , $decPart );
			$val = (float)( "$intPart" . '.' . "$decPart" );
			if ( 0 > $val ) {
				$this -> value = $val;
			} else {
				$this -> value = $prefix * $val;
			}
		} else {
			$val = (float) preg_replace( '/[^0-9]/', '' , $s );
			if ( 0 > $val ) {
				$this -> value = $val;
			} else {
				$this -> value = $prefix * $val;
			}
		}
		return $this -> getFormated();
	}
	
	function getFormated( $outputFormat = false ) {
			if ( false === $outputFormat ) { 
				$outputFormat = $this->outputFormat;
			}
			return sprintf( $outputFormat, $this -> getValueRounded() );
	}
	
	function getValue () {
			return $this -> value;
	}
	
	function getValueRounded () {
			return round( $this -> value, $this -> decimals, $this -> roundMethod );
	}
	
	function setDecimals( $i ) {
		if ( false === $i ) {
			$this -> decimals = $this -> maxDecimals;
		}
		elseif ( $i == intval ( $i ) ) {
			$this -> decimals = intval( $i );
			return true;
		} else {
			return false;
		}	
	}
	
	function setRoundMethod ( $RoundMethod ) {
		if ( in_array( $RoundMethod, array ( PHP_ROUND_HALF_UP, PHP_ROUND_HALF_DOWN, PHP_ROUND_HALF_EVEN, PHP_ROUND_HALF_ODD ) ) ) {
			$this -> roundMethod = $RoundMethod;
			return true;
		} else {
			trigger_error( "(Caller: ) $RoundMethod not known. Only PHP_ROUND_HALF_UP, PHP_ROUND_HALF_DOWN, PHP_ROUND_HALF_EVEN, PHP_ROUND_HALF_ODD are allowed.", E_USER_ERROR );
		}
	}

}

/** function Is4NaC (string [, $decimals=false [, $format='%01.2f' [, ]];
 * 
 * This function use the class Is4NaC to try to become a float for input-strings in a row of international formats:
 
 * Parameters: 
 * 
 * @$string					: The input.
 * @$decimals				: Set the number of digits after the decimal point. If not set: 2.
 * @$format					: Set the number-format for the return. if not set: '%01.2f'
 * @roundMethod(const)		: Show http://php.net/manual/function.round.php
 * 
 * @Return:
 * string					: the rounded and formatet number
 
*/ 

function Is4NaC ( $string, $decimals=false, $format='%01.2f', $roundMethod=PHP_ROUND_HALF_EVEN ) {
	$is = new Is4NaC();
	$is -> outputFormat = $format;
	$is -> setDecimals ( $decimals );
	$is -> setRoundMethod( $roundMethod );
	$r = $is -> setValue( $string );
	if ( false === $format or 'none' === $format )  {
		return $is->getValueRounded();
	} elseif (false === $decimals )  {
		return $is->getValue();
	} else {
		return $r;
	}
}
