Geizkragen/lib/strings.php

84 lines
3.5 KiB
PHP

<?php
/**
* @file strings.php
* @brief Enthält String-Hilfsfunktionen ohne harte Abhängigkeit von Erweiterungen wie mbstring.
*
* @details Diese Datei stellt nützliche Helfer-Funktionen für die Zeichenkettenverarbeitung bereit,
* insbesondere zur Ermittlung der tatsächlichen Zeichenlänge in UTF-8. Das Hauptziel ist es,
* Längenvalidierungen zeichenbasiert anstatt bytebasiert durchzuführen, um korrekte Ergebnisse
* in einer Multibyte-Umgebung wie UTF-8 zu gewährleisten, selbst wenn bestimmte PHP-Extensions fehlen.
*/
// lib/strings.php
// Kleine String-Helper ohne harte Abhängigkeit von mbstring.
// Ziel: Längenvalidierung möglichst „zeichenbasiert“ und UTF-8-tauglich.
/**
* @brief Ermittelt die Länge eines Strings in tatsächlichen Zeichen (nicht Bytes), wenn möglich.
*
* @details Diese Funktion versucht, die genaueste und sicherste Methode zur Bestimmung der
* Zeichenanzahl eines Strings in einer UTF-8-codierten Multibyte-Zeichenkette zu verwenden.
* Dabei bedient sie sich mehrerer Mechanismen in einer festgelegten Prioritätenfolge:
* - Priorität 1: Nutzung von mb_strlen() (sofern die mbstring-Erweiterung aktiv ist).
* - Priorität 2: Nutzung von grapheme_strlen() (sofern die intl-Erweiterung aktiv ist).
* - Priorität 3: Nutzung regulärer Ausdrücke zur UTF-8 Codepoint-Zählung via PCRE.
* - Priorität 4: Fallback auf die native strlen()-Funktion (welche lediglich Bytes zählt, was
* bei Multibyte-Zeichen ungenau ist, aber sicher nicht fehlschlägt).
*
* @param string $s Die Eingabe-Zeichenkette, deren Länge bestimmt werden soll.
*
* @return int Die ermittelte Länge der Zeichenkette. Im Idealfall entspricht dies der Anzahl der Zeichen.
* Im Fallback-Szenario entspricht dies der Anzahl der Bytes.
*/
function str_length(string $s): int
{
/**
* Prüfen, ob die Funktion mb_strlen verfügbar ist.
* Dies ist die sicherste und schnellste Methode, da sie für Multibyte-Strings gemacht ist.
*/
if (function_exists('mb_strlen'))
{
// Rückgabe der Zeichenlänge unter expliziter Angabe des Encodings UTF-8.
return (int)mb_strlen($s, 'UTF-8');
}
/**
* Falls mb_strlen nicht verfügbar ist, prüfen wir, ob die intl-Extension aktiviert ist
* und grapheme_strlen zur Verfügung stellt.
*/
if (function_exists('grapheme_strlen'))
{
// Ermittlung der Anzahl der Grapheme in der Zeichenfolge.
$len = grapheme_strlen($s);
// Überprüfung, ob ein gültiges Ergebnis zurückgeliefert wurde (nicht false).
if ($len !== false)
{
return (int)$len;
}
}
/**
* Falls weder mb_strlen noch grapheme_strlen nutzbar sind,
* versuchen wir die UTF-8 Codepoints manuell via Regex (PCRE) zu zählen.
*/
$m = [];
// Der Modifier 'u' steht für UTF-8-Behandlung, 's' sorgt dafür, dass der Punkt (.) auch Zeilenumbrüche matched.
$ok = @preg_match_all('/./us', $s, $m);
// Wenn preg_match_all erfolgreich war, enthält $ok die Anzahl der Matches (also die Zeichenlänge).
if ($ok !== false)
{
return (int)$ok;
}
/**
* Letzter Fallback-Mechanismus:
* Wenn alle UTF-8 spezifischen Ansätze fehlschlagen, zählen wir einfach die Bytes.
* Dies kann bei Zeichenketten mit Sonderzeichen zu längeren Ergebnissen führen,
* stellt aber sicher, dass in jedem Fall eine Ganzzahl (int) zurückgegeben wird.
*/
return strlen($s);
}