prepare(" SELECT project_id FROM projects WHERE project_id = ? AND client_id = ? "); $stmt->execute([$project_id, $client_id]); if (!$stmt->fetch()) { $_SESSION['error'] = "Project not found or access denied"; header('Location: projects-list.php'); exit; } // Get next batch number $stmt = $shopPdo->prepare(" SELECT COALESCE(MAX(batch_number), 0) + 1 AS next_batch FROM survey_url_batches WHERE project_id = ? "); $stmt->execute([$project_id]); $batch_number = $stmt->fetchColumn(); $urls_to_insert = []; if ($upload_type === 'single') { // Process single URL template $template_url = $_POST['template_url'] ?? ''; $id_pattern = $_POST['id_pattern'] ?? 'numeric'; $url_count = (int)($_POST['url_count'] ?? 0); $custom_prefix = $_POST['custom_prefix'] ?? ''; if (empty($template_url) || $url_count < 1 || $url_count > 5000) { $_SESSION['error'] = "Invalid template URL or count"; header('Location: manage-survey-urls.php?project_id=' . urlencode($project_id)); exit; } // Check if template has {ID} placeholder if (strpos($template_url, '{ID}') === false) { $_SESSION['error'] = "Template URL must contain {ID} placeholder"; header('Location: manage-survey-urls.php?project_id=' . urlencode($project_id)); exit; } // Generate URLs for ($i = 1; $i <= $url_count; $i++) { $unique_id = generateUniqueId($i, $id_pattern, $custom_prefix); $client_url = str_replace('{ID}', $unique_id, $template_url); $rr_proxy_url = generateProxyUrl($project_id, $unique_id); $urls_to_insert[] = [ 'client_url' => $client_url, 'rr_proxy_url' => $rr_proxy_url, 'unique_identifier' => $unique_id ]; } } else if ($upload_type === 'multiple') { // Process multiple URLs $bulk_urls = $_POST['bulk_urls'] ?? ''; $lines = array_filter(array_map('trim', explode("\n", $bulk_urls))); if (empty($lines)) { $_SESSION['error'] = "No URLs provided"; header('Location: manage-survey-urls.php?project_id=' . urlencode($project_id)); exit; } if (count($lines) > 5000) { $_SESSION['error'] = "Maximum 5,000 URLs allowed per batch. You provided " . count($lines) . " URLs."; header('Location: manage-survey-urls.php?project_id=' . urlencode($project_id)); exit; } $unique_ids_used = []; foreach ($lines as $index => $url) { // Validate URL if (!filter_var($url, FILTER_VALIDATE_URL)) { $_SESSION['error'] = "Invalid URL at line " . ($index + 1) . ": " . htmlspecialchars($url); header('Location: manage-survey-urls.php?project_id=' . urlencode($project_id)); exit; } // Extract or generate unique identifier $unique_id = extractUniqueIdFromUrl($url); // Ensure unique ID is unique within this batch $counter = 1; $original_id = $unique_id; while (in_array($unique_id, $unique_ids_used)) { $unique_id = $original_id . '_' . $counter; $counter++; } $unique_ids_used[] = $unique_id; $rr_proxy_url = generateProxyUrl($project_id, $unique_id); $urls_to_insert[] = [ 'client_url' => $url, 'rr_proxy_url' => $rr_proxy_url, 'unique_identifier' => $unique_id ]; } } // Begin transaction $shopPdo->beginTransaction(); try { // Insert batch record $stmt = $shopPdo->prepare(" INSERT INTO survey_url_batches (project_id, batch_number, total_urls, upload_type, created_by) VALUES (?, ?, ?, ?, ?) "); $stmt->execute([ $project_id, $batch_number, count($urls_to_insert), $upload_type, $client_id ]); // Insert URLs $stmt = $shopPdo->prepare(" INSERT INTO survey_urls (project_id, batch_number, client_url, rr_proxy_url, unique_identifier, created_by) VALUES (?, ?, ?, ?, ?, ?) "); foreach ($urls_to_insert as $url_data) { $stmt->execute([ $project_id, $batch_number, $url_data['client_url'], $url_data['rr_proxy_url'], $url_data['unique_identifier'], $client_id ]); } $shopPdo->commit(); $_SESSION['success'] = "Successfully generated " . count($urls_to_insert) . " survey URLs in Batch #" . $batch_number; header('Location: view-batch-urls.php?project_id=' . urlencode($project_id) . '&batch=' . $batch_number); exit; } catch (Exception $e) { $shopPdo->rollBack(); throw $e; } } catch (Exception $e) { $_SESSION['error'] = "Error processing URLs: " . $e->getMessage(); header('Location: manage-survey-urls.php?project_id=' . urlencode($project_id)); exit; } /** * Generate unique identifier based on pattern */ function generateUniqueId($index, $pattern, $prefix = '') { switch ($pattern) { case 'numeric': return (string)$index; case 'alphanumeric': return 'A' . str_pad($index, 4, '0', STR_PAD_LEFT); case 'custom': $cleanPrefix = preg_replace('/[^a-zA-Z0-9]/', '', $prefix); return strtoupper($cleanPrefix) . str_pad($index, 5, '0', STR_PAD_LEFT); default: return (string)$index; } } /** * Generate RR proxy URL * Format: https://relevantreflex.com/s/{encoded_string} */ function generateProxyUrl($project_id, $unique_id) { // Create a short encoded string that maps to project_id + unique_id $data = $project_id . '|' . $unique_id; $encoded = base64_encode($data); // Make it URL-safe $encoded = strtr($encoded, '+/', '-_'); $encoded = rtrim($encoded, '='); return 'https://relevantreflex.com/s/' . $encoded; } /** * Extract unique identifier from URL * Looks for common patterns like uid=, id=, user=, etc. */ function extractUniqueIdFromUrl($url) { // Parse URL $parsed = parse_url($url); // Check query string if (isset($parsed['query'])) { parse_str($parsed['query'], $params); // Look for common parameter names $common_params = ['uid', 'id', 'user', 'userid', 'user_id', 'respondent', 'resp_id']; foreach ($common_params as $param) { if (isset($params[$param]) && !empty($params[$param])) { return $params[$param]; } } // If no common param found, use first parameter value if (!empty($params)) { return reset($params); } } // Fallback: generate from URL hash return substr(md5($url), 0, 10); }