PluginProbe
Booking Calendar / 11.8.3
Booking Calendar v11.8.3
11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 10.11.2 All 203 releases
booking / includes / publish / wpbc-create-pages.php

wpbc-create-pages.php in Booking Calendar 11.8.3, at includes/publish/wpbc-create-pages.php

1,394 lines 50.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @version 1.0
4 * @package Booking Calendar
5 * @subpackage Create pages Functions
6 * @category Functions
7 *
8 * @author wpdevelop
9 * @link https://wpbookingcalendar.com/
10 * @email info@wpbookingcalendar.com
11 *
12 * @modified 2023-05-10
13 * @file ../includes/publish/wpbc-create-pages.php
14 */
15
16 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
17
18
19 /**
20 * Create page for Booking Calendar
21 *
22 * @param array $page_params = array(
23 'post_content' => '[bookingedit]',
24 'post_name' => 'wpbc-booking-edit',
25 'post_title' => esc_html__('Booking edit','booking')
26 )
27 *
28 * @return false|int - ID of the page.
29 */
30 function wpbc_create_page( $page_params = array() ){ // FixIn: 9.6.2.10.
31
32 /* Live demos must never create WordPress content through Booking Calendar. */
33 if ( wpbc_is_booking_form_publishing_restricted() ) {
34 return false;
35 }
36
37 global $wp_rewrite;
38 if ( is_null( $wp_rewrite ) ) { // FixIn: 9.7.1.1.
39 return false;
40 }
41
42 // Create post object
43 $defaults = array(
44 //'menu_order' => 0, // The order the post should be displayed in. Default 0. If new post is a page, it sets the order in which it should appear in the tabs.
45 //'pinged' => '', // Space or carriage return-separated list of URLs that have been pinged. Default empty.
46 //'post_author' => get_current_user_id(), // The user ID number of the author. The ID of the user who added the post. Default is the current user ID.
47 //'post_category' => array(), // Array of category IDs. Defaults to value of the 'default_category' option. post_category no longer exists, try wp_set_post_terms() for setting a post's categories
48 //'post_date' => [ Y-m-d H:i:s ] // The date of the post. Default is the current time. The time post was made.
49 //'post_date_gmt' => [ Y-m-d H:i:s ] // The time post was made, in GMT.
50 //'post_excerpt' => '' //The post excerpt. Default empty. For all your post excerpt needs.
51 //'post_parent' => 0, // Set this for the post it belongs to, if any. Default 0. Sets the parent of the new post.
52 //'post_password' => '', //The password to access the post. Default empty. password for post?
53 //'tags_input' => '', // Array of tag names, slugs, or IDs. Default empty. [ '<tag>, <tag>, <...>' ] //For tags.
54 //'to_ping' => '', // Space or carriage return-separated list of URLs to ping. Default empty. Space or carriage return-separated list of URLs to ping. Default empty.
55 //'tax_input' => '', // Default empty. [ array( 'taxonomy_name' => array( 'term', 'term2', 'term3' ) ) ] // support for custom taxonomies.
56 'ID' => 0, // The post ID. If equal to something other than 0, the post with that ID will be updated. Default 0.
57 'post_type' => 'page', // The post type. Default 'post'. [ 'post' | 'page' | 'link' | 'nav_menu_item' | 'custom_post_type' ] //You may want to insert a regular post, page, link, a menu item or some custom post type
58 'post_status' => 'publish', // [ 'draft' | 'publish' | 'pending'| 'future' | 'private' | 'custom_registered_status' ] // The post status. Default 'draft'. Set the status of the new post.
59 'comment_status' => 'closed', // [ 'closed' | 'open' ] // 'closed' means no comments.
60 'ping_status' => 'closed', // [ 'closed' | 'open' ] // 'closed' means pingbacks or trackbacks turned off
61 'post_content' => '[bookingedit]', // The post content. Default empty. The full text of the post.
62 'post_name' => 'wpbc-booking-edit', // sanitize_title( $post_title ), -- By default, converts accent characters to ASCII characters and further limits the output to alphanumeric characters, underscore (_) and dash (-) // The post name. Default is the sanitized post title when creating a new post. The name (slug) for your post
63 'post_title' => esc_html__('Booking edit','booking') // The post title. Default empty. The title of your post.
64 );
65
66
67 $my_post = wp_parse_args( $page_params, $defaults );
68
69
70 $post_id = wp_insert_post( $my_post, true ); // Insert the post into the database
71
72 if ( ( ! is_wp_error( $post_id ) ) && ( ! empty( $post_id ) ) ) {
73
74 // Success
75
76 // $post = get_post( $post_id );
77 // $post_url = get_permalink( $post_id );
78 wpbc_try_assign_full_width_template( $post_id,
79 array(
80 'excluded_title_parts' => array( 'wide image' ),
81 'excluded_classic_template_files' => array( 'elementor_header_footer' ),
82 'force_elementor_default_template' => true,
83 ) );
84
85 } else {
86 $post_id = false;
87 }
88
89 return $post_id;
90 }
91
92
93 /**
94 * Check whether a template label looks like a usable "Full Width" template.
95 *
96 * Excludes labels that contain unwanted fragments such as "wide image".
97 *
98 * @param string $template_label Human-readable template label.
99 * @param array $excluded_fragments Lowercase fragments to exclude.
100 *
101 * @return bool
102 */
103 function wpbc_is_full_width_template_candidate( $template_label, $excluded_fragments = array() ) {
104
105 $template_label = strtolower( wp_strip_all_tags( (string) $template_label ) );
106
107 if (
108 ( false === strpos( $template_label, 'full' ) ) ||
109 ( false === strpos( $template_label, 'width' ) )
110 ) {
111 return false;
112 }
113
114 foreach ( $excluded_fragments as $excluded_fragment ) {
115 $excluded_fragment = strtolower( (string) $excluded_fragment );
116
117 if ( '' === $excluded_fragment ) {
118 continue;
119 }
120
121 if ( false !== strpos( $template_label, $excluded_fragment ) ) {
122 return false;
123 }
124 }
125
126 return true;
127 }
128
129
130 /**
131 * Attempt to assign a "Full Width" template to a page.
132 *
133 * Supports both classic page templates and block theme templates.
134 * Can skip specific templates, such as Elementor "Elementor Full Width"
135 * or templates containing "Wide Image".
136 *
137 * @param int $post_id Page ID.
138 * @param array $args Optional arguments:
139 * - excluded_title_parts array Fragments excluded from template labels.
140 * - excluded_classic_template_files array Classic template file names to skip.
141 * - force_elementor_default_template bool Whether to force Elementor "Theme/Default".
142 *
143 * @return bool True if a template was assigned, or Elementor default was forced as fallback.
144 */
145 function wpbc_try_assign_full_width_template( $post_id, $args = array() ) {
146
147 if ( empty( $post_id ) || is_wp_error( $post_id ) ) {
148 return false;
149 }
150
151 $post = get_post( $post_id );
152
153 if ( ( ! $post ) || ( 'page' !== $post->post_type ) ) {
154 return false;
155 }
156
157 $defaults = array(
158 'excluded_title_parts' => array( 'wide image' ),
159 'excluded_classic_template_files' => array( 'elementor_header_footer' ),
160 'force_elementor_default_template' => false,
161 );
162
163 $args = wp_parse_args( $args, $defaults );
164
165 $excluded_title_parts = array_map( 'strtolower', (array) $args['excluded_title_parts'] );
166 $excluded_classic_template_files = array_map( 'strtolower', (array) $args['excluded_classic_template_files'] );
167
168 $is_elementor_full_width_skipped = false;
169
170 // -------------------------------------------------------------------------
171 // Classic themes: scan page templates.
172 // get_page_templates() returns template file names keyed by template header.
173 // -------------------------------------------------------------------------
174 if ( function_exists( 'get_page_templates' ) ) {
175
176 $classic_templates = get_page_templates( $post, 'page' );
177
178 foreach ( $classic_templates as $template_name => $template_file ) {
179
180 if ( ! wpbc_is_full_width_template_candidate( $template_name, $excluded_title_parts ) ) {
181 continue;
182 }
183
184 $template_file_lc = strtolower( (string) $template_file );
185
186 if ( in_array( $template_file_lc, $excluded_classic_template_files, true ) ) {
187
188 if ( 'elementor_header_footer' === $template_file_lc ) {
189 $is_elementor_full_width_skipped = true;
190 }
191
192 continue;
193 }
194
195 update_post_meta( $post_id, '_wp_page_template', $template_file );
196
197 return true;
198 }
199 }
200
201 // -------------------------------------------------------------------------
202 // Block themes: scan block templates for pages.
203 // -------------------------------------------------------------------------
204 if ( function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() && function_exists( 'get_block_templates' ) ) {
205
206 $theme_slug = get_stylesheet();
207 $templates = get_block_templates(
208 array(
209 'post_type' => 'page',
210 ),
211 'wp_template'
212 );
213
214 foreach ( $templates as $template ) {
215
216 if ( empty( $template->title ) || empty( $template->slug ) ) {
217 continue;
218 }
219
220 if ( $theme_slug !== $template->theme ) {
221 continue;
222 }
223
224 if ( ! wpbc_is_full_width_template_candidate( $template->title, $excluded_title_parts ) ) {
225 continue;
226 }
227
228 wp_update_post(
229 array(
230 'ID' => $post_id,
231 'page_template' => $template->slug,
232 )
233 );
234
235 return true;
236 }
237 }
238
239 /*
240 * If the only match we found was Elementor Full Width, optionally force
241 * Elementor's default page template instead.
242 */
243 if ( $args['force_elementor_default_template'] && $is_elementor_full_width_skipped ) {
244 return wpbc_set_elementor_default_page_template( $post_id );
245 }
246
247 return false;
248 }
249
250
251 /**
252 * Set Elementor page layout to its default "Theme" template.
253 *
254 * This should be treated as a fallback for Elementor-managed pages.
255 *
256 * @param int $post_id Page ID.
257 *
258 * @return bool
259 */
260 function wpbc_set_elementor_default_page_template( $post_id ) {
261
262 if ( empty( $post_id ) || is_wp_error( $post_id ) ) {
263 return false;
264 }
265
266 // Make sure WordPress itself does not have a forced classic template.
267 delete_post_meta( $post_id, '_wp_page_template' );
268
269 // If Elementor is not active, nothing else to do.
270 if ( ( ! defined( 'ELEMENTOR_VERSION' ) ) && ( ! did_action( 'elementor/loaded' ) ) ) {
271 return true;
272 }
273
274 $elementor_page_settings = get_post_meta( $post_id, '_elementor_page_settings', true );
275
276 if ( ! is_array( $elementor_page_settings ) ) {
277 $elementor_page_settings = array();
278 }
279
280 $elementor_page_settings['default_page_template'] = 'default';
281
282 update_post_meta( $post_id, '_elementor_page_settings', $elementor_page_settings );
283
284 return true;
285 }
286
287
288 /**
289 * Is shortcode or some text exist in specific page
290 *
291 * @param string $relative_url relative URL of the page, if we have absolute url, then get it using: wpbc_make_link_relative( 'https://...' );
292 * @param string $shortcode_to_add shortcode to check '[booking'
293 *
294 * @return bool
295 */
296 function wpbc_is_shortcode_exist_in_page( $relative_url, $shortcode_to_add ) {
297
298 if ( ! empty( $relative_url ) ) {
299
300 $post_obj = get_page_by_path( $relative_url );
301
302 if ( ! empty( $post_obj ) ) {
303 if ( false !== strpos( $post_obj->post_content, $shortcode_to_add ) ) {
304 return true;
305 }
306 }
307 }
308
309 return false;
310 }
311
312 /**
313 * Is shortcode or some text exist in specific page (got by ID)
314 *
315 * @param string $relative_url relative URL of the page, if we have absolute url, then get it using: wpbc_make_link_relative( 'https://...' );
316 * @param string $shortcode_to_add shortcode to check '[booking'
317 *
318 * @return bool
319 */
320 function wpbc_is_shortcode_exist_in_page_with_id( $page_id, $shortcode_to_add ) {
321
322 // FixIn: 10.12.3.1.
323
324 if ( ! empty( $page_id ) ) {
325
326 $post_obj = get_post( $page_id );
327
328 if ( ! empty( $post_obj ) ) {
329 if ( false !== strpos( $post_obj->post_content, $shortcode_to_add ) ) {
330 return true;
331 }
332 }
333 }
334
335 return false;
336 }
337
338
339 /**
340 * Add shortcode, if it does not exist yet, to the page
341 *
342 * @param string $relative_url relative URL of the page, if we have absolute url, then get it using: wpbc_make_link_relative( 'https://...' );
343 * @param string $shortcode_to_add shortcode '[bookingedit]'
344 *
345 * @return bool
346 */
347 function wpbc_add_shortcode_to_exist_page( $relative_url, $shortcode_to_add ) {
348
349 if ( ! empty( $relative_url ) ) {
350
351 $post_obj = get_page_by_path( $relative_url );
352
353 if ( ! empty( $post_obj ) ) {
354 if ( false === strpos( $post_obj->post_content, $shortcode_to_add ) ) { // No such shortcode in this page. So we need to Add it.
355
356 $my_post = array(
357 'ID' => $post_obj->ID,
358 'post_content' => $post_obj->post_content . "\r\n" . $shortcode_to_add
359 );
360 wp_update_post( $my_post ); // Update the post into the database
361
362 return true;
363 }
364 }
365 }
366
367 return false;
368 }
369
370
371 // ---------------------------------------------------------------------------------------------------------------------
372
373 /**
374 * Create new page or add to existing page the shortcode
375 *
376 * @param array $params
377 *
378 * @return array Success or failure response. Publishing restrictions return a
379 * failure before WordPress page lookup or mutation.
380 *
381 * Example:
382 * $result_arr = wpbc_add_shortcode_into_page( array(
383 * 'shortcode' => '[booking resource_id=1]',
384 * 'post_title' => 'Booking Form'
385 * ) );
386 */
387 function wpbc_add_shortcode_into_page( $params = array() ) {
388 /* Enforce the publishing policy at the canonical writer for every caller. */
389 if ( wpbc_is_booking_form_publishing_restricted() ) {
390 return array(
391 'result' => false,
392 'message' => __( 'In the demo versions this operation is not allowed.', 'booking' ),
393 );
394 }
395
396 $defaults = array(
397 'page_post_name' => '', // 'wpbc-booking',
398 'post_title' => esc_html( __( 'Booking Form', 'booking' ) ),
399 'shortcode' => '[booking resource_id=1]',
400 'check_exist_shortcode' => '[booking', // can be an array: array( '[booking resource_id=1]', '[booking type=1]', '[booking]' )
401 'page_id' => 0,
402 'resource_id' => 0 // Optional
403 );
404 $params = wp_parse_args( $params, $defaults );
405
406 if ( empty( $params['page_post_name'] ) ) {
407 $params['page_post_name'] = sanitize_title( $params['post_title'] ); // Get slug for the page
408 }
409
410
411 global $wp_rewrite;
412 if ( is_null( $wp_rewrite ) ) {
413 return array( 'result' => false, 'message' => 'Sorry, we are unable to insert the shortcode into the page. The reason is that wp_rewrite is not initialized.' );
414 }
415 // -----------------------------------------------------------------------------------------------------------------
416
417 $params['page_id'] = intval( $params['page_id'] );
418 if ( ! empty( $params['page_id'] ) ) {
419 $wp_post = get_post( $params['page_id'] );
420 } else {
421 $wp_post = get_page_by_path( $params['page_post_name'] );
422 }
423
424 $relative_post_url = '';
425
426 $post_title = '';
427 $post_url = '';
428 if ( ! empty( $wp_post ) ) {
429 $post_title = $wp_post->post_title;
430 $post_url = get_permalink( $wp_post->ID );
431 }
432
433 if ( empty( $wp_post ) ) { // No default page. Create it.
434
435 $page_params = array(
436 'post_title' => $params['post_title'],
437 'post_content' => $params['shortcode'],
438 'post_name' => $params['page_post_name']
439 );
440 $post_id = wpbc_create_page( $page_params );
441
442 if ( ! empty( $post_id ) ) {
443
444 $new_post = get_post( $post_id );
445 if ( ! empty( $new_post ) ) {
446 $post_title = $new_post->post_title;
447 $post_url = get_permalink( $new_post->ID );
448 }
449
450 $relative_post_url = wpbc_make_link_relative( get_permalink( $post_id ) );
451
452 // Scroll to the booking form.
453 if ( ! empty( $params['resource_id'] ) ) {
454 $post_url .= '#bklnk' . $params['resource_id'];
455 }
456
457 return array( 'result' => true,
458 'relative_url' => $relative_post_url,
459 /* translators: 1: ... */
460 'message' => __( 'A new page has been created.', 'booking' ) . ' ' . sprintf( __( 'The booking form shortcode %1$s has been embedded into the page %2$s', 'booking' )
461 , "<code class='wpbc_inserted_shortcode_view'>{$params['shortcode']}</code>"
462 , "<a class='wpbc_open_page_as_new_tab' href='" . esc_url( $post_url ) . "'>{$post_title}</a>"
463 . " <a target='_blank' class='wpbc_open_page_as_new_tab tooltip_top wpbc-bi-arrow-up-right-square' href='" . esc_url( $post_url ) . "' title='" . esc_attr( __( 'Open in new window', 'booking' ) ) . "'></a>"
464 )
465 );
466 }
467
468 } else {
469 $relative_post_url = wpbc_make_link_relative( get_permalink( $wp_post->ID ) ); // Page already exist, so we need to update the
470 }
471
472 // Check if the shortcode in the page
473 $is_shortcode_already_in_page = false;
474 if ( is_array( $params['check_exist_shortcode'] ) ) {
475 foreach ( $params['check_exist_shortcode'] as $check_shortcode ) {
476 $is_shortcode_already_in_page = wpbc_is_shortcode_exist_in_page( $relative_post_url, $check_shortcode );
477 if ( $is_shortcode_already_in_page ) {
478 break;
479 }
480 }
481 } else {
482 $is_shortcode_already_in_page = wpbc_is_shortcode_exist_in_page( $relative_post_url, $params['check_exist_shortcode'] );
483 }
484
485 // Scroll to the booking form.
486 if ( ! empty( $params['resource_id'] ) ) {
487 $post_url .= '#bklnk' . $params['resource_id'];
488 }
489
490 // Check if existing page has our shortcode. We are checking for 'booking' because it can be '[booking]' or '[booking type=1]' ...
491 if (
492 ( ! $is_shortcode_already_in_page )
493 && ( ! wpbc_is_shortcode_exist_in_page( $relative_post_url, $params['shortcode'] ) )
494 ) {
495 $is_sh_added = wpbc_add_shortcode_to_exist_page( $relative_post_url, $params['shortcode'] );
496
497 if ( $is_sh_added ) {
498 return array( 'result' => true,
499 'relative_url' => $relative_post_url,
500 /* translators: 1: ... */
501 'message' => sprintf( __( 'The booking form shortcode %1$s has been embedded into the page %2$s', 'booking' )
502 , "<code class='wpbc_inserted_shortcode_view'>{$params['shortcode']}</code>"
503 , "<a class='wpbc_open_page_as_new_tab' href='" . esc_url( $post_url ) . "'>{$post_title}</a>"
504 . " <a target='_blank' class='wpbc_open_page_as_new_tab tooltip_top wpbc-bi-arrow-up-right-square' href='" . esc_url( $post_url ) . "' title='" . esc_attr( __( 'Open in new window', 'booking' ) ) . "'></a>"
505
506 )
507 );
508
509 } else {
510 return array( 'result' => false,
511 /* translators: 1: ... */
512 'message' => sprintf( __( 'We are unable to embed the booking form shortcode %1$s into the page %2$s.', 'booking' )
513 , "<code class='wpbc_inserted_shortcode_view'>{$params['shortcode']}</code>"
514 , "<a class='wpbc_open_page_as_new_tab' href='" . esc_url( $post_url ) . "'>{$post_title}</a>"
515 . " <a target='_blank' class='wpbc_open_page_as_new_tab tooltip_top wpbc-bi-arrow-up-right-square' href='" . esc_url( $post_url ) . "' title='" . esc_attr( __( 'Open in new window', 'booking' ) ) . "'></a>"
516 )
517 );
518 }
519 } else {
520
521 return array( 'result' => false,
522 /* translators: 1: ... */
523 'message' => sprintf( __( 'The Booking Calendar shortcode %1$s is already present on this page %2$s.', 'booking' )
524 , "<code class='wpbc_inserted_shortcode_view'>{$params['shortcode']}</code>"
525 , "<a class='wpbc_open_page_as_new_tab' href='" . esc_url( $post_url ) . "'>{$post_title}</a>"
526 . " <a target='_blank' class='wpbc_open_page_as_new_tab tooltip_top wpbc-bi-arrow-up-right-square' href='" . esc_url( $post_url ) . "' title='" . esc_attr( __( 'Open in new window', 'booking' ) ) . "'></a>"
527 )
528 );
529
530 }
531
532 }
533
534
535 // ---------------------------------------------------------------------------------------------------------------------
536 // ---------------------------------------------------------------------------------------------------------------------
537 // ---------------------------------------------------------------------------------------------------------------------
538
539
540 /**
541 * Get starter booking form/page definitions created during plugin activation.
542 *
543 * @return array
544 */
545 function wpbc_get_activation_booking_form_page_configs() {
546
547 return array(
548 'full_day_booking' => array(
549 'template_key' => 'dates_2_columns_hints_full_days', // 'dates_form_with_inline_hints', // FixIn: 11.8.1.1.
550 'form_slug' => 'full_day_booking',
551 'form_title' => esc_html__( 'Full Day Booking Form', 'booking' ),
552 'page_slug' => 'booking-calendar-full-day',
553 'legacy_page_slugs' => array( 'wp-booking-calendar-full-day' ),
554 'page_title' => esc_html__( 'Full Day Booking', 'booking' ),
555 'button_title' => esc_html__( 'Full day booking form', 'booking' ),
556 ),
557 'time_slots_booking' => array(
558 'template_key' => 'time_slots_2_columns_hints',
559 'form_slug' => 'time_slots_booking',
560 'form_title' => esc_html__( 'Time Slots Booking Form', 'booking' ),
561 'page_slug' => 'booking-calendar-time-slots',
562 'legacy_page_slugs' => array( 'wp-booking-calendar-time-slots' ),
563 'page_title' => esc_html__( 'Time Slots Booking', 'booking' ),
564 'button_title' => esc_html__( 'Time slots booking form', 'booking' ),
565 ),
566 'time_appointments_booking' => array(
567 'template_key' => 'time_appointments_3_steps_review_with_hints',
568 'form_slug' => 'time_appointments_booking',
569 'form_title' => esc_html__( 'Time Appointments Booking Form', 'booking' ),
570 'create_page' => false,
571 ),
572 'appointment_services_booking' => array(
573 'template_key' => 'appointments_services_flow',
574 'form_slug' => 'appointment_services_booking',
575 'form_title' => esc_html__( 'Appointment Services Booking Form', 'booking' ),
576 'create_page' => false,
577 'assign_to_default_appointment_service' => true,
578 ),
579 'contact_form' => array(
580 'template_key' => 'contact_form_simple',
581 'form_slug' => 'contact_form',
582 'form_title' => esc_html__( 'Contact Form', 'booking' ),
583 'page_slug' => 'booking-calendar-contact',
584 'legacy_page_slugs' => array( 'wp-booking-calendar-contact' ),
585 'page_title' => esc_html__( 'Contact Form', 'booking' ),
586 'button_title' => esc_html__( 'Contact form', 'booking' ),
587 ),
588 );
589 }
590
591
592 /**
593 * Get starter page definitions created during plugin activation.
594 *
595 * Legacy starter pages keep using their dedicated custom booking forms. The
596 * old Time Appointments form and the dedicated Appointment Service form are
597 * form-only fixtures because the Appointment workflow has one canonical page.
598 *
599 * @return array Starter page definitions keyed by stable purpose.
600 */
601 function wpbc_get_activation_booking_page_configs() {
602
603 $page_configs = wpbc_get_activation_booking_form_page_configs();
604
605 foreach ( $page_configs as $page_key => $page_config ) {
606 if ( isset( $page_config['create_page'] ) && false === (bool) $page_config['create_page'] ) {
607 unset( $page_configs[ $page_key ] );
608 continue;
609 }
610
611 $form_slug = '';
612 if ( isset( $page_config['form_slug'] ) ) {
613 $form_slug = sanitize_text_field( (string) $page_config['form_slug'] );
614 }
615
616 if ( '' === $form_slug ) {
617 unset( $page_configs[ $page_key ] );
618 continue;
619 }
620
621 $shortcode = "[booking resource_id=1 form_type='{$form_slug}']";
622 $page_configs[ $page_key ]['shortcode'] = $shortcode;
623 $page_configs[ $page_key ]['shortcode_checks'] = array(
624 $shortcode,
625 '[booking resource_id=1 form_type="' . $form_slug . '"]',
626 );
627 $page_configs[ $page_key ]['resource_id'] = 1;
628 }
629
630 $page_configs['appointment_booking'] = array(
631 'page_slug' => 'booking-calendar-appointment',
632 'legacy_page_slugs' => array( 'wpbc-appointment-booking' ),
633 'page_title' => esc_html__( 'Book an Appointment', 'booking' ),
634 'button_title' => esc_html__( 'Appointment booking form', 'booking' ),
635 'shortcode' => '[booking_appointment]',
636 'shortcode_checks' => array( '[booking_appointment]', '[booking_appointment ' ),
637 'resource_id' => 0,
638 );
639 $page_configs['resource_selector_booking'] = array(
640 'page_slug' => 'booking-calendar-resource-selection',
641 'legacy_page_slugs' => array(),
642 'page_title' => esc_html__( 'Resource Selection', 'booking' ),
643 'button_title' => esc_html__( 'Resource selection', 'booking' ),
644 'shortcode' => '[booking_resource_selector]',
645 'shortcode_checks' => array( '[booking_resource_selector]', '[booking_resource_selector ' ),
646 'resource_id' => 0,
647 );
648
649 return $page_configs;
650 }
651
652
653 /**
654 * Get the Free Booking Received page definition used during initial activation.
655 *
656 * The legacy slug remains lookup-only so a clean reinstall can reuse a retained
657 * page without making legacy URLs canonical for new installations.
658 *
659 * @return array Confirmation page definition with canonical and legacy slugs.
660 */
661 function wpbc_get_activation_confirmation_page_config() {
662
663 return array(
664 'page_slug' => 'booking-calendar-confirmation',
665 'legacy_page_slugs' => array( 'wpbc-booking-received' ),
666 );
667 }
668
669
670 /**
671 * Get the Personal-edition customer page definitions used during activation.
672 *
673 * @return array Personal page definitions keyed by stable purpose.
674 */
675 function wpbc_get_activation_personal_page_configs() {
676
677 return array(
678 'manage_booking' => array(
679 'page_slug' => 'booking-calendar-manage-booking',
680 'legacy_page_slugs' => array( 'wpbc-my-booking' ),
681 'page_title' => esc_html__( 'My Booking', 'booking' ),
682 'shortcode' => '[bookingedit]',
683 'option_name' => 'booking_url_bookings_edit_by_visitors',
684 ),
685 'my_bookings' => array(
686 'page_slug' => 'booking-calendar-my-bookings',
687 'legacy_page_slugs' => array( 'wpbc-my-bookings-listing' ),
688 'page_title' => esc_html__( 'My Bookings Listing', 'booking' ),
689 'shortcode' => '[bookingcustomerlisting]',
690 'option_name' => 'booking_url_bookings_listing_by_customer',
691 ),
692 );
693 }
694
695
696 /**
697 * Get the Business Small payment-result page definitions used during activation.
698 *
699 * @return array Payment-result definitions keyed by stable outcome.
700 */
701 function wpbc_get_activation_payment_page_configs() {
702
703 return array(
704 'success' => array(
705 'page_slug' => 'booking-calendar-payment-success',
706 'legacy_page_slugs' => array( 'wpbc-booking-payment-successful' ),
707 'page_title' => esc_html__( 'Booking Payment Confirmation', 'booking' ),
708 'page_content' => esc_html__( 'Thank you for your booking. Your payment for the booking has been successfully received.', 'booking' )
709 . "\r\n\r\n[booking_confirm]",
710 'required_shortcode' => '[booking_confirm]',
711 'default_url' => '/successful',
712 'option_names' => array(
713 'booking_stripe_v3_order_successful',
714 'booking_paypal_std_co_order_successful',
715 'booking_paypal_return_url',
716 'booking_authorizenet_order_successful',
717 'booking_sage_order_successful',
718 'booking_redsys_order_successful',
719 'booking_ideal_return_url',
720 'booking_ipay88_return_url',
721 ),
722 ),
723 'failed' => array(
724 'page_slug' => 'booking-calendar-payment-failed',
725 'legacy_page_slugs' => array( 'wpbc-booking-payment-failed' ),
726 'page_title' => esc_html__( 'Booking Payment Failed', 'booking' ),
727 'page_content' => esc_html__( 'Payment Unsuccessful. Please contact us for assistance.', 'booking' ),
728 'required_shortcode' => '',
729 'default_url' => '/failed',
730 'option_names' => array(
731 'booking_stripe_v3_order_failed',
732 'booking_paypal_std_co_order_failed',
733 'booking_paypal_cancel_return_url',
734 'booking_authorizenet_order_failed',
735 'booking_sage_order_failed',
736 'booking_redsys_order_failed',
737 'booking_ideal_cancel_return_url',
738 'booking_ipay88_cancel_return_url',
739 ),
740 ),
741 );
742 }
743
744
745 /**
746 * Check whether an activation payment URL still contains its replaceable default.
747 *
748 * Missing options and the released placeholder paths may be connected to a
749 * newly eligible payment page. Every other value is treated as administrator
750 * configuration and must remain unchanged.
751 *
752 * @param mixed $configured_url Saved payment return URL, or false when absent.
753 * @param string $default_url Released relative placeholder URL.
754 *
755 * @return bool True when activation may store the eligible payment page URL.
756 */
757 function wpbc_should_update_activation_payment_url( $configured_url, $default_url ) {
758
759 if ( false === $configured_url ) {
760 return true;
761 }
762
763 return (string) $default_url === wpbc_make_link_relative( $configured_url );
764 }
765
766
767 /**
768 * Find an existing activation-owned page by its canonical or legacy slug.
769 *
770 * Canonical slugs are checked first. Legacy aliases are used only to preserve
771 * existing pages and prevent duplicates after a full plugin-data reset.
772 *
773 * @param string $page_slug Canonical page slug.
774 * @param array $legacy_page_slugs Previously released page slugs.
775 *
776 * @return WP_Post|null Existing WordPress page, or null when no slug matches.
777 */
778 function wpbc_get_activation_page_by_slugs( $page_slug, $legacy_page_slugs = array() ) {
779
780 $page_slugs = array_merge( array( $page_slug ), (array) $legacy_page_slugs );
781 $page_slugs = array_unique( array_filter( array_map( 'sanitize_title', $page_slugs ) ) );
782
783 foreach ( $page_slugs as $candidate_page_slug ) {
784 $wp_post = get_page_by_path( $candidate_page_slug, OBJECT, 'page' );
785
786 if ( $wp_post instanceof WP_Post ) {
787 return $wp_post;
788 }
789 }
790
791 return null;
792 }
793
794
795 /**
796 * Get the first published activation page matching a canonical or legacy slug.
797 *
798 * This read-only lookup is separate from the activation writer lookup because
799 * activation must recognize retained non-published pages to avoid duplicates,
800 * while public-page navigation must never advertise an inaccessible draft or
801 * trashed canonical page when a published legacy page is still available.
802 *
803 * @param string $page_slug Canonical activation page slug.
804 * @param array $legacy_page_slugs Previously released lookup-only slugs.
805 *
806 * @return WP_Post|null Published page, or null when no public match exists.
807 */
808 function wpbc_get_published_activation_page_by_slugs( $page_slug, $legacy_page_slugs = array() ) {
809
810 $page_slugs = array_merge( array( $page_slug ), (array) $legacy_page_slugs );
811 $page_slugs = array_unique( array_filter( array_map( 'sanitize_title', $page_slugs ) ) );
812
813 foreach ( $page_slugs as $candidate_page_slug ) {
814 $wp_post = get_page_by_path( $candidate_page_slug, OBJECT, 'page' );
815
816 if ( $wp_post instanceof WP_Post && 'publish' === $wp_post->post_status ) {
817 return $wp_post;
818 }
819 }
820
821 return null;
822 }
823
824
825 /**
826 * Get a bundled BFB template record by template key.
827 *
828 * @param string $template_key Template key.
829 *
830 * @return array
831 */
832 function wpbc_get_bfb_template_record_by_key( $template_key ) {
833
834 if (
835 ! function_exists( 'wpbc_bfb_activation__get_templates_registry' ) ||
836 ! function_exists( 'wpbc_bfb_activation__normalize_template_config' )
837 ) {
838 return array();
839 }
840
841 $template_key = sanitize_key( (string) $template_key );
842 $templates = wpbc_bfb_activation__get_templates_registry();
843
844 if ( empty( $templates ) || ! is_array( $templates ) ) {
845 return array();
846 }
847
848 foreach ( $templates as $template_config ) {
849
850 $template_config = wpbc_bfb_activation__normalize_template_config( $template_config );
851
852 if ( $template_key === $template_config['template_key'] ) {
853 return $template_config['record'];
854 }
855 }
856
857 return array();
858 }
859
860
861 /**
862 * Create starter custom booking forms from bundled BFB templates.
863 *
864 * @return bool
865 */
866 function wpbc_create_activation_custom_booking_forms() {
867
868 if (
869 ! function_exists( 'wpbc_is_table_exists' ) ||
870 ! wpbc_is_table_exists( 'booking_form_structures' ) ||
871 ! class_exists( 'WPBC_BFB_Form_Storage' )
872 ) {
873 return false;
874 }
875
876 $configs = wpbc_get_activation_booking_form_page_configs();
877 if ( empty( $configs ) || ! is_array( $configs ) ) {
878 return false;
879 }
880
881 $is_created = false;
882
883 foreach ( $configs as $config ) {
884
885 $form_slug = sanitize_text_field( (string) $config['form_slug'] );
886 if ( '' === $form_slug ) {
887 continue;
888 }
889
890 $existing_form = WPBC_BFB_Form_Storage::get_current_form_by_key( $form_slug, 0, 'published' );
891 if ( ! empty( $existing_form ) ) {
892 continue;
893 }
894
895 $template_record = wpbc_get_bfb_template_record_by_key( $config['template_key'] );
896 if ( empty( $template_record ) ) {
897 continue;
898 }
899
900 // The predefined Time Slots form must select one calendar day independently, // FixIn: 11.4.3.1
901 // from the global/default Calendar Settings day-selection mode.
902 if ( 'time_slots_booking' === $form_slug ) {
903 $form_settings = array();
904 if ( ! empty( $template_record['settings_json'] ) ) {
905 $decoded_settings = json_decode( (string) $template_record['settings_json'], true );
906 if ( is_array( $decoded_settings ) ) {
907 $form_settings = $decoded_settings;
908 }
909 }
910
911 if ( empty( $form_settings['options'] ) || ! is_array( $form_settings['options'] ) ) {
912 $form_settings['options'] = array();
913 }
914
915 $form_settings['options']['booking_type_of_day_selections'] = 'single';
916 $template_record['settings_json'] = function_exists( 'wpbc_form_config__encode_json' )
917 ? wpbc_form_config__encode_json( $form_settings )
918 : wp_json_encode( $form_settings );
919 }
920
921 $template_record['form_slug'] = $form_slug;
922 $template_record['status'] = 'published';
923 $template_record['scope'] = 'global';
924 $template_record['owner_user_id'] = 0;
925 $template_record['booking_resource_id'] = null;
926 $template_record['is_default'] = 0;
927 $template_record['title'] = $config['form_title'];
928 $template_record['picture_url'] = isset( $template_record['picture_url'] ) ? (string) $template_record['picture_url'] : '';
929 if ( function_exists( 'wpbc_bfb_resolve_picture_url' ) ) {
930 $template_record['picture_url'] = wpbc_bfb_resolve_picture_url( $template_record['picture_url'] );
931 }
932
933 $booking_form_id = WPBC_BFB_Form_Storage::save_form( $template_record );
934 if ( ! empty( $booking_form_id ) ) {
935 $is_created = true;
936 }
937 }
938
939 return $is_created;
940 }
941
942
943 /**
944 * Return the ordered activation-page level for a Booking Calendar edition.
945 *
946 * The ordering is intentionally limited to product editions. Page groups use
947 * these levels to determine whether a paid activation has crossed the edition
948 * boundary that first makes those pages available.
949 *
950 * @param string $edition_id Booking Calendar edition identifier.
951 *
952 * @return int Edition level, or -1 when the identifier is not supported.
953 */
954 function wpbc_get_activation_page_edition_level( $edition_id ) {
955
956 $edition_levels = array(
957 'free' => 0,
958 'personal' => 1,
959 'biz_s' => 2,
960 'biz_m' => 3,
961 'biz_l' => 4,
962 'multiuser' => 5,
963 );
964
965 $edition_id = (string) $edition_id;
966
967 return isset( $edition_levels[ $edition_id ] ) ? $edition_levels[ $edition_id ] : -1;
968 }
969
970
971 /**
972 * Check whether a paid-edition transition newly unlocks one page group.
973 *
974 * This pure comparison keeps Free-to-Pro, lower-to-higher, reactivation,
975 * update, and downgrade behavior deterministic and independently testable.
976 *
977 * @param string $previous_edition_id Previously provisioned or detected edition.
978 * @param string $current_edition_id Edition active during this activation.
979 * @param string $required_edition_id First edition that owns the page group.
980 *
981 * @return bool True when this activation crosses the required edition boundary.
982 */
983 function wpbc_is_activation_page_edition_transition( $previous_edition_id, $current_edition_id, $required_edition_id ) {
984
985 $previous_edition_level = wpbc_get_activation_page_edition_level( $previous_edition_id );
986 $current_edition_level = wpbc_get_activation_page_edition_level( $current_edition_id );
987 $required_edition_level = wpbc_get_activation_page_edition_level( $required_edition_id );
988
989 if ( 0 > $previous_edition_level || 0 > $current_edition_level || 1 > $required_edition_level ) {
990 return false;
991 }
992
993 return $previous_edition_level < $required_edition_level
994 && $required_edition_level <= $current_edition_level;
995 }
996
997
998 /**
999 * Check whether activation-owned WordPress pages may be provisioned.
1000 *
1001 * Free-owned pages remain restricted to the immutable first-Free-install
1002 * decision. Paid page groups can additionally opt into the exact Pro edition
1003 * transition that first makes them available. The Pro activation layer owns
1004 * that transition state and exposes it through a narrow filter; normal Free or
1005 * Pro updates therefore remain fail-closed.
1006 *
1007 * @param string $required_edition_id First edition that owns the page group.
1008 *
1009 * @return bool True only during the qualifying initial activation request.
1010 */
1011 function wpbc_should_create_activation_pages( $required_edition_id = 'free' ) {
1012 $required_edition_id = (string) $required_edition_id;
1013 $required_edition_level = wpbc_get_activation_page_edition_level( $required_edition_id );
1014
1015 if ( 0 > $required_edition_level ) {
1016 return false;
1017 }
1018
1019 if ( function_exists( 'wpbc_is_plugin_initial_install' ) && wpbc_is_plugin_initial_install() ) {
1020 return true;
1021 }
1022
1023 if ( 0 === $required_edition_level ) {
1024 return false;
1025 }
1026
1027 /**
1028 * Filter whether the current paid-edition activation newly owns a page group.
1029 *
1030 * @since 11.8.1
1031 *
1032 * @param bool $should_create_pages Fail-closed default decision.
1033 * @param string $required_edition_id First edition that owns the page group.
1034 */
1035 return (bool) apply_filters( 'wpbc_should_create_paid_edition_activation_pages', false, $required_edition_id );
1036 }
1037
1038
1039 /**
1040 * Build starter page content with a booking shortcode.
1041 *
1042 * @param string $shortcode Booking shortcode.
1043 *
1044 * @return string
1045 */
1046 function wpbc_get_activation_booking_page_content( $shortcode ) {
1047
1048 $shortcode = trim( (string) $shortcode );
1049
1050 if ( WPBC_IS_PLAYGROUND ) {
1051 $shortcode = '<style type="text/css"> h1, h2, h3, h4, h5, h6 { font-weight: 500; font-family: var(--wp--preset--font-family--body); } </style>' . $shortcode;
1052 }
1053
1054 return $shortcode;
1055 }
1056
1057
1058 /**
1059 * Create new starter pages with booking forms.
1060 *
1061 * @param array $default_options_to_add Unused. Kept for backward-compatible direct calls.
1062 *
1063 * @return void
1064 */
1065 function wpbc_create_page_with_booking_form( $default_options_to_add = array() ) { // FixIn: 9.6.2.11.
1066
1067 global $wp_rewrite;
1068 if ( is_null( $wp_rewrite ) ) { // FixIn: 9.7.1.1.
1069
1070 // Maybe it was not init, yet.
1071 if ( ! has_action( 'init', 'wpbc_create_page_with_booking_form' ) ) {
1072 add_action( 'init', 'wpbc_create_page_with_booking_form', 99 ); // <- priority to load it last
1073 }
1074
1075 return false;
1076 }
1077
1078 // -----------------------------------------------------------------------------------------------------------------
1079
1080 wpbc_create_activation_custom_booking_forms();
1081
1082 /**
1083 * Fires after activation starter custom forms are available.
1084 *
1085 * Appointment Services uses this boundary to finish its pending starter
1086 * Service seed with the newly created form ID.
1087 *
1088 * @since 11.5.0
1089 */
1090 do_action( 'wpbc_activation_custom_booking_forms_created' );
1091
1092 if ( ! wpbc_should_create_activation_pages() ) {
1093 return;
1094 }
1095
1096 $configs = wpbc_get_activation_booking_page_configs();
1097 if ( empty( $configs ) || ! is_array( $configs ) ) {
1098 return;
1099 }
1100
1101 $front_page_id = 0;
1102
1103 foreach ( $configs as $config ) {
1104
1105 $shortcode = isset( $config['shortcode'] ) ? trim( (string) $config['shortcode'] ) : '';
1106 $shortcode_checks = isset( $config['shortcode_checks'] ) && is_array( $config['shortcode_checks'] )
1107 ? $config['shortcode_checks']
1108 : array( $shortcode );
1109 $resource_id = isset( $config['resource_id'] ) ? absint( $config['resource_id'] ) : 0;
1110
1111 if ( '' === $shortcode ) {
1112 continue;
1113 }
1114
1115 $content = wpbc_get_activation_booking_page_content( $shortcode );
1116 $legacy_page_slugs = isset( $config['legacy_page_slugs'] ) ? (array) $config['legacy_page_slugs'] : array();
1117 $existing_page = wpbc_get_activation_page_by_slugs( $config['page_slug'], $legacy_page_slugs );
1118
1119 $result_arr = wpbc_add_shortcode_into_page(
1120 array(
1121 'page_post_name' => $config['page_slug'],
1122 'page_id' => $existing_page instanceof WP_Post ? $existing_page->ID : 0,
1123 'post_title' => $config['page_title'],
1124 'shortcode' => $content,
1125 'check_exist_shortcode' => $shortcode_checks,
1126 'resource_id' => $resource_id,
1127 )
1128 );
1129
1130 if ( WPBC_IS_PLAYGROUND && empty( $front_page_id ) && ! empty( $result_arr['relative_url'] ) ) {
1131 $wp_post = wpbc_get_activation_page_by_slugs( $config['page_slug'], $legacy_page_slugs );
1132 if ( ! empty( $wp_post ) ) {
1133 $front_page_id = $wp_post->ID;
1134 }
1135 }
1136 }
1137
1138 if ( WPBC_IS_PLAYGROUND && ! empty( $front_page_id ) ) {
1139 update_option( 'show_on_front', 'page' );
1140 update_option( 'page_on_front', $front_page_id );
1141 }
1142 }
1143 add_action( 'wpbc_bfb_activation__form_structures_table__after_create', 'wpbc_create_page_with_booking_form', 20 );
1144 add_action( 'wpbc_bfb_activation__form_structures_table__table_already_exists', 'wpbc_create_page_with_booking_form', 20 );
1145
1146
1147 /**
1148 * Get published starter pages that contain their expected booking form shortcodes.
1149 *
1150 * @return array
1151 */
1152 function wpbc_get_published_activation_booking_pages() {
1153
1154 $pages = array();
1155 $configs = wpbc_get_activation_booking_page_configs();
1156
1157 if ( empty( $configs ) || ! is_array( $configs ) ) {
1158 return $pages;
1159 }
1160
1161 foreach ( $configs as $key => $config ) {
1162
1163 $legacy_page_slugs = isset( $config['legacy_page_slugs'] ) ? (array) $config['legacy_page_slugs'] : array();
1164 $wp_post = wpbc_get_published_activation_page_by_slugs( $config['page_slug'], $legacy_page_slugs );
1165 if ( ! ( $wp_post instanceof WP_Post ) ) {
1166 continue;
1167 }
1168
1169 $shortcode_checks = isset( $config['shortcode_checks'] ) && is_array( $config['shortcode_checks'] )
1170 ? $config['shortcode_checks']
1171 : array();
1172 $is_shortcode_found = false;
1173
1174 foreach ( $shortcode_checks as $shortcode_check ) {
1175 if ( '' === (string) $shortcode_check ) {
1176 continue;
1177 }
1178
1179 if ( wpbc_is_shortcode_exist_in_page_with_id( $wp_post->ID, $shortcode_check ) ) {
1180 $is_shortcode_found = true;
1181 break;
1182 }
1183 }
1184
1185 if ( ! $is_shortcode_found ) {
1186 continue;
1187 }
1188
1189 $post_url = get_permalink( $wp_post->ID );
1190 if ( empty( $post_url ) ) {
1191 continue;
1192 }
1193
1194 $pages[ $key ] = array(
1195 'url' => $post_url,
1196 'button_title' => $config['button_title'],
1197 'page_title' => $config['page_title'],
1198 );
1199 }
1200
1201 return $pages;
1202 }
1203
1204 // ---------------------------------------------------------------------------------------------------------------------
1205
1206
1207 /**
1208 * Create new page and get URL of this page
1209 *
1210 * @param $default_options_to_add
1211 *
1212 * @return void
1213 */
1214 function wpbc_create_page_thank_you( $default_options_to_add ) { // FixIn: 9.6.2.11.
1215
1216 if ( ! wpbc_should_create_activation_pages() ) {
1217 return false;
1218 }
1219
1220 global $wp_rewrite;
1221 if ( is_null( $wp_rewrite ) ) { // FixIn: 9.7.1.1.
1222
1223 // Maybe it was not init, yet
1224 if ( ! has_action( 'init', 'wpbc_create_page_thank_you' ) ) {
1225 add_action( 'init', 'wpbc_create_page_thank_you', 99 ); // <- priority to load it last
1226 }
1227 return false;
1228 }
1229
1230 // -----------------------------------------------------------------------------------------------------------------
1231
1232 $thank_you_page_url = get_bk_option( 'booking_thank_you_page_URL' );
1233
1234 if ( ( empty( $thank_you_page_url ) ) // If No 'Thank you' page in Settings, or it's set as Empty.
1235 || (
1236 ( '/thank-you' == wpbc_make_link_relative( get_bk_option( 'booking_thank_you_page_URL' ) ) )
1237 && ( empty( get_page_by_path( 'thank-you' ) ) ) // FixIn: 9.9.0.27.
1238 )
1239 || ( '/' == wpbc_make_link_relative( get_bk_option( 'booking_thank_you_page_URL' ) ) )
1240 ){
1241 $confirmation_page_config = wpbc_get_activation_confirmation_page_config();
1242 $wp_post = wpbc_get_activation_page_by_slugs(
1243 $confirmation_page_config['page_slug'],
1244 $confirmation_page_config['legacy_page_slugs']
1245 );
1246
1247 $post_url = '';
1248
1249 if ( empty( $wp_post ) ) { // No default page. Create it.
1250
1251 $page_params = array(
1252 'post_title' => esc_html( __( 'Booking Received', 'booking' ) ),
1253 'post_content' => esc_html( __( 'Thank you for your booking. Your booking has been successfully received.', 'booking' ) )
1254 . "\r\n" . ' [booking_confirm]',
1255 'post_name' => $confirmation_page_config['page_slug'],
1256 );
1257 $post_id = wpbc_create_page( $page_params );
1258
1259 if ( ! empty( $post_id ) ) {
1260 $post_url = wpbc_make_link_relative( get_permalink( $post_id ) );
1261 }
1262
1263 } else {
1264 $post_url = wpbc_make_link_relative( get_permalink( $wp_post->ID ) ); // Page already exist, so we need to update the
1265 }
1266
1267 if ( ! empty( $post_url ) ) {
1268 update_bk_option( 'booking_thank_you_page_URL', $post_url );
1269 }
1270 }
1271
1272 // -----------------------------------------------------------------------------------------------------------------
1273
1274 // Check if existing page has our shortcode
1275 $relative_url = wpbc_make_link_relative( get_bk_option( 'booking_thank_you_page_URL' ) );
1276 $is_sh_added = wpbc_add_shortcode_to_exist_page( $relative_url, '[booking_confirm]' );
1277
1278 }
1279 add_bk_action( 'wpbc_before_activation__add_options', 'wpbc_create_page_thank_you' );
1280
1281
1282
1283 /**
1284 * Create pages for [bookingedit] and [bookingcustomerlisting] shortcodes,
1285 *
1286 * if previously was not defined options
1287 * 'booking_url_bookings_edit_by_visitors' and 'booking_url_bookings_listing_by_customer'
1288 * to some pages different from homepage.
1289 *
1290 * @return void
1291 */
1292 function wpbc_create_page_bookingedit(){ // FixIn: 9.6.2.10.
1293
1294 if ( ! wpbc_should_create_activation_pages( 'personal' ) ) {
1295 return false;
1296 }
1297
1298 global $wp_rewrite;
1299 if ( is_null( $wp_rewrite ) ) { // FixIn: 9.7.1.1.
1300 // Maybe it was not init, yet
1301 if ( ! has_action( 'init', 'wpbc_create_page_bookingedit' ) ) {
1302 add_action( 'init', 'wpbc_create_page_bookingedit', 99 ); // <- priority to load it last
1303 }
1304 return false;
1305 }
1306
1307 $page_configs = wpbc_get_activation_personal_page_configs();
1308
1309 foreach ( $page_configs as $page_config ) {
1310 $configured_page_url = get_bk_option( $page_config['option_name'] );
1311 $existing_page = wpbc_get_activation_page_by_slugs(
1312 $page_config['page_slug'],
1313 $page_config['legacy_page_slugs']
1314 );
1315
1316 if ( site_url() === $configured_page_url && ! ( $existing_page instanceof WP_Post ) ) {
1317 $page_id = wpbc_create_page(
1318 array(
1319 'post_content' => $page_config['shortcode'],
1320 'post_name' => $page_config['page_slug'],
1321 'post_title' => $page_config['page_title'],
1322 )
1323 );
1324
1325 if ( ! empty( $page_id ) ) {
1326 update_bk_option( $page_config['option_name'], get_permalink( $page_id ) );
1327 }
1328 } elseif (
1329 ( site_url() === $configured_page_url || empty( $configured_page_url ) )
1330 && $existing_page instanceof WP_Post
1331 ) {
1332 update_bk_option( $page_config['option_name'], get_permalink( $existing_page->ID ) );
1333 }
1334
1335 $relative_page_url = wpbc_make_link_relative( get_bk_option( $page_config['option_name'] ) );
1336 wpbc_add_shortcode_to_exist_page( $relative_page_url, $page_config['shortcode'] );
1337 }
1338
1339 }
1340
1341
1342 function wpbc_create_page_booking_payment_status(){ // FixIn: 9.6.2.13.
1343
1344 if ( ! wpbc_should_create_activation_pages( 'biz_s' ) ) {
1345 return false;
1346 }
1347
1348 global $wp_rewrite;
1349 if ( is_null( $wp_rewrite ) ) { // FixIn: 9.7.1.1.
1350 return false;
1351 }
1352
1353 $page_configs = wpbc_get_activation_payment_page_configs();
1354
1355 foreach ( $page_configs as $page_config ) {
1356 $existing_page = wpbc_get_activation_page_by_slugs(
1357 $page_config['page_slug'],
1358 $page_config['legacy_page_slugs']
1359 );
1360
1361 if ( ! ( $existing_page instanceof WP_Post ) ) {
1362 $page_id = wpbc_create_page(
1363 array(
1364 'post_title' => $page_config['page_title'],
1365 'post_content' => $page_config['page_content'],
1366 'post_name' => $page_config['page_slug'],
1367 )
1368 );
1369 $existing_page = ! empty( $page_id ) ? get_post( $page_id ) : null;
1370 }
1371
1372 if ( ! ( $existing_page instanceof WP_Post ) || 'publish' !== $existing_page->post_status ) {
1373 continue;
1374 }
1375
1376 $page_url_relative = wpbc_make_link_relative( get_permalink( $existing_page->ID ) );
1377 if ( empty( $page_url_relative ) ) {
1378 continue;
1379 }
1380
1381 if ( ! empty( $page_config['required_shortcode'] ) ) {
1382 wpbc_add_shortcode_to_exist_page( $page_url_relative, $page_config['required_shortcode'] );
1383 }
1384
1385 foreach ( $page_config['option_names'] as $option_name ) {
1386 $configured_url = get_bk_option( $option_name );
1387
1388 if ( wpbc_should_update_activation_payment_url( $configured_url, $page_config['default_url'] ) ) {
1389 update_bk_option( $option_name, $page_url_relative );
1390 }
1391 }
1392 }
1393 }
1394