[ 'header' => "User-Agent: Mozilla/5.0\r\n", 'timeout' => 10, ]]); $raw = @file_get_contents($url, false, $ctx); $data = $raw ? json_decode($raw, true) : null; return $data['chart']['result'][0]['meta'] ?? null; } // ── AJAX ───────────────────────────────────────────────────────────────────── if ($_SERVER['REQUEST_METHOD'] === 'POST') { header('Content-Type: application/json'); $action = $_POST['action'] ?? ''; // Fetch one price, auto-convert to USD if needed if ($action === 'fetch') { $symbol = $_POST['symbol']; $meta = yahooFetch($symbol); if (!$meta || !isset($meta['regularMarketPrice'])) { echo json_encode(['price' => null, 'error' => 'no data']); exit; } $price = (float)$meta['regularMarketPrice']; $currency = strtoupper($meta['currency'] ?? 'USD'); $usdPrice = $price; $fxRate = 1.0; if ($currency !== 'USD') { $fxMeta = yahooFetch($currency . 'USD=X'); if ($fxMeta && isset($fxMeta['regularMarketPrice'])) { $fxRate = (float)$fxMeta['regularMarketPrice']; $usdPrice = round($price * $fxRate, 4); } else { // Can't convert — return null so UI marks it failed echo json_encode(['price' => null, 'error' => 'fx_failed', 'currency' => $currency]); exit; } } echo json_encode([ 'price' => $usdPrice, 'raw_price' => $price, 'currency' => $currency, 'fx_rate' => $fxRate, ]); exit; } // Save confirmed prices (only price field, nothing else) if ($action === 'save') { $updates = json_decode($_POST['updates'], true); foreach ($updates as $u) { $i = (int)$u['index']; if (isset($stocks[$i])) { $stocks[$i]['price'] = (float)$u['price']; } } file_put_contents($jsonFile, json_encode($stocks, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); // Verify $check = json_decode(file_get_contents($jsonFile), true); $ok = true; foreach ($updates as $u) { if ((float)$check[(int)$u['index']]['price'] !== (float)$u['price']) { $ok = false; break; } } echo json_encode(['ok' => $ok]); exit; } // Delete a stock if ($action === 'delete') { $i = (int)$_POST['index']; $symbol = $_POST['symbol']; array_splice($stocks, $i, 1); file_put_contents($jsonFile, json_encode($stocks, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); $check = json_decode(file_get_contents($jsonFile), true); $gone = !array_filter($check, fn($s) => $s['stock'] === $symbol); echo json_encode(['ok' => (bool)$gone]); exit; } } ?>
| # | Symbol | Exchange | Saved Price | New Price (USD) | Change | Status |
|---|