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/TemplateLoader.php +182 -185 3.0.2.8 → 3.0.16 View file →
@@ -5,11 +5,13 @@
5 5 namespace Yatra\Core;
6 6
7 7 use Yatra\Core\Routing\Router;
8 8 use Yatra\Core\Routing\PermalinkCanonical;
9 +use Yatra\Core\Routing\UrlParser;
10 +use Yatra\Core\Routing\PageContext;
11 +use Yatra\Core\Template\FseTemplates;
9 12 use Yatra\Services\SettingsService;
10 13 use Yatra\Core\Handlers\BookingConfirmationPageHandler;
11 -use Yatra\Repositories\BookingRepository;
12 14
13 15 /**
14 16 * Template Loader
15 17 *
@@ -34,73 +36,156 @@
34 36 // Initialize rewrite rules and query vars first
35 37 add_action('init', [self::class, 'addTripRewriteRules'], 10);
36 38 add_filter('query_vars', [self::class, 'addCustomQueryVars']);
37 39
38 - // Early template include for booking confirmation (plain permalinks safety net)
39 - add_filter('template_include', [self::class, 'maybeLoadBookingConfirmationTemplate'], 0);
40 + // FSE Site Editor integration — virtual block templates + page-content block.
41 + // No-ops on classic themes.
42 + FseTemplates::init();
40 43
44 + // Prevent WP::handle_404() from marking Yatra URLs as 404 in the first place.
45 + // This is the proper WordPress way — fires before status_header(404) is sent and
46 + // before FSE locate_block_template() reads is_404() to pick 404.html.
47 + add_filter('pre_handle_404', [self::class, 'preventCore404'], 10, 2);
48 +
49 + // Strip the `error404` body class for Yatra requests so FSE themes don't apply
50 + // 404-specific styling to plugin pages.
51 + add_filter('body_class', [self::class, 'filterBodyClass'], 20);
52 +
41 53 add_action('template_redirect', [PermalinkCanonical::class, 'enforce'], 0);
42 54
43 - // Initialize the main router for template handling
55 + // Initialize the main router for template handling. Handlers configure
56 + // $wp_query + a virtual WP_Post here and stash the chosen template in
57 + // PageContext; they do NOT include or exit, so the full template-loader
58 + // pipeline (template hierarchy resolution, wp_head, wp_footer, plugin
59 + // template_include hooks) continues to run normally.
44 60 add_action('template_redirect', [self::class, 'handleTemplateRedirect'], 1);
61 +
62 + // Hand off to WordPress's template-loader: if a Yatra handler queued a
63 + // template via PageContext, swap it in here. Priority 99 ensures we run
64 + // after FSE's locate_block_template() (default priority 10) so we win
65 + // over the theme's block-template choice without disabling FSE for the
66 + // rest of the site.
67 + add_filter('template_include', [self::class, 'filterTemplateInclude'], 99);
45 68 }
46 69
47 70 /**
48 - * Early template include for booking confirmation (plain permalinks)
71 + * Short-circuit WP::handle_404() for Yatra-owned URLs.
72 + *
73 + * Returning true tells WordPress core to skip setting is_404 / status_header(404).
74 + * This keeps FSE/block themes from resolving to 404.html and pulling the wrong
75 + * header template part. The Router still runs on template_redirect to actually
76 + * render the page; this filter only prevents the premature 404 marking.
77 + *
78 + * @param bool $preempt Whether to short-circuit default 404 handling.
79 + * @param \WP_Query $wp_query The main WP_Query instance (unused — detection uses globals).
80 + * @return bool
49 81 */
50 - public static function maybeLoadBookingConfirmationTemplate(string $template): string
82 + public static function preventCore404($preempt, /** @noinspection PhpUnusedParameterInspection */ $wp_query)
51 83 {
52 - global $wp_query;
53 - if (!empty($wp_query->is_404)) {
54 - return $template;
84 + if ($preempt) {
85 + return $preempt;
55 86 }
87 + if (!self::isYatraRequest()) {
88 + return $preempt;
89 + }
90 + // Mirror what WP::handle_404() does on success: do NOT set is_404, but ensure
91 + // status header is 200 so downstream caches / CDNs behave correctly.
92 + status_header(200);
93 + nocache_headers();
94 + return true;
95 + }
56 96
57 - $confirmationId = get_query_var('yatra_booking_confirmation')
58 - ?: ($_GET['yatra_booking_confirmation'] ?? ($_GET['reference'] ?? ($_GET['booking_id'] ?? '')));
59 - if (empty($confirmationId)) {
60 - return $template;
97 + /**
98 + * Remove the `error404` body class for Yatra pages so FSE themes render normal page chrome.
99 + *
100 + * @param array $classes
101 + * @return array
102 + */
103 + public static function filterBodyClass(array $classes): array
104 + {
105 + $ctx = PageContext::instance();
106 + $isYatra = self::isYatraRequest() || $ctx->isHandled();
107 + if (!$isYatra) {
108 + return $classes;
61 109 }
62 110
63 - if (defined('WP_DEBUG') && WP_DEBUG) {
111 + $classes = array_values(array_filter($classes, static function ($c) {
112 + return $c !== 'error404' && $c !== 'error-404';
113 + }));
114 +
115 + if (!in_array('yatra-page', $classes, true)) {
116 + $classes[] = 'yatra-page';
117 + }
118 +
119 + foreach ($ctx->getBodyClasses() as $extra) {
120 + if (!in_array($extra, $classes, true)) {
121 + $classes[] = $extra;
64 122 }
123 + }
65 124
66 - $bookingRepo = new BookingRepository();
67 - $booking = $bookingRepo->findByConfirmationSegment((string) $confirmationId);
68 - if (!$booking) {
69 - if (defined('WP_DEBUG') && WP_DEBUG) {
70 - }
125 + return $classes;
126 + }
127 +
128 + /**
129 + * Public detection helper — true when the current request belongs to a Yatra route.
130 + * Centralises the logic previously in shouldClear404ForYatraRouting() so it can be
131 + * reused by pre_handle_404 and body_class filters.
132 + */
133 + public static function isYatraRequest(): bool
134 + {
135 + return self::shouldClear404ForYatraRouting();
136 + }
137 +
138 + /**
139 + * `template_include` filter — choose between PHP template and FSE block template.
140 + *
141 + * Decision flow when a Yatra handler has queued a template:
142 + * 1. If the admin has customised the matching virtual block template in the
143 + * Site Editor (wp_template post with source = 'custom'), defer to FSE —
144 + * WP renders the customised block template, which embeds Yatra content
145 + * via the `yatra/page-content` server block. Their edits take effect.
146 + * 2. Otherwise return Yatra's PHP template. It's faster, cache-friendly,
147 + * and the path the plugin tested most.
148 + *
149 + * For non-Yatra requests, return $template unchanged so the theme/FSE keep control.
150 + */
151 + public static function filterTemplateInclude(string $template): string
152 + {
153 + $ctx = PageContext::instance();
154 + if (!$ctx->hasTemplate()) {
71 155 return $template;
72 156 }
73 157
74 - // Prevent 404 and set globals
75 - global $wp_query;
76 - $wp_query->is_404 = false;
77 - status_header(200);
78 - $GLOBALS['yatra_booking'] = $booking;
79 - $wp_query->set('yatra_booking_confirmation', $confirmationId);
80 - $wp_query->set('yatra_booking', $booking);
81 -
82 - $template_path = YATRA_PLUGIN_PATH . 'templates/booking-confirmation.php';
83 - if (file_exists($template_path)) {
84 - if (defined('WP_DEBUG') && WP_DEBUG) {
85 - }
86 - return $template_path;
158 + // If the admin has saved a Site-Editor customisation for this page
159 + // type, render via WordPress's block-template canvas with the saved
160 + // content. loadCustomisedCanvas() returns null if no customisation
161 + // exists (the common case) or returns template-canvas.php with the
162 + // canvas globals primed.
163 + $pageType = $ctx->getPageType();
164 + if ($pageType !== '') {
165 + $canvas = FseTemplates::loadCustomisedCanvas($pageType);
166 + if ($canvas !== null) {
167 + return $canvas;
168 + }
87 169 }
88 170
89 - if (defined('WP_DEBUG') && WP_DEBUG) {
90 - }
91 - return $template;
171 + $selected = $ctx->getTemplate();
172 + return $selected !== null ? $selected : $template;
92 173 }
93 174
94 175 /**
95 - * Handle template redirect using the new routing system
176 + * Handle template_redirect:
177 + * 1. Clear residual is_404 (paged-home quirk; pre_handle_404 catches the rest).
178 + * 2. Run the Router — handlers configure $wp_query and queue a template.
179 + * 3. Fall through to WordPress's template-loader. Our template_include
180 + * filter at priority 99 swaps in the Yatra template if one was queued.
181 + *
182 + * No include + exit here — that was the source of the FSE breakage.
96 183 */
97 184 public static function handleTemplateRedirect(): void
98 185 {
99 186 global $wp_query;
100 187
101 - // WordPress often sets 404 for ?paged=N on the front page when the main blog query has no Nth page.
102 - // Yatra listings use the same query vars (?yatra_page=…&paged=2); clear 404 so routing can run.
103 188 if (!empty($wp_query->is_404) && self::shouldClear404ForYatraRouting()) {
104 189 $wp_query->is_404 = false;
105 190 status_header(200);
106 191 }
@@ -108,86 +193,29 @@
108 193 if (!empty($wp_query->is_404)) {
109 194 return;
110 195 }
111 196
112 - // Early plain-permalink handling for booking confirmation via query var
113 - $confirmationId = get_query_var('yatra_booking_confirmation')
114 - ?: ($_GET['yatra_booking_confirmation'] ?? ($_GET['reference'] ?? ($_GET['booking_id'] ?? '')));
115 - if (!empty($confirmationId)) {
116 - $bookingRepo = new BookingRepository();
117 - $booking = $bookingRepo->findByConfirmationSegment((string) $confirmationId);
118 - if ($booking) {
119 - global $wp_query;
120 - $wp_query->is_404 = false;
121 - status_header(200);
122 - $GLOBALS['yatra_booking'] = $booking;
123 - $wp_query->set('yatra_booking_confirmation', $confirmationId);
124 - $wp_query->set('yatra_booking', $booking);
125 - $template_path = YATRA_PLUGIN_PATH . 'templates/booking-confirmation.php';
126 - if (file_exists($template_path)) {
127 - include $template_path;
128 - exit;
129 - }
130 - }
131 - }
132 -
133 197 if (!self::$router) {
134 198 self::$router = new Router();
135 199 }
136 200
137 - // Let the router handle the request
138 201 $handled = self::$router->route();
139 202
140 - // If router didn't handle it, let WordPress continue normally
203 + // Plain-permalink fallback: ?yatra_booking_confirmation=... still needs
204 + // an explicit dispatch because PlainPageMatcher doesn't know about it.
141 205 if (!$handled) {
142 - // Plain permalinks: routing uses ?yatra_page={base from settings} (see PlainPageMatcher).
143 -
144 - // Plain permalink fallback: handle ?yatra_booking_confirmation=
145 - if (!$handled) {
146 - $confirmationId = get_query_var('yatra_booking_confirmation') ?: ($_GET['yatra_booking_confirmation'] ?? '');
147 - if (!empty($confirmationId)) {
148 - $handler = new BookingConfirmationPageHandler();
149 - $handled = $handler->handle([
150 - 'confirmation_id' => sanitize_text_field($confirmationId),
151 - ]);
152 - }
206 + $confirmationId = get_query_var('yatra_booking_confirmation')
207 + ?: ($_GET['yatra_booking_confirmation'] ?? ($_GET['reference'] ?? ($_GET['booking_id'] ?? '')));
208 + if (!empty($confirmationId)) {
209 + $handler = new BookingConfirmationPageHandler();
210 + $handler->handle([
211 + 'confirmation_id' => sanitize_text_field((string) $confirmationId),
212 + ]);
153 213 }
154 -
155 - // Plain permalink fallback: handle ?yatra_login_page= or login requests
156 - if (!$handled) {
157 - $loginPage = get_query_var('yatra_login_page') ?: ($_GET['yatra_login_page'] ?? '');
158 - if (!empty($loginPage)) {
159 - try {
160 - // Security: Validate login page request
161 - if (self::validateLoginRequest()) {
162 - $handler = new \Yatra\Core\Handlers\LoginPageHandler();
163 - $handled = $handler->handle([]);
164 - } else {
165 - // Log security violation
166 - if (defined('WP_DEBUG') && WP_DEBUG) {
167 - error_log('Yatra TemplateLoader: Invalid login request detected from IP: ' . self::getClientIp());
168 - }
169 - }
170 - } catch (Exception $e) {
171 - // Log error for debugging
172 - if (defined('WP_DEBUG') && WP_DEBUG) {
173 - error_log('Yatra TemplateLoader Login Handler Error: ' . $e->getMessage());
174 - }
175 -
176 - // Fallback to default behavior
177 - $handled = false;
178 - }
179 - }
180 - }
181 214 }
182 215
183 - // If still not handled, continue normally
184 - if (!$handled) {
185 - return;
186 - }
187 -
188 - // If router handled it, exit to prevent further processing
189 - exit;
216 + // No exit. The selected Yatra template (if any) is in PageContext;
217 + // filterTemplateInclude() will return it from the template_include filter.
190 218 }
191 219
192 220 /**
193 221 * True when this request should be routed by Yatra even if WP marked it 404 (paged home quirk).
@@ -215,11 +243,11 @@
215 243 }
216 244
217 245 foreach (
218 246 [
219 - SettingsService::getString('destination_base', 'destination'),
220 - SettingsService::getString('activity_base', 'activity'),
221 - SettingsService::getString('trip_category_base', 'trip-category'),
247 + SettingsService::getDestinationBase(),
248 + SettingsService::getActivityBase(),
249 + SettingsService::getTripCategoryBase(),
222 250 ] as $base
223 251 ) {
224 252 $bk = preg_replace('/[^a-zA-Z0-9_-]/', '', $base) ?: '';
225 253 if ($bk === '' || $bk === $tripKey) {
@@ -229,9 +257,9 @@
229 257 return true;
230 258 }
231 259 }
232 260
233 - foreach (['yatra_trip', 'yatra_trip_slug', 'yatra_destination_slug', 'yatra_activity_slug', 'yatra_category_slug', 'yatra_booking_confirmation'] as $key) {
261 + foreach (['yatra_trip', 'yatra_trip_slug', 'yatra_destination_slug', 'yatra_activity_slug', 'yatra_category_slug', 'yatra_booking_confirmation', 'yatra_verify_email'] as $key) {
234 262 if (!isset($_GET[$key])) {
235 263 continue;
236 264 }
237 265 $v = wp_unslash($_GET[$key]);
@@ -239,8 +267,18 @@
239 267 return true;
240 268 }
241 269 }
242 270
271 + if ((string) get_query_var('yatra_verify_email') !== '') {
272 + return true;
273 + }
274 +
275 + $verifyPath = trim(UrlParser::getCleanRequestPath(), '/');
276 + $verifyPrefix = SettingsService::getPermalinkBases()['email_verification_prefix'];
277 + if ($verifyPath !== '' && strpos($verifyPath, $verifyPrefix . '/') === 0) {
278 + return true;
279 + }
280 +
243 281 return (bool) apply_filters('yatra_clear_404_for_routing', false);
244 282 }
245 283
246 284 /**
@@ -247,24 +285,20 @@
247 285 * Add rewrite rules for trip permalinks and listing pages
248 286 */
249 287 public static function addTripRewriteRules(): void
250 288 {
251 - // Use centralized SettingsService for all settings
252 - $trip_base = SettingsService::getTripBase();
253 - $booking_base = SettingsService::getBookingBase();
254 - $account_base = SettingsService::getAccountBase();
255 - $account_base = preg_replace('/[^a-z0-9_-]/i', '', $account_base) ?: 'account';
289 + $bases = SettingsService::getPermalinkBases();
290 + $trip_base = $bases['trip_base'];
291 + $booking_base = $bases['booking_base'];
292 + $account_base = $bases['account_base'];
293 + $destination_base = $bases['destination_base'];
294 + $activity_base = $bases['activity_base'];
295 + $trip_category_base = $bases['trip_category_base'];
296 + $bookingConfirmSeg = $bases['booking_flow_confirmation_segment'];
297 + $legacyBookingConfirmation = $bases['legacy_booking_confirmation_prefix'];
298 + $remainingCheckout = $bases['remaining_checkout_prefix'];
299 + $emailVerifyPrefix = $bases['email_verification_prefix'];
256 300
257 - // Get other bases with sanitization
258 - $destination_base = SettingsService::getString('destination_base', 'destination');
259 - $destination_base = preg_replace('/[^a-z0-9_-]/i', '', $destination_base) ?: 'destination';
260 -
261 - $activity_base = SettingsService::getString('activity_base', 'activity');
262 - $activity_base = preg_replace('/[^a-z0-9_-]/i', '', $activity_base) ?: 'activity';
263 -
264 - $trip_category_base = SettingsService::getString('trip_category_base', 'trip-category');
265 - $trip_category_base = preg_replace('/[^a-z0-9_-]/i', '', $trip_category_base) ?: 'trip-category';
266 -
267 301 // Add query vars first (must be registered before rewrite rules)
268 302 // Single-trip slug query var matches trip URL base (e.g. trip=, tours=)
269 303 add_rewrite_tag('%' . $trip_base . '%', '([^&]+)');
270 304 add_rewrite_tag('%yatra_booking_confirmation%', '([^&]+)');
@@ -269,9 +303,8 @@
269 303 add_rewrite_tag('%' . $trip_base . '%', '([^&]+)');
270 304 add_rewrite_tag('%yatra_booking_confirmation%', '([^&]+)');
271 305 add_rewrite_tag('%yatra_remaining_checkout%', '([^&]+)');
272 306 add_rewrite_tag('%yatra_verify_email%', '([^&]+)');
273 - add_rewrite_tag('%yatra_login_page%', '([^&]+)');
274 307 // Single taxonomy page tags
275 308 add_rewrite_tag('%yatra_destination_slug%', '([^&]+)');
276 309 add_rewrite_tag('%yatra_activity_slug%', '([^&]+)');
277 310 add_rewrite_tag('%yatra_category_slug%', '([^&]+)');
@@ -277,22 +310,15 @@
277 310 add_rewrite_tag('%yatra_category_slug%', '([^&]+)');
278 311 add_rewrite_tag('%yatra_page%', '([a-zA-Z0-9_-]+)');
279 312 add_rewrite_tag('%paged%', '([0-9]+)');
280 313
281 - // Add rewrite rule for email verification: /yatra-verify-email/{token}/
314 + // Add rewrite rule for email verification: /{email_verification_prefix}/{token}/
282 315 add_rewrite_rule(
283 - '^yatra-verify-email/([a-zA-Z0-9_-]+)/?$',
316 + '^' . $emailVerifyPrefix . '/([a-zA-Z0-9_-]+)/?$',
284 317 'index.php?yatra_verify_email=$matches[1]',
285 318 'top'
286 319 );
287 320
288 - // Add rewrite rule for login page: /login
289 - add_rewrite_rule(
290 - '^login/?$',
291 - 'index.php?yatra_login_page=1',
292 - 'top'
293 - );
294 -
295 321 // Trip listing pagination: {trip_base}/page/{n}/
296 322 add_rewrite_rule(
297 323 '^' . $trip_base . '/page/([0-9]+)/?$',
298 324 'index.php?yatra_page=' . $trip_base . '&paged=$matches[1]',
@@ -381,11 +407,11 @@
381 407 'index.php?yatra_page=' . $trip_category_base,
382 408 'top'
383 409 );
384 410
385 - // Pageless booking confirmation: /{booking_base}/confirmation/{reference}/ (before trip slug rule)
411 + // Pageless booking confirmation: /{booking_base}/{confirmation_segment}/{reference}/ (before trip slug rule)
386 412 add_rewrite_rule(
387 - '^' . $booking_base . '/confirmation/([a-zA-Z0-9_-]+)/?$',
413 + '^' . $booking_base . '/' . $bookingConfirmSeg . '/([a-zA-Z0-9_-]+)/?$',
388 414 'index.php?yatra_booking_confirmation=$matches[1]',
389 415 'top'
390 416 );
391 417
@@ -402,25 +428,34 @@
402 428 'index.php?yatra_page=' . $booking_base,
403 429 'top'
404 430 );
405 431
406 - // Add rewrite rule for booking confirmation page slug: /booking-confirmation/{reference}
432 + // Legacy booking confirmation: /{legacy_booking_confirmation_prefix}/{reference}
407 433 add_rewrite_rule(
408 - '^booking-confirmation/([a-zA-Z0-9_-]+)/?$',
434 + '^' . $legacyBookingConfirmation . '/([a-zA-Z0-9_-]+)/?$',
409 435 'index.php?yatra_booking_confirmation=$matches[1]',
410 436 'top'
411 437 );
412 438
413 - // Add rewrite rule for remaining checkout: /remaining-checkout/{token}/
439 + // Remaining checkout: /{remaining_checkout_prefix}/{token}/
414 440 add_rewrite_rule(
415 - '^remaining-checkout/([a-zA-Z0-9_-]+)/?$',
441 + '^' . $remainingCheckout . '/([a-zA-Z0-9_-]+)/?$',
416 442 'index.php?yatra_remaining_checkout=$matches[1]',
417 443 'top'
418 444 );
445 +
446 + /**
447 + * Fires after Yatra registers its core rewrite tags/rules.
448 + *
449 + * Use {@see \Yatra\Services\SettingsService::getPermalinkBases()} for the same slugs/helpers use.
450 + *
451 + * @param array<string, string> $bases
452 + */
453 + do_action('yatra_register_rewrite_rules', $bases);
419 454
420 455 // Check if rewrite rules need flushing (only flush once after plugin update/activation)
421 456 $rewrite_version = get_option('yatra_rewrite_rules_version', '0');
422 - $current_version = '1.0.8'; // Increment this when rewrite rules change
457 + $current_version = '1.0.9'; // Increment this when rewrite rules change
423 458 if ($rewrite_version !== $current_version) {
424 459 flush_rewrite_rules(false);
425 460 update_option('yatra_rewrite_rules_version', $current_version);
426 461 }
@@ -435,9 +470,8 @@
435 470 'yatra_trip', // legacy plain/pretty query var for trip slug
436 471 'yatra_booking_confirmation',
437 472 'yatra_remaining_checkout',
438 473 'yatra_verify_email',
439 - 'yatra_login_page',
440 474 'yatra_account_page',
441 475 'yatra_destination_slug',
442 476 'yatra_activity_slug',
443 477 'yatra_category_slug',
@@ -445,52 +479,15 @@
445 479 'paged',
446 480 ];
447 481
448 482 // Add dynamic base names for plain permalink support
449 - $trip_base = SettingsService::getTripBase();
450 - $destination_base = SettingsService::getString('destination_base', 'destination');
451 - $activity_base = SettingsService::getString('activity_base', 'activity');
452 - $category_base = SettingsService::getString('trip_category_base', 'trip-category');
483 + $pb = SettingsService::getPermalinkBases();
484 + $yatra_vars[] = $pb['trip_base'];
485 + $yatra_vars[] = $pb['destination_base'];
486 + $yatra_vars[] = $pb['activity_base'];
487 + $yatra_vars[] = $pb['trip_category_base'];
453 488
454 - $yatra_vars[] = $trip_base;
455 - $yatra_vars[] = $destination_base;
456 - $yatra_vars[] = $activity_base;
457 - $yatra_vars[] = $category_base;
458 -
459 489 return array_merge($vars, $yatra_vars);
460 - }
461 -
462 - /**
463 - * Validate login page request for security
464 - */
465 - private static function validateLoginRequest(): bool
466 - {
467 - // Check request method
468 - if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
469 - return false;
470 - }
471 -
472 - // Check for suspicious parameters
473 - $suspicious_params = ['exec', 'system', 'eval', 'passthru', 'shell_exec'];
474 - foreach ($suspicious_params as $param) {
475 - if (isset($_GET[$param]) || isset($_POST[$param])) {
476 - return false;
477 - }
478 - }
479 -
480 - // Rate limiting check
481 - $ip = self::getClientIp();
482 - $transient_key = 'yatra_login_request_limit_' . md5($ip);
483 - $requests = get_transient($transient_key) ?: 0;
484 -
485 - // Allow 50 requests per 10 minutes
486 - if ($requests >= 50) {
487 - return false;
488 - }
489 -
490 - set_transient($transient_key, $requests + 1, 10 * MINUTE_IN_SECONDS);
491 -
492 - return true;
493 490 }
494 491
495 492 /**
496 493 * Get client IP address