*/ public static function shortcodeStyleDependencies(): array { self::registerCoreFrontendStylesheets(); return wp_style_is('yatra-common', 'registered') ? ['yatra-common'] : []; } public static function registerCoreFrontendStylesheets(): void { $faPath = YATRA_PLUGIN_PATH . 'assets/vendor/fontawesome/css/all.min.css'; if (file_exists($faPath) && !wp_style_is('yatra-fontawesome-6', 'registered')) { wp_register_style( 'yatra-fontawesome-6', YATRA_PLUGIN_URL . 'assets/vendor/fontawesome/css/all.min.css', [], '6.7.2.' . filemtime($faPath) ); } if (wp_style_is('yatra-common', 'registered')) { return; } $path = YATRA_PLUGIN_PATH . 'assets/css/common.css'; if (!is_readable($path)) { return; } $commonDeps = wp_style_is('yatra-fontawesome-6', 'registered') ? ['yatra-fontawesome-6'] : []; wp_register_style( 'yatra-common', YATRA_PLUGIN_URL . 'assets/css/common.css', $commonDeps, YATRA_VERSION . '.' . filemtime($path) ); } /** * Enqueue frontend assets based on context * * @return void */ public function enqueueAssets(): void { // Only run on frontend if (is_admin()) { return; } // Always enqueue common frontend assets $this->enqueueCommonAssets(); // Enqueue page-specific assets $this->enqueuePageSpecificAssets(); } /** * Enqueue common frontend assets * * @return void */ private function enqueueCommonAssets(): void { // Enqueue common CSS $this->enqueueCommonCss(); // Enqueue common JavaScript $this->enqueueCommonJs(); } /** * Enqueue common CSS files * * @return void */ private function enqueueCommonCss(): void { $cssFiles = [ 'common' => 'common.css', 'listing' => 'listing.css', 'stripe' => 'stripe.css', 'trip' => 'trip.css', 'activity' => 'activity.css', 'destination' => 'destination.css', 'yatra-capacity' => 'yatra-capacity.css', 'video-player' => 'video-player.css', 'tour-viewer' => 'tour-viewer.css', ]; self::registerCoreFrontendStylesheets(); if (wp_style_is('yatra-fontawesome-6', 'registered')) { wp_enqueue_style('yatra-fontawesome-6'); } foreach ($cssFiles as $handle => $filename) { $filePath = YATRA_PLUGIN_PATH . "assets/css/{$filename}"; if (!file_exists($filePath)) { continue; } $styleHandle = 'yatra-' . $handle; $ver = YATRA_VERSION . '.' . filemtime($filePath); if ($handle === 'common') { if (wp_style_is('yatra-common', 'registered')) { wp_enqueue_style('yatra-common'); } else { $deps = wp_style_is('yatra-fontawesome-6', 'registered') ? ['yatra-fontawesome-6'] : []; wp_enqueue_style($styleHandle, YATRA_PLUGIN_URL . "assets/css/{$filename}", $deps, $ver); } continue; } $deps = []; if ($handle !== 'common' && wp_style_is('yatra-common', 'registered')) { $deps[] = 'yatra-common'; } wp_enqueue_style( $styleHandle, YATRA_PLUGIN_URL . "assets/css/{$filename}", $deps, $ver ); } $this->enqueueFrontendThemeVariables(); $this->enqueueFrontendLayoutVariables(); } /** * Override design tokens from Settings (single primary color → related shades). */ private function enqueueFrontendThemeVariables(): void { if (!wp_style_is('yatra-common', 'enqueued')) { return; } $primary = \Yatra\Services\SettingsService::getString( 'frontend_primary_color', \Yatra\Utils\FrontendThemeCss::DEFAULT_PRIMARY ); $primary = \Yatra\Utils\FrontendThemeCss::sanitizePrimaryColor($primary); if (strtolower($primary) === strtolower(\Yatra\Utils\FrontendThemeCss::DEFAULT_PRIMARY)) { return; } $css = \Yatra\Utils\FrontendThemeCss::buildInlineRootCss($primary); if ($css !== '') { wp_add_inline_style('yatra-common', $css); } } /** * Align --yatra-container-max-width with the active theme (theme.json wide/content size or $content_width). */ private function enqueueFrontendLayoutVariables(): void { if (!wp_style_is('yatra-common', 'enqueued')) { return; } $fromSetting = \Yatra\Utils\FrontendThemeCss::sanitizeContainerMaxWidthSetting( \Yatra\Services\SettingsService::getString('frontend_container_max_width', '') ); $max = $fromSetting !== '' ? $fromSetting : \Yatra\Utils\FrontendThemeCss::resolveThemeContainerMaxWidth(); if ($max === null || $max === '') { return; } $maxEsc = esc_attr($max); wp_add_inline_style('yatra-common', ':root{--yatra-container-max-width:' . $maxEsc . ';}'); } /** * Enqueue common JavaScript files * * @return void */ private function enqueueCommonJs(): void { $jsFiles = [ 'api-helper' => 'api-helper.js', 'video-player' => 'video-player.js', 'tour-viewer' => 'tour-viewer.js', 'listing' => 'listing.js', 'listing-filters' => 'listing-filters.js', 'stripe' => 'stripe.js', 'trip' => 'trip.js', ]; foreach ($jsFiles as $handle => $filename) { $filePath = YATRA_PLUGIN_PATH . "assets/js/{$filename}"; if (file_exists($filePath)) { // Set dependencies $dependencies = ['jquery']; if ($handle === 'trip') { $dependencies[] = 'yatra-api-helper'; } // Scripts that call `wp.i18n.__()` for user-facing // strings need wp-i18n as a dependency so the global // exists before they run AND a `wp_set_script_translations` // call below so WordPress loads each one's Jed JSON // catalog (each handle has its own md5-named JSON // because the .po references their respective source // file paths). Add a handle here whenever you wrap a // new string in __() inside its file. $i18nHandles = ['trip', 'listing', 'stripe', 'tour-viewer', 'video-player']; if (in_array($handle, $i18nHandles, true)) { $dependencies[] = 'wp-i18n'; } wp_enqueue_script( "yatra-{$handle}", YATRA_PLUGIN_URL . "assets/js/{$filename}", $dependencies, YATRA_VERSION . '.' . filemtime($filePath), true ); // Mirror the wp-i18n dep list above. wp_set_script_translations // tells WordPress where to look for this script's Jed JSON // catalog (path = plugin's i18n/languages/) and the loader // hashes md5(handle src) to find the right file. if (in_array($handle, $i18nHandles, true) && function_exists('wp_set_script_translations') ) { wp_set_script_translations( "yatra-{$handle}", 'yatra', YATRA_PLUGIN_PATH . 'i18n/languages' ); } } } if (\Yatra\Services\SettingsService::wishlistEnabled()) { $wishPath = YATRA_PLUGIN_PATH . 'assets/js/listing-wishlist.js'; if (file_exists($wishPath)) { wp_enqueue_script( 'yatra-listing-wishlist', YATRA_PLUGIN_URL . 'assets/js/listing-wishlist.js', ['jquery', 'wp-i18n'], YATRA_VERSION . '.' . filemtime($wishPath), true ); if (function_exists('wp_set_script_translations')) { wp_set_script_translations( 'yatra-listing-wishlist', 'yatra', YATRA_PLUGIN_PATH . 'i18n/languages' ); } // Wishlist "Login" should send guests to the configured // My Account page (Settings → Permalink slug), not the raw // wp-login.php screen. Fall back to wp_login_url() only when // no account base is configured so the button never dead-ends. $yatraAccountBase = \Yatra\Services\SettingsService::getAccountBase(); $yatraAccountLoginUrl = $yatraAccountBase !== '' ? home_url('/' . trim($yatraAccountBase, '/') . '/') : wp_login_url(); wp_localize_script('yatra-listing-wishlist', 'yatraWishlistConfig', [ 'enabled' => true, 'restUrl' => rest_url('yatra/v1'), 'nonce' => wp_create_nonce('wp_rest'), 'isLoggedIn' => is_user_logged_in(), 'loginUrl' => $yatraAccountLoginUrl, 'i18n' => [ 'loginRequired' => __('Login Required', 'yatra'), 'loginPrompt' => __('Please login to save trips to your wishlist.', 'yatra'), 'login' => __('Login', 'yatra'), 'cancel' => __('Cancel', 'yatra'), 'genericError' => __('An error occurred. Please try again.', 'yatra'), 'saved' => __('Trip saved to wishlist', 'yatra'), 'removed' => __('Trip removed from wishlist', 'yatra'), 'saveFailed' => __('Failed to save trip', 'yatra'), 'removeFailed' => __('Failed to remove trip', 'yatra'), 'addAria' => __('Add to favorites', 'yatra'), 'removeAria' => __('Remove from favorites', 'yatra'), ], ]); } } } /** * Enqueue page-specific assets * * @return void */ private function enqueuePageSpecificAssets(): void { if (yatra_is_account_page()) { $this->enqueueAccountAssets(); return; } // Check current page context and enqueue specific assets using helper functions if (yatra_is_trip_listing()) { $this->enqueueTripListingAssets(); } if (yatra_is_single_trip()) { $this->enqueueTripDetailAssets(); } if (yatra_is_activity_listing()) { $this->enqueueActivityListingAssets(); } if (yatra_is_destination_listing()) { $this->enqueueDestinationListingAssets(); } if (yatra_is_booking_page()) { $this->enqueueBookingAssets(); } if (yatra_is_taxonomy_page()) { // Taxonomy pages use the same assets as trip listing $this->enqueueTripListingAssets(); } } /** * Enqueue trip listing specific assets * * @return void */ private function enqueueTripListingAssets(): void { $this->enqueueListingFiltersJs(); } /** * Enqueue trip detail specific assets * * @return void */ private function enqueueTripDetailAssets(): void { // Enqueue booking assets for trip detail pages (booking forms) $bookingJs = YATRA_PLUGIN_PATH . 'assets/js/booking.js'; if (file_exists($bookingJs)) { wp_enqueue_script( 'yatra-booking', YATRA_PLUGIN_URL . 'assets/js/booking.js', ['jquery', 'wp-i18n'], YATRA_VERSION . '.' . filemtime($bookingJs), true ); if (function_exists('wp_set_script_translations')) { wp_set_script_translations( 'yatra-booking', 'yatra', YATRA_PLUGIN_PATH . 'i18n/languages' ); } } // International phone-number widget (country flag + dial code) used by // the booking form's tel fields. $this->enqueuePhoneInputAssets(); $this->enqueueCountrySelectAssets(); // Mobile sticky-sidebar + flatpickr init for the single-trip page. Lives in a // dedicated file rather than as inline