283 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			283 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| namespace nur;
 | |
| 
 | |
| /**
 | |
|  * Class txt: gestion des chaines de caractères multi-octets
 | |
|  */
 | |
| class txt {
 | |
|   /**
 | |
|    * Retourner $s converti en chaine, ou "" si $s est faux
 | |
|    *
 | |
|    * $strict indique s'il faut utiliser les règles de PHP pour décider si une
 | |
|    * valeur est fausse. Par exemple, en PHP la chaine "0" est fausse.
 | |
|    *
 | |
|    * ainsi:
 | |
|    * - with(0) vaut "0"
 | |
|    * - with("0") vaut "0"
 | |
|    * - with(0, true) vaut ""
 | |
|    * - with("0", true) vaut ""
 | |
|    *
 | |
|    * NB: cette méthode est identique à str::with()
 | |
|    */
 | |
|   static final function with($s, bool $strict=false): string {
 | |
|     if (!is_string($s)) $s = strval($s);
 | |
|     if (!$strict) return $s;
 | |
|     elseif ($s) return $s;
 | |
|     else return "";
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * tronquer si nécessaire $s à la valeur $length
 | |
|    * la chaine $suffix est rajoutée le cas échéant de façon que la taille
 | |
|    * totale n'excède pas $length caractères.
 | |
|    *
 | |
|    * si $ellips est true et que le troncage est nécessaire, remplacer les 3
 | |
|    * derniers caractères par "..."
 | |
|    */
 | |
|   static final function trunc($s, int $length, bool $ellips=false, ?string $suffix=null) {
 | |
|     if (base::z($s)) return $s;
 | |
|     $s = strval($s);
 | |
|     if ($suffix !== null) $length -= mb_strlen($suffix);
 | |
|     if (mb_strlen($s) > $length) {
 | |
|       if ($ellips && $length > 3) $s = mb_substr($s, 0, $length - 3)."...";
 | |
|       else $s = mb_substr($s, 0, $length);
 | |
|     }
 | |
|     if ($suffix !== null) $s .= $suffix;
 | |
|     return $s;
 | |
|   }
 | |
| 
 | |
|   /** trimmer $s */
 | |
|   static final function trim($s) {
 | |
|     if (base::z($s)) return $s;
 | |
|     else return trim(strval($s));
 | |
|   }
 | |
| 
 | |
|   /** trimmer $s à gauche */
 | |
|   static final function ltrim($s) {
 | |
|     if (base::z($s)) return $s;
 | |
|     else return ltrim(strval($s));
 | |
|   }
 | |
| 
 | |
|   /** trimmer $s à droite */
 | |
|   static final function rtrim($s) {
 | |
|     if (base::z($s)) return $s;
 | |
|     else return rtrim(strval($s));
 | |
|   }
 | |
| 
 | |
|   static final function lower($s) {
 | |
|     if (base::z($s)) return $s;
 | |
|     else return mb_strtolower(strval($s));
 | |
|   }
 | |
| 
 | |
|   static final function lower1($s) {
 | |
|     if (base::z($s)) return $s;
 | |
|     $s = strval($s);
 | |
|     return mb_strtolower(mb_substr($s, 0, 1)).mb_substr($s, 1);
 | |
|   }
 | |
| 
 | |
|   static final function upper($s) {
 | |
|     if (base::z($s)) return $s;
 | |
|     else return mb_strtoupper(strval($s));
 | |
|   }
 | |
| 
 | |
|   static final function upper1($s) {
 | |
|     if (base::z($s)) return $s;
 | |
|     $s = strval($s);
 | |
|     return mb_strtoupper(mb_substr($s, 0, 1)).mb_substr($s, 1);
 | |
|   }
 | |
| 
 | |
|   static final function upperw($s, ?string $delimiters=null) {
 | |
|     if (base::z($s)) return $s;
 | |
|     $s = strval($s);
 | |
|     if ($delimiters === null) $delimiters = " _-\t\r\n\f\v";
 | |
|     $pattern = "/([".preg_quote($delimiters)."])/u";
 | |
|     $words = preg_split($pattern, $s, -1, PREG_SPLIT_DELIM_CAPTURE);
 | |
|     $max = count($words) - 1;
 | |
|     $ucwords = [];
 | |
|     for ($i = 0; $i < $max; $i += 2) {
 | |
|       $s = $words[$i];
 | |
|       $ucwords[] = mb_strtoupper(mb_substr($s, 0, 1)).mb_substr($s, 1);
 | |
|       $ucwords[] = $words[$i + 1];
 | |
|     }
 | |
|     $s = $words[$max];
 | |
|     $ucwords[] = mb_strtoupper(mb_substr($s, 0, 1)).mb_substr($s, 1);
 | |
|     return implode("", $ucwords);
 | |
|   }
 | |
| 
 | |
|   private static function _starts_with(string $prefix, string $s, ?int $min_len=null): bool {
 | |
|     if ($prefix === $s) return true;
 | |
|     $len = mb_strlen($prefix);
 | |
|     if ($min_len !== null && ($len < $min_len || $len > mb_strlen($s))) return false;
 | |
|     return $len == 0 || $prefix === mb_substr($s, 0, $len);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * tester si $s commence par $prefix
 | |
|    * par exemple:
 | |
|    * - starts_with("", "whatever") est true
 | |
|    * - starts_with("fi", "first") est true
 | |
|    * - starts_with("no", "yes") est false
 | |
|    *
 | |
|    * si $min_len n'est pas null, c'est la longueur minimum requise de $prefix
 | |
|    * pour qu'on teste la correspondance. dans le cas contraire, la valeur de
 | |
|    * retour est toujours false, sauf s'il y a égalité. e.g
 | |
|    * - starts_with("a", "abc", 2) est false
 | |
|    * - starts_with("a", "a", 2) est true
 | |
|    */
 | |
|   static final function starts_with(?string $prefix, $s, ?int $min_len=null): bool {
 | |
|     if (base::z($s) || $prefix === null) return false;
 | |
|     else return self::_starts_with($prefix, strval($s), $min_len);
 | |
|   }
 | |
| 
 | |
|   /** Retourner $s sans le préfixe $prefix s'il existe */
 | |
|   static final function without_prefix(?string $prefix, $s) {
 | |
|     if (base::z($s) || $prefix === null) return $s;
 | |
|     $s = strval($s);
 | |
|     if (self::_starts_with($prefix, $s)) {
 | |
|       $s = mb_substr($s, mb_strlen($prefix));
 | |
|     }
 | |
|     return $s;
 | |
|   }
 | |
| 
 | |
|   /** modifier $s en place pour supprimer le préfixe $prefix s'il existe */
 | |
|   static final function del_prefix(&$s, ?string $prefix): void {
 | |
|     $s = self::without_prefix($prefix, $s);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Retourner $s avec le préfixe $prefix
 | |
|    *
 | |
|    * Si $unless_exists, ne pas ajouter le préfixe s'il existe déjà
 | |
|    */
 | |
|   static final function with_prefix(?string $prefix, $s, ?string $sep=null, bool $unless_exists=false) {
 | |
|     if (base::z($s) || $prefix === null) return $s;
 | |
|     $s = strval($s);
 | |
|     if (!self::_starts_with($prefix, $s) || !$unless_exists) {
 | |
|       $s = $prefix.$sep.$s;
 | |
|     }
 | |
|     return $s;
 | |
|   }
 | |
| 
 | |
|   /** modifier $s en place pour ajouter le préfixe $prefix */
 | |
|   static final function add_prefix(&$s, ?string $prefix, bool $unless_exists=true): void {
 | |
|     $s = self::with_prefix($prefix, $s, null, $unless_exists);
 | |
|   }
 | |
| 
 | |
|   private static function _ends_with(?string $suffix, string $s, ?int $min_len=null): bool {
 | |
|     if ($suffix === $s) return true;
 | |
|     $len = mb_strlen($suffix);
 | |
|     if ($min_len !== null && ($len < $min_len || $len > mb_strlen($s))) return false;
 | |
|     return $len == 0 || $suffix === mb_substr($s, -$len);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * tester si $string se termine par $suffix. $prefix doit être de taille non nulle
 | |
|    * par exemple:
 | |
|    * - ends_with("", "whatever") est true
 | |
|    * - ends_with("st", "first") est true
 | |
|    * - ends_with("no", "yes") est false
 | |
|    *
 | |
|    * si $min_len n'est pas null, c'est la longueur minimum requise de $prefix
 | |
|    * pour qu'on teste la correspondance. dans le cas contraire, la valeur de
 | |
|    * retour est toujours false, sauf s'il y a égalité. e.g
 | |
|    * - ends_with("c", "abc", 2) est false
 | |
|    * - ends_with("c", "c", 2) est true
 | |
|    */
 | |
|   static final function ends_with(?string $suffix, $s, ?int $min_len=null): bool {
 | |
|     if (base::z($s) || $suffix === null) return false;
 | |
|     else return self::_ends_with($suffix, strval($s), $min_len);
 | |
|   }
 | |
| 
 | |
|   /** Retourner $s sans le suffixe $suffix s'il existe */
 | |
|   static final function without_suffix(?string $suffix, $s) {
 | |
|     if (base::z($s) || $suffix === null) return $s;
 | |
|     $s = strval($s);
 | |
|     if (self::_ends_with($suffix, $s)) {
 | |
|       $s = mb_substr($s, 0, -mb_strlen($suffix));
 | |
|     }
 | |
|     return $s;
 | |
|   }
 | |
| 
 | |
|   /** modifier $s en place pour supprimer le suffixe $suffix s'il existe */
 | |
|   static final function del_suffix(&$s, ?string $suffix): void {
 | |
|     $s = self::without_suffix($suffix, $s);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Retourner $s avec le suffixe $suffix
 | |
|    *
 | |
|    * Si $unless_exists, ne pas ajouter le suffixe s'il existe déjà
 | |
|    */
 | |
|   static final function with_suffix(?string $suffix, $s, ?string $sep=null, bool $unless_exists=false) {
 | |
|     if (base::z($s) || $suffix === null) return $s;
 | |
|     $s = strval($s);
 | |
|     if (!self::_ends_with($suffix, $s) || !$unless_exists) {
 | |
|       $s = $s.$sep.$suffix;
 | |
|     }
 | |
|     return $s;
 | |
|   }
 | |
| 
 | |
|   /** modifier $s en place pour ajouter le suffixe $suffix */
 | |
|   static final function add_suffix(&$s, ?string $suffix, bool $unless_exists=true): void {
 | |
|     $s = self::with_suffix($suffix, $s, null, $unless_exists);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * ajouter $sep$prefix$text$suffix à $s si $text est non vide
 | |
|    *
 | |
|    * NB: ne rajouter $sep que si $s est non vide
 | |
|    */
 | |
|   static final function addsep(&$s, ?string $sep, ?string $text, ?string $prefix=null, ?string $suffix=null): void {
 | |
|     if (!$text) return;
 | |
|     if ($s) $s .= $sep;
 | |
|     $s .= $prefix.$text.$suffix;
 | |
|   }
 | |
| 
 | |
|   /** si $text est non vide, ajouter $prefix$text$suffix à $s en séparant la valeur avec un espace */
 | |
|   static final function add(&$s, ?string $text, ?string $prefix=null, ?string $suffix=null): void {
 | |
|     self::addsep($s, " ", $text, $prefix, $suffix);
 | |
|   }
 | |
| 
 | |
|   #############################################################################
 | |
|   # divers
 | |
| 
 | |
|   /**
 | |
|    * convertir la chaine $text de l'utf-8 vers l'encoding $charset
 | |
|    *
 | |
|    * supprimer les caractères invalides éventuels, certaines versions de PHP
 | |
|    * ayant un bug avec iconv. (note: est-ce toujours le cas avec PHP >= 7.2 ?)
 | |
|    */
 | |
|   static final function _convert_to(string $text, string $charset): string {
 | |
|     $text = mb_convert_encoding($text, "utf-8", "utf-8");
 | |
|     $text = @iconv("utf-8", $charset, $text);
 | |
|     if ($text === false) $text = "";
 | |
|     return $text;
 | |
|   }
 | |
| 
 | |
|   static final function convert_to($text, string $charset) {
 | |
|     if (base::z($text)) return $text;
 | |
|     return self::_convert_to(strval($text), $charset);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * supprimer les diacritiques de la chaine $text
 | |
|    *
 | |
|    * la translitération se fait avec les règles de la locale spécifiée.
 | |
|    * NB: la translitération ne fonctionne pas si LC_CTYPE == C ou POISX
 | |
|    */
 | |
|   static final function _remove_diacritics(string $text, string $locale="fr_FR.UTF-8"): string {
 | |
|     #XXX est-ce thread-safe?
 | |
|     $olocale = setlocale(LC_CTYPE, 0);
 | |
|     setlocale(LC_CTYPE, $locale);
 | |
|     $text = @iconv("UTF-8", "US-ASCII//TRANSLIT", $text);
 | |
|     if ($text === false) $text = "";
 | |
|     setlocale(LC_CTYPE, $olocale);
 | |
|     return $text;
 | |
|   }
 | |
| 
 | |
|   static final function remove_diacritics($text) {
 | |
|     if (base::z($text)) return $text;
 | |
|     return self::_remove_diacritics(strval($text));
 | |
|   }
 | |
| }
 |