PluginProbe
Easy Hotel – Powerful Hotel Booking / trunk
Easy Hotel – Powerful Hotel Booking vtrunk
2.0.8 2.0.7 2.0.6 2.0.5 2.0.4 2.0.3 2.0.2 2.0.1 2.0.0 1.9.9 1.9.8 1.9.7 1.9.6 1.9.5 1.9.4 1.9.3 1.9.2 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 All 110 releases
easy-hotel / admin / includes / classes / class.search.php

class.search.php in Easy Hotel – Powerful Hotel Booking trunk, at admin/includes/classes/class.search.php

614 lines 27.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3 class ESHB_Search {
4
5 private static $_instance = null;
6
7 public static function instance() {
8
9 if ( is_null( self::$_instance ) ) {
10 self::$_instance = new self();
11 }
12 return self::$_instance;
13
14 }
15
16 public function __construct() {
17
18 add_action( 'plugins_loaded', [ $this, 'init' ] );
19 add_action( "wp_ajax_nopriv_eshb_get_disabled_dates_by_accomodation_id", array ( $this, 'eshb_get_disabled_dates_by_accomodation_id' ) );
20 add_action( "wp_ajax_eshb_get_disabled_dates_by_accomodation_id", array ( $this, 'eshb_get_disabled_dates_by_accomodation_id' ) );
21
22 }
23
24 public function init() {
25 // Add Plugin actions
26 add_filter('theme_page_templates', [$this, 'eshb_register_page_template']);
27 add_filter('template_include', [$this, 'eshb_load_template']);
28 }
29
30 public function eshb_search_page_by_title( $page_title, $post_type = 'page' ) {
31 // Set up the arguments for WP_Query
32 $args = array(
33 'post_type' => $post_type,
34 'post_status' => 'publish', // Only fetch published pages
35 'title' => $page_title,
36 'posts_per_page' => 1, // Limit to one result
37 );
38
39 // Run the query
40 $query = new WP_Query( $args );
41
42 // Check if any post is found
43 if ( $query->have_posts() ) {
44 return $query->posts[0]; // Return the first found page
45 }
46
47 // Return false if no page is found
48 return false;
49 }
50
51 public function eshb_get_disabled_dates_by_accomodation_id($accomodation_id, $start_date = '', $end_date = '') {
52
53 // Verify nonce for security
54 if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), ESHB_Helper::generate_secure_nonce_action('eshb_global_nonce_action'))) {
55 wp_send_json_error(['message' => 'Invalid nonce']);
56 die();
57 }
58
59 if (isset($_POST['accomodation_id'])) {
60 $accomodation_id = sanitize_text_field(wp_unslash($_POST['accomodation_id']));
61 }
62
63 // The calendar posts the currently selected range; without reading it here the
64 // session (season) rules below were always evaluated against empty dates.
65 if (isset($_POST['start_date'])) {
66 $start_date = sanitize_text_field(wp_unslash($_POST['start_date']));
67 }
68
69 if (isset($_POST['end_date'])) {
70 $end_date = sanitize_text_field(wp_unslash($_POST['end_date']));
71 }
72
73 $eshb_settings = get_option('eshb_settings', []);
74 $booked_dates = [];
75 $total_room_bookings_per_date = []; // Track room bookings per date
76 $total_booked_slots_hours = 0;
77 $total_slots_hours = false;
78
79 // Get total rooms allowed for this accommodation
80 $accomodation_metas = get_post_meta($accomodation_id, 'eshb_accomodation_metaboxes', true);
81
82 $is_single_day_plugin_active = get_option('eshb_single_day_activated');
83 $pricing_periodicity = false;
84 if ($is_single_day_plugin_active) {
85 $pricing_periodicity = !empty($accomodation_metas['pricing_periodicity']) ? $accomodation_metas['pricing_periodicity'] : false;
86 $eshb_single_day_settings = get_option( 'eshb_single_day_settings', []);
87 $slots_start_time = $eshb_single_day_settings['start_time'];
88 $slots_end_time = $eshb_single_day_settings['end_time'];
89 $total_slots_hours = ESHB_Helper::eshb_calculate_time_diff('', '', $slots_start_time, $slots_end_time);
90 }
91
92 $holidays = isset($eshb_settings['holidays']) ? $eshb_settings['holidays'] : [];
93 $finally_holidays = [];
94
95 if ( ! empty( $holidays ) ) {
96 foreach ( $holidays as $holiday ) {
97 $accommodation_ids = $holiday['accomodation-ids'] ?? [];
98 $holiday_date = $holiday['holiday-date'] ?? null;
99
100 // Check if holiday is applicable for all or specific accommodation
101 $is_applicable = empty($accommodation_ids) || (is_array($accommodation_ids) && in_array($accomodation_id, $accommodation_ids));
102
103 if ( $is_applicable && $holiday_date ) {
104 if ( is_array($holiday_date) && isset($holiday_date['from'], $holiday_date['to']) ) {
105 $start = DateTime::createFromFormat('Y-m-d', $holiday_date['from']);
106 $end = DateTime::createFromFormat('Y-m-d', $holiday_date['to']);
107 if ( $start && $end ) {
108 $end->modify('+1 day'); // Include end date
109 $interval = new DateInterval('P1D');
110 $dateRange = new DatePeriod($start, $interval, $end);
111
112 foreach ( $dateRange as $date ) {
113 $finally_holidays[] = $date->format('Y-m-d');
114 }
115 }
116 } else {
117 $finally_holidays[] = $holiday_date;
118 }
119 }
120 }
121 }
122
123
124
125 $allowed_total_rooms = isset($accomodation_metas['total_rooms']) ? intval($accomodation_metas['total_rooms']) : 0;
126 $total_rooms = isset($accomodation_metas['total_rooms']) ? intval($accomodation_metas['total_rooms']) : 1;
127 $available_rooms = isset($accomodation_metas['available_rooms']) ? intval($accomodation_metas['available_rooms']) : $total_rooms;
128
129 $min_max_nights_settings = [
130 'required_min_nights' => 1,
131 'required_max_nights' => 999,
132 ];
133
134 $min_max_nights_settings = apply_filters('eshb_min_max_nights_settings_before_search', $min_max_nights_settings, $accomodation_id, $accomodation_metas);
135
136 // Get min stay night by session
137 $session_min_nights_rules = [];
138 if(class_exists('ESHB_ADVANCED_PRICING')){
139
140 $session_min_nights_rules = ESHB_Helper::get_eshb_session_min_nights_rules($accomodation_id);
141
142 $min_stay_night_by_session = ESHB_Helper::get_eshb_min_stay_night_by_session($accomodation_id, $start_date, $end_date);
143 if($min_stay_night_by_session > 0){
144 // max(), not a plain override: booking validation enforces the session
145 // rule AND the global/accomodation rule, so the calendar has to show
146 // whichever is stricter or it would allow a range the server rejects.
147 $min_max_nights_settings['required_min_nights'] = max(
148 (int) $min_max_nights_settings['required_min_nights'],
149 (int) $min_stay_night_by_session
150 );
151 }
152 }
153
154 // Find all bookings for this accommodation
155 $bookings_args = [
156 'post_type' => 'eshb_booking',
157 'posts_per_page' => -1,
158 'post_status' => ['publish', 'deposit-payment', 'pending', 'processing', 'on-hold', 'completed'],
159 'fields' => 'ids',
160 ];
161
162 $bookings = new WP_Query($bookings_args);
163 $checked_in_out_dates = [];
164
165 if ($bookings->have_posts()) {
166 while ($bookings->have_posts()) {
167 $bookings->the_post();
168 $meta_values = get_post_meta(get_the_ID(), 'eshb_booking_metaboxes', true);
169 $booking_status = isset($meta_values['booking_status']) ? $meta_values['booking_status'] : '';
170
171 $completed_booking_status_maps = array(
172 'pending',
173 'deposit-payment',
174 'processing',
175 'on-hold',
176 'completed'
177 );
178
179 // Ensure required keys exist
180 if (is_array($meta_values) && in_array($booking_status, $completed_booking_status_maps) && isset($meta_values['booking_accomodation_id'], $meta_values['booking_start_date'], $meta_values['booking_end_date'])) {
181
182 $booking_accomodation_id = intval($meta_values['booking_accomodation_id']);
183 $booking_start_date = $meta_values['booking_start_date'];
184 $booking_end_date = $meta_values['booking_end_date'];
185 $accommodation_metaboxes = get_post_meta($booking_accomodation_id, 'eshb_accomodation_metaboxes', true);
186 $total_rooms = $accommodation_metaboxes['total_rooms'] ?? 1;
187
188 $booked_accomodation_ids = [];
189 $accomodation_id = ESHB_Helper::get_main_post_id_for_translated($accomodation_id);
190
191 $booking_accomodation_id = ESHB_Helper::get_main_post_id_for_translated($booking_accomodation_id);
192
193 if ($accomodation_id == $booking_accomodation_id) {
194
195 // Convert dates to DateTime objects
196 $start_date = new DateTime($booking_start_date);
197 $end_date = new DateTime($booking_end_date);
198 $booked_id = get_the_ID();
199 $booking_metas = get_post_meta($booked_id, 'eshb_booking_metaboxes', true);
200 $booked_room_quantity = isset($booking_metas['room_quantity']) ? intval($booking_metas['room_quantity']) : 1;
201 $booking_start_time = isset($booking_metas['booking_start_time']) ? intval($booking_metas['booking_start_time']) : '';
202 $booking_end_time = isset($booking_metas['booking_end_time']) ? intval($booking_metas['booking_end_time']) : '';
203
204 $checked_in_out_dates['checked_in'][] = $booking_start_date;
205 $checked_in_out_dates['checked_out'][] = $booking_end_date;
206
207 // NEW: Clone end date and subtract 1 day to exclude checkout day
208 if($booking_start_date !== $booking_end_date) {
209 $actual_end_date = (clone $end_date)->modify('-1 day');
210 }else{
211 $actual_end_date = (clone $end_date)->modify('+1 day');
212 }
213
214
215 $period = new DatePeriod($start_date, new DateInterval('P1D'), $actual_end_date->modify('+1 day'));
216
217 foreach ($period as $date) {
218 $formatted_date = $date->format('Y-m-d');
219
220 if (!isset($total_room_bookings_per_date[$formatted_date])) {
221 $total_room_bookings_per_date[$formatted_date] = 0;
222 }
223
224 $total_room_bookings_per_date[$formatted_date] += $booked_room_quantity;
225 }
226
227 if($booking_start_date === $booking_end_date) {
228 array_pop($total_room_bookings_per_date);
229 }
230
231 }
232 }
233 }
234 }
235
236
237 $total_booked_rooms_in_date_ranges = 0;
238 $dates = [];
239
240 // Determine which dates should be disabled (fully booked)
241 foreach ($total_room_bookings_per_date as $date => $total_booked_rooms) {
242
243 // allow external plugins to modify available slots
244 $available_slots = apply_filters(
245 'eshb_available_slots_in_booked_dates_loop',
246 false,
247 $date,
248 $total_booked_rooms,
249 $accomodation_id
250 );
251
252
253 if($available_slots) {
254 $total_booked_rooms = 0;
255 }
256
257 if ($allowed_total_rooms <= $total_booked_rooms) {
258 $date = new DateTime($date);
259 $booked_dates[] = $date->format('Y, m, d');
260 array_push($dates, array('dates' => $date, 'total_booked_rooms_in_date_ranges' => $total_booked_rooms));
261 }
262
263 }
264
265
266 // Apply filter hook to allow external modifications
267 $booked_dates = apply_filters('eshb_modify_booked_dates', $booked_dates, $accomodation_id);
268
269 $checked_in_out_dates = apply_filters('eshb_modify_checked_in_out_dates', $checked_in_out_dates, $accomodation_id);
270
271 $all_dates = [
272 'checked_in_out_dates' => $checked_in_out_dates,
273 'booked_dates' => $booked_dates,
274 'holiday_dates' => $finally_holidays,
275 'allowed_check_in_day' => '',
276 'single_day' => false,
277 'min_nights' => $min_max_nights_settings['required_min_nights'],
278 'max_nights' => $min_max_nights_settings['required_max_nights'],
279 // Season rules the calendar evaluates itself, so a stay that starts inside a
280 // season is validated on the very first pick instead of one step late.
281 'session_min_nights_rules' => $session_min_nights_rules,
282 'total_room_bookings_per_date' => $total_room_bookings_per_date,
283 ];
284
285 $all_dates = apply_filters('eshb_get_disabled_dates_in_search', $all_dates, $accomodation_id, $accomodation_metas);
286
287
288 if(isset($_POST['action']) && $_POST['action'] == 'eshb_get_disabled_dates_by_accomodation_id'){
289 wp_send_json_success($all_dates);
290 wp_die();
291 }else{
292 return $all_dates;
293 }
294
295 }
296
297 public function eshb_generate_dates_from_date_ranges($start_date, $end_date){
298 // $start_date = '2025, 05, 16'; // Format: YYYY, MM, DD
299 // $end_date = '2025, 05, 26';
300
301 $start = DateTime::createFromFormat('Y, m, d', $start_date);
302 $end = DateTime::createFromFormat('Y, m, d', $end_date);
303 $end->modify('+1 day'); // Include the end date in the range
304
305 $interval = new DateInterval('P1D'); // 1-day interval
306 $daterange = new DatePeriod($start, $interval, $end);
307
308 $dates_array = [];
309
310 foreach ($daterange as $date) {
311 $dates_array[] = $date->format('Y, m, d');
312 }
313 return $dates_array;
314 }
315
316 /**
317 * Booking Blocked Dates ("holidays") from the settings, normalised once.
318 *
319 * The calendar expands these per accommodation on every request; the search
320 * loops over every accommodation, so it reads the option once and keeps the
321 * rules as [ accomodation_ids, dates ] pairs instead of re-expanding the
322 * same ranges for each room.
323 *
324 * An empty accomodation_ids list means the rule closes every accommodation,
325 * which is the same reading used in eshb_get_disabled_dates_by_accomodation_id().
326 */
327 private function eshb_get_blocked_date_rules() {
328
329 $eshb_settings = get_option('eshb_settings', []);
330 $holidays = isset($eshb_settings['holidays']) ? $eshb_settings['holidays'] : [];
331 $rules = [];
332
333 if (empty($holidays) || !is_array($holidays)) {
334 return $rules;
335 }
336
337 foreach ($holidays as $holiday) {
338 $accommodation_ids = $holiday['accomodation-ids'] ?? [];
339 $holiday_date = $holiday['holiday-date'] ?? null;
340
341 if (empty($holiday_date)) {
342 continue;
343 }
344
345 $dates = [];
346
347 if (is_array($holiday_date) && isset($holiday_date['from'], $holiday_date['to'])) {
348 $start = DateTime::createFromFormat('Y-m-d', $holiday_date['from']);
349 $end = DateTime::createFromFormat('Y-m-d', $holiday_date['to']);
350
351 if ($start && $end) {
352 $end->modify('+1 day'); // Include end date
353 $dateRange = new DatePeriod($start, new DateInterval('P1D'), $end);
354
355 foreach ($dateRange as $date) {
356 $dates[] = $date->format('Y-m-d');
357 }
358 }
359 } else {
360 $dates[] = $holiday_date;
361 }
362
363 if (empty($dates)) {
364 continue;
365 }
366
367 $rules[] = [
368 'accomodation_ids' => is_array($accommodation_ids) ? $accommodation_ids : [],
369 'dates' => $dates,
370 ];
371 }
372
373 return $rules;
374 }
375
376 /**
377 * Every date of a stay, checkout day included.
378 *
379 * Inclusive on purpose: get_holiday_dates_in_date_ranges() — the check that
380 * rejects the booking on submit — builds its range the same way, so search
381 * hides exactly what booking would refuse.
382 */
383 private function eshb_get_dates_in_range($start_date, $end_date) {
384
385 $dates = [];
386
387 if (empty($start_date) || empty($end_date) || !strtotime($start_date) || !strtotime($end_date)) {
388 return $dates;
389 }
390
391 $current_date = new DateTime($start_date);
392 $end_date_obj = new DateTime($end_date);
393
394 while ($current_date <= $end_date_obj) {
395 $dates[] = $current_date->format('Y-m-d');
396 $current_date->modify('+1 day');
397 }
398
399 return $dates;
400 }
401
402 /**
403 * Does any Booking Blocked Date rule close this accommodation inside the stay?
404 */
405 private function eshb_is_blocked_in_date_range($accomodation_id, $range_dates, $rules) {
406
407 if (empty($range_dates)) {
408 return false;
409 }
410
411 foreach ($rules as $rule) {
412
413 // Empty list = the rule applies to all accommodations.
414 if (!empty($rule['accomodation_ids']) && !in_array($accomodation_id, $rule['accomodation_ids'])) {
415 continue;
416 }
417
418 if (array_intersect($range_dates, $rule['dates'])) {
419 return true;
420 }
421 }
422
423 return false;
424 }
425
426 public function eshb_get_available_accomodation_ids($start_date, $end_date, $adult_quantity = 0, $children_quantity = 0, $rooms_quantity = 0) {
427 $available_accomodation_ids = [];
428
429 if ($start_date && $end_date) {
430
431 // Step 1: Get all accommodation IDs
432 $accomodations_args = array(
433 'post_type' => 'eshb_accomodation',
434 'posts_per_page' => -1,
435 'fields' => 'ids',
436 );
437
438 // Narrows what the search may offer at all — a tax_query here keeps a
439 // whole category (packages, day trips…) out of the results. Filtered
440 // before the loops below so excluded rooms cost no booking lookups.
441 $accomodations_args = apply_filters('eshb_search_accomodations_query_args', $accomodations_args, $start_date, $end_date);
442
443 $accomodations = new WP_Query($accomodations_args);
444
445 if ($accomodations->have_posts()) {
446 $accomodation_ids = $accomodations->posts;
447
448 // Step 2: Get all bookings with overlapping dates
449 $bookings_args = array(
450 'post_type' => 'eshb_booking',
451 'posts_per_page' => -1,
452 'post_status' => ['publish', 'deposit-payment', 'pending', 'processing', 'on-hold', 'completed'],
453 'fields' => 'ids',
454 );
455
456 $bookings = new WP_Query($bookings_args);
457 $accommodation_bookings = array(); // [accommodation_id => total_booked_rooms]
458 $booked_accomodation_ids = array();
459
460 if ($bookings->have_posts()) {
461 while ($bookings->have_posts()) {
462 $bookings->the_post();
463
464 $meta_values = get_post_meta(get_the_ID(), 'eshb_booking_metaboxes', true);
465 if (!is_array($meta_values)) continue;
466
467 $booking_accomodation_id = intval($meta_values['booking_accomodation_id']);
468 $booking_start_date = $meta_values['booking_start_date'];
469 $booking_end_date = $meta_values['booking_end_date'];
470 $booking_room_quantity = isset($meta_values['room_quantity']) ? intval($meta_values['room_quantity']) : 1;
471 $booking_status = isset($meta_values['booking_status']) ? $meta_values['booking_status'] : '';
472 $valid_statuses = array('deposit-payment', 'pending', 'processing', 'on-hold', 'completed');
473
474 // Only count if booking status is valid and dates overlap
475 if (
476 in_array($booking_status, $valid_statuses) &&
477 $start_date <= $booking_end_date &&
478 $end_date >= $booking_start_date
479 ) {
480 if (!isset($accommodation_bookings[$booking_accomodation_id])) {
481 $accommodation_bookings[$booking_accomodation_id] = 0;
482 }
483
484 $accommodation_bookings[$booking_accomodation_id] += $booking_room_quantity;
485 }
486 }
487 wp_reset_postdata();
488
489 // Step 3: Mark accommodations as fully booked
490 foreach ($accommodation_bookings as $accommodation_id => $booked_rooms) {
491 $accomodation_metaboxes = get_post_meta($accommodation_id, 'eshb_accomodation_metaboxes', true);
492 $total_rooms = !empty($accomodation_metaboxes['total_rooms']) ? intval($accomodation_metaboxes['total_rooms']) : 1;
493
494 if ($booked_rooms >= $total_rooms) {
495 $booked_accomodation_ids[] = $accommodation_id;
496 }
497 }
498
499 // Step 4: Exclude fully booked accommodations
500 $available_accomodation_ids = array_diff($accomodation_ids, $booked_accomodation_ids);
501 } else {
502 // No bookings, all accommodations are available
503 $available_accomodation_ids = $accomodation_ids;
504 }
505
506 // Step 5: Filter by requested capacity
507 if (!empty($available_accomodation_ids)) {
508 foreach ($available_accomodation_ids as $key => $available_accomodation_id) {
509 $accomodation_metaboxes = get_post_meta($available_accomodation_id, 'eshb_accomodation_metaboxes', true);
510
511 $total_capacity = !empty($accomodation_metaboxes['total_capacity']) ? intval($accomodation_metaboxes['total_capacity']) : 1;
512 $adult_capacity = !empty($accomodation_metaboxes['adult_capacity']) ? intval($accomodation_metaboxes['adult_capacity']) : 0;
513 $children_capacity = !empty($accomodation_metaboxes['children_capacity']) ? intval($accomodation_metaboxes['children_capacity']) : 0;
514 $total_rooms = !empty($accomodation_metaboxes['total_rooms']) ? intval($accomodation_metaboxes['total_rooms']) : 1;
515 if(empty($adult_capacity)) {
516 $adult_capacity = $total_capacity;
517 }
518 if(empty($children_capacity)) {
519 $children_capacity = $total_capacity;
520 }
521
522 if (
523 $adult_quantity > $adult_capacity ||
524 $children_quantity > $children_capacity ||
525 $rooms_quantity > $total_rooms
526 ) {
527 unset($available_accomodation_ids[$key]);
528 }
529 }
530 }
531
532 // Step 6: Drop accommodations closed by a Booking Blocked Date rule.
533 // Bookings and capacity alone are not enough — the calendar greys these
534 // dates out and the booking check refuses them, so listing the room as
535 // available here advertises a stay that can never be completed.
536 if (!empty($available_accomodation_ids)) {
537
538 $blocked_rules = $this->eshb_get_blocked_date_rules();
539
540 if (!empty($blocked_rules)) {
541
542 $range_dates = $this->eshb_get_dates_in_range($start_date, $end_date);
543
544 foreach ($available_accomodation_ids as $key => $available_accomodation_id) {
545 if ($this->eshb_is_blocked_in_date_range($available_accomodation_id, $range_dates, $blocked_rules)) {
546 unset($available_accomodation_ids[$key]);
547 }
548 }
549 }
550 }
551 }
552 }
553
554 // The last word on what the search offers, once bookings, capacity and
555 // blocked dates have had theirs. For rules that cannot be written as query
556 // args — use eshb_search_accomodations_query_args when they can, it is cheaper.
557 return apply_filters('eshb_available_accomodation_ids', $available_accomodation_ids, $start_date, $end_date, $adult_quantity, $children_quantity, $rooms_quantity);
558 }
559
560 public function eshb_register_page_template($templates) {
561 $templates['easy-hotel-search.php'] = 'Easy Hotel Search';
562 $templates['easy-hotel-search-result.php'] = 'Easy Hotel Search Result';
563 return $templates;
564 }
565
566 public function eshb_load_template($template) {
567
568 global $post;
569
570 if (is_page() && $post->post_type == 'page') {
571 $template_meta = get_post_meta($post->ID, '_wp_page_template', true);
572
573
574 if ($template_meta == 'easy-hotel-search.php') {
575
576 $plugin_template = ESHB_PL_PATH . '/public/templates/easy-hotel-search.php';
577 $theme_template = get_stylesheet_directory() . '/easy-hotel-booking/easy-hotel-search.php';
578 $child_theme_template = get_template_directory() . '/easy-hotel-booking/easy-hotel-search.php';
579
580 if (file_exists($theme_template)) {
581 $template = $theme_template;
582 } elseif (file_exists($child_theme_template)) {
583 $template = $child_theme_template;
584 } else {
585 $template = $plugin_template;
586 }
587
588 }
589
590 if ($template_meta == 'easy-hotel-search-result.php') {
591
592 $plugin_template = ESHB_PL_PATH . '/public/templates/easy-hotel-search-result.php';
593 $theme_template = get_stylesheet_directory() . '/easy-hotel-booking/easy-hotel-search-result.php';
594 $child_theme_template = get_template_directory() . '/easy-hotel-booking/easy-hotel-search-result.php';
595
596 if (file_exists($theme_template)) {
597 $template = $theme_template;
598 } elseif (file_exists($child_theme_template)) {
599 $template = $child_theme_template;
600 } else {
601 $template = $plugin_template;
602 }
603
604 }
605
606
607 }
608 return $template;
609 }
610
611 }
612
613
614 ESHB_Search::instance();