nur-sery/src/file/csv/AbstractReader.php

110 lines
3.0 KiB
PHP

<?php
namespace nur\sery\file\csv;
use nur\sery\A;
use nur\sery\php\time\Date;
use nur\sery\php\time\DateTime;
abstract class AbstractReader implements IReader {
const SCHEMA = null;
const HEADERS = null;
/** @var ?string nom du fichier depuis lequel lire */
const INPUT = null;
/** @var bool faut-il trimmer le champ avant de le traiter? */
const TRIM = true;
/** @var bool faut-il considérer les chaines vides comme null? */
const PARSE_EMPTY_AS_NULL = true;
/**
* @var bool faut-il forcer le type numérique pour une chaine numérique?
* si false, ne forcer le type numérique que si la chaine ne commence pas zéro
* i.e "06" est une chaine, alors "63" est un nombre
*/
const PARSE_NUMERIC = false;
/**
* @var bool faut-il forcer le type {@link Date} ou {@link DateTime} pour une
* chaine au bon format?
*/
const PARSE_DATE = true;
function __construct($input, ?array $params=null) {
if ($input !== null) $params["input"] = $input;
#
$this->schema = $params["schema"] ?? static::SCHEMA;
$this->headers = $params["headers"] ?? static::HEADERS;
$this->input = $params["input"] ?? static::INPUT;
$this->trim = boolval($params["trim"] ?? static::TRIM);
$this->parseEmptyAsNull = boolval($params["empty_as_null"] ?? static::PARSE_EMPTY_AS_NULL);
$this->parseNumeric = boolval($params["parse_numeric"] ?? static::PARSE_NUMERIC);
$this->parseDate = boolval($params["parse_date"] ?? static::PARSE_DATE);
}
protected ?array $schema;
protected ?array $headers;
protected $input;
protected bool $trim;
protected bool $parseEmptyAsNull;
protected bool $parseNumeric;
protected bool $parseDate;
protected int $isrc = 0, $idest = 0;
protected function cook(array &$row): bool {
if ($this->isrc == 0) {
# ligne d'en-tête
$headers = $this->headers;
if ($headers === null) {
if ($this->schema === null) $headers = null;
else $headers = array_keys($this->schema);
if ($headers === null) $headers = $row;
$this->headers = $headers;
}
return false;
}
A::ensure_size($row, count($this->headers));
$row = array_combine($this->headers, $row);
return true;
}
protected function verifixCol(&$col): void {
if ($this->trim && is_string($col)) {
$col = trim($col);
}
if ($this->parseEmptyAsNull && $col === "") {
# valeur vide --> null
$col = null;
}
if (!is_string($col)) return;
if ($this->parseDate) {
if (DateTime::isa_datetime($col, true)) {
# datetime
$col = new DateTime($col);
} elseif (DateTime::isa_date($col, true)) {
# date
$col = new Date($col);
}
if (!is_string($col)) return;
}
$parseNumeric = $this->parseNumeric || substr($col, 0, 1) !== "0";
if ($parseNumeric) {
$tmp = str_replace(",", ".", $col);
$float = strpos($tmp, ".") !== false;
if (is_numeric($tmp)) {
if ($float) $col = floatval($tmp);
else $col = intval($tmp);
}
}
}
}