PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE=>PDO::FETCH_ASSOC ]); }catch(Exception $e){ http_response_code(500); die("DB error: ".$e->getMessage()); } } /* ===== Helpers ===== */ function base_url_prefix(){ $proto = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https://' : 'http://'; $host = $_SERVER['HTTP_HOST'] ?? 'localhost'; $base = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/'); return $proto.$host.$base; } function normalize_media_url($src){ $src = trim((string)$src); if ($src === '') return ''; if (preg_match('#^https?://#i', $src)) return $src; if (preg_match('#^/?uploads/#i', $src)) { $prefix = base_url_prefix(); $src = ltrim($src, '/'); return rtrim($prefix,'/').'/'.$src; } return rtrim(base_url_prefix(),'/').'/'.ltrim($src,'/'); } function is_youtube($u){ return (bool)preg_match('#(youtube\.com|youtu\.be)#i',$u); } function yt_id($u){ if (preg_match('#youtu\.be/([^?&/]+)#i', $u, $m)) return $m[1]; if (preg_match('#v=([^&]+)#i', $u, $m)) return $m[1]; if (preg_match('#/embed/([^?&/]+)#i', $u, $m)) return $m[1]; return ''; } function is_vimeo($u){ return (bool)preg_match('#vimeo\.com#i',$u); } function vimeo_id($u){ if (preg_match('#vimeo\.com/(\d+)#i', $u, $m)) return $m[1]; if (preg_match('#player\.vimeo\.com/video/(\d+)#i', $u, $m)) return $m[1]; return ''; } function e($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } function render_block($b){ $type = $b['type'] ?? ''; switch ($type) { case 'h1': return '

'.($b['content'] ?? 'Título').'

'; case 'p': return '

'.($b['content'] ?? '').'

'; case 'quote': return '
'.($b['content'] ?? '').'
'; case 'link': { $href = e($b['href'] ?? '#'); $txt = $b['content'] ?? $href; return '

'.$txt.'

'; } case 'img': { $src = normalize_media_url($b['src'] ?? ''); if (!$src) return ''; return '
'; } case 'embed': return (string)($b['embedHtml'] ?? ''); case 'video': { $raw = $b['src'] ?? ''; $src = normalize_media_url($raw); if (!$src) return ''; if (is_youtube($src)) { $id = yt_id($src); if ($id) { return '
'; } } if (is_vimeo($src)) { $id = vimeo_id($src); if ($id) { return '
'; } } // Directo/local (mp4/webm/ogg) $t = strtolower(pathinfo(parse_url($src, PHP_URL_PATH) ?? '', PATHINFO_EXTENSION)); $mime = ($t==='webm'?'video/webm':($t==='ogg'?'video/ogg':'video/mp4')); return '
'; } } return ''; } function render_blocks($json){ $arr = []; try { $arr = json_decode($json ?? '[]', true) ?: []; } catch (Throwable $e) { $arr = []; } if (!is_array($arr)) $arr = []; $html = ''; foreach ($arr as $b) $html .= render_block($b); return $html; } /* ===== Data ===== */ $st = $pdo->query("SELECT id,titulo,estado,portada_url,contenido_json,updated_at FROM noticias WHERE estado IN ('borrador','publicado') ORDER BY updated_at DESC LIMIT 50"); $items = $st->fetchAll(); ?> Noticias

Noticias

Admin
Sin noticias por ahora.