| @@ -63,8 +63,11 @@ | ||
| 63 | 63 | 'currentUserAvatar' => get_avatar($current_user->ID, 96), |
| 64 | 64 | 'siteUrl' => home_url(), |
| 65 | 65 | 'adminUrl' => admin_url('admin.php'), |
| 66 | 66 | 'pluginUrl' => YATRA_PLUGIN_URL, |
| 67 | + // Public URL of the Yatra sitemap (handles plain vs pretty | |
| 68 | + // permalinks), shown in the SEO settings tab. | |
| 69 | + 'sitemapUrl' => \Yatra\Sitemap\SitemapRouter::sitemapUrl(), | |
| 67 | 70 | // Brand-name and brand-logo helpers are filter-backed (defaults |
| 68 | 71 | // wired in includes/helpers.php). Pro's WhiteLabel module |
| 69 | 72 | // overrides the filters when Agency white-label is active. |
| 70 | 73 | 'brandLogoUrl' => function_exists('yatra_get_brand_icon_url') ? yatra_get_brand_icon_url() : '', |
| @@ -153,9 +156,9 @@ | ||
| 153 | 156 | 'locale' => get_locale(), |
| 154 | 157 | 'currency' => \Yatra\Services\SettingsService::getCurrency(), |
| 155 | 158 | 'currencyPosition' => \Yatra\Services\SettingsService::getString('currency_position', 'left'), |
| 156 | 159 | 'currency_position' => \Yatra\Services\SettingsService::getString('currency_position', 'left'), |
| 157 | - 'decimalPlaces' => (int) \Yatra\Services\SettingsService::getString('currency_decimals', '2'), | |
| 160 | + 'decimalPlaces' => \Yatra\Services\SettingsService::getPriceDecimals(), | |
| 158 | 161 | 'thousandSeparator' => \Yatra\Services\SettingsService::getString('thousand_separator', ','), |
| 159 | 162 | 'decimalSeparator' => \Yatra\Services\SettingsService::getString('decimal_separator', '.'), |
| 160 | 163 | 'date_format' => \Yatra\Services\SettingsService::get('date_format', 'Y-m-d'), |
| 161 | 164 | 'time_format' => \Yatra\Services\SettingsService::get('time_format', 'H:i'), |
| @@ -405,9 +408,17 @@ | ||
| 405 | 408 | // Use built assets in production |
| 406 | 409 | $appJs = YATRA_PLUGIN_PATH . 'assets/admin/dist/js/app.js'; |
| 407 | 410 | |
| 408 | 411 | if (file_exists($appJs)) { |
| 409 | - $jsVersion = YATRA_VERSION . '.' . filemtime($appJs) . '.view-icon-fix.' . time() . '.' . microtime(true); | |
| 412 | + // Version on the plugin version + the bundle's own mtime. That | |
| 413 | + // already changes on every update or rebuild, which is exactly | |
| 414 | + // when the cache must be busted. | |
| 415 | + // | |
| 416 | + // This previously appended time() . microtime(true), making the | |
| 417 | + // URL unique on every single request — so the ~3 MB admin bundle | |
| 418 | + // was re-downloaded on every admin page view and could never be | |
| 419 | + // cached by the browser. | |
| 420 | + $jsVersion = YATRA_VERSION . '.' . filemtime($appJs); | |
| 410 | 421 | |
| 411 | 422 | $localized_data = $this->buildAdminLocalizedData(); |
| 412 | 423 | |
| 413 | 424 | // Enqueue our script with media library as dependency |
| @@ -428,11 +439,31 @@ | ||
| 428 | 439 | $jsVersion, |
| 429 | 440 | true |
| 430 | 441 | ); |
| 431 | 442 | |
| 443 | + // The bundle calls the global wp.i18n.__() (it never ships its | |
| 444 | + // own copy), and scripts/extract-js-pot.mjs writes every admin | |
| 445 | + // string's `#:` reference as this bundle's path precisely so | |
| 446 | + // WordPress's md5(handle src) JSON lookup matches. This call is | |
| 447 | + // the missing last link: it tells WordPress to load | |
| 448 | + // i18n/languages/yatra-{locale}-{md5}.json (or the copy under | |
| 449 | + // WP_LANG_DIR/plugins) for the admin UI. Without it, translated | |
| 450 | + // admin strings never reach the SPA. Mirrors FrontendAssetsProvider. | |
| 451 | + if (function_exists('wp_set_script_translations')) { | |
| 452 | + wp_set_script_translations('yatra-admin', 'yatra', YATRA_PLUGIN_PATH . 'i18n/languages'); | |
| 453 | + } | |
| 454 | + | |
| 432 | 455 | // Localize script data |
| 433 | 456 | wp_localize_script('yatra-admin', 'yatraAdmin', $localized_data); |
| 434 | 457 | |
| 458 | + // Phone dataset for admin displays (flag + dial-code detection of | |
| 459 | + // stored "+<code><number>" values in booking details). | |
| 460 | + wp_localize_script('yatra-admin', 'yatraPhoneData', [ | |
| 461 | + 'countries' => \Yatra\Helpers\FormatHelper::getPhoneCountries(), | |
| 462 | + 'priority' => \Yatra\Helpers\FormatHelper::getPhonePriority(), | |
| 463 | + 'flagBase' => YATRA_PLUGIN_URL . 'assets/img/flags/', | |
| 464 | + ]); | |
| 465 | + | |
| 435 | 466 | // Start fetching the ES module as early as possible (helps shorten white/splash time before React runs) |
| 436 | 467 | $app_js_url = YATRA_PLUGIN_URL . 'assets/admin/dist/js/app.js'; |
| 437 | 468 | add_action('admin_head', static function () use ($app_js_url, $jsVersion): void { |
| 438 | 469 | $href = esc_url(add_query_arg('ver', rawurlencode((string) $jsVersion), $app_js_url)); |
| @@ -449,20 +480,23 @@ | ||
| 449 | 480 | * @return bool |
| 450 | 481 | */ |
| 451 | 482 | private function isViteDevServerRunning(string $url): bool |
| 452 | 483 | { |
| 453 | - // Check the actual asset URL, not the root | |
| 484 | + // Check the actual asset URL, not the root. Uses the WP HTTP API | |
| 485 | + // (not raw cURL) per WP.org guidelines. Only ever called in dev mode | |
| 486 | + // (WP_DEBUG && YATRA_DEV_MODE), so it never runs on production loads. | |
| 454 | 487 | $assetUrl = $url . '/assets/admin/dist/js/app.js'; |
| 455 | - $ch = curl_init($assetUrl); | |
| 456 | - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |
| 457 | - curl_setopt($ch, CURLOPT_TIMEOUT, 2); // 2 second timeout | |
| 458 | - curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1); // 1 second connection timeout | |
| 459 | - curl_setopt($ch, CURLOPT_NOBODY, true); // HEAD request only | |
| 460 | - curl_exec($ch); | |
| 461 | - $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); | |
| 462 | - curl_close($ch); | |
| 463 | - | |
| 464 | - return $httpCode === 200; | |
| 488 | + | |
| 489 | + $response = wp_remote_head($assetUrl, [ | |
| 490 | + 'timeout' => 2, | |
| 491 | + 'redirection' => 0, | |
| 492 | + ]); | |
| 493 | + | |
| 494 | + if (is_wp_error($response)) { | |
| 495 | + return false; | |
| 496 | + } | |
| 497 | + | |
| 498 | + return (int) wp_remote_retrieve_response_code($response) === 200; | |
| 465 | 499 | } |
| 466 | 500 | |
| 467 | 501 | /** |
| 468 | 502 | * Add inline script for media library compatibility |