modifs.mineures sans commentaires

This commit is contained in:
Jephté Clain 2025-03-23 08:06:40 +04:00
parent 7257654753
commit 26817d2826
4 changed files with 132 additions and 27 deletions

View File

@ -118,33 +118,71 @@ class KeyAccess extends AbstractAccess {
]);
}
function ensureAssoc(array $keys): void {
$index = 0;
function ensureAssoc(array $keys, ?array $params=null): void {
$dest =& $this->dest;
$prefix = $params["key_prefix"] ?? null;
$suffix = $params["key_suffix"] ?? null;
$index = 0;
foreach ($keys as $key) {
if ($dest !== null && array_key_exists($key, $dest)) continue;
if ($prefix !== null || $suffix !== null) {
$destKey = "$prefix$key$suffix";
} else {
# préserver les clés numériques
$destKey = $key;
}
if ($dest !== null && array_key_exists($destKey, $dest)) continue;
while (in_array($index, $keys, true)) {
$index++;
}
if ($dest !== null && array_key_exists($index, $dest)) {
$dest[$key] = $dest[$index];
$dest[$destKey] = $dest[$index];
unset($dest[$index]);
$index++;
}
}
}
function ensureKeys(array $defaults): void {
function ensureKeys(array $defaults, ?array $params=null): void {
$dest =& $this->dest;
$keys = array_keys($defaults);
$prefix = $params["key_prefix"] ?? null;
$suffix = $params["key_suffix"] ?? null;
foreach ($keys as $key) {
if ($dest === null || !array_key_exists($key, $dest)) {
$dest[$key] = $defaults[$key];
$destKey = "$prefix$key$suffix";
if ($dest === null || !array_key_exists($destKey, $dest)) {
$dest[$destKey] = $defaults[$key];
}
}
}
function ensureOrder(array $keys): void {
function ensureOrder(array $keys, ?array $params=null): void {
$dest =& $this->dest;
if ($dest === null) return;
$prefix = $params["key_prefix"] ?? null;
$suffix = $params["key_suffix"] ?? null;
if ($prefix !== null || $suffix !== null) {
foreach ($keys as &$key) {
$key = "$prefix$key$suffix";
}; unset($key);
}
$destKeys = array_keys($dest);
$keyCount = count($keys);
if (array_slice($destKeys, 0, $keyCount) === $keys) {
# si le tableau a déjà les bonnes clés dans le bon ordre, rien à faire
return;
}
$ordered = [];
foreach ($keys as $key) {
if (array_key_exists($key, $dest)) {
$ordered[$key] = $dest[$key];
unset($dest[$key]);
}
}
$preserveKeys = $params["preserve_keys"] ?? false;
if ($preserveKeys) $dest = cl::merge2($ordered, $dest);
else $dest = array_merge($ordered, $dest);
}
}

View File

@ -5,7 +5,9 @@ use nulib\StateException;
use nulib\str;
use ReflectionClass;
use ReflectionException;
use ReflectionNamedType;
use ReflectionProperty;
use stdClass;
class PropertyAccess extends AbstractAccess {
const PROTECT_DEST = true;
@ -32,24 +34,32 @@ class PropertyAccess extends AbstractAccess {
protected ?ReflectionProperty $property;
private function _getName(string $key): string {
return $this->mapNames? str::us2camel($key): $key;
}
private function _setName(?string $name): void {
if ($this->mapNames) $name = str::us2camel($name);
if ($name !== null) $name = $this->_getName($name);
$this->name = $name;
}
private function _setDest(?object $dest): void {
$this->dest = $dest;
private function _getProperty(?string $name, ?ReflectionClass $class, ?object $object=null): ?ReflectionProperty {
$property = null;
$name = $this->name;
if ($dest !== null && $name !== null) {
$class = new ReflectionClass($dest);
if ($class === null && $object !== null) {
$class = new ReflectionClass($object);
}
if ($class !== null && $name !== null) {
try {
$property = $class->getProperty($name);
$property->setAccessible(true);
} catch (ReflectionException $e) {
}
}
$this->property = $property;
return $property;
}
private function _setDest(?object $dest): void {
$this->dest = $dest;
$this->property = $this->_getProperty($this->name, null, $dest);
}
function reset(?object $dest, ?string $name=null): self {
@ -135,4 +145,39 @@ class PropertyAccess extends AbstractAccess {
if ($key === null) return $this;
return new ChainAccess($this, $key);
}
function ensureAssoc(array $keys, ?array $params=null): void {
# NOP
}
function ensureKeys(array $defaults, ?array $params=null): void {
$dest = $this->dest;
if ($dest === null) {
# comme ne connait pas la classe de l'objet destination, on n'essaie pas
# de le créer
return;
}
$class = new ReflectionClass($dest);
$keys = array_keys($defaults);
$prefix = $params["key_prefix"] ?? null;
$suffix = $params["key_suffix"] ?? null;
foreach ($keys as $key) {
$name = $this->_getName("$prefix$key$suffix");
$property = $this->_getProperty($name, $class);
if ($property !== null) {
$type = $property->getType();
if ($type !== null && !$property->isInitialized($dest) && $type->allowsNull()) {
# initialiser avec null au lieu de $defaults[$key] pour respecter le
# type de la propriété
$property->setValue($dest, null);
}
} elseif (!property_exists($dest, $name)) {
$dest->$name = $defaults[$key];
}
}
}
function ensureOrder(array $keys, ?array $params=null): void {
# NOP
}
}

View File

@ -126,9 +126,9 @@ class KeyAccessTest extends TestCase {
self::assertSame("", $a->get($default));
}
private function _ensureAssoc(?array $orig, ?array $expected, array $keys) {
private function _ensureAssoc(?array $orig, ?array $expected, array $keys, ?array $params=null) {
$v = $orig; $a = new KeyAccess($v);
$a->ensureAssoc($keys);
$a->ensureAssoc($keys, $params);
self::assertSame($expected, $v);
}
function testEnsureAssoc() {
@ -150,9 +150,9 @@ class KeyAccessTest extends TestCase {
$this->_ensureAssoc([1, 2], [1, "a" => 2], $keys);
}
private function _ensureKeys(?array $orig, ?array $expected, array $defaults) {
private function _ensureKeys(?array $orig, ?array $expected, array $defaults, ?array $params=null) {
$v = $orig; $a = new KeyAccess($v);
$a->ensureKeys($defaults);
$a->ensureKeys($defaults, $params);
self::assertSame($expected, $v);
}
function testEnsureKeys() {
@ -168,12 +168,27 @@ class KeyAccessTest extends TestCase {
$this->_ensureKeys(["a" => 1, "b" => 2, "c" => 3, "x"], ["a" => 1, "b" => 2, "c" => 3, "x"], $defaults);
}
private function _ensureAssocKeysOrder(?array $orig, ?array $expected, array $defaults) {
private function _ensureOrder(?array $orig, ?array $expected, array $keys, ?array $params=null) {
$v = $orig; $a = new KeyAccess($v);
$a->ensureOrder($keys, $params);
self::assertSame($expected, $v);
}
function testEnsureOrder() {
$keys = ["a", "b", "c"];
$this->_ensureOrder(null, null, $keys);
$this->_ensureOrder([], [], $keys);
$this->_ensureOrder([1], [1], $keys);
$this->_ensureOrder(["b" => 2, "a" => 1], ["a" => 1, "b" => 2], $keys);
$this->_ensureOrder(["c" => 3, "a" => 1], ["a" => 1, "c" => 3], $keys);
}
private function _ensureAssocKeysOrder(?array $orig, ?array $expected, array $defaults, ?array $params=null) {
$v = $orig; $a = new KeyAccess($v);
$keys = array_keys($defaults);
$a->ensureAssoc($keys);
$a->ensureKeys($defaults);
$a->ensureOrder($keys);
$a->ensureAssoc($keys, $params);
$a->ensureKeys($defaults, $params);
$a->ensureOrder($keys, $params);
self::assertSame($expected, $v);
}
function testEnsureAssocKeysOrder() {
@ -183,11 +198,18 @@ class KeyAccessTest extends TestCase {
$this->_ensureAssocKeysOrder([], ["a" => false, "b" => false, "c" => false], $defaults);
$this->_ensureAssocKeysOrder([1], ["a" => 1, "b" => false, "c" => false], $defaults);
$this->_ensureAssocKeysOrder([1, 2, 3], ["a" => 1, "b" => 2, "c" => 3], $defaults);
$this->_ensureAssocKeysOrder([1, 2, 3, 4], [3 => 4, "a" => 1, "b" => 2, "c" => 3], $defaults);
$this->_ensureAssocKeysOrder(["c" => 3, 1], ["c" => 3, "a" => 1, "b" => false], $defaults);
$this->_ensureAssocKeysOrder(["c" => 3, "b" => 2, 1], ["c" => 3, "b" => 2, "a" => 1], $defaults);
$this->_ensureAssocKeysOrder(["c" => 3, "b" => 2, "a" => 1], ["c" => 3, "b" => 2, "a" => 1], $defaults);
$this->_ensureAssocKeysOrder([1, 2, 3, 4], ["a" => 1, "b" => 2, "c" => 3, 4], $defaults);
$this->_ensureAssocKeysOrder([1, 2, 3, 4], ["a" => 1, "b" => 2, "c" => 3, 3 => 4], $defaults, [
"preserve_keys" => true,
]);
$this->_ensureAssocKeysOrder(["c" => 3, 1], ["a" => 1, "b" => false, "c" => 3], $defaults);
$this->_ensureAssocKeysOrder(["c" => 3, "b" => 2, 1], ["a" => 1, "b" => 2, "c" => 3], $defaults);
$this->_ensureAssocKeysOrder(["c" => 3, "b" => 2, "a" => 1], ["a" => 1, "b" => 2, "c" => 3], $defaults);
$this->_ensureAssocKeysOrder(["a" => 1, 2], ["a" => 1, "b" => 2, "c" => false], $defaults);
$this->_ensureAssocKeysOrder([2, "a" => 1], ["a" => 1, "b" => 2, "c" => false], $defaults);
$this->_ensureAssocKeysOrder([1], ["x_a" => 1, "x_b" => false, "x_c" => false], $defaults, [
"key_prefix" => "x_",
]);
}
}