fix: compatibilidad PHP 7.4 — str_starts_with, str_contains, match, never, mixed
This commit is contained in:
@@ -332,26 +332,26 @@ HTML;
|
||||
private static function typeLabel(string $field, string $type): string
|
||||
{
|
||||
if ($field === 'statuses') {
|
||||
$cls = match ($type) {
|
||||
'sent' => 'badge-blue',
|
||||
'delivered' => 'badge-green',
|
||||
'read' => 'badge-teal',
|
||||
'failed' => 'badge-red',
|
||||
default => 'badge-gray',
|
||||
};
|
||||
switch ($type) {
|
||||
case 'sent': $cls = 'badge-blue'; break;
|
||||
case 'delivered': $cls = 'badge-green'; break;
|
||||
case 'read': $cls = 'badge-teal'; break;
|
||||
case 'failed': $cls = 'badge-red'; break;
|
||||
default: $cls = 'badge-gray'; break;
|
||||
}
|
||||
return '<span class="badge ' . $cls . '">' . self::h($type) . '</span>';
|
||||
}
|
||||
return match ($type) {
|
||||
'text' => '💬 Texto',
|
||||
'image' => '🖼️ Imagen',
|
||||
'audio' => '🎵 Audio',
|
||||
'video' => '🎥 Video',
|
||||
'document' => '📄 Documento',
|
||||
'location' => '📍 Ubicación',
|
||||
'interactive' => '🔘 Interactivo',
|
||||
'button' => '🔲 Botón',
|
||||
default => self::h($type),
|
||||
};
|
||||
switch ($type) {
|
||||
case 'text': return '💬 Texto';
|
||||
case 'image': return '📷 Imagen';
|
||||
case 'audio': return '🎵 Audio';
|
||||
case 'video': return '🎬 Video';
|
||||
case 'document': return '📄 Documento';
|
||||
case 'location': return '📍 Ubicación';
|
||||
case 'interactive': return '🔘 Interactivo';
|
||||
case 'button': return '🔲 Botón';
|
||||
default: return self::h($type);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Render ───────────────────────────────────────────────────────────────
|
||||
|
||||
+29
-25
@@ -92,11 +92,13 @@ class WpWebhook
|
||||
$field = $change['field'] ?? '';
|
||||
$value = $change['value'] ?? [];
|
||||
|
||||
match ($field) {
|
||||
'messages', 'conversations' => self::handleMessages($value),
|
||||
'statuses' => self::handleStatuses($value),
|
||||
default => self::log('INFO', "Campo no manejado: $field"),
|
||||
};
|
||||
if ($field === 'messages' || $field === 'conversations') {
|
||||
self::handleMessages($value);
|
||||
} elseif ($field === 'statuses') {
|
||||
self::handleStatuses($value);
|
||||
} else {
|
||||
self::log('INFO', "Campo no manejado: $field");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,19 +142,19 @@ class WpWebhook
|
||||
'display_phone' => $displayPhone,
|
||||
];
|
||||
|
||||
match ($type) {
|
||||
'text' => self::handleText($msg, $context),
|
||||
'image' => self::handleMedia($msg, $context, 'image'),
|
||||
'audio' => self::handleMedia($msg, $context, 'audio'),
|
||||
'video' => self::handleMedia($msg, $context, 'video'),
|
||||
'document' => self::handleMedia($msg, $context, 'document'),
|
||||
'sticker' => self::handleMedia($msg, $context, 'sticker'),
|
||||
'location' => self::handleLocation($msg, $context),
|
||||
'interactive' => self::handleInteractive($msg, $context),
|
||||
'button' => self::handleButton($msg, $context),
|
||||
'reaction' => self::handleReaction($msg, $context),
|
||||
default => self::log('INFO', "Tipo de mensaje no manejado: $type | from=$from"),
|
||||
};
|
||||
switch ($type) {
|
||||
case 'text': self::handleText($msg, $context); break;
|
||||
case 'image': self::handleMedia($msg, $context, 'image'); break;
|
||||
case 'audio': self::handleMedia($msg, $context, 'audio'); break;
|
||||
case 'video': self::handleMedia($msg, $context, 'video'); break;
|
||||
case 'document': self::handleMedia($msg, $context, 'document'); break;
|
||||
case 'sticker': self::handleMedia($msg, $context, 'sticker'); break;
|
||||
case 'location': self::handleLocation($msg, $context); break;
|
||||
case 'interactive': self::handleInteractive($msg, $context); break;
|
||||
case 'button': self::handleButton($msg, $context); break;
|
||||
case 'reaction': self::handleReaction($msg, $context); break;
|
||||
default: self::log('INFO', "Tipo de mensaje no manejado: $type | from=$from"); break;
|
||||
}
|
||||
}
|
||||
|
||||
// Estados que pueden venir dentro del mismo field 'messages'
|
||||
@@ -198,11 +200,13 @@ class WpWebhook
|
||||
private static function handleInteractive(array $msg, array $ctx): void
|
||||
{
|
||||
$iType = $msg['interactive']['type'] ?? '';
|
||||
$reply = match ($iType) {
|
||||
'button_reply' => $msg['interactive']['button_reply'] ?? [],
|
||||
'list_reply' => $msg['interactive']['list_reply'] ?? [],
|
||||
default => [],
|
||||
};
|
||||
if ($iType === 'button_reply') {
|
||||
$reply = $msg['interactive']['button_reply'] ?? [];
|
||||
} elseif ($iType === 'list_reply') {
|
||||
$reply = $msg['interactive']['list_reply'] ?? [];
|
||||
} else {
|
||||
$reply = [];
|
||||
}
|
||||
$preview = $iType . ': ' . json_encode($reply);
|
||||
self::log('MSG', "[INTERACTIVE/$iType] {$ctx['from']} | reply=" . json_encode($reply));
|
||||
self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], 'interactive', $preview);
|
||||
@@ -262,7 +266,7 @@ class WpWebhook
|
||||
}
|
||||
|
||||
$sigHeader = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? '';
|
||||
if (!str_starts_with($sigHeader, 'sha256=')) {
|
||||
if (strpos($sigHeader, 'sha256=') !== 0) {
|
||||
self::respond(401, ['error' => 'Firma ausente']);
|
||||
}
|
||||
|
||||
@@ -366,7 +370,7 @@ class WpWebhook
|
||||
}
|
||||
}
|
||||
|
||||
private static function respond(int $code, array $body): never
|
||||
private static function respond(int $code, array $body): void
|
||||
{
|
||||
http_response_code($code);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
+3
-3
@@ -15,10 +15,10 @@ declare(strict_types=1);
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
// Ignorar comentarios
|
||||
if ($line === '' || str_starts_with($line, '#')) {
|
||||
if ($line === '' || strpos($line, '#') === 0) {
|
||||
continue;
|
||||
}
|
||||
if (!str_contains($line, '=')) {
|
||||
if (strpos($line, '=') === false) {
|
||||
continue;
|
||||
}
|
||||
[$key, $value] = explode('=', $line, 2);
|
||||
@@ -32,7 +32,7 @@ declare(strict_types=1);
|
||||
}
|
||||
})();
|
||||
|
||||
function env(string $key, mixed $default = null): mixed
|
||||
function env(string $key, $default = null)
|
||||
{
|
||||
return $_ENV[$key] ?? getenv($key) ?: $default;
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@ $base = '';
|
||||
if (file_exists(__DIR__ . '/.env')) {
|
||||
foreach (file(__DIR__ . '/.env') as $line) {
|
||||
$line = trim($line);
|
||||
if (str_starts_with($line, 'APP_BASE=')) {
|
||||
if (strpos($line, 'APP_BASE=') === 0) {
|
||||
$base = rtrim(trim(explode('=', $line, 2)[1]), '/');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($base !== '' && str_starts_with($_SERVER['REQUEST_URI'], $base)) {
|
||||
if ($base !== '' && strpos($_SERVER['REQUEST_URI'], $base) === 0) {
|
||||
$_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'], strlen($base)) ?: '/';
|
||||
}
|
||||
require_once __DIR__ . '/public/index.php';
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ class Auth
|
||||
?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION']
|
||||
?? '';
|
||||
|
||||
if (!str_starts_with($header, 'Bearer ')) {
|
||||
if (strpos($header, 'Bearer ') !== 0) {
|
||||
self::abort(401, 'Token de autorización requerido.');
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ class Auth
|
||||
return base64_decode(strtr($data, '-_', '+/'));
|
||||
}
|
||||
|
||||
private static function abort(int $code, string $message): never
|
||||
private static function abort(int $code, string $message): void
|
||||
{
|
||||
http_response_code($code);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
Reference in New Issue
Block a user