/* ---------- Professional v3 helper functions ---------- */ function get_setting($key, $default = '') { static $cache = null; if ($cache === null) { $cache = []; try { $pdo = db(); if ($pdo) { $stmt = $pdo->query("SELECT setting_key, setting_value FROM settings"); foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) { $cache[$row['setting_key']] = $row['setting_value']; } } } catch (Throwable $e) {} } return array_key_exists($key, $cache) ? $cache[$key] : $default; } function set_setting($key, $value) { $pdo = db(); $stmt = $pdo->prepare("INSERT INTO settings (setting_key, setting_value) VALUES (?, ?) ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)"); return $stmt->execute([$key, $value]); } function compact_logo_path() { return 'assets/img/logo-compact.svg'; } function post_image($post) { $img = $post['image'] ?? ''; if (!$img) return 'assets/img/default-news.svg'; if (strpos($img, 'assets/') === 0 || strpos($img, 'uploads/') === 0) return $img; return 'uploads/' . ltrim($img, '/'); } function get_active_posts($limit = 20, $offset = 0, $where = '', $params = []) { $pdo = db(); $sql = "SELECT p.*, c.name AS category_name, c.slug AS category_slug, a.name AS author_name, a.slug AS author_slug FROM posts p LEFT JOIN categories c ON c.id = p.category_id LEFT JOIN users a ON a.id = p.author_id WHERE p.status = 'published' AND (p.published_at IS NULL OR p.published_at <= NOW())"; if ($where) $sql .= " AND " . $where; $sql .= " ORDER BY COALESCE(p.published_at, p.created_at) DESC LIMIT " . (int)$limit . " OFFSET " . (int)$offset; $stmt = $pdo->prepare($sql); $stmt->execute($params); return $stmt->fetchAll(PDO::FETCH_ASSOC); } function get_slider_posts($limit = 5) { $pdo = db(); $stmt = $pdo->prepare("SELECT p.*, c.name AS category_name, c.slug AS category_slug FROM posts p LEFT JOIN categories c ON c.id = p.category_id WHERE p.status='published' AND p.is_slider=1 AND (p.published_at IS NULL OR p.published_at <= NOW()) ORDER BY p.slider_order ASC, COALESCE(p.published_at, p.created_at) DESC LIMIT ?"); $stmt->bindValue(1, (int)$limit, PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } function get_post_tags($post_id) { $pdo = db(); $stmt = $pdo->prepare("SELECT t.* FROM tags t INNER JOIN post_tags pt ON pt.tag_id=t.id WHERE pt.post_id=? ORDER BY t.name ASC"); $stmt->execute([(int)$post_id]); return $stmt->fetchAll(PDO::FETCH_ASSOC); } function sync_post_tags($post_id, $tags_text) { $pdo = db(); $pdo->prepare("DELETE FROM post_tags WHERE post_id=?")->execute([(int)$post_id]); $tags = preg_split('/[,;\n]+/u', (string)$tags_text); foreach ($tags as $tag) { $name = trim($tag); if ($name === '') continue; $slug = slugify($name); $stmt = $pdo->prepare("INSERT IGNORE INTO tags (name, slug) VALUES (?, ?)"); $stmt->execute([$name, $slug]); $stmt = $pdo->prepare("SELECT id FROM tags WHERE slug=? LIMIT 1"); $stmt->execute([$slug]); $tagId = (int)$stmt->fetchColumn(); if ($tagId) { $pdo->prepare("INSERT IGNORE INTO post_tags (post_id, tag_id) VALUES (?, ?)")->execute([(int)$post_id, $tagId]); } } } function get_ad_html($position) { $pdo = db(); $stmt = $pdo->prepare("SELECT * FROM ads WHERE position=? AND is_active=1 AND (start_date IS NULL OR start_date <= NOW()) AND (end_date IS NULL OR end_date >= NOW()) ORDER BY sort_order ASC, id DESC LIMIT 1"); $stmt->execute([$position]); $ad = $stmt->fetch(PDO::FETCH_ASSOC); if (!$ad) return ''; if ($ad['ad_type'] === 'html' && !empty($ad['html_code'])) { return '
' . e($text) . '
' . $link . '