false, 'message' => 'Method not allowed'], 405); } // ── Page defaults ──────────────────────────────────────────── function getDefaultPages() { return [ [ 'slug' => 'home', 'title' => 'Home Page', 'icon' => 'fa-home', 'url' => '/index.html', 'description' => 'Main landing page with hero, services, and CTA sections', 'status' => 'published', 'meta_title' => 'MSPE | Architects of Digital Resilience', 'meta_description' => 'Next-generation cybersecurity, cloud innovation, and technology consulting.', 'sections' => [ ['key' => 'hero', 'label' => 'Hero', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ['name' => 'subheading', 'type' => 'textarea', 'label' => 'Subheading', 'value' => ''], ['name' => 'cta_text', 'type' => 'text', 'label' => 'CTA Button Text', 'value' => ''], ['name' => 'cta_link', 'type' => 'text', 'label' => 'CTA Button Link', 'value' => ''], ]], ['key' => 'services', 'label' => 'Services', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Section Heading', 'value' => ''], ['name' => 'subheading', 'type' => 'textarea', 'label' => 'Section Subheading', 'value' => ''], ]], ['key' => 'stats', 'label' => 'Stats', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Section Heading', 'value' => ''], ]], ['key' => 'cta', 'label' => 'CTA', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'CTA Heading', 'value' => ''], ['name' => 'text', 'type' => 'textarea', 'label' => 'CTA Text', 'value' => ''], ['name' => 'button_text', 'type' => 'text', 'label' => 'Button Text', 'value' => ''], ['name' => 'button_link', 'type' => 'text', 'label' => 'Button Link', 'value' => ''], ]], ], ], [ 'slug' => 'about', 'title' => 'About Us', 'icon' => 'fa-building', 'url' => '/about.html', 'description' => 'Company story, mission, values, and team information', 'status' => 'published', 'meta_title' => 'About Us - MSPE', 'meta_description' => 'Learn about MSPE — our story, mission, values, and the team behind your digital resilience.', 'sections' => [ ['key' => 'story', 'label' => 'Story', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ['name' => 'content', 'type' => 'textarea', 'label' => 'Content', 'value' => ''], ]], ['key' => 'mission', 'label' => 'Mission', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ['name' => 'content', 'type' => 'textarea', 'label' => 'Content', 'value' => ''], ]], ['key' => 'values', 'label' => 'Values', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ]], ['key' => 'team', 'label' => 'Team', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ['name' => 'subheading', 'type' => 'textarea', 'label' => 'Subheading', 'value' => ''], ]], ], ], [ 'slug' => 'services', 'title' => 'Services', 'icon' => 'fa-concierge-bell', 'url' => '/services.html', 'description' => 'Detailed service offerings and pricing plans', 'status' => 'published', 'meta_title' => 'Services - MSPE', 'meta_description' => 'Explore our cybersecurity, cloud, and IT support services.', 'sections' => [ ['key' => 'it_support', 'label' => 'IT Support', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ['name' => 'content', 'type' => 'textarea', 'label' => 'Content', 'value' => ''], ]], ['key' => 'security', 'label' => 'Security', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ['name' => 'content', 'type' => 'textarea', 'label' => 'Content', 'value' => ''], ]], ['key' => 'cloud', 'label' => 'Cloud', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ['name' => 'content', 'type' => 'textarea', 'label' => 'Content', 'value' => ''], ]], ['key' => 'pricing', 'label' => 'Pricing', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ]], ], ], [ 'slug' => 'portfolio', 'title' => 'Portfolio', 'icon' => 'fa-briefcase', 'url' => '/portfolio.html', 'description' => 'Showcase of completed projects and case studies', 'status' => 'published', 'meta_title' => 'Portfolio - MSPE', 'meta_description' => 'See our completed projects, case studies, and client success stories.', 'sections' => [ ['key' => 'projects', 'label' => 'Projects', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ['name' => 'subheading', 'type' => 'textarea', 'label' => 'Subheading', 'value' => ''], ]], ['key' => 'case_studies', 'label' => 'Case Studies', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ]], ['key' => 'clients', 'label' => 'Clients', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ]], ], ], [ 'slug' => 'news', 'title' => 'News & Events', 'icon' => 'fa-newspaper', 'url' => '/news.html', 'description' => 'Company news, blog posts, and upcoming events', 'status' => 'published', 'meta_title' => 'News & Events - MSPE', 'meta_description' => 'Stay updated with the latest MSPE news, tech insights, and events.', 'sections' => [ ['key' => 'news_list', 'label' => 'News List', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ]], ['key' => 'newsletter', 'label' => 'Newsletter', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ['name' => 'subheading', 'type' => 'textarea', 'label' => 'Subheading', 'value' => ''], ]], ], ], [ 'slug' => 'contact', 'title' => 'Contact', 'icon' => 'fa-envelope', 'url' => '/contact.html', 'description' => 'Contact form, location, and FAQ section', 'status' => 'published', 'meta_title' => 'Contact Us - MSPE', 'meta_description' => 'Get in touch with MSPE for cybersecurity, cloud, and IT services.', 'sections' => [ ['key' => 'form', 'label' => 'Form', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ['name' => 'subheading', 'type' => 'textarea', 'label' => 'Subheading', 'value' => ''], ]], ['key' => 'info_cards', 'label' => 'Info Cards', 'fields' => [ ['name' => 'address', 'type' => 'textarea', 'label' => 'Address', 'value' => ''], ['name' => 'phone', 'type' => 'text', 'label' => 'Phone', 'value' => ''], ['name' => 'email', 'type' => 'text', 'label' => 'Email', 'value' => ''], ['name' => 'hours', 'type' => 'text', 'label' => 'Business Hours', 'value' => ''], ]], ['key' => 'faq', 'label' => 'FAQ', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ]], ], ], ]; } function getDefaultGlobalSections() { return [ [ 'slug' => 'header', 'label' => 'Header / Navigation', 'icon' => 'fa-bars', 'description' => 'Logo, menu items, CTA button', 'fields' => [ ['name' => 'cta_text', 'type' => 'text', 'label' => 'CTA Button Text', 'value' => ''], ['name' => 'cta_link', 'type' => 'text', 'label' => 'CTA Button Link', 'value' => ''], ], ], [ 'slug' => 'footer', 'label' => 'Footer', 'icon' => 'fa-shoe-prints', 'description' => 'Links, contact info, social media', 'fields' => [ ['name' => 'tagline', 'type' => 'textarea', 'label' => 'Footer Tagline', 'value' => ''], ['name' => 'copyright', 'type' => 'text', 'label' => 'Copyright Text', 'value' => ''], ], ], [ 'slug' => 'cta', 'label' => 'CTA Section', 'icon' => 'fa-bullhorn', 'description' => 'Call-to-action banner', 'fields' => [ ['name' => 'heading', 'type' => 'text', 'label' => 'Heading', 'value' => ''], ['name' => 'text', 'type' => 'textarea', 'label' => 'Text', 'value' => ''], ['name' => 'button_text', 'type' => 'text', 'label' => 'Button Text', 'value' => ''], ['name' => 'button_link', 'type' => 'text', 'label' => 'Button Link', 'value' => ''], ], ], [ 'slug' => 'cookie', 'label' => 'Cookie Banner', 'icon' => 'fa-cookie', 'description' => 'GDPR compliance notice', 'fields' => [ ['name' => 'message', 'type' => 'textarea', 'label' => 'Banner Message', 'value' => ''], ['name' => 'button_text', 'type' => 'text', 'label' => 'Accept Button Text', 'value' => ''], ['name' => 'link_text', 'type' => 'text', 'label' => 'Policy Link Text', 'value' => ''], ['name' => 'link_url', 'type' => 'text', 'label' => 'Policy URL', 'value' => ''], ], ], ]; } // ── Handlers ───────────────────────────────────────────────── function getPages() { global $db; $storedPages = $db->getAll('pages'); $storedMap = []; foreach ($storedPages as $p) { $slug = $p['slug'] ?? ''; if ($slug) $storedMap[$slug] = $p; } $pages = getDefaultPages(); foreach ($pages as &$page) { if (isset($storedMap[$page['slug']])) { $stored = $storedMap[$page['slug']]; // Merge saved values into section fields if (!empty($stored['meta_title'])) $page['meta_title'] = $stored['meta_title']; if (!empty($stored['meta_description'])) $page['meta_description'] = $stored['meta_description']; if (isset($stored['status'])) $page['status'] = $stored['status']; if (!empty($stored['sections_data'])) { $savedData = $stored['sections_data']; // key => { fieldName => value } foreach ($page['sections'] as &$section) { if (isset($savedData[$section['key']])) { foreach ($section['fields'] as &$field) { if (isset($savedData[$section['key']][$field['name']])) { $field['value'] = $savedData[$section['key']][$field['name']]; } } } } } if (isset($stored['updated_at'])) $page['updated_at'] = $stored['updated_at']; } } jsonResponse(['success' => true, 'data' => $pages]); } function getPage($id) { global $db; $pages = getDefaultPages(); $default = null; foreach ($pages as $p) { if ($p['slug'] === $id) { $default = $p; break; } } if (!$default) { jsonResponse(['success' => false, 'message' => 'Page not found'], 404); } $stored = $db->query('pages', ['slug' => $id]); if (!empty($stored)) { $stored = array_values($stored)[0]; if (!empty($stored['meta_title'])) $default['meta_title'] = $stored['meta_title']; if (!empty($stored['meta_description'])) $default['meta_description'] = $stored['meta_description']; if (isset($stored['status'])) $default['status'] = $stored['status']; if (!empty($stored['sections_data'])) { $savedData = $stored['sections_data']; foreach ($default['sections'] as &$section) { if (isset($savedData[$section['key']])) { foreach ($section['fields'] as &$field) { if (isset($savedData[$section['key']][$field['name']])) { $field['value'] = $savedData[$section['key']][$field['name']]; } } } } } if (isset($stored['updated_at'])) $default['updated_at'] = $stored['updated_at']; } jsonResponse(['success' => true, 'data' => $default]); } function savePage() { global $db; $data = getRequestBody(); if (empty($data['slug'])) { jsonResponse(['success' => false, 'message' => 'Page slug required'], 400); } $slug = sanitize($data['slug']); $record = [ 'slug' => $slug, 'meta_title' => sanitize($data['meta_title'] ?? ''), 'meta_description' => sanitize($data['meta_description'] ?? ''), 'status' => in_array($data['status'] ?? '', ['published', 'draft']) ? $data['status'] : 'published', 'sections_data' => $data['sections_data'] ?? [], 'updated_at' => date('Y-m-d H:i:s'), ]; $existing = $db->query('pages', ['slug' => $slug]); if (!empty($existing)) { $id = array_values($existing)[0]['id']; $db->update('pages', $id, $record); } else { $db->insert('pages', $record); } jsonResponse(['success' => true, 'message' => 'Page saved successfully']); } // ── Global sections ────────────────────────────────────────── function getGlobalSections() { global $db; $stored = $db->query('pages', ['slug' => '__global__']); $savedData = []; if (!empty($stored)) { $savedData = array_values($stored)[0]['sections_data'] ?? []; } $globals = getDefaultGlobalSections(); foreach ($globals as &$section) { if (isset($savedData[$section['slug']])) { foreach ($section['fields'] as &$field) { if (isset($savedData[$section['slug']][$field['name']])) { $field['value'] = $savedData[$section['slug']][$field['name']]; } } } } jsonResponse(['success' => true, 'data' => $globals]); } function saveGlobalSection() { global $db; $data = getRequestBody(); if (empty($data['section_slug'])) { jsonResponse(['success' => false, 'message' => 'Section slug required'], 400); } $sectionSlug = sanitize($data['section_slug']); $fieldValues = $data['fields'] ?? []; // Load existing global record $existing = $db->query('pages', ['slug' => '__global__']); $record = []; if (!empty($existing)) { $record = array_values($existing)[0]; } $sectionsData = $record['sections_data'] ?? []; $sectionsData[$sectionSlug] = $fieldValues; $saveData = [ 'slug' => '__global__', 'sections_data' => $sectionsData, 'updated_at' => date('Y-m-d H:i:s'), ]; if (!empty($existing)) { $id = array_values($existing)[0]['id']; $db->update('pages', $id, $saveData); } else { $db->insert('pages', $saveData); } jsonResponse(['success' => true, 'message' => 'Global section saved']); }