163 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace nur\v;
 | 
						|
 | 
						|
use nur\A;
 | 
						|
use nur\str;
 | 
						|
use nur\v\model\IPage;
 | 
						|
 | 
						|
/**
 | 
						|
 * Class prefix: gestion des préfixes pour les URLs
 | 
						|
 */
 | 
						|
class prefix {
 | 
						|
  static function get_base_url(): string {
 | 
						|
    $base_url = getenv("BASE_URL");
 | 
						|
    if ($base_url !== false) {
 | 
						|
      return str::without_suffix("/", parse_url($base_url, PHP_URL_PATH));
 | 
						|
    } else {
 | 
						|
      return "";
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * obtenir le chemin par défaut du script courant.
 | 
						|
   * - si la variable d'environnement BASE_URL est définie, alors la valeur est
 | 
						|
   *   exacte.
 | 
						|
   * - sinon, on part du principe que l'application ne sert des pages qu'à sa
 | 
						|
   *   racine, ce qui n'est pas forcément vrai
 | 
						|
   *
 | 
						|
   * la valeur retournée est
 | 
						|
   * - soit le chemin avec le préfixe '/' e.g '/index.php'
 | 
						|
   * - soir la chaine vide ''
 | 
						|
   */
 | 
						|
  static function get_default_self(): string {
 | 
						|
    $script_name = $_SERVER["SCRIPT_NAME"];
 | 
						|
    $base_url = getenv("BASE_URL");
 | 
						|
    if ($base_url !== false) {
 | 
						|
      # d'abord, isoler le chemin de $base_url
 | 
						|
      $base_url = str::without_suffix("/", parse_url($base_url, PHP_URL_PATH));
 | 
						|
      # puis enlever le préfixe
 | 
						|
      return str::without_prefix($base_url, $script_name);
 | 
						|
    }
 | 
						|
    $pos = strrpos($script_name, "/");
 | 
						|
    if ($pos === false) return "";
 | 
						|
    return substr($script_name, $pos);
 | 
						|
  }
 | 
						|
 | 
						|
  static function compute(?string $self): string {
 | 
						|
    if ($self !== null) {
 | 
						|
      if (substr($self, 0, 1) != "/") $self = "/$self";
 | 
						|
    } else {
 | 
						|
      $self = self::get_default_self();
 | 
						|
    }
 | 
						|
    $php_self = $_SERVER["PHP_SELF"];
 | 
						|
    $pos = strpos($php_self, $self);
 | 
						|
    if ($pos === false) return "";
 | 
						|
    $prefix = "";
 | 
						|
    $offset = $pos + 1;
 | 
						|
    while (($pos = strpos($php_self, "/", $offset)) !== false) {
 | 
						|
      $prefix .= "../";
 | 
						|
      $offset = $pos + 1;
 | 
						|
    }
 | 
						|
    return $prefix;
 | 
						|
  }
 | 
						|
 | 
						|
  static function add(string $url, ?string $prefix): string {
 | 
						|
    if ($prefix === null) return $url;
 | 
						|
    if (preg_match('/^(\/)|(https?:\/\/)/', $url)) {
 | 
						|
      # l'url est de la forme /ANY ou http[s]://ANY
 | 
						|
      # url absolue, laisser en l'état
 | 
						|
    } elseif (str::starts_with("./", $url)) {
 | 
						|
      # l'url est de la forme ./ANY
 | 
						|
      # url relative
 | 
						|
      $url = $prefix.substr($url, 2);
 | 
						|
    } elseif (str::starts_with("__PREFIX__/", $url)) {
 | 
						|
      # l'url est de la forme __PREFIX__/ANY
 | 
						|
      # compatibilité: url exprimée par rapport au préfixe
 | 
						|
      $url = $prefix.substr($url, 11);
 | 
						|
    } else {
 | 
						|
      # par défaut, l'url est exprimée par rapport au préfixe
 | 
						|
      $url = $prefix.$url;
 | 
						|
    }
 | 
						|
    return $url;
 | 
						|
  }
 | 
						|
 | 
						|
  #############################################################################
 | 
						|
  # exemple d'implémentation pour utiliser la valeur calculée de prefix
 | 
						|
 | 
						|
  /**
 | 
						|
   * @var string chemin du script correspondant à la page courante, depuis la
 | 
						|
   * racine de l'application e.g. index.php, ou null s'il faut utiliser la
 | 
						|
   * valeur par défaut
 | 
						|
   */
 | 
						|
  protected static $self;
 | 
						|
 | 
						|
  /** @var string */
 | 
						|
  protected static $prefix;
 | 
						|
 | 
						|
  static final function set_self(?string $self) {
 | 
						|
    if ($self === null) $self = self::get_default_self();
 | 
						|
    self::$self = $self;
 | 
						|
    self::$prefix = self::compute($self);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * construire un url avec les paramètres spécifiés. le cas échéant, corriger
 | 
						|
   * l'url en fonction de $self
 | 
						|
   *
 | 
						|
   * cette méthode sera utilisée notamment pour des liens vers des resources
 | 
						|
   * statiques
 | 
						|
   */
 | 
						|
  static final function resu(string $url, ...$params): string {
 | 
						|
    return html::bu(self::add($url, self::$prefix), ...$params);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * construire un url vers le composant destination avec les paramètres
 | 
						|
   * spécifiés. le cas échéant, corriger l'url en fonction de $self
 | 
						|
   *
 | 
						|
   * @param string|IPage $dest composant destination
 | 
						|
   */
 | 
						|
  static final function dynu($dest, ...$params): string {
 | 
						|
    $url = $dest; #XXX $url = route::get_path($dest);
 | 
						|
    return html::bu(self::add($url, self::$prefix), ...$params);
 | 
						|
  }
 | 
						|
 | 
						|
  const BU_STATIC_PARTS = ["scheme", "host", "port", "query", "fragment"];
 | 
						|
 | 
						|
  /**
 | 
						|
   * méthode générique pour construire une url. utiliser des heuristiques pour
 | 
						|
   * déterminer si la destination est une url statique ou si c'est un composant
 | 
						|
   */
 | 
						|
  static final function bu($dest, ...$params): string {
 | 
						|
    $dyn = true;
 | 
						|
    if (is_string($dest)) {
 | 
						|
      # heuristiques pour déterminer si c'est une url statique
 | 
						|
      $parts = parse_url($dest);
 | 
						|
      foreach (self::BU_STATIC_PARTS as $part) {
 | 
						|
        if (A::has($parts, $part)) {
 | 
						|
          # y a-t-il au moins une partie d'une url statique?
 | 
						|
          $dyn = false;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if ($dyn) {
 | 
						|
        # s'il n'y a qu'un chemin, tester si ça ressemble à une url
 | 
						|
        $path = A::get($parts, "path", "");
 | 
						|
        if ($path === "" || $path === ".") $dyn = false;
 | 
						|
        elseif (strpos($path, "/")) $dyn = false;
 | 
						|
        elseif (preg_match('/\.(php|html)\b/', $path)) $dyn = false;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    if ($dyn) {
 | 
						|
      # tenir compte du préfixe, puisque les chemins des composants sont
 | 
						|
      # toujours exprimés depuis la racine
 | 
						|
      $url = $dest; #XXX $url = route::get_path($dest);
 | 
						|
      return html::bu(self::add($url, self::$prefix), ...$params);
 | 
						|
    } else {
 | 
						|
      # ne pas corriger une url statique: on fait confiance à l'utilisateur pour
 | 
						|
      # utiliser des chemins relatifs
 | 
						|
      return html::bu($dest, ...$params);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |