145 lines
4.0 KiB
PHP
145 lines
4.0 KiB
PHP
<?php
|
|
namespace nur\mapper\csv;
|
|
|
|
use nur\b\params\Tparametrable;
|
|
use nur\mapper\item\Seq2AssocMapper;
|
|
|
|
/**
|
|
* Class Csv2AssocMapper: mapper qui analyse un flux de lignes au format CSV et
|
|
* qui produit un flux de tableaux associatifs
|
|
*
|
|
* NB: cette classe ne supporte pas les flux CSV multi-lignes, contrairement à
|
|
* {@link CsvReader}
|
|
*
|
|
* --autogen-properties-and-methods--
|
|
* @method int getSkipLines()
|
|
* @method bool|null setParseHeaders(?bool $value)
|
|
* @method array|null setHeaders(?array $value)
|
|
* @method int setSkipLines(int $value)
|
|
* @method string|null setMapEmpty(?string $value)
|
|
*/
|
|
class Csv2AssocMapper extends AbstractCsvMapper {
|
|
use Tparametrable;
|
|
|
|
function __construct(?iterable $source=null) {
|
|
$this->seq2assoc = new Seq2AssocMapper();
|
|
parent::__construct($source);
|
|
}
|
|
|
|
const PARAMETRABLE_PARAMS_SCHEMA = [
|
|
"parse_headers" => ["?bool", null, "faut-il analyser le premier élément du flux pour calculer la liste des en-têtes en entrée?"],
|
|
"headers" => ["?array", null, "liste et ordre des en-têtes en entrée"],
|
|
"skip_lines" => ["int", 0, "nombre de lignes à sauter en entrée"],
|
|
"map_empty" => ["?string", null, "valeur adoptée pour les chaines vides"],
|
|
];
|
|
|
|
/** @var Seq2AssocMapper */
|
|
private $seq2assoc;
|
|
function pp_setParseHeaders(?bool $parseHeaders): void {
|
|
$this->seq2assoc->setParseKeys($parseHeaders);
|
|
}
|
|
function pp_setHeaders(?array $headers): void {
|
|
$this->seq2assoc->setKeys($headers);
|
|
}
|
|
|
|
/** @var int */
|
|
protected $ppSkipLines;
|
|
|
|
/** @var bool */
|
|
protected $shouldMapEmpty = false;
|
|
|
|
protected $ppMapEmpty = null;
|
|
|
|
function pp_setMapEmpty($mapEmpty=null): void {
|
|
$this->shouldMapEmpty = true;
|
|
$this->ppMapEmpty = $mapEmpty;
|
|
}
|
|
|
|
protected function setup(): void {
|
|
parent::setup();
|
|
$this->seq2assoc->ensureSetup();
|
|
}
|
|
|
|
function _parseLine(): bool {
|
|
if ($this->ppSkipLines > 0) {
|
|
$this->ppSkipLines--;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/** @var array */
|
|
private $headers;
|
|
|
|
function _checkHeader(array $values): bool {
|
|
if ($this->ppMultiSchema && count($values) === 1 && $values[0] === null) {
|
|
# ligne vide, changer de schéma
|
|
$this->seq2assoc->setKeys(null);
|
|
return true;
|
|
}
|
|
return $this->seq2assoc->_checkKeys($values);
|
|
}
|
|
|
|
function _mapRow(array $values): array {
|
|
$row = $this->seq2assoc->_mapValues($values);
|
|
foreach ($row as &$value) {
|
|
if ($value === "" && $this->shouldMapEmpty) $value = $this->ppMapEmpty;
|
|
}; unset($value);
|
|
return $row;
|
|
}
|
|
|
|
function mapper($item) {
|
|
if (!$this->_parseLine()) return $this->mapToNone();
|
|
$values = str_getcsv($item, $this->separator, $this->enclosure, $this->escape);
|
|
if ($this->_checkHeader($values)) return $this->mapToNone();
|
|
return $this->_mapRow($values);
|
|
}
|
|
|
|
protected function teardown(): void {
|
|
parent::teardown();
|
|
$this->seq2assoc->close();
|
|
}
|
|
|
|
#############################################################################
|
|
const _AUTOGEN_CONSTS = [
|
|
"" => [self::class, "_autogen_consts"],
|
|
];
|
|
const _AUTOGEN_LITERALS = /*autogen*/[
|
|
[
|
|
\nur\b\params\parametrable_utils::class,
|
|
'\\nur\\b\\params\\parametrable_utils::class',
|
|
],
|
|
[
|
|
self::PARAMETRABLE_PARAMS_SCHEMA,
|
|
'self::PARAMETRABLE_PARAMS_SCHEMA',
|
|
],
|
|
];
|
|
const _AUTOGEN_METHODS = /*autogen*/[
|
|
[
|
|
\nur\b\params\parametrable_utils::class,
|
|
'_autogen_methods_getters',
|
|
self::PARAMETRABLE_PARAMS_SCHEMA,
|
|
null,
|
|
],
|
|
[
|
|
\nur\b\params\parametrable_utils::class,
|
|
'_autogen_methods_setters',
|
|
self::PARAMETRABLE_PARAMS_SCHEMA,
|
|
null,
|
|
],
|
|
];
|
|
const _AUTO_GETTERS = /*autogen*/[
|
|
'getParseHeaders' => 'parse_headers',
|
|
'getHeaders' => 'headers',
|
|
'getSkipLines' => 'skip_lines',
|
|
'getMapEmpty' => 'map_empty',
|
|
];
|
|
const _AUTO_SETTERS = /*autogen*/[
|
|
'setParseHeaders' => 'parse_headers',
|
|
'setHeaders' => 'headers',
|
|
'setSkipLines' => 'skip_lines',
|
|
'setMapEmpty' => 'map_empty',
|
|
];
|
|
#--autogen-dynamic--
|
|
}
|