| @@ -422,8 +422,21 @@ | ||
| 422 | 422 | return self::$tripColumnExistsCache[$column]; |
| 423 | 423 | } |
| 424 | 424 | |
| 425 | 425 | /** |
| 426 | + * Public, cached column-existence check for the trips table. | |
| 427 | + * | |
| 428 | + * Lets raw SELECTs outside this repository (booking confirmation join, | |
| 429 | + * similar-trips query) add columns introduced by later upgrades — e.g. | |
| 430 | + * `duration_hours` — without failing on an install whose ALTER has not | |
| 431 | + * run yet (see InstallerService::maybeAddTripDurationHoursColumn()). | |
| 432 | + */ | |
| 433 | + public function hasTripColumn(string $column): bool | |
| 434 | + { | |
| 435 | + return $this->tripTableHasColumn($column); | |
| 436 | + } | |
| 437 | + | |
| 438 | + /** | |
| 426 | 439 | * SQL expression for trip "current" list price (matches TripPricingService::resolveRegularCurrentPrice). |
| 427 | 440 | */ |
| 428 | 441 | protected function sqlTripEffectiveListPrice(): string |
| 429 | 442 | { |
| @@ -678,20 +691,21 @@ | ||
| 678 | 691 | foreach (array_unique($filters['age_suitability']) as $age) { |
| 679 | 692 | if (!is_string($age)) { |
| 680 | 693 | continue; |
| 681 | 694 | } |
| 695 | + $ageLimits = self::ageSuitabilityThresholds(); | |
| 682 | 696 | switch ($age) { |
| 683 | 697 | case 'family-friendly': |
| 684 | - $ageParts[] = '(t.age_min IS NULL OR t.age_min <= 5)'; | |
| 698 | + $ageParts[] = '(t.age_min IS NULL OR t.age_min <= ' . (int) $ageLimits['family_max'] . ')'; | |
| 685 | 699 | break; |
| 686 | 700 | case 'kids-friendly': |
| 687 | - $ageParts[] = '(t.age_min IS NULL OR t.age_min <= 12)'; | |
| 701 | + $ageParts[] = '(t.age_min IS NULL OR t.age_min <= ' . (int) $ageLimits['kids_max'] . ')'; | |
| 688 | 702 | break; |
| 689 | 703 | case 'senior-friendly': |
| 690 | - $ageParts[] = '(t.age_max IS NULL OR t.age_max >= 65)'; | |
| 704 | + $ageParts[] = '(t.age_max IS NULL OR t.age_max >= ' . (int) $ageLimits['senior_min'] . ')'; | |
| 691 | 705 | break; |
| 692 | 706 | case 'adults-only': |
| 693 | - $ageParts[] = 't.age_min >= 18'; | |
| 707 | + $ageParts[] = 't.age_min >= ' . (int) $ageLimits['adults_min']; | |
| 694 | 708 | break; |
| 695 | 709 | } |
| 696 | 710 | } |
| 697 | 711 | if ($ageParts !== []) { |
| @@ -3717,16 +3731,48 @@ | ||
| 3717 | 3731 | return 0; |
| 3718 | 3732 | } |
| 3719 | 3733 | |
| 3720 | 3734 | /** |
| 3735 | + * Age thresholds behind the suitability filters. | |
| 3736 | + * | |
| 3737 | + * These were repeated as literals in six places — the filter query and the | |
| 3738 | + * count query for each band — so an operator whose "kids" means under 18 | |
| 3739 | + * rather than under 12 had no way to say so, and changing it meant editing | |
| 3740 | + * the same number in six spots and hoping none were missed. | |
| 3741 | + * | |
| 3742 | + * @return array{family_max:int, kids_max:int, senior_min:int, adults_min:int} | |
| 3743 | + */ | |
| 3744 | + public static function ageSuitabilityThresholds(): array | |
| 3745 | + { | |
| 3746 | + $defaults = [ | |
| 3747 | + 'family_max' => 5, | |
| 3748 | + 'kids_max' => 12, | |
| 3749 | + 'senior_min' => 65, | |
| 3750 | + 'adults_min' => 18, | |
| 3751 | + ]; | |
| 3752 | + | |
| 3753 | + $filtered = (array) apply_filters('yatra_age_suitability_thresholds', $defaults); | |
| 3754 | + | |
| 3755 | + foreach ($defaults as $key => $fallback) { | |
| 3756 | + $filtered[$key] = isset($filtered[$key]) && is_numeric($filtered[$key]) | |
| 3757 | + ? (int) $filtered[$key] | |
| 3758 | + : $fallback; | |
| 3759 | + } | |
| 3760 | + | |
| 3761 | + return $filtered; | |
| 3762 | + } | |
| 3763 | + | |
| 3764 | + /** | |
| 3721 | 3765 | * Count family friendly trips |
| 3722 | 3766 | */ |
| 3723 | 3767 | public function countByFamilyFriendly(): int |
| 3724 | 3768 | { |
| 3725 | 3769 | $table = $this->getTableName(); |
| 3770 | + $limit = (int) self::ageSuitabilityThresholds()['family_max']; | |
| 3771 | + | |
| 3726 | 3772 | return (int) $this->wpdb->get_var( |
| 3727 | - "SELECT COUNT(*) FROM {$table} | |
| 3728 | - WHERE status = 'publish' AND (age_min IS NULL OR age_min <= 5)" | |
| 3773 | + "SELECT COUNT(*) FROM {$table} | |
| 3774 | + WHERE status = 'publish' AND (age_min IS NULL OR age_min <= {$limit})" | |
| 3729 | 3775 | ); |
| 3730 | 3776 | } |
| 3731 | 3777 | |
| 3732 | 3778 | /** |
| @@ -3734,11 +3780,13 @@ | ||
| 3734 | 3780 | */ |
| 3735 | 3781 | public function countByKidsFriendly(): int |
| 3736 | 3782 | { |
| 3737 | 3783 | $table = $this->getTableName(); |
| 3784 | + $limit = (int) self::ageSuitabilityThresholds()['kids_max']; | |
| 3785 | + | |
| 3738 | 3786 | return (int) $this->wpdb->get_var( |
| 3739 | - "SELECT COUNT(*) FROM {$table} | |
| 3740 | - WHERE status = 'publish' AND (age_min IS NULL OR age_min <= 12)" | |
| 3787 | + "SELECT COUNT(*) FROM {$table} | |
| 3788 | + WHERE status = 'publish' AND (age_min IS NULL OR age_min <= {$limit})" | |
| 3741 | 3789 | ); |
| 3742 | 3790 | } |
| 3743 | 3791 | |
| 3744 | 3792 | /** |
| @@ -3746,11 +3794,13 @@ | ||
| 3746 | 3794 | */ |
| 3747 | 3795 | public function countBySeniorFriendly(): int |
| 3748 | 3796 | { |
| 3749 | 3797 | $table = $this->getTableName(); |
| 3798 | + $limit = (int) self::ageSuitabilityThresholds()['senior_min']; | |
| 3799 | + | |
| 3750 | 3800 | return (int) $this->wpdb->get_var( |
| 3751 | - "SELECT COUNT(*) FROM {$table} | |
| 3752 | - WHERE status = 'publish' AND (age_max IS NULL OR age_max >= 65)" | |
| 3801 | + "SELECT COUNT(*) FROM {$table} | |
| 3802 | + WHERE status = 'publish' AND (age_max IS NULL OR age_max >= {$limit})" | |
| 3753 | 3803 | ); |
| 3754 | 3804 | } |
| 3755 | 3805 | |
| 3756 | 3806 | /** |
| @@ -3758,11 +3808,13 @@ | ||
| 3758 | 3808 | */ |
| 3759 | 3809 | public function countByAdultsOnly(): int |
| 3760 | 3810 | { |
| 3761 | 3811 | $table = $this->getTableName(); |
| 3812 | + $limit = (int) self::ageSuitabilityThresholds()['adults_min']; | |
| 3813 | + | |
| 3762 | 3814 | return (int) $this->wpdb->get_var( |
| 3763 | - "SELECT COUNT(*) FROM {$table} | |
| 3764 | - WHERE status = 'publish' AND age_min >= 18" | |
| 3815 | + "SELECT COUNT(*) FROM {$table} | |
| 3816 | + WHERE status = 'publish' AND age_min >= {$limit}" | |
| 3765 | 3817 | ); |
| 3766 | 3818 | } |
| 3767 | 3819 | |
| 3768 | 3820 | /** |