From 4a9eecbda89c4df3a85e00f325e8eb97fb9b1dd5 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Wed, 16 Jul 2025 17:54:26 +0400 Subject: [PATCH] modifs.mineures sans commentaires --- php/src/app/args.php | 86 ++++++++++++++++++++++++++++++++++++++ php/tests/app/argsTest.php | 23 ++++++++++ 2 files changed, 109 insertions(+) diff --git a/php/src/app/args.php b/php/src/app/args.php index 3804bbc..db56ce1 100644 --- a/php/src/app/args.php +++ b/php/src/app/args.php @@ -4,6 +4,7 @@ namespace nulib\app; use nulib\A; use nulib\cl; use nulib\cv; +use nulib\file; use nulib\str; class args { @@ -71,17 +72,102 @@ class args { return $array; } + /** + * convertir une liste d'arguments en tableau qui est utilisable comme un + * filtre de base de données ou des données d'une requête REST. les arguments + * peuvent être de la forme: + * - "name=value" + * qui devient dans le tableau ["name" => "value"] + * - "+arg" ou "arg" + * qui devient dans le tableau ["arg" => true] + * - "-arg" ou "~arg" + * qui est stocké dans le tableau $query ["arg" => false] + * + * si $allow_file == true, les formes d'arguments suivantes sont reconnues + * aussi: + * - "name=@file" (1 argument) OU + * "name=@" "file" (2 arguments) + * qui deviennent ["name" => new FileReader(file)] + */ + static function build_query(?array $args, bool $allow_file=true): ?array { + $query = null; + $args ??= []; + $keys = array_keys($args); + $index = 0; + $count = count($keys); + while ($index < $count) { + $arg = $args[$keys[$index++]]; + [$name, $value] = str::split_pair($arg, "="); + $checkType = true; + if ($value === null) { + if (str::del_prefix($name, "+")) { + $value = true; + } elseif (str::del_prefix($name, "-") || str::del_prefix($name, "~")) { + $value = false; + } else { + $value = true; + } + } elseif ($allow_file) { + if ($value === "@") { + $value = $args[$keys[$index++]]; + $value = file::reader($value); + $checkType = false; + } elseif (substr($value, 0, 1) === "@") { + $value = substr($value, 1); + $value = file::reader($value); + $checkType = false; + } + } + if ($checkType) { + if (str::del_suffix($name, ":int")) { + if (str::del_suffix($name, ":array")) { + $value = array_map([self::class, "tint"], self::tarray($value)); + } else { + $value = self::tint($value); + } + } elseif (str::del_suffix($name, ":bool")) { + if (str::del_suffix($name, ":array")) { + $value = array_map([self::class, "tbool"], self::tarray($value)); + } else { + $value = self::tbool($value); + } + } elseif (str::del_suffix($name, ":array")) { + $value = self::tarray($value); + if (str::del_suffix($name, ":int")) { + $value = array_map([self::class, "tint"], $value); + } elseif (str::del_suffix($name, ":bool")) { + $value = array_map([self::class, "tbool"], $value); + } + } + } + if (cl::has($query, $name)) { + A::ensure_array($query[$name]); + $query[$name][] = $value; + } else { + $query[$name] = $value; + } + } + return $query; + } + /** * convertir une liste d'arguments de façon qu'ils soient utilisables pour un * appel de méthode. les arguments peuvent être de la forme: * - "name=value" * qui est stocké dans le tableau $query ["name" => "value"] + * il est possible de forcer le type de la valeur avec l'un des suffixes + * :int, :bool ou :array, e.g + * un entier: "name:int=42" + * un tableau de chaines: "name:array=a,b,c" + * un tableau d'entiers: "name:array:int=1,2,3" * - "+arg" * qui est stocké dans le tableau $query ["arg" => true] * - "-arg" ou "~arg" * qui est stocké dans le tableau $query ["arg" => false] * - "array:sval,key:aval,..." * qui devient l'argument ["sval", "key" => "aval", ...] + * il est possible de forcer le types des éléments avec le préfixe int: ou + * bool: e.g "array:int:1,2,3" * - "int:value" * qui devient l'argument intval("value") * - "bool:value" diff --git a/php/tests/app/argsTest.php b/php/tests/app/argsTest.php index f4f5619..c0a894c 100644 --- a/php/tests/app/argsTest.php +++ b/php/tests/app/argsTest.php @@ -24,6 +24,27 @@ class argsTest extends TestCase { self::assertSame(["x", "1", "2", "3", "y"], args::from_array(["x", [1, 2, 3], "y"])); } + function testBuild_query() { + self::assertSame(null, args::build_query(null)); + self::assertSame(null, args::build_query([])); + + self::assertSame(["a" => true], args::build_query(["a"])); + self::assertSame(["a" => true], args::build_query(["+a"])); + self::assertSame(["a" => false], args::build_query(["-a"])); + self::assertSame(["a" => false], args::build_query(["~a"])); + self::assertSame(["x" => "a"], args::build_query(["x=a"])); + self::assertSame(["x" => 0], args::build_query(["x:int=0"])); + self::assertSame(["x" => 42], args::build_query(["x:int=42"])); + self::assertSame(["x" => false], args::build_query(["x:bool=0"])); + self::assertSame(["x" => true], args::build_query(["x:bool=42"])); + self::assertSame(["x" => ["a", "b"]], args::build_query(["x:array=a,b"])); + self::assertSame(["x" => [0, 42]], args::build_query(["x:array:int=0,42"])); + self::assertSame(["x" => [0, 42]], args::build_query(["x:int:array=0,42"])); + + self::assertSame(["x" => "a", "y" => "b"], args::build_query(["x=a", "y=b"])); + self::assertSame(["x" => ["a", "b"]], args::build_query(["x=a", "x=b"])); + } + function testBuild_method_args() { self::assertSame([], args::build_method_args(null)); self::assertSame([], args::build_method_args([])); @@ -67,5 +88,7 @@ class argsTest extends TestCase { self::assertSame([["x" => [0, 42]]], args::build_method_args(["x:int:array=0,42"])); self::assertSame([["x" => "a", "y" => "b"], "a", "b"], args::build_method_args(["x=a", "a", "y=b", "b"])); + + self::assertSame([["x" => ["a", "b"]]], args::build_method_args(["x=a", "x=b"])); } }