cheKey][$threeChars])
&&
\strpos($str, $threeChars) !== false
) {
// DEBUG
//\var_dump($str, $threeChars, $REPLACE_HELPER_CACHE[$cacheKey][$threeChars]);
$charDone[$threeChars] = true;
$str = \str_replace($threeChars, $REPLACE_HELPER_CACHE[$cacheKey][$threeChars], $str);
// DEBUG
//\var_dump($str, "\n");
}
}
foreach ($matches[0] as $keyTmp => $char) {
if (isset($matches[0][$keyTmp + 1])) {
$twoChars = $matches[0][$keyTmp + 0] . $matches[0][$keyTmp + 1];
} else {
$twoChars = null;
}
if (
$twoChars
&&
!isset($charDone[$twoChars])
&&
isset($REPLACE_HELPER_CACHE[$cacheKey][$twoChars])
&&
\strpos($str, $twoChars) !== false
) {
// DEBUG
//\var_dump($str, $twoChars, $REPLACE_HELPER_CACHE[$cacheKey][$twoChars]);
$charDone[$twoChars] = true;
$str = \str_replace($twoChars, $REPLACE_HELPER_CACHE[$cacheKey][$twoChars], $str);
// DEBUG
//\var_dump($str, "\n");
}
}
}
foreach ($matches[0] as $char) {
if (
!isset($charDone[$char])
&&
isset($REPLACE_HELPER_CACHE[$cacheKey][$char])
&&
\strpos($str, $char) !== false
) {
// DEBUG
//\var_dump($str, $char, $REPLACE_HELPER_CACHE[$cacheKey][$char]);
$charDone[$char] = true;
$str = \str_replace($char, $REPLACE_HELPER_CACHE[$cacheKey][$char], $str);
// DEBUG
//\var_dump($str, "\n");
}
}
}
if (!isset(self::$ASCII_MAPS[$language])) {
$use_transliterate = true;
}
if ($use_transliterate) {
$str = self::to_transliterate($str, null, false);
}
if ($remove_unsupported_chars) {
$str = (string) \str_replace(["\n\r", "\n", "\r", "\t"], ' ', $str);
$str = (string) \preg_replace('/' . self::$REGEX_ASCII . '/', '', $str);
}
return $str;
}
/**
* Convert given string to safe filename (and keep string case).
*
* EXAMPLE:
* ASCII::to_filename('שדגשדג.png', true)); // 'shdgshdg.png'
*
*
* @param string $str
The string input.
* @param bool $use_transliterateASCII::to_transliterate() is used by default - unsafe characters are * simply replaced with hyphen otherwise.
* @param string $fallback_charThe fallback character. - "-" is the default
* * @psalm-pure * * @return string *A string that contains only safe characters for a filename.
*/ public static function to_filename( string $str, bool $use_transliterate = true, string $fallback_char = '-' ): string { if ($use_transliterate) { $str = self::to_transliterate($str, $fallback_char); } $fallback_char_escaped = \preg_quote($fallback_char, '/'); $str = (string) \preg_replace( [ '/[^' . $fallback_char_escaped . '.\\-a-zA-Z\d\\s]/', // 1) remove un-needed chars '/\s+/u', // 2) convert spaces to $fallback_char '/[' . $fallback_char_escaped . ']+/u', // 3) remove double $fallback_char's ], [ '', $fallback_char, $fallback_char, ], $str ); return \trim($str, $fallback_char); } /** * Converts a string into a URL-friendly slug. * * - This includes replacing non-ASCII characters with their closest ASCII equivalents, removing remaining * non-ASCII and non-alphanumeric characters, and replacing whitespace with $separator. * - The separator defaults to a single dash, and the string is also converted to lowercase. * - The language of the source string can also be supplied for language-specific transliteration. * * @param string $strThe string input.
* @param string $separator [optional]The string used to replace whitespace.
* @param string $language [optional]Language of the source string. * (default is 'en') | ASCII::*_LANGUAGE_CODE
* @param arrayA map of replaceable strings.
* @param bool $replace_extra_symbols [optional]Add some more replacements e.g. "£" with " * pound ".
* @param bool $use_str_to_lower [optional]Use "string to lower" for the input.
* @param bool $use_transliterate [optional]Use ASCII::to_transliterate() for unknown * chars.
* @psalm-pure * * @return string *The URL-friendly slug.
* * @phpstan-param ASCII::*_LANGUAGE_CODE $language */ public static function to_slugify( string $str, string $separator = '-', string $language = self::ENGLISH_LANGUAGE_CODE, array $replacements = [], bool $replace_extra_symbols = false, bool $use_str_to_lower = true, bool $use_transliterate = false ): string { if ($str === '') { return ''; } foreach ($replacements as $from => $to) { $str = \str_replace($from, $to, $str); } $str = self::to_ascii( $str, $language, false, $replace_extra_symbols, $use_transliterate ); $str = \str_replace('@', $separator, $str); $str = (string) \preg_replace( '/[^a-zA-Z\\d\\s\\-_' . \preg_quote($separator, '/') . ']/', '', $str ); if ($use_str_to_lower) { $str = \strtolower($str); } $str = (string) \preg_replace('/^[\'\\s]+|[\'\\s]+$/', '', $str); $str = (string) \preg_replace('/\\B([A-Z])/', '-\1', $str); $str = (string) \preg_replace('/[\\-_\\s]+/', $separator, $str); $l = \strlen($separator); if ($l && \strpos($str, $separator) === 0) { $str = (string) \substr($str, $l); } if (\substr($str, -$l) === $separator) { $str = (string) \substr($str, 0, \strlen($str) - $l); } return $str; } /** * Returns an ASCII version of the string. A set of non-ASCII characters are * replaced with their closest ASCII counterparts, and the rest are removed * unless instructed otherwise. * * EXAMPLE:
* ASCII::to_transliterate('déjà σσς iıii'); // 'deja sss iiii'
*
*
* @param string $str The input string.
* @param string|null $unknown [optional]Character use if character unknown. (default is '?') * But you can also use NULL to keep the unknown chars.
* @param bool $strict [optional]Use "transliterator_transliterate()" from PHP-Intl * * @psalm-pure * * @return string *
A String that contains only ASCII characters.
*/ public static function to_transliterate( string $str, $unknown = '?', bool $strict = false ): string { static $UTF8_TO_TRANSLIT = null; static $TRANSLITERATOR = null; static $SUPPORT_INTL = null; if ($str === '') { return ''; } if ($SUPPORT_INTL === null) { $SUPPORT_INTL = \extension_loaded('intl'); } // check if we only have ASCII, first (better performance) $str_tmp = $str; if (self::is_ascii($str)) { return $str; } $str = self::clean($str); // check again if we only have ASCII, now ... if ( $str_tmp !== $str && self::is_ascii($str) ) { return $str; } if ( $strict && $SUPPORT_INTL === true ) { if (!isset($TRANSLITERATOR)) { // INFO: see "*-Latin" rules via "transliterator_list_ids()" $TRANSLITERATOR = \transliterator_create('NFKC; [:Nonspacing Mark:] Remove; NFKC; Any-Latin; Latin-ASCII;'); } // INFO: https://unicode.org/cldr/utility/character.jsp $str_tmp = \transliterator_transliterate($TRANSLITERATOR, $str); if ($str_tmp !== false) { // check again if we only have ASCII, now ... if ( $str_tmp !== $str && self::is_ascii($str_tmp) ) { return $str_tmp; } $str = $str_tmp; } } if (self::$ORD === null) { self::$ORD = self::getData('ascii_ord'); } \preg_match_all('/.|[^\x00]$/us', $str, $array_tmp); $chars = $array_tmp[0]; $ord = null; $str_tmp = ''; foreach ($chars as &$c) { $ordC0 = self::$ORD[$c[0]]; if ($ordC0 >= 0 && $ordC0 <= 127) { $str_tmp .= $c; continue; } $ordC1 = self::$ORD[$c[1]]; // ASCII - next please if ($ordC0 >= 192 && $ordC0 <= 223) { $ord = ($ordC0 - 192) * 64 + ($ordC1 - 128); } if ($ordC0 >= 224) { $ordC2 = self::$ORD[$c[2]]; if ($ordC0 <= 239) { $ord = ($ordC0 - 224) * 4096 + ($ordC1 - 128) * 64 + ($ordC2 - 128); } if ($ordC0 >= 240) { $ordC3 = self::$ORD[$c[3]]; if ($ordC0 <= 247) { $ord = ($ordC0 - 240) * 262144 + ($ordC1 - 128) * 4096 + ($ordC2 - 128) * 64 + ($ordC3 - 128); } // We only process valid UTF-8 chars (<= 4 byte), so we don't need this code here ... /* if ($ordC0 >= 248) { $ordC4 = self::$ORD[$c[4]]; if ($ordC0 <= 251) { $ord = ($ordC0 - 248) * 16777216 + ($ordC1 - 128) * 262144 + ($ordC2 - 128) * 4096 + ($ordC3 - 128) * 64 + ($ordC4 - 128); } if ($ordC0 >= 252) { $ordC5 = self::$ORD[$c[5]]; if ($ordC0 <= 253) { $ord = ($ordC0 - 252) * 1073741824 + ($ordC1 - 128) * 16777216 + ($ordC2 - 128) * 262144 + ($ordC3 - 128) * 4096 + ($ordC4 - 128) * 64 + ($ordC5 - 128); } } } */ } } if ( $ordC0 === 254 || $ordC0 === 255 || $ord === null ) { $str_tmp .= $unknown ?? $c; continue; } $bank = $ord >> 8; if (!isset($UTF8_TO_TRANSLIT[$bank])) { $UTF8_TO_TRANSLIT[$bank] = self::getDataIfExists(\sprintf('x%03x', $bank)); } $new_char = $ord & 255; if (isset($UTF8_TO_TRANSLIT[$bank][$new_char])) { // keep for debugging /* echo "file: " . sprintf('x%02x', $bank) . "\n"; echo "char: " . $c . "\n"; echo "ord: " . $ord . "\n"; echo "new_char: " . $new_char . "\n"; echo "new_char: " . mb_chr($new_char) . "\n"; echo "ascii: " . $UTF8_TO_TRANSLIT[$bank][$new_char] . "\n"; echo "bank:" . $bank . "\n\n"; */ $new_char = $UTF8_TO_TRANSLIT[$bank][$new_char]; /* @noinspection PhpStatementHasEmptyBodyInspection */ if ($unknown === null && $new_char === '') { // nothing } elseif ( $new_char === '[?]' || $new_char === '[?] ' ) { $c = $unknown ?? $c; } else { $c = $new_char; } } else { // keep for debugging missing chars /* echo "file: " . sprintf('x%02x', $bank) . "\n"; echo "char: " . $c . "\n"; echo "ord: " . $ord . "\n"; echo "new_char: " . $new_char . "\n"; echo "new_char: " . mb_chr($new_char) . "\n"; echo "bank:" . $bank . "\n\n"; */ $c = $unknown ?? $c; } $str_tmp .= $c; } return $str_tmp; } /** * WARNING: This method will return broken characters and is only for special cases. * * Convert a UTF-8 encoded string to a single-byte string suitable for * functions that need the same string length after the conversion. * * The function simply uses (and updates) a tailored dynamic encoding * (in/out map parameter) where non-ascii characters are remapped to * the range [128-255] in order of appearance. * * Thus, it supports up to 128 different multibyte code points max over * the whole set of strings sharing this encoding. * * Source: https://github.com/KEINOS/mb_levenshtein * * @param string $strUTF-8 string to be converted to extended ASCII.
* @param array $mapInternal-Map of code points to ASCII characters.
* * @return string *Mapped broken string.
* * @phpstan-param array