PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 All 84 releases
← All changes | app/Hooks/CacheHooks.php +52 -0 3.0.3 → 3.0.16 View file →
@@ -306,8 +306,9 @@
306 306 public static function onItineraryDayCreated(int $dayId, array $data): void
307 307 {
308 308 self::invalidateListingCaches();
309 309 Cache::clearByPrefix('yatra_trip_');
310 + self::invalidateItineraryCaches((int) ($data['trip_id'] ?? 0), 0);
310 311 Logger::info("Cache invalidated for itinerary day creation", ['day_id' => $dayId]);
311 312 }
312 313
313 314 public static function onItineraryDayUpdated(int $dayId, array $data): void
@@ -314,8 +315,11 @@
314 315 {
315 316 Cache::delete(Cache::PREFIX_TRIP_DATA . ($data['trip_id'] ?? ''));
316 317 self::invalidateListingCaches();
317 318 Cache::clearByPrefix('yatra_trip_');
319 + // Also blow the itinerary-prefixed cache so the day-edit page doesn't
320 + // serve stale entries (same root cause as the activity hook below).
321 + self::invalidateItineraryCaches((int) ($data['trip_id'] ?? 0), 0);
318 322 Logger::info("Cache invalidated for itinerary day update", ['day_id' => $dayId]);
319 323 }
320 324
321 325 public static function onItineraryDayDeleted(int $dayId): void
@@ -321,8 +325,9 @@
321 325 public static function onItineraryDayDeleted(int $dayId): void
322 326 {
323 327 self::invalidateListingCaches();
324 328 Cache::clearByPrefix('yatra_trip_');
329 + self::invalidateItineraryCaches(0, 0);
325 330 Logger::info("Cache invalidated for itinerary day deletion", ['day_id' => $dayId]);
326 331 }
327 332
328 333 /**
@@ -331,8 +336,9 @@
331 336 public static function onItineraryActivityCreated(int $activityId, array $data): void
332 337 {
333 338 self::invalidateListingCaches();
334 339 Cache::clearByPrefix('yatra_trip_');
340 + self::invalidateItineraryCaches((int) ($data['trip_id'] ?? 0), $activityId);
335 341 Logger::info("Cache invalidated for itinerary activity creation", ['activity_id' => $activityId]);
336 342 }
337 343
338 344 public static function onItineraryActivityUpdated(int $activityId, array $data): void
@@ -339,8 +345,9 @@
339 345 {
340 346 Cache::delete(Cache::PREFIX_TRIP_DATA . ($data['trip_id'] ?? ''));
341 347 self::invalidateListingCaches();
342 348 Cache::clearByPrefix('yatra_trip_');
349 + self::invalidateItineraryCaches((int) ($data['trip_id'] ?? 0), $activityId);
343 350 Logger::info("Cache invalidated for itinerary activity update", ['activity_id' => $activityId]);
344 351 }
345 352
346 353 public static function onItineraryActivityDeleted(int $activityId): void
@@ -346,7 +353,52 @@
346 353 public static function onItineraryActivityDeleted(int $activityId): void
347 354 {
348 355 self::invalidateListingCaches();
349 356 Cache::clearByPrefix('yatra_trip_');
357 + self::invalidateItineraryCaches(0, $activityId);
350 358 Logger::info("Cache invalidated for itinerary activity deletion", ['activity_id' => $activityId]);
359 + }
360 +
361 + /**
362 + * Clear every cache layer that can serve stale itinerary data after a write.
363 + *
364 + * The day-edit page reads via `GET /trips/{id}` → TripRepository::findWithRelationsCached
365 + * → cached under `yatra_query_trip_with_relations_<id>` (PREFIX_QUERY_RESULT).
366 + * That entire object — including `itinerary_days[].entries[].order` — is cached
367 + * for the trip-data TTL. Until *that* key is dropped, the React load mapper sees
368 + * the OLD order and a drag-sort reorder appears not to persist on reload.
369 + *
370 + * Three prefix families touch this data; we have to hit all of them:
371 + * 1. `yatra_query_*` (PREFIX_QUERY_RESULT) — caches `trip_with_relations_<id>`,
372 + * `trips_with_filters_*`, etc. The actual culprit for reorder reverts.
373 + * 2. `yatra_trip_*` (PREFIX_TRIP_DATA) — `yatra_trip_<id>` from findByIdCached.
374 + * 3. `yatra_itinerary_*` (KEY_ITINERARY_BY_TRIP_ID + per-entry keys) — used by
375 + * direct ItineraryRepository::getByTripId reads (admin itinerary screen).
376 + *
377 + * `Cache::invalidateTrip($tripId)` already covers (1) + (2); we add (3) for the
378 + * itinerary-specific keys it doesn't know about.
379 + *
380 + * @param int $tripId Trip whose caches to clear (0 = unknown).
381 + * @param int $activityId Activity row id for per-entry cache keys (0 = skip).
382 + */
383 + private static function invalidateItineraryCaches(int $tripId, int $activityId): void
384 + {
385 + // (1) + (2): drops PREFIX_TRIP_DATA + PREFIX_QUERY_RESULT — the actual fix
386 + // for "reorder doesn't survive reload". The React day-edit page reads from
387 + // the trip-with-relations cache, so until this clears, save→reload returns
388 + // the pre-reorder snapshot.
389 + if ($tripId > 0) {
390 + Cache::invalidateTrip($tripId);
391 + }
392 +
393 + // (3): itinerary-prefixed caches that PREFIX_QUERY_RESULT doesn't include.
394 + if ($tripId > 0) {
395 + Cache::delete(Cache::KEY_ITINERARY_BY_TRIP_ID . '_' . $tripId);
396 + }
397 + Cache::clearByPrefix('yatra_itinerary_');
398 +
399 + if ($activityId > 0) {
400 + Cache::delete(Cache::KEY_ACTIVITY_ENTRY . '_' . $activityId);
401 + Cache::delete(Cache::KEY_ITINERARY_ENTRY_WITH_RELATIONS . '_' . $activityId);
402 + }
351 403 }
352 404 }