diff --git a/src/sys/IContent.php b/src/sys/IContent.php index d5e2412..c7a2728 100644 --- a/src/sys/IContent.php +++ b/src/sys/IContent.php @@ -2,7 +2,8 @@ namespace nur\sery\sys; /** - * Interface IContent: un objet capable de produire du contenu à afficher + * Interface IContent: un objet capable de produire du contenu à afficher. le + * contenu retourné doit être pris tel quel,sans plus d'analyse */ interface IContent { /** retourner le contenu à afficher */ diff --git a/src/sys/IStaticContent.php b/src/sys/IStaticContent.php new file mode 100644 index 0000000..1721ae9 --- /dev/null +++ b/src/sys/IStaticContent.php @@ -0,0 +1,9 @@ +print(); $dest[] = ob_get_clean(); return $dest; - } elseif (!is_iterable($contents)) { + } elseif (is_scalar($contents)) { $dest[] = $contents; return $dest; + } elseif (!is_iterable($contents)) { + $dest[] = strval($contents); + return $dest; } + # sinon parcourir $contents foreach ($contents as $value) { - self::flatten($value, $dest); + if ($value === null) continue; + elseif (is_scalar($value)) $dest[] = $value; + else self::flatten($value, $dest); } return $dest; } @@ -41,6 +63,10 @@ class content { if ($quote) $contents = htmlspecialchars($contents); $dest[] = $contents; return $dest; + } elseif ($contents instanceof IStaticContent) { + $contents = $contents->getContent(); + $dest = cl::merge($dest, self::resolve_static($contents, $dest_class, false)); + return $dest; } elseif ($contents instanceof IContent) { $dest[] = $contents; return $dest; @@ -53,8 +79,10 @@ class content { } foreach ($contents as $content) { if ($content === null) continue; - elseif (is_string($content)) $dest[] = $content; - elseif ($contents instanceof IContent) $dest[] = $content; + elseif ($contents instanceof IStaticContent) { + $contents = $content->getContent(); + $dest = cl::merge($dest, self::resolve_static($contents, $dest_class, false)); + } elseif ($contents instanceof IContent) $dest[] = $content; elseif ($contents instanceof IPrintable) $dest[] = $content; elseif (!is_array($content)) $dest[] = $content; else { @@ -67,13 +95,15 @@ class content { # - ou une définition d'objet d'une des formes suivantes # - [class, ...args] # - [[class], ...args] - $class = false; + $func_isa_class = false; if (array_key_exists(0, $content) && is_array($content[0])) { # $content est de la forme [func_or_class, ...args] $func = $content[0]; $args = array_slice($content, 1); - if (func::is_class($func)) { - $class = true; + if (func::is_static($func)) { + func::ensure_func($func, $dest_class, $args); + } elseif (func::is_class($func)) { + $func_isa_class = true; func::fix_class_args($func, $args); } else { func::ensure_func($func, $dest_class, $args); @@ -81,8 +111,10 @@ class content { } else { # $content est de la forme $func $func = $content; - if (func::is_class($func)) { - $class = true; + if (func::is_static($func)) { + func::ensure_func($func, $dest_class, $args); + } elseif (func::is_class($func)) { + $func_isa_class = true; func::fix_class_args($func, $args); } else { func::ensure_func($func, $dest_class, $args); @@ -90,19 +122,29 @@ class content { } # chaque argument est un contenu statique foreach ($args as &$arg) { + $array = is_array($arg); $arg = self::resolve_static($arg, $dest_class, false); $arg = self::flatten($arg); - switch (count($arg)) { - case 0: $arg = null; break; - case 1: $arg = $arg[0]; break; - default: $arg = implode("", $arg); + if ($array) { + $arg = [implode("", $arg)]; + } else { + switch (count($arg)) { + case 0: $arg = null; break; + case 1: $arg = $arg[0]; break; + default: $arg = implode("", $arg); + } } }; unset($arg); # puis appeler la fonction - if ($class) $content = func::cons($func, ...$args); + if ($func_isa_class) $content = func::cons($func, ...$args); else $content = func::call($func, ...$args); $dest[] = $content; } } + return $dest; + } + + static function to_string($contents, $dest_class=null, bool $quote=true): string { + return implode("", self::flatten(self::resolve_static($contents, $dest_class, $quote))); } } diff --git a/src/sys/func.php b/src/sys/func.php index 5a2fa7f..798d77f 100644 --- a/src/sys/func.php +++ b/src/sys/func.php @@ -18,8 +18,11 @@ class func { * tester si $func est une chaine de la forme "XXX::method" où XXX est une * chaine quelconque éventuellement vide, ou un tableau de la forme ["method"] * ou [anything, "method", ...] + * + * Avec la forme tableau, "method" ne doit pas contenir le caractère '\', pour + * pouvoir utiliser conjointement {@link is_class()} */ - static final function is_static($func): bool { + static final function is_static($func, bool $allowClass=false): bool { if (is_string($func)) { $pos = strpos($func, "::"); if ($pos === false) return false; @@ -27,10 +30,14 @@ class func { } elseif (is_array($func) && array_key_exists(0, $func)) { $count = count($func); if ($count == 1) { - return is_string($func[0]) && strlen($func[0]) > 0; + if (!is_string($func[0]) || strlen($func[0]) == 0) return false; + if (strpos($func[0], "\\") !== false) return false; + return true; } elseif ($count > 1) { if (!array_key_exists(1, $func)) return false; - return is_string($func[1]) && strlen($func[1]) > 0; + if (!is_string($func[1]) || strlen($func[1]) == 0) return false; + if (strpos($func[1], "\\") !== false) return false; + return true; } } return false; @@ -351,7 +358,8 @@ class func { * * NB: il est possible d'avoir {@link is_static()} et {@link is_class()} * vraies pour la même valeur. s'il faut supporter les deux cas, appeler - * {@link is_class()} d'abord + * {@link is_static()} d'abord, mais dans ce cas, on ne supporte que les + * classes qui sont dans un package */ static final function is_class($class): bool { if (is_string($class)) { diff --git a/tests/sys/contentTest.php b/tests/sys/contentTest.php new file mode 100644 index 0000000..21a62b5 --- /dev/null +++ b/tests/sys/contentTest.php @@ -0,0 +1,38 @@ +", "")); + self::assertSame([""], content::resolve_static([""], [""])); + + self::assertSame( + "

title<q/>

hellobrave<q/>world

", + content::to_string([ + [html::H1, "title"], + [html::P, [ + "hello", + [html::SPAN, "brave"], + [html::SPAN, ["world"]], + ]], + ])); + } +} + diff --git a/tests/sys/impl/AContent.php b/tests/sys/impl/AContent.php new file mode 100644 index 0000000..3f2bd32 --- /dev/null +++ b/tests/sys/impl/AContent.php @@ -0,0 +1,10 @@ +content"]; + } +} diff --git a/tests/sys/impl/APrintable.php b/tests/sys/impl/APrintable.php new file mode 100644 index 0000000..fe46369 --- /dev/null +++ b/tests/sys/impl/APrintable.php @@ -0,0 +1,10 @@ +printable

"; + } +} diff --git a/tests/sys/impl/AStaticContent.php b/tests/sys/impl/AStaticContent.php new file mode 100644 index 0000000..2458746 --- /dev/null +++ b/tests/sys/impl/AStaticContent.php @@ -0,0 +1,12 @@ +tag = $tag; + $this->contents = $contents; + } + + protected $tag; + protected $contents; + + function getContent(): iterable { + return [ + "<$this->tag>", + ...content::q($this->contents), + "tag>", + ]; + } +} diff --git a/tests/sys/impl/html.php b/tests/sys/impl/html.php new file mode 100644 index 0000000..392c724 --- /dev/null +++ b/tests/sys/impl/html.php @@ -0,0 +1,14 @@ +