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/Core/Routing/PrettyRouteMatcher.php +41 -11 3.0.3 → 3.0.16 View file →
@@ -18,10 +18,26 @@
18 18 public static function match(string $path): ?array
19 19 {
20 20 $path = trim($path, '/');
21 21
22 + /**
23 + * Override pretty-path routing entirely (runs before built-in rules).
24 + * Return a route array shaped like handler data: keys include `type` (trip|taxonomy|listing|…),
25 + * and type-specific keys such as `slug`, `taxonomy_type`, `listing_type`, `base`, `paged`, etc.
26 + *
27 + * @param array<string,mixed>|null $route_data Resolved route or null to use core matching.
28 + * @param string $path Trimmed relative path ({@see UrlParser::getCleanRequestPath()} after `yatra_frontend_request_path`).
29 + */
30 + $override = apply_filters('yatra_pretty_route_match', null, $path);
31 + if (is_array($override) && isset($override['type']) && is_string($override['type']) && $override['type'] !== '') {
32 + return $override;
33 + }
34 +
35 + $pb = SettingsService::getPermalinkBases();
36 +
22 37 // 1. Email verification
23 - if (preg_match('/^yatra-verify-email\/([a-zA-Z0-9_-]+)$/', $path, $matches)) {
38 + $evQuoted = preg_quote($pb['email_verification_prefix'], '/');
39 + if (preg_match('/^' . $evQuoted . '\/([a-zA-Z0-9_-]+)$/', $path, $matches)) {
24 40 return [
25 41 'type' => 'email_verification',
26 42 'token' => $matches[1],
27 43 ];
@@ -44,14 +60,25 @@
44 60 'paged' => max(1, (int) $matches[1]),
45 61 ];
46 62 }
47 63
64 + // Captured slug segments come in as URL-encoded UTF-8 when the request
65 + // path contains non-ASCII characters (e.g. Cyrillic "моя-семья"
66 + // arrives here as `%D0%BC%D0%BE%D1%8F-...`). The DB stores the raw
67 + // decoded slug, so we must decode + normalise once here before
68 + // returning the route data — otherwise downstream handlers query
69 + // `findBySlug('%D0%BC...')` and 404 every non-Latin URL. Mirrors WP
70 + // core's behaviour in `get_page_by_path`.
71 + $decodeSlug = static function (string $raw): string {
72 + return \Yatra\Helpers\SlugHelper::generate($raw);
73 + };
74 +
48 75 // 5. Single trip
49 76 if (preg_match('/^' . preg_quote($trip_base, '/') . '\/([^\/]+)\/?$/', $path, $matches)) {
50 77 if ($matches[1] !== 'page') {
51 78 return [
52 79 'type' => 'trip',
53 - 'slug' => $matches[1],
80 + 'slug' => $decodeSlug($matches[1]),
54 81 'base' => $trip_base,
55 82 ];
56 83 }
57 84 }
@@ -57,11 +84,11 @@
57 84 }
58 85
59 86 // 6. Taxonomy (pagination before single slug)
60 87 $bases = [
61 - 'destination' => SettingsService::getString('destination_base', 'destination'),
62 - 'activity' => SettingsService::getString('activity_base', 'activity'),
63 - 'category' => SettingsService::getString('trip_category_base', 'trip-category'),
88 + 'destination' => SettingsService::getDestinationBase(),
89 + 'activity' => SettingsService::getActivityBase(),
90 + 'category' => SettingsService::getTripCategoryBase(),
64 91 ];
65 92
66 93 foreach ($bases as $type => $base) {
67 94 if (preg_match('/^' . preg_quote($base, '/') . '\/([^\/]+)\/page\/(\d+)\/?$/', $path, $matches)) {
@@ -67,9 +94,9 @@
67 94 if (preg_match('/^' . preg_quote($base, '/') . '\/([^\/]+)\/page\/(\d+)\/?$/', $path, $matches)) {
68 95 return [
69 96 'type' => 'taxonomy',
70 97 'taxonomy_type' => $type,
71 - 'slug' => $matches[1],
98 + 'slug' => $decodeSlug($matches[1]),
72 99 'base' => $base,
73 100 'paged' => max(1, (int) $matches[2]),
74 101 ];
75 102 }
@@ -79,9 +106,9 @@
79 106 if (preg_match('/^' . preg_quote($base, '/') . '\/([^\/]+)\/?$/', $path, $matches)) {
80 107 return [
81 108 'type' => 'taxonomy',
82 109 'taxonomy_type' => $type,
83 - 'slug' => $matches[1],
110 + 'slug' => $decodeSlug($matches[1]),
84 111 'base' => $base,
85 112 ];
86 113 }
87 114 }
@@ -104,11 +131,12 @@
104 131 'base' => $trip_base,
105 132 ];
106 133 }
107 134
108 - // 8. Booking confirmation (pageless: /{booking_base}/confirmation/{ref}/ + legacy slug)
135 + // 8. Booking confirmation (pageless: /{booking_base}/{confirmation_segment}/{ref}/ + legacy slug)
109 136 $booking_base = SettingsService::getBookingBase();
110 - if (preg_match('/^' . preg_quote($booking_base, '/') . '\/confirmation\/([a-zA-Z0-9_-]+)$/', $path, $matches)) {
137 + $confirmSeg = preg_quote($pb['booking_flow_confirmation_segment'], '/');
138 + if (preg_match('/^' . preg_quote($booking_base, '/') . '\/' . $confirmSeg . '\/([a-zA-Z0-9_-]+)$/', $path, $matches)) {
111 139 return [
112 140 'type' => 'booking_confirmation',
113 141 'confirmation_id' => $matches[1],
114 142 ];
@@ -113,9 +141,10 @@
113 141 'confirmation_id' => $matches[1],
114 142 ];
115 143 }
116 144
117 - if (preg_match('/^booking-confirmation\/([a-zA-Z0-9_-]+)$/', $path, $matches)) {
145 + $legacyConfQuoted = preg_quote($pb['legacy_booking_confirmation_prefix'], '/');
146 + if (preg_match('/^' . $legacyConfQuoted . '\/([a-zA-Z0-9_-]+)$/', $path, $matches)) {
118 147 return [
119 148 'type' => 'booking_confirmation',
120 149 'confirmation_id' => $matches[1],
121 150 ];
@@ -121,9 +150,10 @@
121 150 ];
122 151 }
123 152
124 153 // 9. Remaining checkout (rewrite) and legacy checkout/ path
125 - if (preg_match('/^remaining-checkout\/([a-zA-Z0-9_-]+)$/', $path, $matches)) {
154 + $remQuoted = preg_quote($pb['remaining_checkout_prefix'], '/');
155 + if (preg_match('/^' . $remQuoted . '\/([a-zA-Z0-9_-]+)$/', $path, $matches)) {
126 156 return [
127 157 'type' => 'checkout',
128 158 'token' => $matches[1],
129 159 ];