Publication initiale de RelaisSMS : documentation et sources nettoyees
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Sms;
|
||||
|
||||
class SmsMessageLength
|
||||
{
|
||||
private const GSM_BASIC = "@\u{00A3}$\u{00A5}\u{00E8}\u{00E9}\u{00F9}\u{00EC}\u{00F2}\u{00C7}\n\u{00D8}\u{00F8}\r\u{00C5}\u{00E5}\u{0394}_\u{03A6}\u{0393}\u{039B}\u{03A9}\u{03A0}\u{03A8}\u{03A3}\u{0398}\u{039E}\u{00C6}\u{00E6}\u{00DF}\u{00C9} !\"#\u{00A4}%&'()*+,-./0123456789:;<=>?\u{00A1}ABCDEFGHIJKLMNOPQRSTUVWXYZ\u{00C4}\u{00D6}\u{00D1}\u{00DC}\u{00A7}\u{00BF}abcdefghijklmnopqrstuvwxyz\u{00E4}\u{00F6}\u{00F1}\u{00FC}\u{00E0}";
|
||||
|
||||
private const GSM_EXTENDED = "^{}\\[~]|\u{20AC}";
|
||||
|
||||
public function fitsInOneSms(string $message): bool
|
||||
{
|
||||
return $this->units($message) <= $this->singleSmsCapacity($message);
|
||||
}
|
||||
|
||||
public function units(string $message): int
|
||||
{
|
||||
if (! $this->usesGsmAlphabet($message)) {
|
||||
return intdiv(strlen(mb_convert_encoding($message, 'UTF-16BE', 'UTF-8')), 2);
|
||||
}
|
||||
|
||||
return array_sum(array_map(
|
||||
fn (string $character): int => str_contains(self::GSM_EXTENDED, $character) ? 2 : 1,
|
||||
mb_str_split($message),
|
||||
));
|
||||
}
|
||||
|
||||
public function singleSmsCapacity(string $message): int
|
||||
{
|
||||
return $this->usesGsmAlphabet($message) ? 160 : 70;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate a value so that prefix + value + suffix still fits in one SMS.
|
||||
*/
|
||||
public function truncateBetween(string $prefix, string $value, string $suffix, string $marker = '[...]'): string
|
||||
{
|
||||
if ($this->fitsInOneSms($prefix.$value.$suffix)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$truncated = '';
|
||||
|
||||
foreach (mb_str_split($value) as $character) {
|
||||
if (! $this->fitsInOneSms($prefix.$truncated.$character.$marker.$suffix)) {
|
||||
break;
|
||||
}
|
||||
|
||||
$truncated .= $character;
|
||||
}
|
||||
|
||||
if ($this->fitsInOneSms($prefix.$truncated.$marker.$suffix)) {
|
||||
return rtrim($truncated).$marker;
|
||||
}
|
||||
|
||||
return rtrim($truncated);
|
||||
}
|
||||
|
||||
private function usesGsmAlphabet(string $message): bool
|
||||
{
|
||||
foreach (mb_str_split($message) as $character) {
|
||||
if (! str_contains(self::GSM_BASIC, $character) && ! str_contains(self::GSM_EXTENDED, $character)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user