modifs.mineures sans commentaires
This commit is contained in:
		
							parent
							
								
									cd7a96f181
								
							
						
					
					
						commit
						b97515782b
					
				@ -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 */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								src/sys/IStaticContent.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/sys/IStaticContent.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
<?php
 | 
			
		||||
namespace nur\sery\sys;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Interface IStaticContent: comme {@link IContent} mais la liste retournée est
 | 
			
		||||
 * une liste de contenu statique à analyser récursivement
 | 
			
		||||
 */
 | 
			
		||||
interface IStaticContent extends IContent {
 | 
			
		||||
}
 | 
			
		||||
@ -1,13 +1,29 @@
 | 
			
		||||
<?php
 | 
			
		||||
namespace nur\sery\sys;
 | 
			
		||||
 | 
			
		||||
use nulib\cl;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class content: gestionnaire de contenu (statique ou dynamique)
 | 
			
		||||
 */
 | 
			
		||||
class content {
 | 
			
		||||
  /**
 | 
			
		||||
   * quoter $vs si c'est un scalaire. sinon retourner le tableau tel quel
 | 
			
		||||
   *
 | 
			
		||||
   * NB: cette méthode est accessible via la fonction globale {@link q()}
 | 
			
		||||
   */
 | 
			
		||||
  static final function q($contents): iterable {
 | 
			
		||||
    if ($contents === null || $contents === false) return [];
 | 
			
		||||
    elseif ($contents instanceof IContent) return [$contents];
 | 
			
		||||
    elseif ($contents instanceof IPrintable) return [$contents];
 | 
			
		||||
    elseif (is_iterable($contents)) return $contents;
 | 
			
		||||
    else return [htmlspecialchars(strval($contents))];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * applatir $contents, et retourner une liste de valeurs scalaires:
 | 
			
		||||
   * - les instances de IContent et IPrintable sont remplacées par leur contenu
 | 
			
		||||
   * - les chaines sont ajoutées telles quelles
 | 
			
		||||
   * - les autres objets sont transformés en chaine de caractère avec strval()
 | 
			
		||||
   */
 | 
			
		||||
  static function flatten($contents, ?array &$dest=null): array {
 | 
			
		||||
@ -20,12 +36,18 @@ class content {
 | 
			
		||||
      $contents->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)));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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)) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								tests/sys/contentTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								tests/sys/contentTest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
<?php
 | 
			
		||||
namespace nur\sery\sys;
 | 
			
		||||
 | 
			
		||||
use nur\sery\sys\impl\html;
 | 
			
		||||
use PHPUnit\Framework\TestCase;
 | 
			
		||||
 | 
			
		||||
class contentTest extends TestCase {
 | 
			
		||||
  function testFlattern() {
 | 
			
		||||
    self::assertSame([], content::flatten(null));
 | 
			
		||||
    self::assertSame([], content::flatten([null]));
 | 
			
		||||
    self::assertSame([""], content::flatten(""));
 | 
			
		||||
    self::assertSame([""], content::flatten([""]));
 | 
			
		||||
 | 
			
		||||
    self::assertSame(["a", "b", "c", "d"], content::flatten(["a", ["b", ["c"], "d"]]));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function testResolve_static() {
 | 
			
		||||
    self::assertSame([], content::resolve_static(null, null));
 | 
			
		||||
    self::assertSame([], content::resolve_static([null], [null]));
 | 
			
		||||
    self::assertSame([""], content::resolve_static("", ""));
 | 
			
		||||
    self::assertSame([""], content::resolve_static([""], [""]));
 | 
			
		||||
 | 
			
		||||
    self::assertSame(["<quoted>"], content::resolve_static("<quoted>", "<quoted>"));
 | 
			
		||||
    self::assertSame(["<non-quoted>"], content::resolve_static(["<non-quoted>"], ["<non-quoted>"]));
 | 
			
		||||
 | 
			
		||||
    self::assertSame(
 | 
			
		||||
      "<h1>title<q/></h1><p>hello<nq/><span>brave<q/></span><span>world<nq/></span></p>",
 | 
			
		||||
      content::to_string([
 | 
			
		||||
        [html::H1, "title<q/>"],
 | 
			
		||||
        [html::P, [
 | 
			
		||||
          "hello<nq/>",
 | 
			
		||||
          [html::SPAN, "brave<q/>"],
 | 
			
		||||
          [html::SPAN, ["world<nq/>"]],
 | 
			
		||||
        ]],
 | 
			
		||||
      ]));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								tests/sys/impl/AContent.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/sys/impl/AContent.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
<?php
 | 
			
		||||
namespace nur\sery\sys\impl;
 | 
			
		||||
 | 
			
		||||
use nur\sery\sys\IContent;
 | 
			
		||||
 | 
			
		||||
class AContent implements IContent {
 | 
			
		||||
  function getContent(): iterable {
 | 
			
		||||
    return ["<span>content</span>"];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								tests/sys/impl/APrintable.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/sys/impl/APrintable.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
			
		||||
<?php
 | 
			
		||||
namespace nur\sery\sys\impl;
 | 
			
		||||
 | 
			
		||||
use nur\sery\sys\IPrintable;
 | 
			
		||||
 | 
			
		||||
class APrintable implements IPrintable {
 | 
			
		||||
  function print(): void {
 | 
			
		||||
    echo "<p>printable</p>";
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								tests/sys/impl/AStaticContent.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tests/sys/impl/AStaticContent.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
<?php
 | 
			
		||||
namespace nur\sery\sys\impl;
 | 
			
		||||
 | 
			
		||||
use nur\sery\sys\IStaticContent;
 | 
			
		||||
 | 
			
		||||
class AStaticContent implements IStaticContent {
 | 
			
		||||
  function getContent(): iterable {
 | 
			
		||||
    return [
 | 
			
		||||
      [html::P, "static content"],
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								tests/sys/impl/ATag.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tests/sys/impl/ATag.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
<?php
 | 
			
		||||
namespace nur\sery\sys\impl;
 | 
			
		||||
 | 
			
		||||
use nur\sery\sys\content;
 | 
			
		||||
use nur\sery\sys\IStaticContent;
 | 
			
		||||
 | 
			
		||||
class ATag implements IStaticContent {
 | 
			
		||||
  function __construct(string $tag, $contents=null) {
 | 
			
		||||
    $this->tag = $tag;
 | 
			
		||||
    $this->contents = $contents;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected $tag;
 | 
			
		||||
  protected $contents;
 | 
			
		||||
 | 
			
		||||
  function getContent(): iterable {
 | 
			
		||||
    return [
 | 
			
		||||
      "<$this->tag>",
 | 
			
		||||
      ...content::q($this->contents),
 | 
			
		||||
      "</$this->tag>",
 | 
			
		||||
    ];
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								tests/sys/impl/html.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								tests/sys/impl/html.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
<?php
 | 
			
		||||
namespace nur\sery\sys\impl;
 | 
			
		||||
 | 
			
		||||
class html {
 | 
			
		||||
  const H1 = [self::class, "h1"];
 | 
			
		||||
  const DIV = [self::class, "div"];
 | 
			
		||||
  const P = [self::class, "p"];
 | 
			
		||||
  const SPAN = [self::class, "span"];
 | 
			
		||||
 | 
			
		||||
  static function h1($contents) { return new ATag("h1", $contents); }
 | 
			
		||||
  static function div($contents) { return new ATag("div", $contents); }
 | 
			
		||||
  static function p($contents) { return new ATag("p", $contents); }
 | 
			
		||||
  static function span($contents) { return new ATag("span", $contents); }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user