mirror of
https://github.com/devcode-it/openstamanager.git
synced 2025-06-05 22:09:38 +02:00
Aggiunta di un controllo per evitare la conversione erronea di numeri particolari (Partita IVA, ...) nel caso sia utilizzata l'estensione intl.
552 lines
14 KiB
PHP
552 lines
14 KiB
PHP
<?php
|
|
|
|
namespace Intl;
|
|
|
|
use DateTime;
|
|
use NumberFormatter;
|
|
|
|
/**
|
|
* Classe per gestire la formattazione di date e numeri in convenzioni differenti.
|
|
*
|
|
* @since 2.3
|
|
*/
|
|
class Formatter
|
|
{
|
|
protected static $standards = [
|
|
'timestamp' => 'Y-m-d H:i:s',
|
|
'date' => 'Y-m-d',
|
|
'time' => 'H:i:s',
|
|
'number' => [
|
|
'decimals' => '.',
|
|
'thousands' => '',
|
|
],
|
|
];
|
|
|
|
/** @var NumberFormatter|array Oggetto dedicato alla formattazione dei numeri */
|
|
protected $numberFormatter;
|
|
protected $precision;
|
|
|
|
/** @var string Pattern per i timestamp */
|
|
protected $timestampPattern;
|
|
/** @var string Pattern per le date */
|
|
protected $datePattern;
|
|
/** @var string Pattern per gli orari */
|
|
protected $timePattern;
|
|
|
|
public function __construct($locale, $timestamp = null, $date = null, $time = null, $number = [])
|
|
{
|
|
if (class_exists('NumberFormatter')) {
|
|
$this->numberFormatter = new NumberFormatter($locale, NumberFormatter::DECIMAL);
|
|
} else {
|
|
$this->numberFormatter = $number;
|
|
}
|
|
|
|
$this->setTimestampPattern($timestamp);
|
|
|
|
$this->setDatePattern($date);
|
|
|
|
$this->setTimePattern($time);
|
|
}
|
|
|
|
/**
|
|
* Restituisce gli elementi di separazione secondo la formattazione in utilizzo.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getStandardFormats()
|
|
{
|
|
return static::$standards;
|
|
}
|
|
|
|
/**
|
|
* Restituisce gli elementi di separazione secondo la formattazione in utilizzo.
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function format($value)
|
|
{
|
|
if (!empty($value)) {
|
|
if ($this->isStandardDate($value)) {
|
|
$value = $this->formatDate($value);
|
|
} elseif ($this->isStandardTime($value)) {
|
|
$value = $this->formatTime($value);
|
|
} elseif ($this->isStandardTimestamp($value)) {
|
|
$value = $this->formatTimestamp($value);
|
|
} elseif ($this->isStandardNumber($value)) {
|
|
$value = $this->formatNumber($value);
|
|
}
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Restituisce gli elementi di separazione secondo la formattazione in utilizzo.
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function parse($value)
|
|
{
|
|
if (!empty($value)) {
|
|
if ($this->isFormattedDate($value)) {
|
|
$value = $this->parseDate($value);
|
|
} elseif ($this->isFormattedTime($value)) {
|
|
$value = $this->parseTime($value);
|
|
} elseif ($this->isFormattedTimestamp($value)) {
|
|
$value = $this->parseTimestamp($value);
|
|
} elseif ($this->isFormattedNumber($value)) {
|
|
$value = $this->parseNumber($value);
|
|
}
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
// Gestione della conversione dei numeri
|
|
|
|
/**
|
|
* Converte un numero da una formattazione all'altra.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return string
|
|
*/
|
|
public function formatNumber($value, $decimals = null)
|
|
{
|
|
$value = trim($value);
|
|
|
|
if (isset($decimals)) {
|
|
$original = $this->getPrecision();
|
|
$this->setPrecision($decimals);
|
|
}
|
|
|
|
if (is_object($this->numberFormatter)) {
|
|
$result = $this->numberFormatter->format($value);
|
|
} else {
|
|
$number = number_format($value, $this->getPrecision(), $this->getStandardFormats()['number']['decimals'], $this->getStandardFormats()['number']['thousands']);
|
|
|
|
$result = $this->customNumber($number, $this->getStandardFormats()['number'], $this->getNumberSeparators());
|
|
}
|
|
|
|
if (isset($decimals)) {
|
|
$this->setPrecision($original);
|
|
}
|
|
|
|
return is_numeric($value) ? $result : false;
|
|
}
|
|
|
|
/**
|
|
* Converte un numero da una formattazione all'altra.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return string
|
|
*/
|
|
public function parseNumber($value)
|
|
{
|
|
if ($value[0] == '+' || $value[0] == '-') {
|
|
$sign = $value[0];
|
|
$value = substr($value, 1);
|
|
}
|
|
|
|
// Controllo sull'effettiva natura del numero
|
|
$integer = str_replace(array_values($this->getNumberSeparators()), '', $value);
|
|
if (!ctype_digit($integer) || (strlen($integer) != strlen((int) $integer))) {
|
|
return false;
|
|
}
|
|
|
|
$value = $sign.$value;
|
|
|
|
if (is_object($this->numberFormatter)) {
|
|
$result = $this->numberFormatter->parse($value);
|
|
} else {
|
|
$result = $this->customNumber($value, $this->getNumberSeparators(), $this->getStandardFormats()['number']);
|
|
}
|
|
|
|
$result = is_numeric($result) ? floatval($result) : false;
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Controlla se l'elemento indicato è un numero.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isStandardNumber($value)
|
|
{
|
|
$result = $this->formatNumber($value);
|
|
|
|
return !is_bool($result);
|
|
}
|
|
|
|
/**
|
|
* Controlla se l'elemento indicato è un numero.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isFormattedNumber($value)
|
|
{
|
|
$result = $this->parseNumber($value);
|
|
|
|
return !is_bool($result);
|
|
}
|
|
|
|
/**
|
|
* Imposta la precisione di default per i numeri da formattare.
|
|
*
|
|
* @param int $decimals
|
|
*/
|
|
public function setPrecision($decimals)
|
|
{
|
|
if (is_object($this->numberFormatter)) {
|
|
$this->numberFormatter->setAttribute(NumberFormatter::FRACTION_DIGITS, $decimals);
|
|
} else {
|
|
$this->precision = $decimals;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Restituisce la precisione di default per i numeri da formattare.
|
|
*
|
|
* @return int
|
|
*/
|
|
public function getPrecision()
|
|
{
|
|
return is_object($this->numberFormatter) ? $this->numberFormatter->getAttribute(NumberFormatter::FRACTION_DIGITS) : $this->precision;
|
|
}
|
|
|
|
/**
|
|
* Restituisce gli elementi di separazione secondo la formattazione in utilizzo.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getNumberSeparators()
|
|
{
|
|
return [
|
|
'decimals' => is_object($this->numberFormatter) ? $this->numberFormatter->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL) : $this->numberFormatter['decimals'],
|
|
'thousands' => is_object($this->numberFormatter) ? $this->numberFormatter->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL) : $this->numberFormatter['thousands'],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Converte l'elemento in una rappresentazione numerica.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return array
|
|
*/
|
|
public function customNumber($value, $current, $format)
|
|
{
|
|
$value = trim($value);
|
|
|
|
if (strlen($value) == 0) {
|
|
return false;
|
|
}
|
|
|
|
$sign = null;
|
|
if ($value[0] == '+' || $value[0] == '-') {
|
|
$sign = $value[0];
|
|
$value = trim(substr($value, 1));
|
|
} elseif (!is_numeric($value[0])) {
|
|
return false;
|
|
}
|
|
|
|
if (strlen($value) == 0) {
|
|
return false;
|
|
}
|
|
|
|
$pieces = explode($current['decimals'], $value);
|
|
if (count($pieces) > 2) {
|
|
return false;
|
|
}
|
|
$integer = $pieces[0];
|
|
$decimal = (isset($pieces[1])) ? $pieces[1] : null;
|
|
|
|
if (!empty($current['thousands'])) {
|
|
$error = true;
|
|
if (floor(strlen($integer) / 4) == substr_count($integer, $current['thousands'])) {
|
|
$values = str_split(strrev($integer), 4);
|
|
|
|
foreach ($values as $key => $value) {
|
|
if (strlen($value) == 4 && ends_with($value, $current['thousands'])) {
|
|
$values[$key] = substr($value, 0, -1);
|
|
}
|
|
}
|
|
|
|
$integer = strrev(implode($values));
|
|
|
|
$error = substr_count($integer, $current['thousands']);
|
|
}
|
|
|
|
if (!empty($error)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!ctype_digit($integer) || (strlen($integer) != strlen((int) $integer)) || (isset($decimal) && !ctype_digit($decimal))) {
|
|
return false;
|
|
}
|
|
|
|
$result = $sign.number_format($integer, 0, '', $format['thousands']);
|
|
|
|
if (isset($decimal)) {
|
|
$result .= $format['decimals'].$decimal;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
// Gestione della conversione dei timestamp
|
|
|
|
/**
|
|
* Converte un timestamp da una formattazione all'altra.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return string
|
|
*/
|
|
public function formatTimestamp($value)
|
|
{
|
|
$object = DateTime::createFromFormat(static::$standards['timestamp'], $value);
|
|
$result = is_object($object) ? $object->format($this->getTimestampPattern()) : false;
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Converte un timestamp da una formattazione all'altra.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return string
|
|
*/
|
|
public function parseTimestamp($value)
|
|
{
|
|
$object = DateTime::createFromFormat($this->getTimestampPattern(), $value);
|
|
$result = is_object($object) ? $object->format(static::$standards['timestamp']) : false;
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Controlla se l'elemento indicato è un timestamp.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isStandardTimestamp($value)
|
|
{
|
|
$result = $this->formatTimestamp($value);
|
|
|
|
return !is_bool($result);
|
|
}
|
|
|
|
/**
|
|
* Controlla se l'elemento indicato è un timestamp.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isFormattedTimestamp($value)
|
|
{
|
|
$result = $this->parseTimestamp($value);
|
|
|
|
return !is_bool($result);
|
|
}
|
|
|
|
/**
|
|
* Restituisce il formato del timestamp.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getTimestampPattern($type = null)
|
|
{
|
|
return $this->timestampPattern;
|
|
}
|
|
|
|
/**
|
|
* Imposta il formato del timestamp.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function setTimestampPattern($pattern)
|
|
{
|
|
return $this->timestampPattern = $pattern;
|
|
}
|
|
|
|
// Gestione della conversione delle date
|
|
|
|
/**
|
|
* Converte una data da una formattazione all'altra.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return string
|
|
*/
|
|
public function formatDate($value)
|
|
{
|
|
$object = DateTime::createFromFormat(static::$standards['date'], $value);
|
|
|
|
// Fallback per la gestione dei timestamp
|
|
$object = !is_object($object) ? DateTime::createFromFormat(static::$standards['timestamp'], $value) : $object;
|
|
|
|
$result = is_object($object) ? $object->format($this->getDatePattern()) : false;
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Converte una data da una formattazione all'altra.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return string
|
|
*/
|
|
public function parseDate($value)
|
|
{
|
|
$object = DateTime::createFromFormat($this->getDatePattern(), $value);
|
|
$result = is_object($object) ? $object->format(static::$standards['date']) : false;
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Controlla se l'elemento indicato è una data.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isStandardDate($value)
|
|
{
|
|
$result = $this->formatDate($value);
|
|
|
|
return !is_bool($result);
|
|
}
|
|
|
|
/**
|
|
* Controlla se l'elemento indicato è una data.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isFormattedDate($value)
|
|
{
|
|
$result = $this->parseDate($value);
|
|
|
|
return !is_bool($result);
|
|
}
|
|
|
|
/**
|
|
* Restituisce il formato del timestamp.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getDatePattern($type = null)
|
|
{
|
|
return $this->datePattern;
|
|
}
|
|
|
|
/**
|
|
* Imposta il formato del timestamp.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function setDatePattern($pattern)
|
|
{
|
|
return $this->datePattern = $pattern;
|
|
}
|
|
|
|
// Gestione della conversione degli orarii
|
|
|
|
/**
|
|
* Converte un orario da una formattazione all'altra.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return string
|
|
*/
|
|
public function formatTime($value)
|
|
{
|
|
$object = DateTime::createFromFormat(static::$standards['time'], $value);
|
|
|
|
// Fallback per la gestione dei timestamp
|
|
$object = !is_object($object) ? DateTime::createFromFormat(static::$standards['timestamp'], $value) : $object;
|
|
|
|
$result = is_object($object) ? $object->format($this->getTimePattern()) : false;
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Converte un orario da una formattazione all'altra.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return string
|
|
*/
|
|
public function parseTime($value)
|
|
{
|
|
$object = DateTime::createFromFormat($this->getTimePattern(), $value);
|
|
$result = is_object($object) ? $object->format(static::$standards['time']) : false;
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Controlla se l'elemento indicato è un orario.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isStandardTime($value)
|
|
{
|
|
$result = $this->formatTime($value);
|
|
|
|
return !is_bool($result);
|
|
}
|
|
|
|
/**
|
|
* Controlla se l'elemento indicato è un orario.
|
|
*
|
|
* @param string $value
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isFormattedTime($value)
|
|
{
|
|
$result = $this->parseTime($value);
|
|
|
|
return !is_bool($result);
|
|
}
|
|
|
|
/**
|
|
* Restituisce il formato del orario.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getTimePattern($type = null)
|
|
{
|
|
return $this->timePattern;
|
|
}
|
|
|
|
/**
|
|
* Imposta il formato del orario.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function setTimePattern($pattern)
|
|
{
|
|
return $this->timePattern = $pattern;
|
|
}
|
|
}
|