PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4", ] ); // --- Fetch newest completed CA entry --- // Assumes h305_ca77_entries is either a view or table already filtered to "completed" rows $sql = " SELECT model_year, model, ADM_StateOrProvince, ADM_Country, condition_value, opinion_value_today FROM h305_ca77_entries ORDER BY submitdate DESC, id DESC LIMIT 1 "; $row = $pdo->query($sql)->fetch(PDO::FETCH_ASSOC); // --- Helpers for casing normalization (same pattern as CB / CL) --- $keepCaps = static function (string $w): bool { // Keep original word case if it's already an acronym (2+ caps) or has a digit return (bool)preg_match('/[A-Z]{2,}/', $w) || (bool)preg_match('/\d/', $w); }; $word = static function (?string $w) use ($keepCaps): string { if ($w === null || $w === '') { return ''; } // Respect hyphenated parts independently if (strpos($w, '-') !== false) { $parts = explode('-', $w); foreach ($parts as &$x) { $x = $keepCaps($x) ? $x : ucfirst(strtolower($x)); } return implode('-', $parts); } // Already looks like an acronym or has digits -> leave alone if ($keepCaps($w)) { return $w; } $dot = substr($w, -1) === '.'; $base = $dot ? substr($w, 0, -1) : $w; $done = ucfirst(strtolower($base)); return $dot ? ($done . '.') : $done; }; $titleCase = static function (?string $s) use ($word): string { if ($s === null) { return ''; } $s = trim($s); if ($s === '') { return ''; } $t = preg_split('/\s+/', $s) ?: []; foreach ($t as &$x) { $x = $word($x); } return trim(implode(' ', $t), ", "); }; // --- Build display line --- if (!$row) { $line = 'Latest Registry Entry: No completed entries found.'; } else { // Location: "WA, Australia" (skip empties, title-case each part) $region = $titleCase($row['ADM_StateOrProvince'] ?? ''); $country = $titleCase($row['ADM_Country'] ?? ''); $loc = trim( implode(', ', array_filter([$region, $country], static fn($v) => $v !== '')), ', ' ); // Normalize opinion_value_today using CL rules: // >=1000 => use as-is ($12500 => $12,500) // 100..999 => treat as dollars ($750 => $750) // 1..99 => treat as thousands (6 => $6,000) // otherwise => "Not Entered" $valFinal = 'Not Entered'; if (isset($row['opinion_value_today']) && $row['opinion_value_today'] !== '') { $n = (float)$row['opinion_value_today']; if ($n >= 1000) { $valFinal = '$' . number_format($n, 0); } elseif ($n >= 100) { $valFinal = '$' . number_format($n, 0); } elseif ($n > 0) { $valFinal = '$' . number_format($n * 1000, 0); } } // Condition decoding (same mapping you provided, with fallback) $condRaw = $row['condition_value'] ?? ''; $condMap = [ 'E' => 'Excellent', 'Exc' => 'Excellent', 'G' => 'Good', 'Goo' => 'Good', 'F' => 'Fair', 'P' => 'Poor', 'Par' => 'Parts Bike', 'R' => 'Restored', 'Res' => 'Restored', 'Rat' => 'Rat', ]; $condNice = $condMap[$condRaw] ?? ($condRaw !== '' ? $condRaw : 'Not Entered'); // Gracefully handle blanks so we don't get double-spaces like " Honda " $yr = isset($row['model_year']) ? trim((string)$row['model_year']) : ''; $model = isset($row['model']) ? trim((string)$row['model']) : ''; $bikePart = trim($yr . ' Honda ' . $model); $locPart = $loc !== '' ? (' — ' . $loc) : ''; $line = 'Latest Registry Entry: ' . $bikePart . $locPart . ' — Condition: ' . $condNice . ' — Value: ' . $valFinal; } // --- Build final HTML snippet (static, safe to INCLUDEPHP in phpBB) --- $builtTs = (new DateTime('now'))->format('Y-m-d H:i:s T'); // These first two lines are harmless in phpBB output: and $charset = ''; $stamp = ''; $htmlOut = $charset . "\n" . $stamp . "\n" . $line . "\n"; // --- Write atomically to shared include dir --- $jobDir = __DIR__; // wherever this script lives $includeDir = '/home/mstoic3/public_html/shared/include'; $includeTmp = $includeDir . '/latest_ca77.tmp'; $includeDst = $includeDir . '/latest_ca77.html'; $jsonPath = $jobDir . '/latest_ca77.json'; $logPath = $jobDir . '/logs/latest_ca77.log'; // reserved for future logging if (!is_dir($includeDir)) { if (!mkdir($includeDir, 0755, true) && !is_dir($includeDir)) { throw new RuntimeException("Failed to create include dir: $includeDir"); } } if (file_put_contents($includeTmp, $htmlOut, LOCK_EX) === false) { throw new RuntimeException('Failed to write temp include file'); } if (!rename($includeTmp, $includeDst)) { @unlink($includeTmp); throw new RuntimeException('Failed to move include into place'); } // --- Optional JSON breadcrumb for debugging / external consumption --- @file_put_contents( $jsonPath, json_encode( [ 'line' => $line, 'stamp' => $builtTs, 'ts' => date('c'), ], JSON_UNESCAPED_UNICODE ) ); // --- Done --- echo "OK\n"; exit(0); } catch (Throwable $e) { // Minimal error surface; log server-side, generic public output error_log("[generate_latest_ca77.php] " . $e->getMessage()); if (function_exists('http_response_code')) { @http_response_code(500); } echo "ERROR\n"; exit(1); }