orders, clear cart on success, creative multi-project picker session_start(); if (empty($_SESSION['user'])) { header('Location: signup.php'); exit; } require_once 'db.php'; require_once 'functions.php'; // optional (csrf helpers) $conn = db(); // ---------- Helpers ---------- function esc($x){ return htmlspecialchars((string)$x, ENT_QUOTES, 'UTF-8'); } function get_csrf_token() { return function_exists('csrf_token') ? csrf_token() : ($_SESSION['__csrf'] ??= bin2hex(random_bytes(16))); } // ✅ renamed to avoid recursion function verify_csrf_token($t) { if (function_exists('verify_csrf')) { // call the global one from functions.php if present return \verify_csrf($t); } return isset($_SESSION['__csrf']) && hash_equals($_SESSION['__csrf'], (string)$t); } function resolve_vendor_from_vendors(mysqli $conn, array $pub): array { $email = trim((string)($pub['vendor_email'] ?? '')); $vid = (int)($pub['vendor_id'] ?? 0); // 1️⃣ Prefer vendor_email if ($email !== '') { try { $stmt = $conn->prepare(" SELECT vendor_name, vendor_email FROM vendors WHERE TRIM(COALESCE(vendor_email,'')) = TRIM(?) LIMIT 1 "); $stmt->bind_param('s', $email); $stmt->execute(); $res = $stmt->get_result(); if ($v = $res->fetch_assoc()) { $stmt->close(); return [ 'vendor_name' => (string)$v['vendor_name'], 'vendor_email' => (string)$v['vendor_email'] ]; } $stmt->close(); } catch (Throwable $e) {} } // 2️⃣ Fallback: vendor_id if ($vid > 0) { try { $stmt = $conn->prepare(" SELECT vendor_name, vendor_email FROM vendors WHERE id = ? LIMIT 1 "); $stmt->bind_param('i', $vid); $stmt->execute(); $res = $stmt->get_result(); if ($v = $res->fetch_assoc()) { $stmt->close(); return [ 'vendor_name' => (string)$v['vendor_name'], 'vendor_email' => (string)$v['vendor_email'] ]; } $stmt->close(); } catch (Throwable $e) {} } // 3️⃣ Final fallback: publisher snapshot return [ 'vendor_name' => (string)($pub['vendor_name'] ?? ''), 'vendor_email' => (string)($pub['vendor_email'] ?? '') ]; } function favicon_from_link($link) { $host = parse_url($link, PHP_URL_HOST); if (!$host && $link) $host = $link; return 'https://www.google.com/s2/favicons?sz=32&domain=' . urlencode((string)$host); } /** Month list: current + next 12 */ function month_options(): array { $out = []; $start = new DateTime('first day of this month 00:00:00'); for ($i=0; $i<=12; $i++) { $d = (clone $start)->modify("+$i month"); $out[] = ['val'=>$d->format('Y-m'), 'label'=>$d->format('M Y')]; } return $out; } /* ---------- Placement normalizer (from publishers.type_of_content) ---------- */ /* Storage rules: * - GP or Guest Post -> "Guest Post" * - PR or press release -> "PR" * - news/article -> "News Article" * - affiliate -> "Affiliate" * (Other known values pass through) */ function normalize_placement_from_type(?string $t): ?string { $t = trim((string)$t); if ($t === '') return null; $l = mb_strtolower($t); if ($l === 'news article' || $l === 'article') return 'News Article'; if ($l === 'pr' || $l === 'press release') return 'PR'; if ($l === 'guest post' || $l === 'gp') return 'Guest Post'; if ($l === 'affiliate') return 'Affiliate'; return $t; } // ---------- POST handling ---------- $errors = []; $okMsg = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!verify_csrf_token($_POST['token'] ?? '')) { // ✅ use the renamed helper $errors[] = 'Invalid request. Please refresh and try again.'; } else { // Remove single row from cart if (isset($_POST['remove_id'])) { $rid = (int)$_POST['remove_id']; if (!empty($_SESSION['cart']) && is_array($_SESSION['cart'])) { $_SESSION['cart'] = array_values(array_filter( $_SESSION['cart'], fn($v) => (int)$v !== $rid )); } $okMsg = 'Item removed from cart.'; } // Checkout: validate & insert orders elseif (isset($_POST['action']) && $_POST['action'] === 'checkout') { $months = $_POST['month'] ?? []; // month[VID] => 'YYYY-MM' $projMap = $_POST['project_ids'] ?? []; // project_ids[VID][] => [pid,...] // Collect cart IDs $cartIds = []; if (!empty($_SESSION['cart']) && is_array($_SESSION['cart'])) { $cartIds = array_values(array_unique(array_map('intval', $_SESSION['cart']))); $cartIds = array_filter($cartIds, fn($v)=> $v>0); } if (!$cartIds) { $errors[] = 'Your cart is empty.'; } // Server-side validation: each row must have month + ≥1 project $rowErrors = []; if ($cartIds) { foreach ($cartIds as $vid) { $vidKey = (int)$vid; $hasMonth = isset($months[$vidKey]) && preg_match('/^\d{4}-\d{2}$/', (string)$months[$vidKey]); $picks = isset($projMap[$vidKey]) && is_array($projMap[$vidKey]) ? array_filter(array_map('intval', $projMap[$vidKey])) : []; if (!$hasMonth || empty($picks)) { $rowErrors[$vidKey] = (!$hasMonth ? 'Select a month' : '') . (empty($picks) ? ( !$hasMonth ? ' and ' : '' ) . 'choose at least one project' : ''); } } } if ($rowErrors) { $errors[] = 'Please complete the Month and select at least one Project for each publication.'; } // If valid, insert orders if (!$errors && $cartIds) { // Pull publisher snapshots once (include vendor_name AND type_of_content for placement) $in = implode(',', array_map('intval', $cartIds)); $vendors = []; if ($vres = $conn->query("SELECT id, agency_name, vendor_name, vendor_email, vendor_id, type_of_content FROM publishers WHERE id IN ($in) ")) { while ($r = $vres->fetch_assoc()) $vendors[(int)$r['id']] = $r; } // ✅ INSERT uses new schema: item_number, invoice, paid_screenshot (left NULL here) $insertSql = " INSERT INTO orders ( date, project_id, publisher_id, agency_name, vendor_name, vendor_email, item_number, placement, topic_copy, live_link, seo_status, vendor_status, cost_usd, cost_inr, invoice, payment_status, paid_screenshot, remarks, created_at ) VALUES ( ?, ?, ?, ?, ?, ?, NULL, ?, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NOW() ) "; $stmt = $conn->prepare($insertSql); if (!$stmt) { $errors[] = 'Could not prepare order insertion. ' . $conn->error; } else { $created = 0; foreach ($cartIds as $vid) { $vid = (int)$vid; // Month -> YYYY-MM-01 $ym = (isset($months[$vid]) && preg_match('/^\d{4}-\d{2}$/', (string)$months[$vid])) ? (string)$months[$vid] : date('Y-m'); $orderDate = $ym . '-01'; // Publisher snapshot $vrow = $vendors[$vid] ?? null; if (!$vrow) { $rowErrors[$vid] = 'Publisher not found.'; continue; } $agency = (string)($vrow['agency_name'] ?? ''); $vendorData = resolve_vendor_from_vendors($conn, $vrow); $vendor = $vendorData['vendor_name']; $vendorEmail= $vendorData['vendor_email']; $placementV = normalize_placement_from_type($vrow['type_of_content'] ?? ''); // Selected projects for this publisher $projIds = isset($projMap[$vid]) && is_array($projMap[$vid]) ? array_filter(array_map('intval', $projMap[$vid])) : []; foreach ($projIds as $pid) { if ($pid <= 0) continue; // ✅ Bind: date (s), project_id (i), publisher_id (i), agency_name (s), vendor_name (s), placement (s) $stmt->bind_param( 'siissss', $orderDate, // s $pid, // i $vid, // i (publisher_id) $agency, // s $vendor, // s (from vendors table if possible) $vendorEmail, // s (from vendors table if possible) $placementV // s ); if ($stmt->execute()) { $created++; } else { $errors[] = "Insert failed: " . $stmt->error; } } } $stmt->close(); if (!empty($rowErrors)) $errors[] = 'Some rows had issues and were skipped.'; if (empty($errors)) { if (!empty($created)) { $_SESSION['cart'] = []; // clear cart ✅ $okMsg = "Created {$created} order(s) and cleared the cart."; } else { $errors[] = 'No orders were created.'; } } } } } } } // ---------- Load cart + form data ---------- $ids = []; if (!empty($_SESSION['cart']) && is_array($_SESSION['cart'])) { $ids = array_values(array_unique(array_map(fn($v)=> (int)$v, $_SESSION['cart']))); $ids = array_filter($ids, fn($v)=> $v > 0); } $items = []; if ($ids) { // Reverse order so newest added (last in array) comes first $ids = array_reverse($ids); $in = implode(',', array_map('intval', $ids)); $order = implode(',', array_map('intval', $ids)); $sql = " SELECT p.id, p.agency_name, COALESCE(v.vendor_name, p.vendor_name) AS vendor_name, p.publication_name, p.website_link FROM publishers p LEFT JOIN vendors v ON ( (v.vendor_email IS NOT NULL AND v.vendor_email <> '' AND v.vendor_email = p.vendor_email) OR (p.vendor_id IS NOT NULL AND p.vendor_id > 0 AND v.id = p.vendor_id) ) WHERE p.id IN ($in) ORDER BY FIELD(p.id, $order) "; if ($res = $conn->query($sql)) { while ($row = $res->fetch_assoc()) { $items[] = $row; } } } // ---------- Group items by Vendor + Agency ---------- $groupedItems = []; foreach ($items as $row) { $vendor = trim((string)($row['vendor_name'] ?? '')); $agency = trim((string)($row['agency_name'] ?? '')); $key = strtolower($vendor . '||' . $agency); if (!isset($groupedItems[$key])) { $groupedItems[$key] = [ 'vendor_name' => $vendor, 'agency_name' => $agency, 'items' => [] ]; } $groupedItems[$key]['items'][] = $row; } // All projects for dropdown $projects = []; if ($pres = $conn->query("SELECT id, name FROM projects ORDER BY name ASC")) { while ($r = $pres->fetch_assoc()) $projects[] = $r; } $token = get_csrf_token(); $monthOpts = month_options(); // Now render page with shared header/footer include 'includes/header.php'; ?>
Your cart is empty.