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