261 lines
7.9 KiB
PHP
261 lines
7.9 KiB
PHP
<?php
|
|
namespace nur\mapper\item;
|
|
|
|
use nur\A;
|
|
use nur\b\IllegalAccessException;
|
|
use nur\b\params\Tparametrable;
|
|
use nur\b\ValueException;
|
|
use nur\data\types\Metadata;
|
|
use nur\mapper\base\Mapper;
|
|
|
|
/**
|
|
* Class SchemaMapper
|
|
*
|
|
* --autogen-properties-and-methods--
|
|
* @method bool isUseKey()
|
|
* @method bool isEnsureKnownTypes()
|
|
* @method bool isRecursive()
|
|
* @method bool isEnsureTypes()
|
|
* @method bool isThrow()
|
|
* @method bool isKeepResults()
|
|
* @method bool isCheckRequired()
|
|
* @method array|null setSchema(?array $value)
|
|
* @method bool setUseKey(bool $value)
|
|
* @method bool setEnsureKnownTypes(bool $value)
|
|
* @method bool setRecursive(bool $value)
|
|
* @method bool setEnsureTypes(bool $value)
|
|
* @method bool setThrow(bool $value)
|
|
* @method bool setKeepResults(bool $value)
|
|
* @method bool setCheckRequired(bool $value)
|
|
*/
|
|
class SchemaMapper extends Mapper {
|
|
use Tparametrable;
|
|
|
|
protected function SCHEMA(): ?array {
|
|
return self::SCHEMA;
|
|
} const SCHEMA = null;
|
|
|
|
function __construct(?array $schema=null, ?iterable $source=null) {
|
|
parent::__construct($source);
|
|
$this->pp_setSchema($schema);
|
|
}
|
|
|
|
const MULTIPLEX_RESULTS_COLS = "cols";
|
|
const MULTIPLEX_RESULTS_ROWS = "rows";
|
|
|
|
const PARAMETRABLE_PARAMS_SCHEMA = [
|
|
"schema" => ["?array", null, "schéma des données"],
|
|
"use_key" => ["bool", false, "faut-il tenir compte des clés fournies par la source"],
|
|
"ensure_known_types" => ["bool", false, "faut-il vérifier et convertir les types connus?"],
|
|
"recursive" => ["bool", true, "faut-il appliquer les schémas de façon récursive"],
|
|
"ensure_types" => ["bool", true, "faut-il vérifier et convertir les types connus?"],
|
|
"throw" => ["bool", false, "faut-il lancer une exception si certains champs sont invalides?"],
|
|
"keep_results" => ["bool", false, "faut-il garder le résultat des analyses et l'insérer dans le flux?"],
|
|
"multiplex_results" => [["string"], null, "faut-il multiplexer champs et résultats d'analyse",
|
|
"allowed_values" => [self::MULTIPLEX_RESULTS_COLS, self::MULTIPLEX_RESULTS_ROWS],
|
|
],
|
|
"check_required" => ["bool", false, "faut-il vérifier que les champs requis soient présents"],
|
|
];
|
|
|
|
/** @var Metadata */
|
|
protected $md;
|
|
|
|
function pp_setSchema(?array $schema): self {
|
|
if ($schema === null) $schema = $this->SCHEMA();
|
|
if ($schema !== null) $this->md = new Metadata($schema);
|
|
return $this;
|
|
}
|
|
|
|
/** @var bool */
|
|
protected $ppUseKey;
|
|
|
|
/** @var bool */
|
|
protected $ppEnsureKnownTypes;
|
|
|
|
/** @var bool */
|
|
protected $ppRecursive;
|
|
|
|
/** @var bool */
|
|
protected $ppEnsureTypes;
|
|
|
|
/** @var bool */
|
|
protected $ppThrow;
|
|
|
|
/** @var bool */
|
|
protected $ppKeepResults;
|
|
|
|
/** @var string|null */
|
|
protected $ppMultiplexResults;
|
|
|
|
function pp_setMultiplexResults(string $multiplexResults): self {
|
|
switch ($multiplexResults) {
|
|
case "cols":
|
|
case "col":
|
|
case "c":
|
|
$multiplexResults = self::MULTIPLEX_RESULTS_COLS;
|
|
break;
|
|
case "rows":
|
|
case "row":
|
|
case "r":
|
|
$multiplexResults = self::MULTIPLEX_RESULTS_ROWS;
|
|
break;
|
|
default:
|
|
throw ValueException::unexpected_value($multiplexResults, [
|
|
self::MULTIPLEX_RESULTS_COLS,
|
|
self::MULTIPLEX_RESULTS_ROWS,
|
|
]);
|
|
}
|
|
$this->ppMultiplexResults = $multiplexResults;
|
|
return $this;
|
|
}
|
|
|
|
function setMultiplexResults(string $multiplexResults=self::MULTIPLEX_RESULTS_COLS): void {
|
|
$this->pp_setMultiplexResults($multiplexResults);
|
|
}
|
|
|
|
/** @var bool */
|
|
protected $ppCheckRequired;
|
|
|
|
const OKEY_NB_ERRORS_TOTAL = "nb_errors_total";
|
|
|
|
function getNbErrorsTotal(): int {
|
|
return $this->getOvalue(self::OKEY_NB_ERRORS_TOTAL);
|
|
}
|
|
|
|
protected function setup(): void {
|
|
$this->setOvalue(self::OKEY_NB_ERRORS_TOTAL, 0);
|
|
}
|
|
|
|
function mapper($item, $key=null) {
|
|
if (!$this->ppUseKey) $key = null;
|
|
$md = $this->md;
|
|
$md->ensureSchema($item, $key, ["recursive" => $this->ppRecursive]);
|
|
$itemResults = null;
|
|
if ($this->ppEnsureTypes) {
|
|
$md->verifix($item, $results, $this->ppThrow, $this->ppRecursive);
|
|
$nbErrors = 0;
|
|
foreach ($results as $result) {
|
|
if (!$result["valid"]) {
|
|
$nbErrors++;
|
|
$this->incOvalue(self::OKEY_NB_ERRORS_TOTAL);
|
|
}
|
|
}
|
|
if ($this->ppKeepResults) {
|
|
$item = [
|
|
"item" => $item,
|
|
"results" => $results,
|
|
"nb_errors" => $nbErrors,
|
|
];
|
|
} elseif ($this->ppMultiplexResults !== null) {
|
|
switch ($this->ppMultiplexResults) {
|
|
case "cols":
|
|
$mitem = ["[nb_errors]" => $nbErrors];
|
|
foreach ($item as $key => $value) {
|
|
$mitem[$key] = $value;
|
|
$result = A::get($results, $key);
|
|
if ($result !== null) {
|
|
$result = $result["valid"]? null: $result["error"];
|
|
}
|
|
$mitem["[${key}_error]"] = $result;
|
|
}
|
|
foreach ($md->getCikeys() as $key) {
|
|
$result = A::get($results, $key);
|
|
if ($result !== null) {
|
|
$result = $result["valid"]? null: $result["error"];
|
|
}
|
|
$mitem["[${key}_error]"] = $result;
|
|
}
|
|
$item = $mitem;
|
|
break;
|
|
case "rows":
|
|
# construire la ligne avec les résultats
|
|
$mitem = ["[nb_errors]" => $nbErrors];
|
|
foreach ($item as $key => $value) {
|
|
$result = A::get($results, $key);
|
|
if ($result !== null) {
|
|
$result = $result["valid"]? null: $result["error"];
|
|
}
|
|
$mitem[$key] = $result;
|
|
}
|
|
foreach ($md->getCikeys() as $key) {
|
|
$result = A::get($results, $key);
|
|
if ($result !== null) {
|
|
$result = $result["valid"]? null: $result["error"];
|
|
}
|
|
$mitem[$key] = $result;
|
|
}
|
|
$itemResults = $mitem;
|
|
# puis ajouter la colonne manquante dans l'objet original
|
|
$mitem = ["[nb_errors]" => $nbErrors];
|
|
foreach ($item as $key => $value) {
|
|
$mitem[$key] = $value;
|
|
}
|
|
foreach ($md->getCikeys() as $key) {
|
|
$mitem[$key] = null;
|
|
}
|
|
$item = $mitem;
|
|
break;
|
|
default:
|
|
throw IllegalAccessException::unexpected_state();
|
|
}
|
|
}
|
|
} elseif ($this->ppCheckRequired) {
|
|
$md->checkRequired($item);
|
|
}
|
|
if ($itemResults === null) return $item;
|
|
else return $this->mapTo([$item, $itemResults]);
|
|
}
|
|
|
|
#############################################################################
|
|
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*/[
|
|
'getSchema' => 'schema',
|
|
'isUseKey' => 'use_key',
|
|
'isEnsureKnownTypes' => 'ensure_known_types',
|
|
'isRecursive' => 'recursive',
|
|
'isEnsureTypes' => 'ensure_types',
|
|
'isThrow' => 'throw',
|
|
'isKeepResults' => 'keep_results',
|
|
'getMultiplexResults' => 'multiplex_results',
|
|
'isCheckRequired' => 'check_required',
|
|
];
|
|
const _AUTO_SETTERS = /*autogen*/[
|
|
'setSchema' => 'schema',
|
|
'setUseKey' => 'use_key',
|
|
'setEnsureKnownTypes' => 'ensure_known_types',
|
|
'setRecursive' => 'recursive',
|
|
'setEnsureTypes' => 'ensure_types',
|
|
'setThrow' => 'throw',
|
|
'setKeepResults' => 'keep_results',
|
|
'setMultiplexResults' => 'multiplex_results',
|
|
'setCheckRequired' => 'check_required',
|
|
];
|
|
#--autogen-dynamic--
|
|
}
|