PluginProbe
Booking Calendar / 11.8.4
Booking Calendar v11.8.4
11.8.4 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 All 204 releases
← All changes | includes/page-form-builder/save-load/bfb-activate.php +407 -407 11.8.1 → 11.8.4 View file →
@@ -1,4 +1,4 @@
1 1 <?php
2 2 /**
3 3 * Booking Form Builder - Activation helpers.
4 4 *
@@ -273,16 +273,16 @@
273 273 * So the preview page itself does not need to be private.
274 274 *
275 275 * @return false|int
276 276 */
277 -function wpbc_bfb_activation__create_preview_page_raw() {
278 -
279 - /* Reuse an existing preview page on demos, but never auto-create one. */
280 - if ( function_exists( 'wpbc_is_this_demo' ) && wpbc_is_this_demo() ) {
281 - return false;
282 - }
283 -
284 - $page_data = array(
277 +function wpbc_bfb_activation__create_preview_page_raw() {
278 +
279 + /* Reuse an existing preview page on demos, but never auto-create one. */
280 + if ( function_exists( 'wpbc_is_this_demo' ) && wpbc_is_this_demo() ) {
281 + return false;
282 + }
283 +
284 + $page_data = array(
285 285 'post_title' => __( 'Booking Form Preview', 'booking' ),
286 286 'post_content' => '', // Content will be injected dynamically at preview time by bfb-preview.php.
287 287 'post_status' => 'publish',
288 288 'post_type' => 'page',
@@ -413,17 +413,17 @@
413 413 * Activation hook entry: ensure the preview page exists.
414 414 *
415 415 * @return void
416 416 */
417 -function wpbc_bfb_activation__preview_page() {
418 - // Activation callbacks also run during version upgrades. Keep page creation
419 - // strictly inside the verified first-install boundary.
420 - if ( ! function_exists( 'wpbc_should_create_activation_pages' ) || ! wpbc_should_create_activation_pages() ) {
421 - return;
422 - }
423 -
424 - wpbc_bfb_activation__ensure_preview_page_exists();
425 -}
417 +function wpbc_bfb_activation__preview_page() {
418 + // Activation callbacks also run during version upgrades. Keep page creation
419 + // strictly inside the verified first-install boundary.
420 + if ( ! function_exists( 'wpbc_should_create_activation_pages' ) || ! wpbc_should_create_activation_pages() ) {
421 + return;
422 + }
423 +
424 + wpbc_bfb_activation__ensure_preview_page_exists();
425 +}
426 426 add_bk_action( 'wpbc_free_version_activation', 'wpbc_bfb_activation__preview_page' );
427 427
428 428
429 429 /**
@@ -510,23 +510,23 @@
510 510 }
511 511 add_bk_action( 'wpbc_free_version_deactivation', 'wpbc_bfb_deactivation__form_structures_table' );
512 512
513 513
514 -/**
515 - * Check the shared activation decision before provisioning a Standard form.
516 - *
517 - * The wrapper name is retained for compatibility with existing Form Builder
518 - * callers and tests. The core detector additionally requires the canonical
519 - * booking table to be absent, so a missing version option on an established
520 - * installation cannot be mistaken for a new install.
521 - *
522 - * @return bool True only during a genuine first-install activation request.
523 - */
524 -function wpbc_bfb_is_brand_new_install__before_version_update() {
525 -
526 - return function_exists( 'wpbc_is_plugin_initial_install' ) && wpbc_is_plugin_initial_install();
527 -}
514 +/**
515 + * Check the shared activation decision before provisioning a Standard form.
516 + *
517 + * The wrapper name is retained for compatibility with existing Form Builder
518 + * callers and tests. The core detector additionally requires the canonical
519 + * booking table to be absent, so a missing version option on an established
520 + * installation cannot be mistaken for a new install.
521 + *
522 + * @return bool True only during a genuine first-install activation request.
523 + */
524 +function wpbc_bfb_is_brand_new_install__before_version_update() {
528 525
526 + return function_exists( 'wpbc_is_plugin_initial_install' ) && wpbc_is_plugin_initial_install();
527 +}
528 +
529 529 /**
530 530 * Let the initial standard BFB form follow the global calendar days-selection setting.
531 531 *
532 532 * Some bundled templates intentionally override days selection for their own use case.
@@ -536,9 +536,9 @@
536 536 * @param array $template_record Form Builder template record.
537 537 *
538 538 * @return array
539 539 */
540 -function wpbc_bfb_activation__set_standard_form_default_days_selection( $template_record ) {
540 +function wpbc_bfb_activation__set_standard_form_default_days_selection( $template_record ) {
541 541
542 542 if ( empty( $template_record ) || ! is_array( $template_record ) ) {
543 543 return $template_record;
544 544 }
@@ -560,26 +560,26 @@
560 560 $template_record['settings_json'] = function_exists( 'wpbc_form_config__encode_json' )
561 561 ? wpbc_form_config__encode_json( $settings )
562 562 : wp_json_encode( $settings );
563 563
564 - return $template_record;
565 -}
566 -
567 -/**
568 - * Get the bundled template key used for a brand-new Standard form.
569 - *
570 - * Every customer edition starts with the spacious vertical full-day form. The
571 - * surrounding activation gate limits this choice to a genuine first install,
572 - * so upgrades, reactivations, and existing forms remain unchanged.
573 - *
574 - * @return string Stable bundled template key for a genuine first install.
575 - */
576 -function wpbc_bfb_activation__get_initial_standard_template_key() {
577 -
578 - return 'dates_vertical_hints_full_days';
579 -}
564 + return $template_record;
565 +}
580 566
581 567 /**
568 + * Get the bundled template key used for a brand-new Standard form.
569 + *
570 + * Every customer edition starts with the spacious vertical full-day form. The
571 + * surrounding activation gate limits this choice to a genuine first install,
572 + * so upgrades, reactivations, and existing forms remain unchanged.
573 + *
574 + * @return string Stable bundled template key for a genuine first install.
575 + */
576 +function wpbc_bfb_activation__get_initial_standard_template_key() {
577 +
578 + return 'dates_vertical_hints_full_days';
579 +}
580 +
581 +/**
582 582 * Maybe create the initial standard BFB form from a bundled template.
583 583 *
584 584 * Used only during brand new plugin activation, before booking_version_num
585 585 * gets updated. Upgrades keep migrating the existing legacy configuration.
@@ -585,9 +585,9 @@
585 585 * gets updated. Upgrades keep migrating the existing legacy configuration.
586 586 *
587 587 * @return bool
588 588 */
589 -function wpbc_bfb_maybe_create_initial_standard_form_from_template() {
589 +function wpbc_bfb_maybe_create_initial_standard_form_from_template() {
590 590
591 591 if ( ! wpbc_bfb_is_brand_new_install__before_version_update() ) {
592 592 return false;
593 593 }
@@ -595,21 +595,21 @@
595 595 if ( ! class_exists( 'WPBC_BFB_Form_Storage' ) ) {
596 596 return false;
597 597 }
598 598
599 - if ( function_exists( 'wpbc_get_bfb_template_record_by_key' ) ) {
600 - $template_key = wpbc_bfb_activation__get_initial_standard_template_key();
601 - $template_record = wpbc_get_bfb_template_record_by_key( $template_key );
602 -
603 - // Preserve a usable first-install form if a registry filter removes the
604 - // new starter template.
605 - if ( empty( $template_record ) && 'dates_2_columns_sidebar_hints' !== $template_key ) {
606 - $template_record = wpbc_get_bfb_template_record_by_key( 'dates_2_columns_sidebar_hints' );
607 - }
608 - } else {
609 - $template_record = array();
610 - }
599 + if ( function_exists( 'wpbc_get_bfb_template_record_by_key' ) ) {
600 + $template_key = wpbc_bfb_activation__get_initial_standard_template_key();
601 + $template_record = wpbc_get_bfb_template_record_by_key( $template_key );
611 602
603 + // Preserve a usable first-install form if a registry filter removes the
604 + // new starter template.
605 + if ( empty( $template_record ) && 'dates_2_columns_sidebar_hints' !== $template_key ) {
606 + $template_record = wpbc_get_bfb_template_record_by_key( 'dates_2_columns_sidebar_hints' );
607 + }
608 + } else {
609 + $template_record = array();
610 + }
611 +
612 612 if ( empty( $template_record ) || ! is_array( $template_record ) ) {
613 613 return false;
614 614 }
615 615
@@ -629,320 +629,320 @@
629 629 }
630 630
631 631 $booking_form_id = WPBC_BFB_Form_Storage::save_form( $template_record );
632 632
633 - return ! empty( $booking_form_id );
634 -}
635 -
636 -
637 -/**
638 - * Get the dedicated bundled template for the current live-demo edition.
639 - *
640 - * @param int $owner_user_id Optional MultiUser owner ID.
641 - *
642 - * @return string Template key, or an empty string outside a supported demo.
643 - */
644 -function wpbc_bfb_live_demo__get_template_key( $owner_user_id = 0 ) {
645 -
646 - if ( ! function_exists( 'wpbc_is_this_demo' ) || ! wpbc_is_this_demo() ) {
647 - return '';
648 - }
649 -
650 - $owner_user_id = absint( $owner_user_id );
651 -
652 - if ( class_exists( 'wpdev_bk_multiuser' ) ) {
653 - return ( $owner_user_id > 0 ) ? 'demo_multiuser_owner_1' : 'demo_multiuser';
654 - }
655 - if ( class_exists( 'wpdev_bk_biz_l' ) ) {
656 - return 'demo_business_large';
657 - }
658 - if ( class_exists( 'wpdev_bk_biz_m' ) ) {
659 - return 'demo_business_medium';
660 - }
661 - if ( class_exists( 'wpdev_bk_biz_s' ) ) {
662 - return 'demo_business_small';
663 - }
664 - if ( class_exists( 'wpdev_bk_personal' ) ) {
665 - return 'demo_personal';
666 - }
667 -
668 - return '';
669 -}
670 -
671 -
672 -/**
673 - * Get the global Form Style used by the current live-demo edition.
674 - *
675 - * @return string Form Style preset key.
676 - */
677 -function wpbc_bfb_live_demo__get_form_style() {
678 -
679 - if ( class_exists( 'wpdev_bk_multiuser' ) || class_exists( 'wpdev_bk_biz_l' ) ) {
680 - return 'light_bordered';
681 - }
682 - if ( class_exists( 'wpdev_bk_biz_m' ) ) {
683 - return 'light_soft';
684 - }
685 - if ( class_exists( 'wpdev_bk_biz_s' ) ) {
686 - return 'light_bordered';
687 - }
688 - if ( class_exists( 'wpdev_bk_personal' ) ) {
689 - return 'light_none';
690 - }
691 -
692 - return 'light_bordered';
693 -}
694 -
695 -
696 -/**
697 - * Provision a live-demo standard form from a real bundled BFB template.
698 - *
699 - * Normal owner activation is idempotent and preserves an existing form. The
700 - * explicit demo reset path may request replacement to restore fixture data.
701 - *
702 - * @param int $owner_user_id Owner ID, or 0 for the global/Super Admin form.
703 - * @param string $template_key Optional explicit bundled template key.
704 - * @param bool $replace Whether to replace an existing standard form.
705 - *
706 - * @return int|false Booking form ID on success, false on failure.
707 - */
708 -function wpbc_bfb_live_demo__provision_standard_form( $owner_user_id = 0, $template_key = '', $replace = false ) {
709 -
710 - if ( ! function_exists( 'wpbc_is_this_demo' ) || ! wpbc_is_this_demo() ) {
711 - return false;
712 - }
713 - if ( ! class_exists( 'WPBC_BFB_Form_Storage' ) ) {
714 - return false;
715 - }
716 - if ( function_exists( 'wpbc_is_table_exists' ) && ! wpbc_is_table_exists( 'booking_form_structures' ) ) {
717 - return false;
718 - }
719 -
720 - $owner_user_id = absint( $owner_user_id );
721 - $template_key = sanitize_key( (string) $template_key );
722 - if ( '' === $template_key ) {
723 - $template_key = wpbc_bfb_live_demo__get_template_key( $owner_user_id );
724 - }
725 - if ( '' === $template_key ) {
726 - return false;
727 - }
728 -
729 - $existing = WPBC_BFB_Form_Storage::get_current_form_by_key( 'standard', $owner_user_id, 'published' );
730 - if ( ! empty( $existing->booking_form_id ) && ! $replace ) {
731 - return (int) $existing->booking_form_id;
732 - }
733 -
734 - $template_record = function_exists( 'wpbc_get_bfb_template_record_by_key' )
735 - ? wpbc_get_bfb_template_record_by_key( $template_key )
736 - : array();
737 -
738 - if (
739 - empty( $template_record ) ||
740 - ! is_array( $template_record ) ||
741 - empty( $template_record['structure_json'] ) ||
742 - empty( $template_record['engine'] ) ||
743 - 'bfb' !== (string) $template_record['engine']
744 - ) {
745 - return false;
746 - }
747 -
748 - $template_record['form_slug'] = 'standard';
749 - $template_record['status'] = 'published';
750 - $template_record['scope'] = ( $owner_user_id > 0 ) ? 'user' : 'global';
751 - $template_record['owner_user_id'] = $owner_user_id;
752 - $template_record['booking_resource_id'] = null;
753 - $template_record['is_default'] = 1;
754 - $template_record['title'] = __( 'Standard', 'booking' );
755 - $template_record['description'] = '';
756 - $template_record['picture_url'] = isset( $template_record['picture_url'] ) ? (string) $template_record['picture_url'] : '';
757 -
758 - if ( function_exists( 'wpbc_bfb_resolve_picture_url' ) ) {
759 - $template_record['picture_url'] = wpbc_bfb_resolve_picture_url( $template_record['picture_url'] );
760 - }
761 -
762 - $booking_form_id = WPBC_BFB_Form_Storage::save_form( $template_record );
763 -
764 - return ! empty( $booking_form_id ) ? (int) $booking_form_id : false;
765 -}
766 -
767 -
768 -/**
769 - * Return regular-owner fixtures used by the MultiUser live demo.
770 - *
771 - * @return array Owner user ID => bundled template key.
772 - */
773 -function wpbc_bfb_live_demo__get_multiuser_owner_template_map() {
774 -
775 - $owner_templates = array(
776 - 3 => 'demo_multiuser_owner_1',
777 - 4 => 'demo_multiuser_owner_2',
778 - 5 => 'demo_multiuser_owner_3',
779 - );
780 -
781 - /**
782 - * Allow a private demo installation to use different owner IDs while
783 - * retaining the same centralized provisioning flow.
784 - *
785 - * @param array $owner_templates Owner user ID => template key.
786 - */
787 - $owner_templates = apply_filters( 'wpbc_bfb_live_demo_multiuser_owner_templates', $owner_templates );
788 -
789 - return is_array( $owner_templates ) ? $owner_templates : array();
790 -}
791 -
792 -
793 -/**
794 - * Apply all standard-form fixtures required by the active live demo.
795 - *
796 - * This is the canonical final activation step. It intentionally replaces demo
797 - * fixtures, but never runs on customer installations.
798 - *
799 - * @return bool True when every applicable fixture was saved.
800 - */
801 -function wpbc_bfb_live_demo__provision_all_standard_forms() {
802 -
803 - if ( ! function_exists( 'wpbc_is_this_demo' ) || ! wpbc_is_this_demo() ) {
804 - return false;
805 - }
806 -
807 - // Pro-only reactivation does not necessarily rerun the Free activation
808 - // callback that normally synchronizes bundled template rows.
809 - if ( function_exists( 'wpbc_bfb_activation__seed_templates' ) ) {
810 - wpbc_bfb_activation__seed_templates();
811 - }
812 -
813 - $is_success = ( false !== wpbc_bfb_live_demo__provision_standard_form( 0, '', true ) );
814 -
815 - // Form Style is a site-wide setting, not part of an individual form row.
816 - // Write directly to the global option so the result is deterministic even
817 - // when finalization runs from a regular MultiUser administrator session.
818 - update_option( 'booking_form_style', wpbc_bfb_live_demo__get_form_style() );
819 -
820 - // Live demos intentionally showcase the shared accent experience. Customer
821 - // installations keep the backward-compatible disabled default.
822 - $form_accent_defaults = function_exists( 'wpbc_bfb_settings__get_default_form_accent_options' )
823 - ? wpbc_bfb_settings__get_default_form_accent_options()
824 - : array( 'booking_form_accent_color' => WPBC_DEFAULT_FORM_ACCENT_COLOR );
825 - update_option( 'booking_form_accent_enabled', 'On' );
826 - update_option( 'booking_form_accent_color', $form_accent_defaults['booking_form_accent_color'] );
827 -
828 - if ( class_exists( 'wpdev_bk_multiuser' ) ) {
829 - foreach ( wpbc_bfb_live_demo__get_multiuser_owner_template_map() as $owner_user_id => $template_key ) {
830 - $owner_user_id = absint( $owner_user_id );
831 - $template_key = sanitize_key( (string) $template_key );
832 - if ( $owner_user_id <= 0 || '' === $template_key ) {
833 - $is_success = false;
834 - continue;
835 - }
836 -
837 - if ( function_exists( 'get_userdata' ) && ! get_userdata( $owner_user_id ) ) {
838 - $is_success = false;
839 - continue;
840 - }
841 -
842 - if ( false === wpbc_bfb_live_demo__provision_standard_form( $owner_user_id, $template_key, true ) ) {
843 - $is_success = false;
844 - }
845 - }
846 - }
847 -
848 - return $is_success;
849 -}
850 -
851 -
852 -/**
853 - * Ensure that a regular MultiUser owner has an independent standard BFB form.
854 - *
855 - * Existing owner forms are never overwritten. On normal installations the
856 - * current global standard form is cloned, preserving the Super Admin's chosen
857 - * Builder structure. Live demos use their dedicated bundled fixture instead.
858 - *
859 - * @param int $owner_user_id Regular MultiUser owner ID.
860 - *
861 - * @return int|false Booking form ID on success, false on failure.
862 - */
863 -function wpbc_bfb_ensure_standard_form_for_owner( $owner_user_id ) {
864 -
865 - $owner_user_id = absint( $owner_user_id );
866 - if ( $owner_user_id <= 0 || ! class_exists( 'WPBC_BFB_Form_Storage' ) ) {
867 - return false;
868 - }
869 - if ( function_exists( 'wpbc_is_table_exists' ) && ! wpbc_is_table_exists( 'booking_form_structures' ) ) {
870 - return false;
871 - }
872 -
873 - $existing = WPBC_BFB_Form_Storage::get_current_form_by_key( 'standard', $owner_user_id, 'published' );
874 - if ( ! empty( $existing->booking_form_id ) ) {
875 - return (int) $existing->booking_form_id;
876 - }
877 -
878 - if ( function_exists( 'wpbc_is_this_demo' ) && wpbc_is_this_demo() ) {
879 - return wpbc_bfb_live_demo__provision_standard_form( $owner_user_id, '', false );
880 - }
881 -
882 - $global_standard = WPBC_BFB_Form_Storage::get_current_form_by_key( 'standard', 0, 'published' );
883 - $form_record = ! empty( $global_standard ) ? get_object_vars( $global_standard ) : array();
884 -
885 - if ( empty( $form_record['structure_json'] ) && function_exists( 'wpbc_get_bfb_template_record_by_key' ) ) {
886 - $form_record = wpbc_get_bfb_template_record_by_key( 'dates_2_columns_sidebar_hints' );
887 - }
888 - if (
889 - empty( $form_record ) ||
890 - ! is_array( $form_record ) ||
891 - empty( $form_record['structure_json'] ) ||
892 - empty( $form_record['engine'] ) ||
893 - 'bfb' !== (string) $form_record['engine']
894 - ) {
895 - return false;
896 - }
897 -
898 - unset(
899 - $form_record['booking_form_id'],
900 - $form_record['created_at'],
901 - $form_record['created_by'],
902 - $form_record['updated_at'],
903 - $form_record['updated_by']
904 - );
905 -
906 - $form_record['form_slug'] = 'standard';
907 - $form_record['status'] = 'published';
908 - $form_record['scope'] = 'user';
909 - $form_record['owner_user_id'] = $owner_user_id;
910 - $form_record['booking_resource_id'] = null;
911 - $form_record['is_default'] = 1;
912 - $form_record['title'] = __( 'Standard', 'booking' );
913 - $form_record['description'] = '';
914 -
915 - $booking_form_id = WPBC_BFB_Form_Storage::save_form( $form_record );
916 -
917 - return ! empty( $booking_form_id ) ? (int) $booking_form_id : false;
918 -}
633 + return ! empty( $booking_form_id );
634 +}
919 635
636 +
920 637 /**
638 + * Get the dedicated bundled template for the current live-demo edition.
639 + *
640 + * @param int $owner_user_id Optional MultiUser owner ID.
641 + *
642 + * @return string Template key, or an empty string outside a supported demo.
643 + */
644 +function wpbc_bfb_live_demo__get_template_key( $owner_user_id = 0 ) {
645 +
646 + if ( ! function_exists( 'wpbc_is_this_demo' ) || ! wpbc_is_this_demo() ) {
647 + return '';
648 + }
649 +
650 + $owner_user_id = absint( $owner_user_id );
651 +
652 + if ( class_exists( 'wpdev_bk_multiuser' ) ) {
653 + return ( $owner_user_id > 0 ) ? 'demo_multiuser_owner_1' : 'demo_multiuser';
654 + }
655 + if ( class_exists( 'wpdev_bk_biz_l' ) ) {
656 + return 'demo_business_large';
657 + }
658 + if ( class_exists( 'wpdev_bk_biz_m' ) ) {
659 + return 'demo_business_medium';
660 + }
661 + if ( class_exists( 'wpdev_bk_biz_s' ) ) {
662 + return 'demo_business_small';
663 + }
664 + if ( class_exists( 'wpdev_bk_personal' ) ) {
665 + return 'demo_personal';
666 + }
667 +
668 + return '';
669 +}
670 +
671 +
672 +/**
673 + * Get the global Form Style used by the current live-demo edition.
674 + *
675 + * @return string Form Style preset key.
676 + */
677 +function wpbc_bfb_live_demo__get_form_style() {
678 +
679 + if ( class_exists( 'wpdev_bk_multiuser' ) || class_exists( 'wpdev_bk_biz_l' ) ) {
680 + return 'light_bordered';
681 + }
682 + if ( class_exists( 'wpdev_bk_biz_m' ) ) {
683 + return 'light_soft';
684 + }
685 + if ( class_exists( 'wpdev_bk_biz_s' ) ) {
686 + return 'light_bordered';
687 + }
688 + if ( class_exists( 'wpdev_bk_personal' ) ) {
689 + return 'light_none';
690 + }
691 +
692 + return 'light_bordered';
693 +}
694 +
695 +
696 +/**
697 + * Provision a live-demo standard form from a real bundled BFB template.
698 + *
699 + * Normal owner activation is idempotent and preserves an existing form. The
700 + * explicit demo reset path may request replacement to restore fixture data.
701 + *
702 + * @param int $owner_user_id Owner ID, or 0 for the global/Super Admin form.
703 + * @param string $template_key Optional explicit bundled template key.
704 + * @param bool $replace Whether to replace an existing standard form.
705 + *
706 + * @return int|false Booking form ID on success, false on failure.
707 + */
708 +function wpbc_bfb_live_demo__provision_standard_form( $owner_user_id = 0, $template_key = '', $replace = false ) {
709 +
710 + if ( ! function_exists( 'wpbc_is_this_demo' ) || ! wpbc_is_this_demo() ) {
711 + return false;
712 + }
713 + if ( ! class_exists( 'WPBC_BFB_Form_Storage' ) ) {
714 + return false;
715 + }
716 + if ( function_exists( 'wpbc_is_table_exists' ) && ! wpbc_is_table_exists( 'booking_form_structures' ) ) {
717 + return false;
718 + }
719 +
720 + $owner_user_id = absint( $owner_user_id );
721 + $template_key = sanitize_key( (string) $template_key );
722 + if ( '' === $template_key ) {
723 + $template_key = wpbc_bfb_live_demo__get_template_key( $owner_user_id );
724 + }
725 + if ( '' === $template_key ) {
726 + return false;
727 + }
728 +
729 + $existing = WPBC_BFB_Form_Storage::get_current_form_by_key( 'standard', $owner_user_id, 'published' );
730 + if ( ! empty( $existing->booking_form_id ) && ! $replace ) {
731 + return (int) $existing->booking_form_id;
732 + }
733 +
734 + $template_record = function_exists( 'wpbc_get_bfb_template_record_by_key' )
735 + ? wpbc_get_bfb_template_record_by_key( $template_key )
736 + : array();
737 +
738 + if (
739 + empty( $template_record ) ||
740 + ! is_array( $template_record ) ||
741 + empty( $template_record['structure_json'] ) ||
742 + empty( $template_record['engine'] ) ||
743 + 'bfb' !== (string) $template_record['engine']
744 + ) {
745 + return false;
746 + }
747 +
748 + $template_record['form_slug'] = 'standard';
749 + $template_record['status'] = 'published';
750 + $template_record['scope'] = ( $owner_user_id > 0 ) ? 'user' : 'global';
751 + $template_record['owner_user_id'] = $owner_user_id;
752 + $template_record['booking_resource_id'] = null;
753 + $template_record['is_default'] = 1;
754 + $template_record['title'] = __( 'Standard', 'booking' );
755 + $template_record['description'] = '';
756 + $template_record['picture_url'] = isset( $template_record['picture_url'] ) ? (string) $template_record['picture_url'] : '';
757 +
758 + if ( function_exists( 'wpbc_bfb_resolve_picture_url' ) ) {
759 + $template_record['picture_url'] = wpbc_bfb_resolve_picture_url( $template_record['picture_url'] );
760 + }
761 +
762 + $booking_form_id = WPBC_BFB_Form_Storage::save_form( $template_record );
763 +
764 + return ! empty( $booking_form_id ) ? (int) $booking_form_id : false;
765 +}
766 +
767 +
768 +/**
769 + * Return regular-owner fixtures used by the MultiUser live demo.
770 + *
771 + * @return array Owner user ID => bundled template key.
772 + */
773 +function wpbc_bfb_live_demo__get_multiuser_owner_template_map() {
774 +
775 + $owner_templates = array(
776 + 3 => 'demo_multiuser_owner_1',
777 + 4 => 'demo_multiuser_owner_2',
778 + 5 => 'demo_multiuser_owner_3',
779 + );
780 +
781 + /**
782 + * Allow a private demo installation to use different owner IDs while
783 + * retaining the same centralized provisioning flow.
784 + *
785 + * @param array $owner_templates Owner user ID => template key.
786 + */
787 + $owner_templates = apply_filters( 'wpbc_bfb_live_demo_multiuser_owner_templates', $owner_templates );
788 +
789 + return is_array( $owner_templates ) ? $owner_templates : array();
790 +}
791 +
792 +
793 +/**
794 + * Apply all standard-form fixtures required by the active live demo.
795 + *
796 + * This is the canonical final activation step. It intentionally replaces demo
797 + * fixtures, but never runs on customer installations.
798 + *
799 + * @return bool True when every applicable fixture was saved.
800 + */
801 +function wpbc_bfb_live_demo__provision_all_standard_forms() {
802 +
803 + if ( ! function_exists( 'wpbc_is_this_demo' ) || ! wpbc_is_this_demo() ) {
804 + return false;
805 + }
806 +
807 + // Pro-only reactivation does not necessarily rerun the Free activation
808 + // callback that normally synchronizes bundled template rows.
809 + if ( function_exists( 'wpbc_bfb_activation__seed_templates' ) ) {
810 + wpbc_bfb_activation__seed_templates();
811 + }
812 +
813 + $is_success = ( false !== wpbc_bfb_live_demo__provision_standard_form( 0, '', true ) );
814 +
815 + // Form Style is a site-wide setting, not part of an individual form row.
816 + // Write directly to the global option so the result is deterministic even
817 + // when finalization runs from a regular MultiUser administrator session.
818 + update_option( 'booking_form_style', wpbc_bfb_live_demo__get_form_style() );
819 +
820 + // Live demos intentionally showcase the shared accent experience. Customer
821 + // installations keep the backward-compatible disabled default.
822 + $form_accent_defaults = function_exists( 'wpbc_bfb_settings__get_default_form_accent_options' )
823 + ? wpbc_bfb_settings__get_default_form_accent_options()
824 + : array( 'booking_form_accent_color' => WPBC_DEFAULT_FORM_ACCENT_COLOR );
825 + update_option( 'booking_form_accent_enabled', 'On' );
826 + update_option( 'booking_form_accent_color', $form_accent_defaults['booking_form_accent_color'] );
827 +
828 + if ( class_exists( 'wpdev_bk_multiuser' ) ) {
829 + foreach ( wpbc_bfb_live_demo__get_multiuser_owner_template_map() as $owner_user_id => $template_key ) {
830 + $owner_user_id = absint( $owner_user_id );
831 + $template_key = sanitize_key( (string) $template_key );
832 + if ( $owner_user_id <= 0 || '' === $template_key ) {
833 + $is_success = false;
834 + continue;
835 + }
836 +
837 + if ( function_exists( 'get_userdata' ) && ! get_userdata( $owner_user_id ) ) {
838 + $is_success = false;
839 + continue;
840 + }
841 +
842 + if ( false === wpbc_bfb_live_demo__provision_standard_form( $owner_user_id, $template_key, true ) ) {
843 + $is_success = false;
844 + }
845 + }
846 + }
847 +
848 + return $is_success;
849 +}
850 +
851 +
852 +/**
853 + * Ensure that a regular MultiUser owner has an independent standard BFB form.
854 + *
855 + * Existing owner forms are never overwritten. On normal installations the
856 + * current global standard form is cloned, preserving the Super Admin's chosen
857 + * Builder structure. Live demos use their dedicated bundled fixture instead.
858 + *
859 + * @param int $owner_user_id Regular MultiUser owner ID.
860 + *
861 + * @return int|false Booking form ID on success, false on failure.
862 + */
863 +function wpbc_bfb_ensure_standard_form_for_owner( $owner_user_id ) {
864 +
865 + $owner_user_id = absint( $owner_user_id );
866 + if ( $owner_user_id <= 0 || ! class_exists( 'WPBC_BFB_Form_Storage' ) ) {
867 + return false;
868 + }
869 + if ( function_exists( 'wpbc_is_table_exists' ) && ! wpbc_is_table_exists( 'booking_form_structures' ) ) {
870 + return false;
871 + }
872 +
873 + $existing = WPBC_BFB_Form_Storage::get_current_form_by_key( 'standard', $owner_user_id, 'published' );
874 + if ( ! empty( $existing->booking_form_id ) ) {
875 + return (int) $existing->booking_form_id;
876 + }
877 +
878 + if ( function_exists( 'wpbc_is_this_demo' ) && wpbc_is_this_demo() ) {
879 + return wpbc_bfb_live_demo__provision_standard_form( $owner_user_id, '', false );
880 + }
881 +
882 + $global_standard = WPBC_BFB_Form_Storage::get_current_form_by_key( 'standard', 0, 'published' );
883 + $form_record = ! empty( $global_standard ) ? get_object_vars( $global_standard ) : array();
884 +
885 + if ( empty( $form_record['structure_json'] ) && function_exists( 'wpbc_get_bfb_template_record_by_key' ) ) {
886 + $form_record = wpbc_get_bfb_template_record_by_key( 'dates_2_columns_sidebar_hints' );
887 + }
888 + if (
889 + empty( $form_record ) ||
890 + ! is_array( $form_record ) ||
891 + empty( $form_record['structure_json'] ) ||
892 + empty( $form_record['engine'] ) ||
893 + 'bfb' !== (string) $form_record['engine']
894 + ) {
895 + return false;
896 + }
897 +
898 + unset(
899 + $form_record['booking_form_id'],
900 + $form_record['created_at'],
901 + $form_record['created_by'],
902 + $form_record['updated_at'],
903 + $form_record['updated_by']
904 + );
905 +
906 + $form_record['form_slug'] = 'standard';
907 + $form_record['status'] = 'published';
908 + $form_record['scope'] = 'user';
909 + $form_record['owner_user_id'] = $owner_user_id;
910 + $form_record['booking_resource_id'] = null;
911 + $form_record['is_default'] = 1;
912 + $form_record['title'] = __( 'Standard', 'booking' );
913 + $form_record['description'] = '';
914 +
915 + $booking_form_id = WPBC_BFB_Form_Storage::save_form( $form_record );
916 +
917 + return ! empty( $booking_form_id ) ? (int) $booking_form_id : false;
918 +}
919 +
920 +/**
921 921 * Import legacy "standard" booking form as initial BFB structure.
922 922 *
923 923 * @return void
924 924 */
925 -function wpbc_bfb__import_old_booking_forms() {
926 -
927 - if ( wpbc_bfb_maybe_create_initial_standard_form_from_template() ) {
928 - return;
929 - }
930 -
931 - if ( function_exists( 'wpbc_bfb_import_legacy_forms' ) ) {
932 - wpbc_bfb_import_legacy_forms(
933 - array(
934 - 'mode' => 'all_global',
935 - 'import_standard' => true,
936 - 'import_custom' => true,
937 - 'skip_if_exists' => true,
938 - 'set_bfb_form_not_defined' => false,
939 - )
940 - );
941 - }
942 -}
925 +function wpbc_bfb__import_old_booking_forms() {
943 926
927 + if ( wpbc_bfb_maybe_create_initial_standard_form_from_template() ) {
928 + return;
929 + }
944 930
931 + if ( function_exists( 'wpbc_bfb_import_legacy_forms' ) ) {
932 + wpbc_bfb_import_legacy_forms(
933 + array(
934 + 'mode' => 'all_global',
935 + 'import_standard' => true,
936 + 'import_custom' => true,
937 + 'skip_if_exists' => true,
938 + 'set_bfb_form_not_defined' => false,
939 + )
940 + );
941 + }
942 +}
943 +
944 +
945 945 /**
946 946 * Remove BFB Preview page from rendered nav menus.
947 947 *
948 948 * @param array $sorted_menu_items Menu item objects.
@@ -1203,50 +1203,50 @@
1203 1203 * $mode = 'all_users'; // Import booking forms for == All Users ==.
1204 1204 *
1205 1205 * @return void
1206 1206 */
1207 -function wpbc_bfb_import_legacy_forms__on_activation() {
1207 +function wpbc_bfb_import_legacy_forms__on_activation() {
1208 1208
1209 1209 if ( ! is_admin() ) {
1210 1210 return;
1211 1211 }
1212 1212
1213 - if ( false === ( $is_in_action_late_activation = get_transient( 'wpbc_pro_versions__late_activation_60' ) ) ) {
1214 - return;
1215 - }
1216 -
1217 - delete_transient( 'wpbc_pro_versions__late_activation_60' );
1218 -
1219 - $import_version = '11.3.1';
1220 -
1221 - // Live demos use dedicated BFB fixtures as their canonical source. Importing
1222 - // legacy options here would overwrite the fixtures installed during the
1223 - // activation request, especially because the old demo importer used
1224 - // skip_if_exists=false.
1225 - if ( wpbc_is_this_demo() ) {
1226 - if ( wpbc_bfb_live_demo__provision_all_standard_forms() ) {
1227 - update_option( 'wpbc_bfb_legacy_import_done_for_pro', $import_version );
1228 - } else {
1229 - // Keep a bounded retry available if activation dependencies were not
1230 - // ready yet on this request.
1231 - $retry_count = is_numeric( $is_in_action_late_activation ) ? absint( $is_in_action_late_activation ) : 0;
1232 - if ( $retry_count < 3 ) {
1233 - set_transient( 'wpbc_pro_versions__late_activation_60', $retry_count + 1, HOUR_IN_SECONDS );
1234 - }
1235 - }
1236 - return;
1237 - }
1238 -
1239 - if ( $import_version === get_option( 'wpbc_bfb_legacy_import_done_for_pro', '' ) ) {
1240 - return;
1241 - }
1242 -
1243 - $summary = wpbc_bfb_import_legacy_forms(
1213 + if ( false === ( $is_in_action_late_activation = get_transient( 'wpbc_pro_versions__late_activation_60' ) ) ) {
1214 + return;
1215 + }
1216 +
1217 + delete_transient( 'wpbc_pro_versions__late_activation_60' );
1218 +
1219 + $import_version = '11.3.1';
1220 +
1221 + // Live demos use dedicated BFB fixtures as their canonical source. Importing
1222 + // legacy options here would overwrite the fixtures installed during the
1223 + // activation request, especially because the old demo importer used
1224 + // skip_if_exists=false.
1225 + if ( wpbc_is_this_demo() ) {
1226 + if ( wpbc_bfb_live_demo__provision_all_standard_forms() ) {
1227 + update_option( 'wpbc_bfb_legacy_import_done_for_pro', $import_version );
1228 + } else {
1229 + // Keep a bounded retry available if activation dependencies were not
1230 + // ready yet on this request.
1231 + $retry_count = is_numeric( $is_in_action_late_activation ) ? absint( $is_in_action_late_activation ) : 0;
1232 + if ( $retry_count < 3 ) {
1233 + set_transient( 'wpbc_pro_versions__late_activation_60', $retry_count + 1, HOUR_IN_SECONDS );
1234 + }
1235 + }
1236 + return;
1237 + }
1238 +
1239 + if ( $import_version === get_option( 'wpbc_bfb_legacy_import_done_for_pro', '' ) ) {
1240 + return;
1241 + }
1242 +
1243 + $summary = wpbc_bfb_import_legacy_forms(
1244 1244 array(
1245 1245 'mode' => ( class_exists( 'wpdev_bk_multiuser' ) ) ? 'all_users' : 'all_global',
1246 1246 'import_standard' => true,
1247 1247 'import_custom' => true,
1248 - 'skip_if_exists' => true,
1248 + 'skip_if_exists' => true,
1249 1249 'set_bfb_form_not_defined' => true,
1250 1250 )
1251 1251 );
1252 1252 update_option( 'wpbc_bfb_legacy_import_done_for_pro', $import_version );
@@ -1258,17 +1258,17 @@
1258 1258 * Schedule one deferred legacy-form import after Pro activation. The import runs on a later request while this transient exists.
1259 1259 *
1260 1260 * @return void
1261 1261 */
1262 -function wpbc_pro_versions__late_activation(){
1263 -
1264 - // A regular MultiUser owner activation runs the Pro activation callbacks in
1265 - // its own context. It must not schedule a later demo-wide reset.
1266 - if ( false !== apply_bk_filter( 'wpbc_is_user_in_activation_process' ) ) {
1267 - return;
1268 - }
1269 -
1270 - // Get any existing copy of our transient data
1262 +function wpbc_pro_versions__late_activation(){
1263 +
1264 + // A regular MultiUser owner activation runs the Pro activation callbacks in
1265 + // its own context. It must not schedule a later demo-wide reset.
1266 + if ( false !== apply_bk_filter( 'wpbc_is_user_in_activation_process' ) ) {
1267 + return;
1268 + }
1269 +
1270 + // Get any existing copy of our transient data
1271 1271 if ( false === ( $is_in_action_late_activation = get_transient( 'wpbc_pro_versions__late_activation_60' ) ) ) {
1272 1272 // It wasn't there, so regenerate the data and save the transient
1273 1273 $is_in_action_late_activation = true;
1274 1274 set_transient( 'wpbc_pro_versions__late_activation_60', $is_in_action_late_activation, HOUR_IN_SECONDS );