$value] devient ["--my-arg", "$value"] * - ["myOpt" => true] devient ["--my-opt"] * - ["myOpt" => false] est omis * - les autres valeurs sont transformées en chaines puis ajoutée * * ainsi, ["myOpt" => "value", "myArg", "myBool" => true] * devient ["--my-opt", "value", "myArg", "--my-bool"] */ static function from_array(?array $array): array { $args = []; if ($array === null) return $args; $index = 0; foreach ($array as $arg => $value) { if ($value === false) continue; if ($arg === $index) { $index++; } else { $arg = str::us2camel($arg); $arg = str::camel2us($arg, false, "-"); $arg = str_replace("_", "-", $arg); $args[] = "--$arg"; if (is_array($value)) $value[] = "--"; elseif ($value === true) $value = null; } if (is_array($value)) { A::merge($args, array_map("strval", $value)); } elseif ($value !== null) { $args[] = "$value"; } } return $args; } private static function tint(string $value): int { return intval($value); } private static function tbool(string $value): bool { return boolval($value); } private static function tarray(string $value): ?array { if ($value === "") return null; $tmparray = explode(",", $value); $array = null; foreach ($tmparray as $tmpvalue) { [$tmpkey, $tmpvalue] = str::split_pair($tmpvalue); if ($tmpvalue === null) cv::swap($tmpkey, $tmpvalue); if ($tmpkey === null) { $array[] = $tmpvalue; } else { if (str::del_suffix($tmpkey, ":int")) { $tmpvalue = self::tint($tmpvalue); } elseif (str::del_suffix($tmpkey, ":bool")) { $tmpvalue = self::tbool($tmpvalue); } $array[$tmpkey] = $tmpvalue; } } 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" * qui devient l'argument boolval("value") * - "value" * qui devient l'argument "value" * * à la fin, la liste des arguments est retournée [$arguments...] * si le tableau $query est renseigné, il est en premier dans la liste des * arguments e.g [$query, $arguments...] */ static function build_method_args(?array $args): ?array { $query = null; $margs = []; $args ??= []; foreach ($args as $arg) { [$name, $value] = str::split_pair($arg, "="); if ($value === null) { if (str::del_prefix($name, "+")) { $value = true; } elseif (str::del_prefix($name, "-") || str::del_prefix($name, "~")) { $value = false; } elseif (str::del_prefix($name, "int:")) { $margs[] = self::tint($name); continue; } elseif (str::del_prefix($name, "bool:")) { $margs[] = self::tbool($name); continue; } elseif (str::del_prefix($name, "array:")) { if (str::del_prefix($name, "int:")) { $map = [self::class, "tint"]; } elseif (str::del_prefix($name, "bool:")) { $map = [self::class, "tbool"]; } else { $map = null; } $value = self::tarray($name); if ($map !== null) $value = array_map($map, $value); $margs[] = $value; continue; } else { $margs[] = $name; continue; } } 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; } } if ($query !== null) array_unshift($margs, $query); return $margs; } }