| @@ -4,9 +4,8 @@ | ||
| 4 | 4 | |
| 5 | 5 | namespace Yatra; |
| 6 | 6 | |
| 7 | 7 | use Yatra\Core\Container; |
| 8 | -use Yatra\Core\Database; | |
| 9 | 8 | use Yatra\Providers\AppServiceProvider; |
| 10 | 9 | use Yatra\Providers\RouteServiceProvider; |
| 11 | 10 | use Yatra\Providers\AdminServiceProvider; |
| 12 | 11 | use Yatra\Providers\FrontendAssetsProvider; |
| @@ -75,10 +74,10 @@ | ||
| 75 | 74 | if (class_exists('\Yatra\Services\NoticeService')) { |
| 76 | 75 | \Yatra\Services\NoticeService::init(); |
| 77 | 76 | } |
| 78 | 77 | |
| 79 | - if (class_exists('\Yatra\Admin\StatsUsage')) { | |
| 80 | - \Yatra\Admin\StatsUsage::instance()->init(); | |
| 78 | + if (class_exists('\Yatra\Services\StatsUsage')) { | |
| 79 | + \Yatra\Services\StatsUsage::instance()->init(); | |
| 81 | 80 | } |
| 82 | 81 | |
| 83 | 82 | // Initialize Dynamic Pricing Service |
| 84 | 83 | // DISABLED: Automatic dynamic pricing was adding 15% markup for trips with ≤5 spots |
| @@ -109,14 +108,18 @@ | ||
| 109 | 108 | |
| 110 | 109 | // Set up WordPress hooks |
| 111 | 110 | $this->setupWordPressHooks(); |
| 112 | 111 | |
| 113 | - // Load text domain | |
| 114 | - $this->loadTextDomain(); | |
| 112 | + // Load text domain on `init` — calling load_(plugin_)textdomain before `init` | |
| 113 | + // triggers WP 6.7+ _doing_it_wrong notices (and Loco's "premature text domain" | |
| 114 | + // warning). Use priority 1 so it runs before code that translates on `init`. | |
| 115 | + if (did_action('init')) { | |
| 116 | + $this->loadTextDomain(); | |
| 117 | + } else { | |
| 118 | + add_action('init', [$this, 'loadTextDomain'], 1); | |
| 119 | + } | |
| 115 | 120 | |
| 116 | 121 | } catch (\Throwable $e) { |
| 117 | - error_log('Yatra plugin initialization error: ' . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine()); | |
| 118 | - | |
| 119 | 122 | // Show admin notice if in admin area |
| 120 | 123 | if (is_admin()) { |
| 121 | 124 | add_action('admin_notices', function() use ($e) { |
| 122 | 125 | echo '<div class="notice notice-error"><p><strong>Yatra:</strong> ' . |
| @@ -206,9 +209,8 @@ | ||
| 206 | 209 | $instance->register(); |
| 207 | 210 | } |
| 208 | 211 | $instances[$class] = $instance; |
| 209 | 212 | } catch (\Throwable $e) { |
| 210 | - error_log("Yatra: Failed to register provider {$class}: " . $e->getMessage()); | |
| 211 | 213 | continue; |
| 212 | 214 | } |
| 213 | 215 | } |
| 214 | 216 | |
| @@ -218,9 +220,8 @@ | ||
| 218 | 220 | if (method_exists($instance, 'boot')) { |
| 219 | 221 | $instance->boot(); |
| 220 | 222 | } |
| 221 | 223 | } catch (\Throwable $e) { |
| 222 | - error_log("Yatra: Failed to boot provider {$class}: " . $e->getMessage()); | |
| 223 | 224 | continue; |
| 224 | 225 | } |
| 225 | 226 | } |
| 226 | 227 | } |
| @@ -252,11 +253,29 @@ | ||
| 252 | 253 | { |
| 253 | 254 | // Register activation/deactivation hooks |
| 254 | 255 | register_activation_hook(YATRA_PLUGIN_FILE, [$this, 'activate']); |
| 255 | 256 | register_deactivation_hook(YATRA_PLUGIN_FILE, [$this, 'deactivate']); |
| 256 | - | |
| 257 | - // Check for plugin upgrades | |
| 258 | - add_action('admin_init', [$this, 'upgrade']); | |
| 257 | + | |
| 258 | + if (class_exists(\Yatra\Upgrades\FreeUpgradeRunner::class)) { | |
| 259 | + \Yatra\Upgrades\FreeUpgradeRunner::register(); | |
| 260 | + } | |
| 261 | + | |
| 262 | + // On user registration, link any guest bookings made under | |
| 263 | + // the same email. Otherwise a customer who booked as guest | |
| 264 | + // first and then created an account would lose visibility of | |
| 265 | + // that earlier booking from My Account (the rows live with | |
| 266 | + // user_id=0 and the customer page filters by user_id). | |
| 267 | + if (class_exists('\\Yatra\\Services\\CustomerService')) { | |
| 268 | + add_action('user_register', static function ($user_id): void { | |
| 269 | + try { | |
| 270 | + (new \Yatra\Services\CustomerService())->linkGuestBookingsToUser((int) $user_id); | |
| 271 | + } catch (\Throwable $e) { | |
| 272 | + // Never block registration on a reconciliation | |
| 273 | + // failure. The booking remains accessible via the | |
| 274 | + // confirmation email link either way. | |
| 275 | + } | |
| 276 | + }, 20, 1); | |
| 277 | + } | |
| 259 | 278 | } |
| 260 | 279 | |
| 261 | 280 | /** |
| 262 | 281 | * Ensure database tables exist |
| @@ -289,14 +308,9 @@ | ||
| 289 | 308 | if (class_exists('\Yatra\Migration\MigrationProgress')) { |
| 290 | 309 | $migrationService = new \Yatra\Migration\MigrationProgress(); |
| 291 | 310 | $result = $migrationService->processMigration($dataType, (bool) $force); |
| 292 | 311 | |
| 293 | - // Log result for debugging | |
| 294 | - if (isset($result['success']) && $result['success']) { | |
| 295 | - error_log("Yatra Migration completed for {$dataType}: migrated={$result['migrated']}, skipped={$result['skipped']}, failed={$result['failed']}"); | |
| 296 | - } else { | |
| 297 | - error_log("Yatra Migration failed for {$dataType}: " . ($result['error'] ?? 'Unknown error')); | |
| 298 | - } | |
| 312 | + | |
| 299 | 313 | } |
| 300 | 314 | }, 10, 2); |
| 301 | 315 | |
| 302 | 316 | // Register background hook for all data types migration via cron |
| @@ -330,28 +344,20 @@ | ||
| 330 | 344 | flush_rewrite_rules(); |
| 331 | 345 | } |
| 332 | 346 | |
| 333 | 347 | /** |
| 334 | - * Plugin upgrade logic | |
| 348 | + * Plugin deactivation | |
| 335 | 349 | */ |
| 336 | - public function upgrade(): void | |
| 350 | + public function deactivate(): void | |
| 337 | 351 | { |
| 338 | - $current_version = get_option('yatra_version', '1.0.0'); | |
| 339 | - | |
| 340 | - if (version_compare($current_version, YATRA_VERSION, '<')) { | |
| 341 | - Database::createTables(); | |
| 342 | - update_option('yatra_version', YATRA_VERSION); | |
| 352 | + // Clear the booking maintenance sweeps so a deactivated plugin leaves no | |
| 353 | + // orphan events behind in WP-Cron. They are re-scheduled on `init` when | |
| 354 | + // the plugin is active again; the expiry activation floor is an option, | |
| 355 | + // so it survives and still protects pre-existing bookings. | |
| 356 | + foreach (['yatra_booking_expiry', 'yatra_booking_reminder', 'yatra_booking_completion'] as $hook) { | |
| 357 | + wp_clear_scheduled_hook($hook); | |
| 343 | 358 | } |
| 344 | 359 | |
| 345 | - \Yatra\Services\InstallerService::maybeBackfillEmailTemplateDefaults(); | |
| 346 | - \Yatra\Services\InstallerService::maybeNormalizeMigratedCouponDiscountStatuses(); | |
| 347 | - } | |
| 348 | - | |
| 349 | - /** | |
| 350 | - * Plugin deactivation | |
| 351 | - */ | |
| 352 | - public function deactivate(): void | |
| 353 | - { | |
| 354 | 360 | // Clean up if needed |
| 355 | 361 | flush_rewrite_rules(); |
| 356 | 362 | } |
| 357 | 363 | |
| @@ -372,10 +378,13 @@ | ||
| 372 | 378 | if (file_exists(WP_LANG_DIR . '/loco/plugins/yatra-' . $locale . '.mo')) { |
| 373 | 379 | load_textdomain('yatra', WP_LANG_DIR . '/loco/plugins/yatra-' . $locale . '.mo'); |
| 374 | 380 | } |
| 375 | 381 | |
| 376 | - // Load from plugin directory (fallback) | |
| 377 | - load_plugin_textdomain('yatra', false, 'i18n/languages'); | |
| 382 | + // Load from the plugin's own i18n/languages folder (fallback). The 3rd | |
| 383 | + // arg is relative to WP_PLUGIN_DIR, so it MUST include the plugin folder | |
| 384 | + // name — a bare 'i18n/languages' resolves to wp-content/plugins/i18n/ | |
| 385 | + // languages (which doesn't exist), so bundled translations never load. | |
| 386 | + load_plugin_textdomain('yatra', false, dirname(YATRA_PLUGIN_BASENAME) . '/i18n/languages'); | |
| 378 | 387 | } |
| 379 | 388 | |
| 380 | 389 | /** |
| 381 | 390 | * Get container instance |