'qm', '/m\x{00B3}/u' => 'm3', '/ä/' => 'ae', '/ö/' => 'oe', '/ü/' => 'ue', '/Ä/' => 'Ae', '/Ö/' => 'Oe', '/Ü/' => 'Ue', '/\x{00DF}/u' => 'ss', //ß '/\x{20AC}/u' => 'EURO', //€ '/\x{0026}/u' => 'und', //& ]; /** * Returns true if string starts with needle. * * @example startsWith('Apple', 'A') -> true * * @param string $haystack * @param string $needle * * @return bool */ public static function startsWith($haystack, $needle) { self::ensureString($haystack); self::ensureString($needle); return $needle === '' || strpos($haystack, $needle) === 0; } /** * Returns true if string ends with needle. * * @example endsWith('Apple', 'e') -> true * * @param string $haystack * @param string $needle * * @return bool */ public static function endsWith($haystack, $needle) { self::ensureString($haystack); self::ensureString($needle); return $needle === substr($haystack, strlen($haystack) - strlen($needle), strlen($needle)); } /** * Returns true if needle appears anywhere in string. * * @example contains('Apple', 'pp') -> true * * @param string $haystack * @param string $needle * * @return bool */ public static function contains($haystack, $needle) { self::ensureString($haystack); self::ensureString($needle); return $needle === '' || strpos($haystack, $needle) !== false; } /** * Pads a string up to a specific length. * * @example padLeft('a', 4, '-') -> '---a' * @example padLeft('a', 4, '-+') -> '-+-a' * * @param string $string * @param int $length * @param string $pad * * @return string */ public static function padLeft($string, $length, $pad = ' ') { self::ensureString($string); self::ensureInteger($length); self::ensureString($pad); return self::generatePadding($length - mb_strlen($string), $pad) . $string; } /** * Pads a string up to a specific length. * * @example padRight('a', 4, '-') -> 'a---' * @example padRight('a', 4, '-+') -> 'a-+-' * * @param string $string * @param int $length * @param string $pad * * @return string */ public static function padRight($string, $length, $pad = ' ') { self::ensureString($string); self::ensureInteger($length); self::ensureString($pad); return $string . self::generatePadding($length - mb_strlen($string), $pad); } /** * Generates a filesystem-friendly (win, mac, linux) file name from a given string * * @param string $value * * @return string file name */ public static function toFilename($value) { self::ensureString($value); $sanitize = [ '/\s+/' => '_', //space '/:\\\/' => '-', //drive name '/\\\\\\\/' => '-', //unc path '/[\\/\\\<>:|]/' => '-', //seperators and reserved '/"/' => '\'', '/[\*\?&]+/' => '', //other special chars '/[\x{0000}-\x{001F}]/u' => '', '/[\x{0080}-\x{FFFF}]/u' => '', //only ascii ]; $filename = preg_replace(array_keys(self::$transliteration), array_values(self::$transliteration), $value); $filename = preg_replace(array_keys($sanitize), array_values($sanitize), $filename); $filename = trim($filename, '.'); if ($filename === '') { throw new StringUtilException( sprintf('The specified string "%s" cannot be converted to a valid file name', $value) ); } return $filename; } /** Deletes all non-ASCII non-printable characters from a string * * Only characters between 32 to 127 (inclusive) remain. * * @param string $value * * @return string empty if whole string was non-ASCII */ public static function toAscii($value) { self::ensureString($value); $value = preg_replace(['/[\x{0000}-\x{001F}]/u', '/[\x{0080}-\x{FFFF}]/u'], ['', ''], $value); return $value; } /** * Transforms a String to Title case. * * Use delimiter='' to only capitalize the first character. * * @example "foo Bar BaZ" => "Foo Bar Baz" * * @param string $value * @param string $delimiters all characters that seperate words * * @return string */ public static function toTitleCase($value, $delimiters = '\s\v') { self::ensureString($value); self::ensureString($delimiters); $inWords = [$value]; $outWords = []; if ($delimiters !== '') { $regex = sprintf('/[%s]/', $delimiters); $inWords = preg_split($regex, $value); } foreach ($inWords as $word) { if ($word !== '') { $outWords[] = mb_strtoupper(mb_substr($word, 0, 1)) . mb_strtolower(mb_substr($word, 1, mb_strlen($word))); } } return implode(' ', $outWords); } /** * Format a nubmer of Bytes to KB, MB etc. * * @example formatBytes(1024, ' ') -> '1,0 KB' * * @param integer $bytes * @param string $separator * * @return string */ public static function formatBytes($bytes, $separator = '') { self::ensureInteger($bytes); $bytes = (int)$bytes; if ($bytes <= 0) { return sprintf('0%sBytes', $separator); } $units = ['Bytes', 'KB', 'MB', 'GB', 'TB']; $exponent = (int)floor(log($bytes) / log(1024)); if ($exponent > count($units) - 1) { $exponent = count($units) - 1; } $size = $bytes / pow(1024, $exponent); return sprintf('%s%s%s', number_format($size, 1, ',', '.'), $separator, $units[$exponent] ); } /** * Parse PHP byte size Values to number of bytes. * * Shorthand Format is used in php_ini (e.g. post_max_size). * * @example parsePhpShorthandByte('1M') -> 1048576 * * @param string $phpSize php shorthand byte format * * @return int */ public static function parsePhpByteSize($phpSize) { self::ensureString($phpSize); preg_match('/^(\d+)([kKmMgG]?)$/', $phpSize, $matches); if (empty($matches)) { throw new InvalidArgumentException(sprintf('"%s" is not a PHP size format.', $phpSize)); } $sizes = ['' => 0, 'K' => 1, 'M' => 2, 'G' => 3]; $number = (int)$matches[1]; $unit = strtoupper($matches[2]); $exponent = $sizes[$unit]; $bytes = $number * pow(1024, $exponent); return (int)$bytes; } /** * Generates a random String with specified length * * @param int $length * @param bool $secure true=create cryptographically secure string * * @throws InsecureRandomStringException * * @return string */ public static function random($length, $secure = false) { $random = self::randomByOpenSsl($length, $secure); if ($random === false) { $random = self::randomByRandomBytes($length); } if ($random !== false) { return $random; } if ($random === false && $secure === true) { throw new InsecureRandomStringException('Could not generate cryptographically secure random string.'); } return self::randomByMd5($length); } /** * @param int $length * @param bool $secure * * @return string|false */ private static function randomByOpenSsl($length, $secure = false) { if (function_exists('openssl_random_pseudo_bytes')) { $bytes = openssl_random_pseudo_bytes(ceil($length / 2), $cryptoStrong); if ($bytes === false || ($secure === true && $cryptoStrong === false)) { return false; } return substr(bin2hex($bytes), 0, $length); } return false; } /** * random_bytes steht erst ab PHP7 zur Verfügung * * @param int $length * * @return string|false */ private static function randomByRandomBytes($length) { $random = false; if (function_exists('random_bytes')) { try { $bytes = random_bytes(ceil($length / 2)); $random = substr(bin2hex($bytes), 0, $length); } catch (Exception $e) { } } return $random; } /** * @param int $length * * @return string|false */ private static function randomByMd5($length) { $random = ''; for ($i = 0; $i * 32 <= $length; $i++) { $val = mt_rand(); $random .= md5((string)$val); } $random = substr($random, 0, $length); return $random; } /** * @param int $lengthDelta * @param string $sequence * * @return string */ private static function generatePadding($lengthDelta, $sequence) { if ($sequence === '' || $lengthDelta < 1) { return ''; } $padding = ''; for ($i = 0; $i < $lengthDelta; $i++) { $delta = $lengthDelta - mb_strlen($padding); $subSequence = mb_substr($sequence, 0, $delta); $padding .= $subSequence; } return $padding; } /** * @param mixed $value * * @throws InvalidArgumentException * * @return void */ private static function ensureString($value) { $type = gettype($value); if ($type !== 'string') { throw new InvalidArgumentException(sprintf('Wrong type "%s". Only "string" is allowed.', $type)); } } /** * @param mixed $value * * @throws InvalidArgumentException * * @return void */ private static function ensureInteger($value) { $type = gettype($value); if ($type !== 'integer') { throw new InvalidArgumentException(sprintf('Wrong type "%s". Only "integer" allowed.', $type)); } } }