&rand= * * Headless Chrome access (no session, called from headlessChrome_pdf.php): * ?rid=&rand=&ptoken= * The ptoken is a short-lived file written by the generator. This lets Chrome * render the page without a PHP session cookie. */ require_once __DIR__ . '/../../../config/database.php'; require_once __DIR__ . '/../../../lib/auth.php'; require_once __DIR__ . '/../../../lib/print_auth.php'; require_once __DIR__ . '/../../../vendor/autoload.php'; if (session_status() === PHP_SESSION_NONE) { session_start(); } $recordId = (int) ($_GET['rid'] ?? 0); $randId = trim( $_GET['rand'] ?? ''); $clientId = (int) ($_GET['cid'] ?? 0); $printMode = isset($_GET['ptoken']) || isset($_GET['print']); if (!$recordId || $randId === '') { http_response_code(400); die('Invalid request parameters'); } if ($printMode) { authenticatePrintPage($recordId, $randId); } else { requireLogin(); } try { $pdo = getDBConnection(); $userId = $printMode ? null : getCurrentUserId(); $stmt = $pdo->prepare('SELECT * FROM plant_records WHERE id = ? AND rand = ?'); $stmt->execute([$recordId, $randId]); $row = $stmt->fetch(PDO::FETCH_ASSOC); if (!$row) { http_response_code(404); die('Plant record not found'); } // Load spec ranges $specs = []; if (!empty($row['crop_type'])) { $stmtSpec = $pdo->prepare('SELECT * FROM plant_specifications WHERE plant_type = ? LIMIT 1'); $stmtSpec->execute([$row['crop_type']]); $specs = $stmtSpec->fetch(PDO::FETCH_ASSOC) ?: []; } // Load saved report comments $savedComments = [ 'general_details' => '', 'ai_interpretation' => '', 'recommended_details' => '', 'foliar_details' => '', ]; // In print/headless mode there is no session user; use the record owner's id instead. $reportUserId = $userId ?? (int)($row['modx_user_id'] ?? 0); $stmtRpt = $pdo->prepare( 'SELECT comment FROM reports WHERE record_id = ? AND modx_user_id = ? ORDER BY id DESC LIMIT 1' ); $stmtRpt->execute([$recordId, $reportUserId]); $savedRow = $stmtRpt->fetchColumn(); if ($savedRow) { $decoded = json_decode($savedRow, true); if (is_array($decoded)) { $savedComments = array_merge($savedComments, $decoded); } } } catch (PDOException $e) { error_log('DB error in plant-report.php: ' . $e->getMessage()); die('Database error occurred'); } $h = fn($v) => htmlspecialchars((string)($v ?? ''), ENT_QUOTES, 'UTF-8'); $today = date('jS F Y'); $pageTitle = 'Plant Report' . (!empty($row['client_name']) ? ' — ' . $row['client_name'] : ''); $siteName = 'Crop Monitor'; // Parse and render markdown text from AI-generated report sections function formatReportText(string $text): string { if (trim($text) === '') { return '

No content saved.

'; } $parsedown = new Parsedown(); $parsedown->setSafeMode(true); return $parsedown->text($text); } ?> Plant Analysis Report | Crop Monitor
Record not found or access denied.
Crop Monitor
Plant Analysis Report
CLIENT: SAMPLE ID:
ADDRESS: DATE SAMPLED:
LAB NUMBER:
CROP:
PLANT TYPE:

General Comment
AI Plant Interpretation
Foliar Program

Any recommendations provided by Crop Monitor are advice only. We are not paid consultants and accept no responsibility for any of our suggestions. No control can be exercised over storage, handling, mixing, application, or use, or over weather, plant or soil conditions before, during or after application — all of which may affect the performance of our program. No responsibility for, or liability for, any failure in performance, losses, damage or injuries consequential or otherwise arising from such storage, mixing, application or use will be accepted under any circumstances whatsoever. The buyer assumes all responsibility for the use of any of our products.