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);
 | |
|     }
 | |
|   }
 | |
| }
 |