$length) { if ($ellips && $length > 3) $s = substr($s, 0, $length - 3)."..."; else $s = substr($s, 0, $length); } if ($suffix !== null) $s .= $suffix; return $s; } /** trimmer $s */ static final function trim(?string $s): ?string { if ($s === null) return null; else return trim($s); } /** trimmer $s à gauche */ static final function ltrim(?string $s): ?string { if ($s === null) return null; else return ltrim($s); } /** trimmer $s à droite */ static final function rtrim(?string $s): ?string { if ($s === null) return null; else return rtrim($s); } static final function lower(?string $s): ?string { if ($s === null) return null; else return strtolower($s); } static final function lower1(?string $s): ?string { if ($s === null) return null; else return lcfirst($s); } static final function upper(?string $s): ?string { if ($s === null) return null; else return strtoupper($s); } static final function upper1(?string $s): ?string { if ($s === null) return null; else return ucfirst($s); } static final function upperw(?string $s, ?string $delimiters=null): ?string { if ($s === null) return null; if ($delimiters !== null) return ucwords($s, $delimiters); else return ucwords($s, " _-\t\r\n\f\v"); } protected static final function _starts_with(string $prefix, string $s, ?int $min_len=null): bool { if ($prefix === $s) return true; $len = strlen($prefix); if ($min_len !== null && ($len < $min_len || $len > strlen($s))) return false; return $len == 0 || $prefix === 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, ?string $s, ?int $min_len=null): bool { if ($s === null || $prefix === null) return false; else return self::_starts_with($prefix, $s, $min_len); } /** Retourner $s sans le préfixe $prefix s'il existe */ static final function without_prefix(?string $prefix, ?string $s): ?string { if ($s === null || $prefix === null) return $s; if (self::_starts_with($prefix, $s)) $s = substr($s, strlen($prefix)); return $s; } /** * modifier $s en place pour supprimer le préfixe $prefix s'il existe * * retourner true si le préfixe a été enlevé. */ static final function del_prefix(?string &$s, ?string $prefix): bool { if ($s === null || !self::_starts_with($prefix, $s)) return false; $s = self::without_prefix($prefix, $s); return true; } /** * 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, ?string $s, ?string $sep=null, bool $unless_exists=false): ?string { if ($s === null || $prefix === null) return $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 * * retourner true si le préfixe a été ajouté. */ static final function add_prefix(?string &$s, ?string $prefix, bool $unless_exists=true): bool { if (($s === null || self::_starts_with($prefix, $s)) && $unless_exists) return false; $s = self::with_prefix($prefix, $s, null, $unless_exists); return true; } protected static final function _ends_with(string $suffix, string $s, ?int $min_len=null): bool { if ($suffix === $s) return true; $len = strlen($suffix); if ($min_len !== null && ($len < $min_len || $len > strlen($s))) return false; return $len == 0 || $suffix === substr($s, -$len); } /** * tester si $string se termine par $suffix * 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, ?string $s, ?int $min_len=null): bool { if ($s === null || $suffix === null) return false; else return self::_ends_with($suffix, $s, $min_len); } /** Retourner $s sans le suffixe $suffix s'il existe */ static final function without_suffix(?string $suffix, ?string $s): ?string { if ($s === null || $suffix === null) return $s; if (self::_ends_with($suffix, $s)) $s = substr($s, 0, -strlen($suffix)); return $s; } /** * modifier $s en place pour supprimer le suffixe $suffix s'il existe * * retourner true si le suffixe a été enlevé. */ static final function del_suffix(?string &$s, ?string $suffix): bool { if ($s === null || !self::_ends_with($suffix, $s)) return false; $s = self::without_suffix($suffix, $s); return true; } /** * 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, ?string $s, ?string $sep=null, bool $unless_exists=false): ?string { if ($s === null || $suffix === null) return $s; if (!self::_ends_with($suffix, $s) || !$unless_exists) $s = $s.$sep.$suffix; return $s; } /** * modifier $s en place pour ajouter le suffixe $suffix * * retourner true si le suffixe a été ajouté. */ static final function add_suffix(?string &$s, ?string $suffix, bool $unless_exists=true): bool { if (($s === null || self::_ends_with($suffix, $s)) && $unless_exists) return false; $s = self::with_suffix($suffix, $s, null, $unless_exists); return true; } /** splitter $s en deux chaines séparées par $sep */ static final function split_pair(?string $s, string $sep=":"): array { if ($s === null) return [null, null]; $parts = explode($sep, $s, 2); if ($parts === false) return [null, null]; if (count($parts) < 2) $parts[] = null; return $parts; } /** retourner $line sans son caractère de fin de ligne */ static final function strip_nl(?string $line): ?string { if ($line === null) return null; if (substr($line, -2) == "\r\n") { $line = substr($line, 0, -2); } elseif (substr($line, -1) == "\n") { $line = substr($line, 0, -1); } elseif (substr($line, -1) == "\r") { $line = substr($line, 0, -1); } return $line; } /** * normaliser le caractère de fin de ligne: tous les occurrences de [CR]LF et CR sont remplacées par LF */ static final function norm_nl(?string $s): ?string { if ($s === null) return null; $s = str_replace("\r\n", "\n", $s); $s = str_replace("\r", "\n", $s); return $s; } /** * joindre les éléments de $parts comme avec implode(), mais en ignorant les * valeurs fausses (cela n'inclue pas la chaine "0") * * pour chaque valeur du tableau avec une clé associative, c'est la clé qui * est utilisée mais uniquement si la valeur est vraie */ static final function join(string $glue, ?array $values): ?string { if ($values === null) return null; $pieces = []; $index = 0; foreach ($values as $key => $value) { if (is_array($value)) $value = self::join($glue, $value); if ($key === $index) { $index++; if (cv::t($value)) $pieces[] = $value; } elseif (cv::t($value)) { $pieces[] = $key; } } return implode($glue, $pieces); } /** * comme {@link join()} mais en ignorant les valeurs fausses selon les règles * de PHP */ static final function pjoin(string $glue, ?array $values): ?string { if ($values === null) return null; $pieces = []; $index = 0; foreach ($values as $key => $value) { if (is_array($value)) $value = self::join($glue, $value); if ($key === $index) { $index++; if ($value) $pieces[] = $value; } elseif ($value) { $pieces[] = $key; } } return implode($glue, $pieces); } const CAMEL_PATTERN0 = '/([A-Z0-9]+)$/A'; const CAMEL_PATTERN1 = '/([A-Z0-9]+)[A-Z]/A'; const CAMEL_PATTERN2 = '/([^A-Z]+)/A'; const CAMEL_PATTERN3 = '/([A-Z][^A-Z]*)/A'; /** * convertir une chaine de la forme "camelCase" en "under_score". le premier * ensemble de caractères en majuscule est considéré comme étant en minuscule * * par exemple: * - 'myCamelCase' devient 'my_camel_case' * - 'AValue' devient 'a_value' * - 'UPPERValue' devient 'upper_value' * - 'UPPER' devient 'upper' * - 'aXYZ' devient 'a_x_y_z' * * $delimiter est le séparateur en sortie ('_' par défaut) * $upper indique s'il faut transformer le résultat en majuscule */ static final function camel2us(?string $camel, bool $upper=false, string $delimiter="_"): ?string { if ($camel === null || $camel === "") return $camel; $parts = []; if (preg_match(self::CAMEL_PATTERN0, $camel, $vs, PREG_OFFSET_CAPTURE)) { # que des majuscules } elseif (preg_match(self::CAMEL_PATTERN1, $camel, $vs, PREG_OFFSET_CAPTURE)) { # préfixe en majuscule } elseif (preg_match(self::CAMEL_PATTERN2, $camel, $vs, PREG_OFFSET_CAPTURE)) { # préfixe en minuscule } else { throw ValueException::invalid($camel, "camel string"); } $parts[] = strtolower($vs[1][0]); $index = intval($vs[1][1]) + strlen($vs[1][0]); while (preg_match(self::CAMEL_PATTERN3, $camel, $vs, PREG_OFFSET_CAPTURE, $index)) { $parts[] = strtolower($vs[1][0]); $index = intval($vs[1][1]) + strlen($vs[1][0]); } $us = implode($delimiter, $parts); if ($upper) $us = strtoupper($us); return $us; } const US_PATTERN = '/([ _\-\t\r\n\f\v])/'; /** * convertir une chaine de la forme "under_score" en "camelCase" * * par exemple, 'my_camel_case' devient 'myCamelCalse' * et 'UPPER_VALUE' devient 'upperValue' * * si la chaine de départ ne contient pas de delimiter, e.g 'myValue', elle * est retournée inchangée */ static final function us2camel(?string $us, ?string $delimiters=null): ?string { if ($us === null || $us === "") return $us; if ($delimiters === null) $pattern = self::US_PATTERN; else $pattern = '/(['.preg_quote($delimiters).'])/'; $parts = preg_split($pattern, $us); $count = count($parts); if ($count == 1) return $us; for ($i = 0; $i < $count; $i++) { $part = strtolower($parts[$i]); if ($i > 0) $part = ucfirst($part); $parts[$i] = $part; } return implode("", $parts); } }