1

Newsletter v1.0
Nuevo módulo para Risus Nova 2.0 — PHPost
Nuevo módulo para Risus Nova 2.0 — PHPost
Captura
[img]Registrate o inicia tu sesión para ver este contenido[/img]
[img]Registrate o inicia tu sesión para ver este contenido[/img]
Sistema de newsletter con consentimiento explícito (RGPD). Los usuarios eligen si quieren recibir comunicaciones al registrarse. El admin puede enviar emails personalizados a todos los suscritos o por rangos específicos.
📧 Características
- Casilla opcional en el registro — consentimiento explícito
- Panel admin con estadísticas: suscritos / no suscritos / total
- Enviar por rango o a todos los suscritos
- Personalización con [usuario] para el nombre del destinatario
- Botón desactivado si no hay suscritos
- Email con enlace para cancelar la suscripción
- Cumple con el RGPD
🛠️ Instalación
Paso 1 — Ejecutar el instalador
Sube la carpeta install/ a la raíz y accede a:
Código: ( Seleccionar Todo )
Registrate o inicia tu sesión para ver este contenido⚠️ Elimina la carpeta install/ cuando termine.
Paso 2 — Subir los archivos
Código: ( Seleccionar Todo )
p.registro.form.tpl → themes/default/templates/php_files/
m.admin_newsletter.tpl → themes/default/templates/admin_mods/Paso 3 — En c.registro.php
Buscar:
Código: ( Seleccionar Todo )
$tsData['user_id'] = db_exec('insert_id');Debajo agregar:
Código: ( Seleccionar Todo )
// ── Newsletter: guardar consentimiento ──
$newsletter = !empty($_POST['newsletter']) ? 1 : 0;
db_exec([__FILE__, __LINE__], 'query',
"UPDATE u_miembros SET user_newsletter = '$newsletter'
WHERE user_id = '{$tsData['user_id']}'"
);
// ────────────────────────────────────────Paso 4 — En admin.php
Buscar:
Código: ( Seleccionar Todo )
} elseif($action == 'feed'){Arriba agregar:
Código: ( Seleccionar Todo )
} elseif($action == 'newsletter'){
// Estadísticas
$stats = [
'suscritos' => 0,
'no_suscritos' => 0,
'total' => 0,
];
$r = db_exec('fetch_row', db_exec([__FILE__, __LINE__], 'query',
"SELECT
SUM(user_newsletter = 1) AS s,
SUM(user_newsletter = 0) AS n,
COUNT(*) AS t
FROM u_miembros WHERE user_activo = '1' AND user_baneado = '0'"
));
if ($r) {
$stats['suscritos'] = (int)$r[0];
$stats['no_suscritos'] = (int)$r[1];
$stats['total'] = (int)$r[2];
}
$smarty->assign('tsNewsletterStats', $stats);
// Rangos con conteo de suscritos
$rangos = result_array(db_exec([__FILE__, __LINE__], 'query',
"SELECT r.rango_id, r.r_name, r.r_color,
COUNT(u.user_id) AS suscritos
FROM u_rangos AS r
LEFT JOIN u_miembros AS u
ON u.user_rango = r.rango_id
AND u.user_newsletter = '1'
AND u.user_activo = '1'
AND u.user_baneado = '0'
GROUP BY r.rango_id
ORDER BY r.r_cant ASC"
)) ?: [];
$smarty->assign('tsNewsletterRangos', $rangos);
// Enviar
if (!empty($_GET['save']) && !empty($_POST['nl_subject']) && !empty($_POST['nl_body'])) {
$asunto = $tsCore->setSecure($_POST['nl_subject']);
$cuerpo = $_POST['nl_body'];
$rangos_sel = $_POST['rangos'] ?? [];
$todos = empty($rangos_sel);
if ($todos) {
$where = "user_newsletter = '1' AND user_activo = '1' AND user_baneado = '0'";
} else {
$ids = implode(',', array_map('intval', $rangos_sel));
$where = "user_newsletter = '1' AND user_activo = '1' AND user_baneado = '0' AND user_rango IN ($ids)";
}
$usuarios = result_array(db_exec([__FILE__, __LINE__], 'query',
"SELECT user_id, user_name, user_email FROM u_miembros WHERE $where"
)) ?: [];
if (empty($usuarios)) {
$smarty->assign('tsNewsletterError', 'No hay usuarios suscritos en los rangos seleccionados.');
} else {
require_once TS_CLASS . 'c.emails.php';
$total = 0;
foreach ($usuarios as $u) {
$msg = str_replace('[usuario]', $u['user_name'], $cuerpo);
$html = '<div style="font-family:Arial,sans-serif;max-width:600px;margin:0 auto;">';
$html .= '<div style="background:#3498db;padding:16px 24px;">';
$html .= '<h1 style="color:#fff;margin:0;font-size:22px;">' . $tsCore->settings['titulo'] . '</h1>';
$html .= '</div>';
$html .= '<div style="padding:24px;background:#fff;border:1px solid #eee;">';
$html .= '<p style="font-size:15px;color:#333;line-height:1.7;">' . nl2br(htmlspecialchars($msg)) . '</p>';
$html .= '</div>';
$html .= '<div style="padding:12px 24px;background:#f8f9fa;font-size:11px;color:#999;text-align:center;">';
$html .= 'Para cancelar la suscripción accede a tu <a href="' . $tsCore->settings['url'] . '/cuenta/">cuenta</a>.';
$html .= '</div></div>';
$tsEmail = new tsEmail('newsletter', 'newsletter');
$tsEmail->emailTo = $u['user_email'];
$tsEmail->emailSubject = $asunto;
$tsEmail->emailBody = $html;
$tsEmail->emailHeaders = $tsEmail->setEmailHeaders();
$tsEmail->sendEmail($tsCore->settings['email'], $u['user_email'], $asunto, $html);
$total++;
}
$smarty->assign('tsNewsletterEnviado', $total);
}
}Paso 5 — Añadir en t.admin.tpl
Antes del {/if} final añade:
Código: ( Seleccionar Todo )
{elseif $tsAction == 'newsletter'}
{include file='admin_mods/m.admin_newsletter.tpl'}Paso 6 — En m.admin_sidemenu.tpl agregan esto donde quieran:
Código: ( Seleccionar Todo )
<li><a href="{$tsConfig.url}/admin/newsletter"><i class="fa-solid fa-envelope-open-text"></i> Newsletter</a></li>Paso 7 — Borrar la caché
Borra el contenido de la carpeta [b]/cache/ del sitio.[/b]
🔒 RGPD
- El usuario da consentimiento explícito al registrarse
- Puede cancelar la suscripción desde su cuenta
- Solo se envía a usuarios que aceptaron recibirlo
- Las contraseñas nunca se incluyen en ningún email
🗑️ Desinstalar
Código: ( Seleccionar Todo )
ALTER TABLE u_miembros DROP COLUMN user_newsletter;Elimina los archivos y quita los hooks.
Descarga
Mediafire
Debes agradecer para ver el contenido...
Google Drive
Debes agradecer para ver el contenido...
¿Tienes dudas o encuentras algún problema? Déjalo en los comentarios.[/b]
Mediafire
Debes agradecer para ver el contenido...
Google Drive
Debes agradecer para ver el contenido...
¿Tienes dudas o encuentras algún problema? Déjalo en los comentarios.[/b]




Facebook
Twitter
Reddit
Digg
del.icio.us
Tumblr
Pinterest
Blogger
Fark
LinkedIn
Mix
Google