479 lines
23 KiB
PHP
479 lines
23 KiB
PHP
<?php
|
|
|
|
/**
|
|
* API dell'editor newsletter (risponde sempre in JSON, tranne "preview" che restituisce HTML).
|
|
*
|
|
* GET action=load&id= bozza completa
|
|
* POST action=save salvataggio automatico (controllo revisione)
|
|
* GET action=versions&id= storico versioni
|
|
* GET action=version_html&idversion= anteprima di una versione (HTML)
|
|
* POST action=snapshot salva una versione con nome
|
|
* POST action=restore ripristina una versione
|
|
* POST action=preview HTML di anteprima + controlli
|
|
* POST action=upload_image carica e ottimizza un'immagine
|
|
* POST action=send_test invia una prova
|
|
* POST action=publish crea/aggiorna la bozza in The Newsletter
|
|
* POST action=create|duplicate|delete
|
|
* GET action=list_wp newsletter presenti in WordPress
|
|
* POST action=import_wp importa una newsletter di WordPress
|
|
*
|
|
* NB: la protezione della pagina (solo staff) va aggiunta come per le altre pagine admin.
|
|
*/
|
|
ob_start();
|
|
require_once('include/headscript.php');
|
|
require_once(__DIR__ . '/class/mailer.php');
|
|
require_once(__DIR__ . '/class/NewsletterRenderer.php');
|
|
require_once(__DIR__ . '/class/NewsletterWp.php');
|
|
|
|
function out(array $payload, int $code = 200): void
|
|
{
|
|
if (ob_get_length() !== false) ob_end_clean();
|
|
http_response_code($code);
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
header('Cache-Control: no-store');
|
|
echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
exit;
|
|
}
|
|
|
|
function fail(string $msg, int $code = 400, array $extra = []): void
|
|
{
|
|
out(['success' => false, 'message' => $msg] + $extra, $code);
|
|
}
|
|
|
|
$pdo = DBHandlerSelect::getInstance()->getConnection();
|
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
|
|
$userId = (int) $iduserlogin;
|
|
$action = $_REQUEST['action'] ?? '';
|
|
$isPost = $_SERVER['REQUEST_METHOD'] === 'POST';
|
|
|
|
const NL_MAX_JSON = 2 * 1024 * 1024; // 2 MB di blocchi bastano e avanzano
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Funzioni di supporto
|
|
* ---------------------------------------------------------------------- */
|
|
|
|
function draftRow(PDO $pdo, int $id): array
|
|
{
|
|
$st = $pdo->prepare("SELECT * FROM newsletter_drafts WHERE iddraft = ? AND deleted_at IS NULL");
|
|
$st->execute([$id]);
|
|
$d = $st->fetch(PDO::FETCH_ASSOC);
|
|
if (!$d) fail('Newsletter non trovata.', 404);
|
|
return $d;
|
|
}
|
|
|
|
function draftPayload(array $d): array
|
|
{
|
|
$wpStatus = null;
|
|
if (!empty($d['wp_email_id']) && NewsletterWp::isConfigured()) {
|
|
try {
|
|
$wpStatus = NewsletterWp::statuses([(int) $d['wp_email_id']])[(int) $d['wp_email_id']] ?? 'deleted';
|
|
} catch (Throwable $e) {
|
|
$wpStatus = null;
|
|
}
|
|
}
|
|
|
|
return [
|
|
'id' => (int) $d['iddraft'],
|
|
'title' => $d['title'],
|
|
'subject' => $d['subject'],
|
|
'preheader' => $d['preheader'],
|
|
'blocks' => json_decode($d['blocks'] ?: '[]', true) ?: [],
|
|
'settings' => NewsletterRenderer::settings(json_decode($d['settings'] ?: '{}', true) ?: []),
|
|
'revision' => (int) $d['revision'],
|
|
'updated_at' => $d['updated_at'],
|
|
'wp_email_id' => $d['wp_email_id'] !== null ? (int) $d['wp_email_id'] : null,
|
|
'wp_pushed_at' => $d['wp_pushed_at'],
|
|
'wp_status' => $wpStatus,
|
|
];
|
|
}
|
|
|
|
/** Legge e valida blocchi + impostazioni inviati dall'editor. */
|
|
function readContent(): array
|
|
{
|
|
$blocksRaw = (string) ($_POST['blocks'] ?? '[]');
|
|
$settingsRaw = (string) ($_POST['settings'] ?? '{}');
|
|
|
|
if (strlen($blocksRaw) > NL_MAX_JSON) fail('La newsletter è troppo grande.', 413);
|
|
|
|
$blocks = json_decode($blocksRaw, true);
|
|
$settings = json_decode($settingsRaw, true);
|
|
if (!is_array($blocks) || !is_array($settings)) fail('Dati non validi.', 422);
|
|
|
|
$clean = [];
|
|
foreach ($blocks as $b) {
|
|
if (!is_array($b) || !in_array($b['type'] ?? '', NewsletterRenderer::BLOCK_TYPES, true)) continue;
|
|
$b['id'] = preg_replace('/[^a-z0-9]/i', '', (string) ($b['id'] ?? '')) ?: bin2hex(random_bytes(6));
|
|
$clean[] = $b;
|
|
}
|
|
|
|
return [
|
|
'title' => mb_substr(trim((string) ($_POST['title'] ?? '')), 0, 255),
|
|
'subject' => mb_substr(trim((string) ($_POST['subject'] ?? '')), 0, 255),
|
|
'preheader' => mb_substr(trim((string) ($_POST['preheader'] ?? '')), 0, 255),
|
|
'blocks' => $clean,
|
|
'settings' => $settings,
|
|
];
|
|
}
|
|
|
|
function addVersion(PDO $pdo, array $d, string $note, int $userId): void
|
|
{
|
|
$pdo->prepare("INSERT INTO newsletter_draft_versions
|
|
(iddraft, revision, subject, preheader, blocks, settings, note, created_by, created_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())")
|
|
->execute([(int) $d['iddraft'], (int) $d['revision'], $d['subject'], $d['preheader'], $d['blocks'], $d['settings'], mb_substr($note, 0, 100), $userId]);
|
|
|
|
// Tiene le ultime 200 versioni per newsletter
|
|
$pdo->prepare("DELETE FROM newsletter_draft_versions
|
|
WHERE iddraft = ? AND idversion NOT IN (
|
|
SELECT idversion FROM (SELECT idversion FROM newsletter_draft_versions WHERE iddraft = ? ORDER BY idversion DESC LIMIT 200) keep
|
|
)")->execute([(int) $d['iddraft'], (int) $d['iddraft']]);
|
|
}
|
|
|
|
function createDraft(PDO $pdo, int $userId, string $title, string $subject, string $preheader, array $blocks, array $settings, ?int $wpId = null): int
|
|
{
|
|
$pdo->prepare("INSERT INTO newsletter_drafts
|
|
(title, subject, preheader, blocks, settings, revision, wp_email_id, created_by, updated_by, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, 1, ?, ?, ?, NOW(), NOW())")
|
|
->execute([$title, $subject, $preheader, json_encode($blocks, JSON_UNESCAPED_UNICODE), json_encode($settings, JSON_UNESCAPED_UNICODE), $wpId, $userId, $userId]);
|
|
return (int) $pdo->lastInsertId();
|
|
}
|
|
|
|
function baseUrl(): string
|
|
{
|
|
if (!empty($_ENV['NEWSLETTER_BASE_URL'])) return rtrim($_ENV['NEWSLETTER_BASE_URL'], '/');
|
|
$https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? '') === 'https';
|
|
$dir = rtrim(str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME'] ?? '/')), '/');
|
|
return ($https ? 'https' : 'http') . '://' . ($_SERVER['HTTP_HOST'] ?? 'localhost') . $dir;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* Azioni
|
|
* ---------------------------------------------------------------------- */
|
|
try {
|
|
switch ($action) {
|
|
|
|
case 'load':
|
|
out(['success' => true, 'draft' => draftPayload(draftRow($pdo, (int) ($_GET['id'] ?? 0)))]);
|
|
|
|
case 'save':
|
|
if (!$isPost) fail('Metodo non consentito.', 405);
|
|
$id = (int) ($_POST['id'] ?? 0);
|
|
$rev = (int) ($_POST['revision'] ?? -1);
|
|
$force = ($_POST['force'] ?? '') === '1';
|
|
$c = readContent();
|
|
|
|
$sql = "UPDATE newsletter_drafts
|
|
SET title = ?, subject = ?, preheader = ?, blocks = ?, settings = ?,
|
|
revision = revision + 1, updated_by = ?, updated_at = NOW()
|
|
WHERE iddraft = ? AND deleted_at IS NULL" . ($force ? '' : ' AND revision = ?');
|
|
$params = [
|
|
$c['title'],
|
|
$c['subject'],
|
|
$c['preheader'],
|
|
json_encode($c['blocks'], JSON_UNESCAPED_UNICODE),
|
|
json_encode($c['settings'], JSON_UNESCAPED_UNICODE),
|
|
$userId,
|
|
$id
|
|
];
|
|
if (!$force) $params[] = $rev;
|
|
|
|
$st = $pdo->prepare($sql);
|
|
$st->execute($params);
|
|
|
|
$d = draftRow($pdo, $id);
|
|
if ($st->rowCount() === 0) {
|
|
fail('Questa newsletter è stata salvata da un\'altra parte (un\'altra scheda o un altro computer).', 409, [
|
|
'conflict' => true,
|
|
'revision' => (int) $d['revision'],
|
|
'updated_at' => $d['updated_at'],
|
|
]);
|
|
}
|
|
|
|
// Versione automatica ogni 10 minuti di lavoro
|
|
$st = $pdo->prepare("SELECT MAX(created_at) FROM newsletter_draft_versions WHERE iddraft = ?");
|
|
$st->execute([$id]);
|
|
$last = $st->fetchColumn();
|
|
if (!$last || strtotime($last) < time() - 600) {
|
|
addVersion($pdo, $d, 'Automatica', $userId);
|
|
}
|
|
|
|
out(['success' => true, 'revision' => (int) $d['revision'], 'updated_at' => $d['updated_at']]);
|
|
|
|
case 'versions':
|
|
$st = $pdo->prepare("SELECT v.idversion, v.revision, v.note, v.created_at, v.subject,
|
|
TRIM(CONCAT(COALESCE(u.first_name, ''), ' ', COALESCE(u.last_name, ''))) AS author
|
|
FROM newsletter_draft_versions v
|
|
LEFT JOIN auth_users u ON u.id = v.created_by
|
|
WHERE v.iddraft = ?
|
|
ORDER BY v.idversion DESC LIMIT 200");
|
|
$st->execute([(int) ($_GET['id'] ?? 0)]);
|
|
out(['success' => true, 'versions' => $st->fetchAll(PDO::FETCH_ASSOC)]);
|
|
|
|
case 'version_html':
|
|
$st = $pdo->prepare("SELECT * FROM newsletter_draft_versions WHERE idversion = ?");
|
|
$st->execute([(int) ($_GET['idversion'] ?? 0)]);
|
|
$v = $st->fetch(PDO::FETCH_ASSOC);
|
|
if (!$v) fail('Versione non trovata.', 404);
|
|
if (ob_get_length() !== false) ob_end_clean();
|
|
header('Content-Type: text/html; charset=utf-8');
|
|
echo NewsletterRenderer::renderDocument(json_decode($v['blocks'] ?: '[]', true) ?: [], json_decode($v['settings'] ?: '{}', true) ?: [], $v['subject'], $v['preheader'], true);
|
|
exit;
|
|
|
|
case 'snapshot':
|
|
if (!$isPost) fail('Metodo non consentito.', 405);
|
|
$d = draftRow($pdo, (int) ($_POST['id'] ?? 0));
|
|
addVersion($pdo, $d, trim((string) ($_POST['note'] ?? '')) ?: 'Salvata a mano', $userId);
|
|
out(['success' => true]);
|
|
|
|
case 'restore':
|
|
if (!$isPost) fail('Metodo non consentito.', 405);
|
|
$id = (int) ($_POST['id'] ?? 0);
|
|
$d = draftRow($pdo, $id);
|
|
|
|
$st = $pdo->prepare("SELECT * FROM newsletter_draft_versions WHERE idversion = ? AND iddraft = ?");
|
|
$st->execute([(int) ($_POST['idversion'] ?? 0), $id]);
|
|
$v = $st->fetch(PDO::FETCH_ASSOC);
|
|
if (!$v) fail('Versione non trovata.', 404);
|
|
|
|
$pdo->beginTransaction();
|
|
addVersion($pdo, $d, 'Prima del ripristino', $userId);
|
|
$pdo->prepare("UPDATE newsletter_drafts SET subject = ?, preheader = ?, blocks = ?, settings = ?,
|
|
revision = revision + 1, updated_by = ?, updated_at = NOW() WHERE iddraft = ?")
|
|
->execute([$v['subject'], $v['preheader'], $v['blocks'], $v['settings'], $userId, $id]);
|
|
$pdo->commit();
|
|
|
|
out(['success' => true, 'draft' => draftPayload(draftRow($pdo, $id))]);
|
|
|
|
case 'preview':
|
|
if (!$isPost) fail('Metodo non consentito.', 405);
|
|
$c = readContent();
|
|
$real = NewsletterRenderer::renderDocument($c['blocks'], $c['settings'], $c['subject'], $c['preheader']);
|
|
out([
|
|
'success' => true,
|
|
'html' => NewsletterRenderer::renderDocument($c['blocks'], $c['settings'], $c['subject'], $c['preheader'], true),
|
|
'kb' => (int) round(strlen($real) / 1024),
|
|
'checks' => NewsletterRenderer::checks($c['blocks'], $c['subject'], $c['preheader'], $real),
|
|
]);
|
|
|
|
case 'upload_image':
|
|
if (!$isPost) fail('Metodo non consentito.', 405);
|
|
$f = $_FILES['image'] ?? null;
|
|
if (!$f || ($f['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
|
|
$why = [
|
|
UPLOAD_ERR_INI_SIZE => 'il file supera il limite del server (upload_max_filesize)',
|
|
UPLOAD_ERR_FORM_SIZE => 'il file è troppo grande',
|
|
UPLOAD_ERR_PARTIAL => 'caricamento interrotto',
|
|
UPLOAD_ERR_NO_FILE => 'nessun file ricevuto',
|
|
UPLOAD_ERR_NO_TMP_DIR => 'manca la cartella temporanea sul server',
|
|
UPLOAD_ERR_CANT_WRITE => 'il server non riesce a scrivere il file',
|
|
][$f['error'] ?? UPLOAD_ERR_NO_FILE] ?? 'errore sconosciuto';
|
|
fail('Caricamento non riuscito: ' . $why . '.');
|
|
}
|
|
if ($f['size'] > 15 * 1024 * 1024) fail('Immagine troppo grande (massimo 15 MB).');
|
|
|
|
$info = @getimagesize($f['tmp_name']);
|
|
$mime = $info['mime'] ?? '';
|
|
$ext = ['image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/webp' => 'webp'][$mime] ?? null;
|
|
if (!$ext) fail('Formato non supportato: usa JPG, PNG, GIF o WebP.');
|
|
|
|
$dirRel = 'assets/uploads/newsletter/' . date('Y/m');
|
|
$dirAbs = __DIR__ . '/' . $dirRel;
|
|
if (!is_dir($dirAbs) && !@mkdir($dirAbs, 0755, true)) {
|
|
fail('Impossibile creare la cartella ' . $dirRel . ': controlla i permessi di assets/uploads.', 500);
|
|
}
|
|
if (!is_writable($dirAbs)) fail('La cartella ' . $dirRel . ' non è scrivibile: controlla i permessi.', 500);
|
|
|
|
$name = date('Ymd_His') . '_' . bin2hex(random_bytes(4));
|
|
[$w, $h] = $info;
|
|
$note = '';
|
|
|
|
// Si può ottimizzare? Serve GD con il formato giusto
|
|
$reader = ['image/jpeg' => 'imagecreatefromjpeg', 'image/png' => 'imagecreatefrompng', 'image/webp' => 'imagecreatefromwebp'][$mime] ?? null;
|
|
$canResize = $mime !== 'image/gif' && $reader && function_exists($reader) && function_exists('imagecreatetruecolor');
|
|
|
|
if (!$canResize) {
|
|
// GIF (forse animata) oppure server senza GD: salviamo l'originale
|
|
if ($mime !== 'image/gif' && $f['size'] > 3 * 1024 * 1024) {
|
|
fail('Il server non può ridimensionare le immagini (manca la libreria GD) e questa supera 3 MB: riducila prima di caricarla.');
|
|
}
|
|
$file = $name . '.' . $ext;
|
|
if (!move_uploaded_file($f['tmp_name'], $dirAbs . '/' . $file)) fail('Impossibile salvare l\'immagine.', 500);
|
|
if ($mime !== 'image/gif') $note = 'Caricata senza ottimizzazione (sul server manca la libreria GD).';
|
|
} else {
|
|
try {
|
|
@ini_set('memory_limit', '512M'); // le foto dal telefono sono grandi
|
|
$src = @$reader($f['tmp_name']);
|
|
if (!$src) fail('Immagine non leggibile o danneggiata.');
|
|
|
|
// Foto dal telefono: raddrizza secondo l'orientamento EXIF
|
|
if ($mime === 'image/jpeg' && function_exists('exif_read_data')) {
|
|
$o = (int) (@exif_read_data($f['tmp_name'])['Orientation'] ?? 1);
|
|
$rot = [3 => 180, 6 => -90, 8 => 90][$o] ?? 0;
|
|
if ($rot) {
|
|
$src = imagerotate($src, $rot, 0);
|
|
$w = imagesx($src);
|
|
$h = imagesy($src);
|
|
}
|
|
}
|
|
|
|
$nw = min($w, 1200); // il doppio della larghezza email: nitida sugli schermi retina
|
|
$nh = max(1, (int) round($h * $nw / $w));
|
|
|
|
// PNG con trasparenza resta PNG, il resto diventa JPG (molto più leggero)
|
|
$keepPng = false;
|
|
if ($mime === 'image/png') {
|
|
$ct = ord((string) file_get_contents($f['tmp_name'], false, null, 25, 1));
|
|
$keepPng = in_array($ct, [4, 6], true);
|
|
}
|
|
|
|
$dst = imagecreatetruecolor($nw, $nh);
|
|
if ($keepPng) {
|
|
imagealphablending($dst, false);
|
|
imagesavealpha($dst, true);
|
|
} else {
|
|
imagefill($dst, 0, 0, imagecolorallocate($dst, 255, 255, 255));
|
|
}
|
|
imagecopyresampled($dst, $src, 0, 0, 0, 0, $nw, $nh, $w, $h);
|
|
|
|
$file = $name . ($keepPng ? '.png' : '.jpg');
|
|
$ok = $keepPng ? imagepng($dst, $dirAbs . '/' . $file, 9) : imagejpeg($dst, $dirAbs . '/' . $file, 82);
|
|
imagedestroy($src);
|
|
imagedestroy($dst);
|
|
if (!$ok) fail('Impossibile salvare l\'immagine ottimizzata.', 500);
|
|
[$w, $h] = [$nw, $nh];
|
|
} catch (Throwable $e) {
|
|
error_log('newsletter_api [upload_image]: ' . $e->getMessage());
|
|
fail('Ottimizzazione non riuscita: ' . $e->getMessage(), 500);
|
|
}
|
|
}
|
|
|
|
out([
|
|
'success' => true,
|
|
'url' => baseUrl() . '/' . $dirRel . '/' . $file,
|
|
'width' => $w,
|
|
'height' => $h,
|
|
'kb' => (int) round(filesize($dirAbs . '/' . $file) / 1024),
|
|
'note' => $note,
|
|
]);
|
|
|
|
case 'send_test':
|
|
if (!$isPost) fail('Metodo non consentito.', 405);
|
|
$d = draftRow($pdo, (int) ($_POST['id'] ?? 0));
|
|
$to = trim((string) ($_POST['to'] ?? ''));
|
|
if (!filter_var($to, FILTER_VALIDATE_EMAIL)) fail('Indirizzo email non valido.');
|
|
|
|
$p = draftPayload($d);
|
|
$html = NewsletterRenderer::renderDocument($p['blocks'], $p['settings'], $p['subject'], $p['preheader'], true);
|
|
|
|
$clean = fn($v) => trim((string) $v, "\" \t\n\r\0\x0B");
|
|
$mail = new \PHPMailer\PHPMailer\PHPMailer(true);
|
|
$mail->isSMTP();
|
|
$mail->Host = $clean($_ENV['MAIL_HOST'] ?? '');
|
|
$mail->SMTPAuth = true;
|
|
$mail->Username = $_ENV['MAIL_USERNAME'] ?? '';
|
|
$mail->Password = $_ENV['MAIL_PASSWORD'] ?? '';
|
|
$mail->SMTPSecure = $clean($_ENV['MAIL_ENCRYPTION'] ?? 'ssl');
|
|
$mail->Port = (int) ($_ENV['MAIL_PORT'] ?? 465);
|
|
$mail->Timeout = 20;
|
|
$mail->CharSet = 'UTF-8';
|
|
$mail->setFrom($clean($_ENV['MAIL_FROM_ADDRESS'] ?? ''), $clean($_ENV['MAIL_FROM_NAME'] ?? 'YogaSoul'));
|
|
$mail->addAddress($to);
|
|
$mail->isHTML(true);
|
|
$mail->Subject = '[PROVA] ' . ($p['subject'] ?: '(senza oggetto)');
|
|
$mail->Body = $html;
|
|
$mail->AltBody = str_replace('{name}', 'Maria', NewsletterRenderer::renderText($p['blocks'], $p['preheader']));
|
|
$mail->send();
|
|
|
|
out(['success' => true, 'message' => 'Prova inviata a ' . $to . '.']);
|
|
|
|
case 'publish':
|
|
if (!$isPost) fail('Metodo non consentito.', 405);
|
|
$id = (int) ($_POST['id'] ?? 0);
|
|
$d = draftRow($pdo, $id);
|
|
$p = draftPayload($d);
|
|
|
|
$html = NewsletterRenderer::renderDocument($p['blocks'], $p['settings'], $p['subject'], $p['preheader']);
|
|
$checks = NewsletterRenderer::checks($p['blocks'], $p['subject'], $p['preheader'], $html);
|
|
$errors = array_filter($checks, fn($c) => $c[0] === 'error');
|
|
|
|
if ($errors && ($_POST['confirm'] ?? '') !== '1') {
|
|
out(['success' => false, 'needs_confirm' => true, 'checks' => $checks, 'message' => 'Ci sono problemi da controllare.']);
|
|
}
|
|
if (trim($p['subject']) === '') fail("Manca l'oggetto: in WordPress non si può inviare senza.");
|
|
|
|
$text = NewsletterRenderer::renderText($p['blocks'], $p['preheader']);
|
|
[$wpId, $created] = NewsletterWp::push($p['wp_email_id'], $p['subject'], $p['preheader'], $html, $text, $p['settings']);
|
|
|
|
$pdo->prepare("UPDATE newsletter_drafts SET wp_email_id = ?, wp_pushed_at = NOW() WHERE iddraft = ?")->execute([$wpId, $id]);
|
|
addVersion($pdo, $d, 'Pubblicata su The Newsletter', $userId);
|
|
|
|
out([
|
|
'success' => true,
|
|
'wp_id' => $wpId,
|
|
'created' => $created,
|
|
'admin_url' => NewsletterWp::adminUrl(),
|
|
'message' => $created
|
|
? "Creata in The Newsletter (n. $wpId). Il pubblico è impostato come l'ultima newsletter: controllalo prima di inviare."
|
|
: "Aggiornata in The Newsletter (n. $wpId).",
|
|
]);
|
|
|
|
case 'create':
|
|
if (!$isPost) fail('Metodo non consentito.', 405);
|
|
$title = trim((string) ($_POST['title'] ?? '')) ?: 'Newsletter del ' . date('d/m/Y');
|
|
$id = createDraft($pdo, $userId, $title, '', '', NewsletterRenderer::starterBlocks(), NewsletterRenderer::defaultSettings());
|
|
out(['success' => true, 'id' => $id]);
|
|
|
|
case 'duplicate':
|
|
if (!$isPost) fail('Metodo non consentito.', 405);
|
|
$d = draftRow($pdo, (int) ($_POST['id'] ?? 0));
|
|
$blocks = json_decode($d['blocks'] ?: '[]', true) ?: [];
|
|
foreach ($blocks as &$b) $b['id'] = bin2hex(random_bytes(6));
|
|
unset($b);
|
|
$id = createDraft($pdo, $userId, 'Copia di ' . $d['title'], $d['subject'], $d['preheader'], $blocks, json_decode($d['settings'] ?: '{}', true) ?: []);
|
|
out(['success' => true, 'id' => $id]);
|
|
|
|
case 'delete':
|
|
if (!$isPost) fail('Metodo non consentito.', 405);
|
|
$pdo->prepare("UPDATE newsletter_drafts SET deleted_at = NOW(), updated_by = ? WHERE iddraft = ?")
|
|
->execute([$userId, (int) ($_POST['id'] ?? 0)]);
|
|
out(['success' => true]);
|
|
|
|
case 'list_wp':
|
|
out(['success' => true, 'emails' => NewsletterWp::listEmails(40)]);
|
|
|
|
case 'import_wp':
|
|
if (!$isPost) fail('Metodo non consentito.', 405);
|
|
$wpId = (int) ($_POST['wp_id'] ?? 0);
|
|
$imp = NewsletterWp::import($wpId);
|
|
// Se in WordPress non è ancora partita, la colleghiamo: "Pubblica" aggiornerà quella
|
|
$status = NewsletterWp::statuses([$wpId])[$wpId] ?? '';
|
|
$id = createDraft(
|
|
$pdo,
|
|
$userId,
|
|
$imp['subject'] ?: 'Importata da WordPress',
|
|
$imp['subject'],
|
|
$imp['preheader'],
|
|
$imp['blocks'],
|
|
$imp['settings'],
|
|
$status === 'new' ? $wpId : null
|
|
);
|
|
out(['success' => true, 'id' => $id, 'linked' => $status === 'new']);
|
|
|
|
default:
|
|
fail('Azione sconosciuta.', 404);
|
|
}
|
|
} catch (\PHPMailer\PHPMailer\Exception $e) {
|
|
fail('Invio non riuscito: ' . $e->getMessage(), 502);
|
|
} catch (PDOException $e) {
|
|
if ($pdo->inTransaction()) $pdo->rollBack();
|
|
error_log('newsletter_api [' . $action . '] DB: ' . $e->getMessage());
|
|
fail('Errore del database. Riprova; se continua controlla il log.', 500);
|
|
} catch (RuntimeException $e) {
|
|
fail($e->getMessage(), 409);
|
|
} catch (Throwable $e) {
|
|
if ($pdo->inTransaction()) $pdo->rollBack();
|
|
error_log('newsletter_api [' . $action . ']: ' . $e->getMessage() . ' @' . $e->getFile() . ':' . $e->getLine());
|
|
fail('Errore del server. Riprova; se continua controlla il log.', 500);
|
|
}
|