<?php
if ( ! defined( 'ABSPATH' ) ) exit;                                             // Exit if accessed directly

class wpdev_booking {

    public $popover_front_end_js_is_writed;		//FixIn: Flex TimeLine 1.0		-- previos this was private and not public property

    // <editor-fold defaultstate="collapsed" desc="  C O N S T R U C T O R  &  P r o p e r t i e s ">

    var $wpdev_bk_personal;

    function __construct() {

	    $this->popover_front_end_js_is_writed = false;

	    if ( class_exists( 'wpdev_bk_personal' ) ) {
		    $this->wpdev_bk_personal = new wpdev_bk_personal();
	    } else {
		    $this->wpdev_bk_personal = false;
	    }

		// User defined - hooks
		add_action( 'wpdev_bk_add_calendar', array( &$this, 'add_calendar_action' ), 10, 2 );
		add_action( 'wpdev_bk_add_form', array( &$this, 'add_booking_form_action' ), 10, 2 );
		add_bk_action( 'wpdevbk_add_form', array( &$this, 'add_booking_form_action' ) );
		add_filter( 'wpdev_bk_get_form', array( &$this, 'get_booking_form_action' ), 10, 2 );
		add_bk_filter( 'wpdevbk_get_booking_form', array( &$this, 'get_booking_form_action' ) );
		add_filter( 'wpdev_bk_get_showing_date_format', array( &$this, 'get_showing_date_format' ), 10, 1 );

	    // Get script for calendar activation
		add_bk_filter( 'pre_get_calendar_html', 'wpbc_pre_get_calendar_html' );

	    add_action( 'init', array( $this, 'wpbc_shortcodes_init' ), 9999 );              // <- priority  to  load it last
    }
    // </editor-fold>


	/**
	 *  S H O R T C O D E s      Init
	 *
	 * @return void
	 */
	function wpbc_shortcodes_init(){
	    add_shortcode( 'booking',                array( &$this, 'booking_shortcode' ) );
	    add_shortcode( 'bookingcalendar',        array( &$this, 'booking_calendar_only_shortcode' ) );
	    add_shortcode( 'bookingform',            array( &$this, 'bookingform_shortcode' ) );
	    add_shortcode( 'bookingedit',            array( &$this, 'bookingedit_shortcode' ) );
	    add_shortcode( 'bookingsearch',          array( &$this, 'bookingsearch_shortcode' ) );
	    add_shortcode( 'bookingsearchresults',   array( &$this, 'bookingsearchresults_shortcode' ) );
	    add_shortcode( 'bookingselect',          array( &$this, 'bookingselect_shortcode' ) );
	    add_shortcode( 'bookingresource',        array( &$this, 'bookingresource_shortcode' ) );
	    add_shortcode( 'bookingtimeline',        array( &$this, 'bookingtimeline_shortcode' ) );
	    add_shortcode( 'bookingcustomerlisting', array( &$this, 'bookingcustomerlisting_shortcode' ) );					// FixIn: 8.1.3.5.
	}


    // <editor-fold defaultstate="collapsed" desc="   S U P P O R T     F U N C T I O N S     ">

	    function silent_deactivate_WPBC() {
	        deactivate_plugins( WPBC_PLUGIN_DIRNAME . '/' . WPBC_PLUGIN_FILENAME, true );
	    }


	    // Change date format
		function get_showing_date_format( $mydate ) {
			$date_format = get_bk_option( 'booking_date_format' );
			if ( $date_format == '' ) {
				$date_format = "d.m.Y";
			}

			$time_format = get_bk_option( 'booking_time_format' );
			if ( $time_format !== false ) {
				$time_format = ' ' . $time_format;
				$my_time     = gmdate( 'H:i:s', $mydate );
				if ( $my_time == '00:00:00' ) {
					$time_format = '';
				}
			} else {
				$time_format = '';
			}

			// return gmdate($date_format . $time_format , $mydate);
			return date_i18n( $date_format, $mydate ) . '<sup class="booking-table-time">' . date_i18n( $time_format, $mydate ) . '</sup>';
		}

    // </editor-fold>


    // <editor-fold defaultstate="collapsed" desc="   B O O K I N G s       A D M I N       F U N C T I O N s   ">

		/**
		 * Generate booking CAPTCHA fields  for booking form
		 *
		 * @param $bk_tp    resource ID
		 *
		 * @return string|true
		 */
	    function createCapthaContent($bk_tp) {

		    $admin_uri = ltrim( str_replace( get_site_url( null, '', 'admin' ), '', admin_url( 'admin.php?' ) ), '/' );

			$server_request_uri = ( ( isset( $_SERVER['REQUEST_URI'] ) ) ? sanitize_text_field( $_SERVER['REQUEST_URI'] ) : '' );  /* phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash */ /* FixIn: sanitize_unslash */

		    if ( ( get_bk_option( 'booking_is_use_captcha' ) !== 'On' )
		         || (
					      ( strpos( $server_request_uri, $admin_uri ) !== false )
		               && ( ! wpbc_is_settings_form_page() )
		            )
		    ) {
			    return '';
		    } else {

			    $html = wpbc_captcha__simple__generate_html_content( $bk_tp );

			    return $html;
		    }
	    }

	    // Get default Booking resource
	    function get_default_type() {

		    if ( $this->wpdev_bk_personal !== false ) {
			    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
			    if ( ( isset( $_GET['booking_type'] ) ) && ( $_GET['booking_type'] != '' ) ) {
				    $bk_type = sanitize_text_field( wp_unslash( $_GET['booking_type'] ) );  /* phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing */ /* FixIn: sanitize_unslash */
			    } else {
				    $bk_type = $this->wpdev_bk_personal->get_default_booking_resource_id();
			    }
		    } else {
			    $bk_type = 1;
		    }

		    return $bk_type;
	    }

    // </editor-fold>


    // <editor-fold defaultstate="collapsed" desc="   C L I E N T   S I D E     &    H O O K S ">


			/**
			 * Deprecated! Get booking form
			 *
			 * @param $resource_id
			 * @param $my_boook_count
			 * @param $my_booking_form
			 * @param $my_selected_dates_without_calendar
			 * @param $start_month_calendar
			 * @param $bk_otions
			 *
			 * @return mixed|string|null
			 */
			function get_booking_form_action( $resource_id = 1, $my_boook_count = 1, $my_booking_form = 'standard', $my_selected_dates_without_calendar = '', $start_month_calendar = false, $bk_otions = array() ) {

				$res = $this->add_booking_form_action($resource_id,$my_boook_count, 0, $my_booking_form , $my_selected_dates_without_calendar, $start_month_calendar, $bk_otions );
				return $res;
			}

			/**
			 * Deprecated! Show booking form from action call - wpdev_bk_add_form.
			 *
			 * @param $resource_id
			 * @param $cal_count
			 * @param $is_echo
			 * @param $my_booking_form
			 * @param $my_selected_dates_without_calendar
			 * @param $start_month_calendar
			 * @param $bk_otions
			 *
			 * @return mixed|string|void|null
			 */
			function add_booking_form_action( $resource_id = 1, $cal_count = 1, $is_echo = 1, $my_booking_form = 'standard', $my_selected_dates_without_calendar = '', $start_month_calendar = false, $bk_otions = array() ) {

				return $this->wpbc_process__booking_form( array(
					'resource_id'                     => $resource_id,
					'cal_count'                       => $cal_count,
					'is_echo'                         => $is_echo,
					'custom_booking_form'             => $my_booking_form,
					'selected_dates_without_calendar' => $my_selected_dates_without_calendar,
					'start_month_calendar'            => $start_month_calendar,
					'bk_otions'                       => $bk_otions,
				) );
			}

			/**
			 * Deprecated! For [bookingcalendar ... ] shortcode Only!
			 *
			 * @param $resource_id
			 * @param $cal_count
			 * @param $is_echo
			 * @param $start_month_calendar
			 * @param $bk_otions
			 *
			 * @return string|void
			 */
			function add_calendar_action( $resource_id = 1, $cal_count = 1, $is_echo = 1, $start_month_calendar = false, $bk_otions = array() ) {

				return $this->wpbc_process__availability_calendar( array(
					'resource_id'                     => $resource_id,
					'cal_count'                       => $cal_count,
					'is_echo'                         => $is_echo,
					'start_month_calendar'            => $start_month_calendar,
					'bk_otions'                       => $bk_otions,
				) );
			}



	/**
	 * Show booking form from action (call - wpdev_bk_add_form)
	 *
	 * @param array $params_arr - params: array(
	 *                                           'resource_id'                        => 1,
	 *                                           'cal_count'                          => 1,
	 *                                           'is_echo'                            => 1,
	 *                                           'my_booking_form'                    => 'standard',
	 *                                           'my_selected_dates_without_calendar' => '',
	 *                                           'start_month_calendar'               => false,
	 *                                           'bk_otions'                          => array(),
	 *                                        )
	 *
	 * @return mixed|string|void|null
	 */
	function wpbc_process__booking_form( $params_arr = array() ) {

		// Default parameters.
		$default_params = array(
			'resource_id'                     => 1,
			'cal_count'                       => 1,
			'is_echo'                         => 1,
			'custom_booking_form'             => 'standard',
			'selected_dates_without_calendar' => '',
			'start_month_calendar'            => false,
			'bk_otions'                       => array(),
			'calendar_dates_start'                      => '',
			'calendar_dates_end'                        => '',
		);
		$params_arr     = wp_parse_args( $params_arr, $default_params );

		//--------------------------------------------------------------------------------------------------------------
		// If resource_id conatins several resources: '5;3;9', then get only first resource ID, e.g. '5'.
		$aggregate_resource_id_arr = array();
		if ( strpos( $params_arr['resource_id'], ';' ) !== false ) {
			$aggregate_resource_id_arr       = explode( ';', $params_arr['resource_id'] );
			$params_arr['resource_id'] = $aggregate_resource_id_arr[0];
		}

		//--------------------------------------------------------------------------------------------------------------
		// Check if booking resource exist.
		if ( empty( $params_arr['resource_id'] ) ) {
			$my_result = __( 'Booking resource type is not defined. This can be, when at the URL is wrong booking hash.', 'booking' );
			if ( $params_arr['is_echo'] ) {
				echo $my_result;    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			} else {
				return $my_result;
			}
			return;
		}

		$is_booking_resource_exist = apply_bk_filter( 'wpdev_is_booking_resource_exist', true, $params_arr['resource_id'], $params_arr['is_echo'] );
        if (! $is_booking_resource_exist) {
            if ( $params_arr['is_echo'] )     echo 'Booking resource does not exist.' . ' [ID=' . esc_attr( $params_arr['resource_id'] ) . ']';
            return 'Booking resource does not exist.' . ' [ID=' . esc_attr( $params_arr['resource_id'] ) . ']';
        }

		//--------------------------------------------------------------------------------------------------------------
		// == MU ==  Define   $this->client_side_active_params_of_user  to  specific User,    depends from belonging booking resource to specific User
		make_bk_action( 'check_multiuser_params_for_client_side', $params_arr['resource_id'] );


		//--------------------------------------------------------------------------------------------------------------
		// Get Booking ID and booking resource ID, if we EDIT booking
	    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
		if ( isset( $_GET['booking_hash'] ) ) {

			/* phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing */
			$get_booking_hash = ( ( isset( $_GET['booking_hash'] ) ) ? sanitize_text_field( wp_unslash( $_GET['booking_hash'] ) ) : '' );  // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing

			$my_booking_id_type = wpbc_hash__get_booking_id__resource_id( $get_booking_hash );

			$is_error = false;                                                                                          // FixIn: 9.1.3.2.
			if ( $my_booking_id_type !== false ) {

				list( $my_edited_bk_id, $my_boook_type ) = $my_booking_id_type;

				if ( $my_boook_type == '' ) {
					$is_error = '<div class="wpbc_after_booking_thank_you_section"><div class="wpbc_ty__container"><div class="wpbc_ty__header"><strong>' . esc_html__( 'Oops!', 'booking' ) . '</strong> ' . __( 'We could not find your booking. The link you used may be incorrect or has expired. If you need assistance, please contact our support team.', 'booking' ) . '</div></div></div>';
				}
			} else {
				$is_error = '<div class="wpbc_after_booking_thank_you_section"><div class="wpbc_ty__container"><div class="wpbc_ty__header"><strong>' . esc_html__( 'Oops!', 'booking' ) . '</strong> ' . __( 'We could not find your booking. The link you used may be incorrect or has expired. If you need assistance, please contact our support team.', 'booking' ) . '</div></div></div>';
			}

			if ( false !== $is_error ) {
				if ( $params_arr['is_echo'] ) {
					// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
					echo $is_error;
				}
				return $is_error;
			}

			// Check situation when  we have editing "child booking resource",  so  need to  reupdate calendar and form  to have it for parent resource.  // FixIn: 10.10.1.2  && ( ! isset( $_GET['resource_no_update'] ) )
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
			if ( ( ! isset( $_GET['booking_pay'] ) ) &&
				( function_exists( 'wpbc_is_this_child_resource' ) ) &&
				( wpbc_is_this_child_resource( $my_boook_type ) )
			) {
				$bk_parent_br_id           = wpbc_get_parent_resource( $my_boook_type );
				$params_arr['resource_id'] = $bk_parent_br_id;
			}
		}

		//--------------------------------------------------------------------------------------------------------------
		// Get JS vars for      Booked dates | Rates | Availability    &   define function  for showing calendar
		$calendar_load_params = array(
			'resource_id'                     => $params_arr['resource_id'],
			'aggregate_resource_id_arr'       => $aggregate_resource_id_arr,
			'selected_dates_without_calendar' => $params_arr['selected_dates_without_calendar'],
			'calendar_number_of_months'       => $params_arr['cal_count'],
			'start_month_calendar'            => $params_arr['start_month_calendar'],
			'shortcode_options'               => $params_arr['bk_otions'],
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
			'custom_form'                     => ( isset( $_GET['booking_form'] ) ) ? wpbc_clean_text_value( $_GET['booking_form'] ) : $params_arr['custom_booking_form'],
			'calendar_dates_start'                      => $params_arr['calendar_dates_start'],
			'calendar_dates_end'                        => $params_arr['calendar_dates_end'],
		);

		if (
			( ! empty( $calendar_load_params ['calendar_dates_start'] ) ) &&
			( empty( $calendar_load_params ['calendar_dates_end'] ) )
		) {
			$calendar_load_params ['calendar_dates_end'] = gmdate( 'Y-m-d', strtotime( '+' . intval( wpbc_get_max_visible_days_in_calendar() ) . ' days', strtotime( $calendar_load_params ['calendar_dates_start'] ) ) );
		}
		if (
			( empty( $calendar_load_params ['calendar_dates_start'] ) ) &&
			( ! empty( $calendar_load_params ['calendar_dates_end'] ) )
		) {
			$calendar_load_params ['calendar_dates_start'] = gmdate( 'Y-m-d', strtotime( '-' . intval( wpbc_get_max_visible_days_in_calendar() ) . ' days', strtotime( $calendar_load_params ['calendar_dates_end'] ) ) );
		}

		$start_script_code = wpbc__calendar__load( $calendar_load_params );


		if ( $params_arr['selected_dates_without_calendar'] !== '' ) {                                                             // FixIn: 9.3.1.1.
			// Disable booked time slots, for predefined selected date in the booking form (it's shortcode for booking form,  without the calendar)
			$start_script_code .= '<script type="text/javascript"> ' . wpbc_jq_ready_start();                                      // FixIn: 10.1.3.7.
			$start_script_code .= " bkDisableBookedTimeSlots( jQuery( '#date_booking" . $params_arr['resource_id'] . "' ).val(), " . $params_arr['resource_id'] . " ); ";
			$start_script_code .= wpbc_jq_ready_end() . '</script>';                                                          // FixIn: 10.1.3.7.
		}


		//--------------------------------------------------------------------------------------------------------------
		// Get booking form content
        $my_result =  ' ' . $this->get__client_side_booking_content($params_arr['resource_id'], $params_arr['custom_booking_form'], $params_arr['selected_dates_without_calendar'], $params_arr['cal_count'], $params_arr['bk_otions'] ) . ' ' . $start_script_code ;
		// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
        $my_result = apply_filters('wpdev_booking_form', $my_result , $params_arr['resource_id']);        // Add DIV structure, where to show payment form


		// == MU ==
        make_bk_action('finish_check_multiuser_params_for_client_side', $params_arr['resource_id'] );

		if ( $params_arr['is_echo'] ) {
			echo $my_result;   // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		} else {
			return $my_result;
		}
    }


	/**
	 * Show Availability Calendar (Only)
	 *
	 * @param array $params_arr - params: array(
	 *                                           'resource_id'                        => 1,
	 *                                           'cal_count'                          => 1,
	 *                                           'is_echo'                            => 1,
	 *                                           'my_booking_form'                    => 'standard',
	 *                                           'my_selected_dates_without_calendar' => '',
	 *                                           'start_month_calendar'               => false,
	 *                                           'bk_otions'                          => array(),
	 *                                        )
	 *
	 * @return mixed|string|void|null
	 */
	function wpbc_process__availability_calendar( $params_arr = array() ) {

		// Default parameters.
		$default_params = array(
			'resource_id'                     => 1,
			'cal_count'                       => 1,
			'is_echo'                         => 1,
			'start_month_calendar'            => false,
			'bk_otions'                       => array(),
			'calendar_dates_start'            => '',
			'calendar_dates_end'              => '',
		);
		$params_arr     = wp_parse_args( $params_arr, $default_params );


		//--------------------------------------------------------------------------------------------------------------
		// If resource_id conatins several resources: '5;3;9', then get only first resource ID, e.g. '5'.
		$aggregate_resource_id_arr = array();
		if ( strpos( $params_arr['resource_id'], ';' ) !== false ) {
			$aggregate_resource_id_arr = explode( ';', $params_arr['resource_id'] );
			$params_arr['resource_id'] = $aggregate_resource_id_arr[0];
		}

		//--------------------------------------------------------------------------------------------------------------
		// == MU ==  Define   $this->client_side_active_params_of_user  to  specific User,    depends from belonging booking resource to specific User
        make_bk_action('check_multiuser_params_for_client_side', $params_arr['resource_id'] );

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
		if ( isset( $_GET['booking_hash'] ) ) {
			$get_booking_hash = ( ( isset( $_GET['booking_hash'] ) ) ? sanitize_text_field( wp_unslash( $_GET['booking_hash'] ) ) : '' );  /* phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing */ /* FixIn: sanitize_unslash */
			$my_booking_id_type = wpbc_hash__get_booking_id__resource_id( $get_booking_hash );
			if ( $my_booking_id_type != false ) {
				if ( $my_booking_id_type[1] == '' ) {
					$my_result = '<div class="wpbc_after_booking_thank_you_section"><div class="wpbc_ty__container"><div class="wpbc_ty__header"><strong>' . esc_html__( 'Oops!', 'booking' ) . '</strong> ' . __( 'We could not find your booking. The link you used may be incorrect or has expired. If you need assistance, please contact our support team.', 'booking' ) . '</div></div></div>';
					if ( $params_arr['is_echo'] ) {
						echo $my_result;  // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
					} else {
						return $my_result;
					}
					return;
				}
			}
		}


		//--------------------------------------------------------------------------------------------------------------
		// Get JS vars for      Booked dates | Rates | Availability    &   define function  for showing calendar
		$calendar_load_params = array(
			'resource_id'                     => $params_arr['resource_id'],
			'aggregate_resource_id_arr'       => $aggregate_resource_id_arr,
			'selected_dates_without_calendar' => '',
			'calendar_number_of_months'       => $params_arr['cal_count'],
			'start_month_calendar'            => $params_arr['start_month_calendar'],
			'shortcode_options'               => $params_arr['bk_otions'],
			'custom_form'                     => 'standard',                  // Because we show only  'AVAILABILITY CALENDAR' without the form,  at all.
			'calendar_dates_start'            => $params_arr['calendar_dates_start'],
			'calendar_dates_end'              => $params_arr['calendar_dates_end'],
		);

		if (
			( ! empty( $calendar_load_params ['calendar_dates_start'] ) ) &&
			( empty( $calendar_load_params ['calendar_dates_end'] ) )
		) {
			$calendar_load_params ['calendar_dates_end'] = gmdate( 'Y-m-d', strtotime( '+' . intval( wpbc_get_max_visible_days_in_calendar() ) . ' days', strtotime( $calendar_load_params ['calendar_dates_start'] ) ) );
		}
		if (
			( empty( $calendar_load_params ['calendar_dates_start'] ) ) &&
			( ! empty( $calendar_load_params ['calendar_dates_end'] ) )
		) {
			$calendar_load_params ['calendar_dates_start'] = gmdate( 'Y-m-d', strtotime( '-' . intval( wpbc_get_max_visible_days_in_calendar() ) . ' days', strtotime( $calendar_load_params ['calendar_dates_end'] ) ) );
		}

		$start_script_code = wpbc__calendar__load( $calendar_load_params );

        $my_result = '<div style="clear:both;height:10px;"></div>' . wpbc_pre_get_calendar_html( $params_arr['resource_id'], $params_arr['cal_count'], $params_arr['bk_otions'] );

        $my_result .=   ' ' . $start_script_code ;
		// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
        $my_result = apply_filters('wpdev_booking_calendar', $my_result , $params_arr['resource_id']);


        $booking_form_is_using_bs_css = get_bk_option( 'booking_form_is_using_bs_css' );
        $my_result = '<span ' . (($booking_form_is_using_bs_css == 'On') ? 'class="wpdevelop"' : '') . '>' . $my_result . '</span>';

		// == MU ==
        make_bk_action('finish_check_multiuser_params_for_client_side', $params_arr['resource_id'] );

		if ( $params_arr['is_echo'] ) {
			echo $my_result;           // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		} else {
			return $my_result;
		}
    }


	// *****************************************************************************************************************

    // == Get content at client side of  C A L E N D A R ===============================================================
	function get__client_side_booking_content( $resource_id = 1, $my_booking_form = 'standard', $my_selected_dates_without_calendar = '', $cal_count = 1, $bk_otions = array() ) {

        $nl = '<div style="clear:both;height:10px;"></div>';                                                            // New line
        if ($my_selected_dates_without_calendar=='') {
			// Get HTML  with  [calendar] shortcode and Styles for calendar. Get legend html.
            $calendar = wpbc_pre_get_calendar_html( $resource_id, $cal_count, $bk_otions );
        } else {
            $calendar = '<textarea rows="3" cols="50" id="date_booking' . $resource_id . '" name="date_booking' . $resource_id . '"  autocomplete="off" style="display:none;">' . $my_selected_dates_without_calendar . '</textarea>';   // Calendar code
        }

	    // FixIn: 8.2.1.1.
        $form = '<a name="bklnk' . $resource_id . '" id="bklnk' . $resource_id . '"></a><div id="booking_form_div' . $resource_id . '" class="booking_form_div">';
        // FixIn: 6.0.1.5.
        $custom_params = array();
        if (! empty($bk_otions)) {
            $param ='\s*([name|value]+)=[\'"]{1}([^\'"]+)[\'"]{1}\s*'; // Find all possible options
            $pattern_to_search='%\s*{([^\s]+)' . $param . $param .'}\s*[,]?\s*%';
            preg_match_all($pattern_to_search, $bk_otions, $matches, PREG_SET_ORDER);
            //debuge($matches);
            foreach ( $matches as $matche_value ) {
                if ( $matche_value[1] == 'parameter' ) {
                    $custom_params[ $matche_value[3] ]= $matche_value[5];
                }
            }
        }

		// FixIn: 11.0.1.
		// FixIn: 11.0.1. BFB-aware loader with legacy fallback.
		$bfb_form_html = '';

		if ( function_exists( 'wpbc_bfb_get_booking_form_source' ) ) {

			// -----------------------------------------------------------------
			// 1) Build loader args for BFB (slug + optional status / form_id).
			// -----------------------------------------------------------------
			$context = 'frontend';
			if ( ! empty( $custom_params['context'] ) && 'preview' === $custom_params['context'] ) {
				$context = 'preview';
			}

			$bfb_loader_args = array(
				// May be empty; loader will resolve via resource_id → default form.
				'form_slug'   => (string) $my_booking_form,
				'resource_id' => (int) $resource_id,
				'context'     => $context,
			);

			// Optional: explicit BFB form ID, e.g. [booking ... bfb_form_id="123"].
			if ( ! empty( $custom_params['bfb_form_id'] ) ) {
				$bfb_loader_args['form_id'] = (int) $custom_params['bfb_form_id'];
			}

			// Optional: status override, e.g. [booking ... bfb_form_status="preview"].
			if ( ! empty( $custom_params['bfb_form_status'] ) ) {
				$bfb_loader_args['bfb_form_status'] = sanitize_key( $custom_params['bfb_form_status'] );
			}

			// -----------------------------------------------------------------
			// 2) Get BFB source (shortcodes string) from the new loader.
			// -----------------------------------------------------------------
			$bfb_source = wpbc_bfb_get_booking_form_source( $bfb_loader_args );

			if ( '' !== trim( $bfb_source ) ) {

				// -----------------------------------------------------------------
				// 3) Give core / addons a chance to fully handle rendering.
				// -----------------------------------------------------------------
				$bfb_form_html = apply_filters(
					'wpbc_bfb_render_booking_form_source',
					'',                // Default HTML (empty) – filter may replace it.
					$bfb_source,       // Source shortcodes string.
					$resource_id,
					$my_booking_form,
					$custom_params
				);

				if ( '' === $bfb_form_html ) {

					// -----------------------------------------------------------------
					// 4) Fallback: universal shortcode engine.
					// -----------------------------------------------------------------

					// Build rendering context for the universal shortcode engine.
					// - booking_type is required so engine knows which resource we are working with.
					// - We keep any {parameter ...} values in the context for filters, under the same keys.
					$render_args = array_merge(
						is_array( $custom_params ) ? $custom_params : array(),
						array(
							'booking_type' => (int) $resource_id,
						)
					);

					// In Pro versions we can pass the "owner" so the Adapter
					// (WPBC_BFB_FormShortcodeEngine_Adapter) can keep legacy pieces
					// like CAPTCHA, canonicalization, etc. working.
					if ( ! empty( $this->wpdev_bk_personal ) ) {
						$render_args['owner'] = $this->wpdev_bk_personal;
					}

					// Check for the active language in the Booking Form.
					$bfb_source = wpbc_lang( $bfb_source );

					// FixIn: 6.0.1.5. Replace {parameter ...} tokens with values.
					if ( ! empty( $custom_params ) && is_array( $custom_params ) ) {
						foreach ( $custom_params as $custom_params_key => $custom_params_value ) {
							$bfb_source = str_replace( $custom_params_key, $custom_params_value, $bfb_source );
						}
					}

					$bfb_source    = wpbc_bf__replace_custom_html_shortcodes( $bfb_source );
					$bfb_form_html = wpbc_render_booking_form_shortcodes( $bfb_source, $render_args );
				}
			}
		}


		if ( '' !== $bfb_form_html ) {

			// Use BFB-rendered form HTML.
			$form .= $bfb_form_html;

			// Re-update other hints, such as availability times hint.
			$form = apply_filters( 'wpbc_booking_form_content__after_load', $form, $resource_id, $my_booking_form );

		} else {
			// -----------------------------------------------------------------
			// Legacy behaviour: advanced or Simple mode HTML.
			// -----------------------------------------------------------------

			// FixIn: 6.0.1.5.
			if ( $this->wpdev_bk_personal !== false ) {
				$form .= $this->wpdev_bk_personal->get_booking_form( $resource_id, $my_booking_form, $custom_params );
			} else {
				$form .= wpbc_simple_form__get_booking_form__as_html( $resource_id );

				// Re-update other hints,  such  as availability times hint.
				$form = apply_filters( 'wpbc_booking_form_content__after_load', $form, $resource_id, $my_booking_form );
			}
		}




        // Insert calendar into form
		if ( strpos( $form, '[calendar]' ) !== false ) {
			$form = str_replace( '[calendar]', $calendar, $form );
		} else {
			$form = '<div class="booking_form_div">' . $calendar . '</div>' . $nl . $form;
		}

        // Replace additional calendars like [calendar id=9] to  HTML and JS code
        $form = apply_bk_filter( 'wpdev_check_for_additional_calendars_in_form'
                                                                            , $form
                                                                            , $resource_id
                                                                            , array(
                                                                                    'booking_form' => $my_booking_form ,
                                                                                    'selected_dates' => $my_selected_dates_without_calendar ,
                                                                                    'cal_count' => $cal_count ,
                                                                                    'otions' => $bk_otions
                                                                                    )
                                    );

        if ( strpos($form, '[captcha]') !== false ) {
            $captcha = $this->createCapthaContent($resource_id);
            $form =str_replace('[captcha]', $captcha ,$form);
        }

        // Set additional "Check in/out" times, if activated to  use change-over days!
		$form = apply_filters( 'wpbc_booking_form_html__update__append_change_over_times', $form, $resource_id );



        // Add booking type field
        $form      .= '<input id="bk_type' . $resource_id . '" name="bk_type' . $resource_id . '" class="" type="hidden" value="' . $resource_id . '" /></div>';
        $submitting = '<div id="submiting' . $resource_id . '"></div><div class="form_bk_messages" id="form_bk_messages' . $resource_id . '" ></div>';

        //Params: $action = -1, $name = "_wpnonce", $referer = true , $echo = true

        $wpbc_nonce = wp_nonce_field('CALCULATE_THE_COST', ( "wpbc_nonceCALCULATE_THE_COST" . $resource_id) ,  true , false );


        $res = $form . $submitting . $wpbc_nonce;

        $my_random_id = time() * wp_rand(0,1000);
        $my_random_id = 'form_id'. $my_random_id;

        $booking_form_is_using_bs_css = get_bk_option( 'booking_form_is_using_bs_css');
        $booking_form_format_type     = get_bk_option( 'booking_form_format_type');
		$booking_form_theme           = get_bk_option( 'booking_form_theme');

		$return_form = '<div id="' . esc_attr($my_random_id) . '" '
		                 . ' class="wpbc_container wpbc_form wpbc_container_booking_form '
		                    . ( ( wpbc_is_this_demo() == 'On' ) ? 'wpbc_demo_site ' : '' )
		                    . esc_attr( $booking_form_theme ) . ' '
		                    . ( ( $booking_form_is_using_bs_css == 'On' ) ? 'wpdevelop ' : '' )
		               . '" >' .
                         '<form  id="booking_form' . intval($resource_id) . '"   class="booking_form ' . esc_attr($booking_form_format_type) . '" method="post" action="">' .
                       '<div id="ajax_respond_insert' . intval($resource_id) . '" class="ajax_respond_insert" style="display:none;"></div>' .
                       $res.
                         '</form></div>';

        $return_form .= '<div id="booking_form_garbage' . intval($resource_id) . '" class="booking_form_garbage"></div>';

        if ($my_selected_dates_without_calendar == '' ) {
            // Check according already shown Booking Calendar  and set do not visible of it

			$warn = sprintf( 'Warning! The booking calendar for this resource with the ID = %d is already on the page. Find more details here: https://wpbookingcalendar.com/faq/why-the-booking-calendar-widget-not-show-on-page/', (int) $resource_id );

	        $return_form .= '<script type="text/javascript"> ' . wpbc_jq_ready_start();                                 // FixIn: 10.1.3.7.
			$return_form .=  ' jQuery(".widget_wpdev_booking .booking_form.form-horizontal").removeClass("form-horizontal");
			                        var calendars__on_this_page_list = _wpbc.get_other_param( "calendars__on_this_page" ) || [];
			                        var visible_calendars_count = calendars__on_this_page_list.length;
                                    if (visible_calendars_count !== null ) {
                                        for (var i=0;i< visible_calendars_count ;i++){
                                          if ( _wpbc.get_other_param( "calendars__on_this_page" )[i] === ' . intval($resource_id) . ' ) {
                                          	console.log("%c%s", "color: #e77; font-weight:bold", ' . wp_json_encode( $warn ) . ');
                                          }
                                        }
                                        _wpbc.get_other_param( "calendars__on_this_page" )[ visible_calendars_count ]=' . intval( $resource_id ) . ';
                                    } ';
		    $return_form .= wpbc_jq_ready_end() . '</script>';                                                          // FixIn: 10.1.3.7.
        } else {
            //FixIn:6.1.1.16	// FixIn: 8.2.1.13.
	        $return_form .= '<script type="text/javascript"> ' . wpbc_jq_ready_start();                                 // FixIn: 10.1.3.7.
            $return_form .= ' if(typeof( wpbc_show_cost_hints_after_few_seconds ) == "function") {  wpbc_show_cost_hints_after_few_seconds(' . intval($resource_id) . ');  } ';
            $return_form .= ' else if (typeof( showCostHintInsideBkForm ) == "function") {  showCostHintInsideBkForm(' . intval($resource_id) . ');  } ';	// Legacy function  support.
			$return_form .= wpbc_jq_ready_end() . '</script>';                                                          // FixIn: 10.1.3.7.
        }

        $is_use_auto_fill_for_logged = get_bk_option( 'booking_is_use_autofill_4_logged_user' ) ;


        // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
        if (! isset($_GET['booking_hash']))
            if ($is_use_auto_fill_for_logged == 'On') {

                $curr_user = wpbc_get_current_user();
                if ( $curr_user->ID > 0 ) {
					$user_nick_name = get_user_meta( $curr_user->ID, 'nickname' );
					$user_nick_name = ( empty( $user_nick_name ) ) ? '' : $user_nick_name[0];                           // FixIn: 8.7.1.5.

					$return_form .= '<script type="text/javascript"> ' . wpbc_jq_ready_start();                         // FixIn: 10.1.3.7.
                    $return_form .= 'var bk_af_submit_form = document.getElementById( "booking_form' . intval( $resource_id ) . '" );
                    				if ( ! bk_af_submit_form ) { console.error( "WPBC: No booking form: booking_form. " ); return; }
                                    var bk_af_count = bk_af_submit_form.elements.length;
                                    var bk_af_element;
                                    var bk_af_reg;
                                    for (var bk_af_i=0; bk_af_i<bk_af_count; bk_af_i++)   {
                                        bk_af_element = bk_af_submit_form.elements[bk_af_i];
                                        // FixIn: 9.4.3.4.
                                        if  (  ( bk_af_element.type == "text" ) ||   ( bk_af_element.type == "email" ) ) 
                                            if    ( bk_af_element.name !== ("date_booking' . intval($resource_id) . '" ) )
                                            {
                                                // NickName	// FixIn: 8.6.1.2.
                                                bk_af_reg = /^([A-Za-z0-9_\-\.])*(nickname){1}([A-Za-z0-9_\-\.])*$/;
                                                if(bk_af_reg.test(bk_af_element.name) != false)
                                                    if (bk_af_element.value == "" )
                                                        bk_af_element.value  = ' . wp_json_encode( (string) $user_nick_name ) . ';                                                        
                                                // Second Name
                                                bk_af_reg = /^([A-Za-z0-9_\-\.])*(last|second){1}([_\-\.])?name([A-Za-z0-9_\-\.])*$/;
                                                if(bk_af_reg.test(bk_af_element.name) != false)
                                                    if (bk_af_element.value == "" )
                                                        bk_af_element.value  = '.wp_json_encode( (string) $curr_user->last_name).';
                                                // First Name
                                                bk_af_reg = /^name([0-9_\-\.])*$/;
                                                if(bk_af_reg.test(bk_af_element.name) != false)
                                                    if (bk_af_element.value == "" )
                                                        bk_af_element.value  = '.wp_json_encode( (string) $curr_user->first_name).';
                                                bk_af_reg = /^([A-Za-z0-9_\-\.])*(first|my){1}([_\-\.])?name([A-Za-z0-9_\-\.])*$/;
                                                if(bk_af_reg.test(bk_af_element.name) != false)
                                                    if (bk_af_element.value == "" )
                                                        bk_af_element.value  = '.wp_json_encode( (string) $curr_user->first_name).';
                                                // Email
                                                bk_af_reg = /^(e)?([_\-\.])?mail([0-9_\-\.])*$/;
                                                if(bk_af_reg.test(bk_af_element.name) != false)
                                                    if (bk_af_element.value == "" )
                                                        bk_af_element.value  = '.wp_json_encode( (string) $curr_user->user_email).';
												// Phone
					                            bk_af_reg = /^([A-Za-z0-9_\-\.])*(phone|fone){1}([A-Za-z0-9_\-\.])*$/;
					                            if(bk_af_reg.test(bk_af_element.name) != false)
					                                if (bk_af_element.value == "" )
					                                    bk_af_element.value  = '.wp_json_encode( (string) $curr_user->phone_number).';
					                            // NB Enfants
					                            bk_af_reg = /^(e)?([_\-\.])?nb_enfant([0-9_\-\.])*$/;
					                            if(bk_af_reg.test(bk_af_element.name) != false)
					                                if (bk_af_element.value == "" )
					                                    bk_af_element.value  = '.wp_json_encode( (string) $curr_user->nb_enfant).';                                                                                            
                                                // URL
                                                bk_af_reg = /^([A-Za-z0-9_\-\.])*(URL|site|web|WEB){1}([A-Za-z0-9_\-\.])*$/;
                                                if(bk_af_reg.test(bk_af_element.name) != false)
                                                    if (bk_af_element.value == "" )
                                                        bk_af_element.value  = '.wp_json_encode( (string) $curr_user->user_url).';
                                           }
                                    }';
					$return_form .= wpbc_jq_ready_end() . '</script>';                                                          // FixIn: 10.1.3.7.
                }
             }

        return $return_form ;
    }
    // </editor-fold>


	// FixIn: 8.7.11.13.
	function wpbc_test_speed_shortcode( $attr ) {

	    if ( wpbc_is_on_edit_page() ) {
		    return wpbc_get_preview_for_shortcode( 'booking_test_speed', $attr );      // FixIn: 9.9.0.39.
	    }

		$attr = wpbc_escape_shortcode_params( $attr );          //FixIn: 9.7.3.6.1

    	 echo '<h4>Booking Calendar Test</h4>';

    	 $datesArray = Array(
	            '2021-09-10'
		     ,  '2021-09-11'
		     ,  '2021-09-12'
		     ,  '2021-09-13'
		     ,  '2021-09-14'
		     ,  '2021-09-15'
		     ,  '2021-09-16'
		     ,  '2021-09-17'
		     ,  '2021-09-18'
		) ;
    	 for( $i = 0; $i < 1 ; $i++) {
$result = wpbc_api_is_dates_booked( $datesArray, $resource_id = 13 );
//debuge((int) $result );
    	 }

    	debuge_speed('(int)');
    	 echo '<hr/>';
    	 echo '<hr/>';
	}


    // <editor-fold defaultstate="collapsed" desc="   S H O R T    C O D E S ">

	// FixIn: 8.1.3.5.
	/** Listing customners bookings in timeline view
	 *
	 * @param $attr	- The same parameters as for bookingtimeline shortcode (function)
	 *
	 * @return mixed|string|void
	 */
	function bookingcustomerlisting_shortcode( $attr ){

		if ( ! class_exists( 'wpdev_bk_personal' ) ) {
			return '<strong>' . esc_html__('This shortcode available in Pro versions,  only!' ,'booking') . '</strong> ';
		}

	    if ( wpbc_is_on_edit_page() ) {
		    return wpbc_get_preview_for_shortcode( 'bookingcustomerlisting', $attr );      // FixIn: 9.9.0.39.
	    }

		$attr = wpbc_escape_shortcode_params( $attr );          //FixIn: 9.7.3.6.1

		// FixIn: 8.4.5.11.
		if (! is_array($attr)) {
			$attr = array();
		}
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
		if ( ( isset( $_GET['booking_hash'] ) ) || ( isset( $attr['booking_hash'] ) ) ) {


			// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
			if ( isset( $_GET['booking_hash'] ) ) {
				$get_booking_hash = ( ( isset( $_GET['booking_hash'] ) ) ? sanitize_text_field( wp_unslash( $_GET['booking_hash'] ) ) : '' );  /* phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing */ /* FixIn: sanitize_unslash */
				$my_booking_id_type = wpbc_hash__get_booking_id__resource_id( $get_booking_hash );

				$attr['booking_hash'] = $get_booking_hash;
			} else {
				$my_booking_id_type = wpbc_hash__get_booking_id__resource_id( $attr['booking_hash'] );
			}

			if ( $my_booking_id_type !== false ) {

				if ( ! isset( $attr['type' ] ) ) {																		// 8.1.3.5.2

					$br_list = wpbc_get_all_booking_resources_list();
					$br_list = array_keys( $br_list );
					$br_list = implode(',',$br_list);
					$attr['type' ] = $br_list;		//wpbc_get_default_resource();
				}
				if ( ! isset( $attr['view_days_num' ] ) ) {
					$attr['view_days_num' ] = 30;
				}
				if ( ! isset( $attr['scroll_start_date' ] ) ) {
					$attr['scroll_start_date' ] = '';
				}
				if ( ! isset( $attr['scroll_day' ] ) ) {
					$attr['scroll_day' ] = 0;
				}
				if ( ! isset( $attr['scroll_month' ] ) ) {
					$attr['scroll_month' ] = 0;
				}
				if ( ! isset( $attr['header_title' ] ) ) {
					$attr['header_title' ] = __( 'My bookings' , 'booking');
				}

				$timeline_results = $this->bookingtimeline_shortcode( $attr );

				return $timeline_results ;

			} else {
				return '<div class="wpbc_after_booking_thank_you_section"><div class="wpbc_ty__container"><div class="wpbc_ty__header"><strong>' . esc_html__('Oops!' ,'booking') . '</strong> ' . esc_html__('We could not find your booking. The link you used may be incorrect or has expired. If you need assistance, please contact our support team.' ,'booking') . '</div></div></div>';
			}

		} else {
			return __( 'This page can only be accessed through links in emails related to your booking.', 'booking' )
			       . ' <br/><em>'
			       /* translators: 1: ... */
			       . sprintf( __( 'Please check more about configuration at  %1$sthis page%2$s', 'booking' ), '<a href="https://wpbookingcalendar.com/faq/configure-editing-cancel-payment-bookings-for-visitors/" target="_blank">', '</a>.' )
			       . '</em>';
		}
	}


    /**
	 * TimeLine shortcode
     *
     * @param type $attr
     * @return type
     *
     * Shortcodes exmaples:
     *
     *
** Matrix:
     * 1 Month View Mode:
[bookingtimeline type="3,4,1,5,6,7,8,9,2,10,11,12,14" view_days_num=30 scroll_start_date="" scroll_month=0 header_title='All Bookings']
     * 2 Months View Mode:
[bookingtimeline type="1,5,6,7,8,9,2,10,11,12,3,4,14" view_days_num=60 scroll_start_date="" scroll_month=-1 header_title='All Bookings']
     * 1 Week View Mode:
[bookingtimeline type="3,4" view_days_num=7 scroll_start_date="" scroll_day=-7 header_title='All Bookings']
     * 1 Day View Mode:
[bookingtimeline type="3,4" view_days_num=1 scroll_start_date="" scroll_day=0 header_title='All Bookings']

** Single:
     * 1 Month  View Mode:
[bookingtimeline type="4" view_days_num=30 scroll_start_date="" scroll_day=-15 scroll_month=0 header_title='All Bookings']
     * 3 Months View Mode:
[bookingtimeline type="4" view_days_num=90 scroll_start_date="" scroll_day=-30]
     * 1 Year View Mode:
[bookingtimeline type="4" view_days_num=365 scroll_start_date="" scroll_month=-3]


     */
    function bookingtimeline_shortcode($attr) {

	    if ( wpbc_is_on_edit_page() ) {
		    return wpbc_get_preview_for_shortcode( 'bookingtimeline', $attr );      // FixIn: 9.9.0.39.
	    }

		$attr = wpbc_escape_shortcode_params( $attr );          //FixIn: 9.7.3.6.1

    	// FixIn: 8.6.1.13.
		$timeline_results = bookingflextimeline_shortcode($attr);
		return $timeline_results;
    }


			/**
			 * Shortcode Processing -- 'Booking Form' -- [booking resource_id=1 nummonths=2 ]
			 *
			 * @param array $attr - params.
			 *
			 * @return mixed|string|null
			 */
			function booking_shortcode( $attr ) {

			    if ( wpbc_is_on_edit_page() ) {
				    return wpbc_get_preview_for_shortcode( 'booking', $attr );      // FixIn: 9.9.0.39.
			    }

				$attr = wpbc_escape_shortcode_params( $attr );          //FixIn: 9.7.3.6.1

				// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
				if ( isset( $_GET['booking_hash'] ) ) {

					return __( 'You need to use special shortcode [bookingedit] for booking editing.', 'booking' ) . ' ' .
						   /* translators: 1: URL  to FAQ page. */
						   sprintf( __( 'Please check FAQ instruction how to configure it here %s', 'booking' ), '<a href="https://wpbookingcalendar.com/faq/configure-editing-cancel-payment-bookings-for-visitors/">https://wpbookingcalendar.com/faq/configure-editing-cancel-payment-bookings-for-visitors/</a>' );
				}

				$cal_count            = get_bk_option( 'booking_client_cal_count' );
				$resource_id          = 1;
				$custom_booking_form  = 'standard';
				$start_month_calendar = false;
				$bk_otions            = array();

				if ( isset( $attr['nummonths'] ) ) {
					$cal_count = intval( $attr['nummonths'] );
				}
				if ( isset( $attr['resource_id'] ) ) {
					$attr['type'] = intval( $attr['resource_id'] );         // FixIn: 10.2.2.2.
				}
				if ( isset( $attr['type'] ) ) {
					$resource_id = intval( $attr['type'] );                 // FixIn: 10.2.2.2.
				}
				if ( isset( $attr['form_type'] ) ) {
					$custom_booking_form = $attr['form_type'];
				}
				if ( isset( $attr['agregate'] ) && ( ! empty( $attr['agregate'] ) ) ) {
					$resource_id .= ';' . $attr['agregate'];
				}
				if ( isset( $attr['aggregate'] ) && ( ! empty( $attr['aggregate'] ) ) ) {
					$resource_id .= ';' . $attr['aggregate'];
				}
				// Escape any XSS in aggregate parameter.
				$resource_id = str_replace( ',', ';', wpbc_clean_digit_or_csd( $resource_id ) );

				if ( isset( $attr['startmonth'] ) ) { // Set start month of calendar, fomrat: '2011-1'

					$start_month_calendar = explode( '-', $attr['startmonth'] );
					if ( ( is_array( $start_month_calendar ) ) && ( count( $start_month_calendar ) > 1 ) ) {
					} else {
						$start_month_calendar = false;
					}

				}
				if ( isset( $attr['options'] ) ) {
					$bk_otions = $attr['options'];
				}

				$shortcode_params = array(
					'resource_id'                     => $resource_id,
					'cal_count'                       => $cal_count,
					'is_echo'                         => 0,
					'custom_booking_form'             => $custom_booking_form,
					'selected_dates_without_calendar' => '',
					'start_month_calendar'            => $start_month_calendar,
					'bk_otions'                       => $bk_otions,
				);

				if ( ! empty( $attr['calendar_dates_start'] ) ) {
					$shortcode_params['calendar_dates_start'] = wpbc_sanitize_date( $attr['calendar_dates_start'] );
				}
				if ( ! empty( $attr['calendar_dates_end'] ) ) {
					$shortcode_params['calendar_dates_end'] = wpbc_sanitize_date( $attr['calendar_dates_end'] );
				}

				$res = $this->wpbc_process__booking_form( $shortcode_params );

		        return $res;
		    }


			/**
			 * Shortcode Processing -- 'Availability Calendar Only' -- [bookingcalendar resource_id=1 nummonths=2 ]
			 *
			 * @param array $attr - params.
			 *
			 * @return mixed|string|null
			 */
			function booking_calendar_only_shortcode($attr) {

			    if ( wpbc_is_on_edit_page() ) {
				    return wpbc_get_preview_for_shortcode( 'bookingcalendar', $attr );                                  // FixIn: 9.9.0.39.
			    }

				$attr = wpbc_escape_shortcode_params( $attr );                                                          // FixIn: 9.7.3.6.1.

				$cal_count            = get_bk_option( 'booking_client_cal_count' );
				$resource_id          = 1;
				$start_month_calendar = false;
				$bk_otions            = array();


				if ( isset( $attr['nummonths'] ) ) {
					$cal_count = intval( $attr['nummonths'] );        // FixIn: 10.14.8.1.
				}
				if ( isset( $attr['resource_id'] ) ) {
					$attr['type'] = intval( $attr['resource_id'] );                                                     // FixIn: 10.2.2.2.
				}
				if ( isset( $attr['type'] ) ) {
					$resource_id = intval( $attr['type'] );                                                             // FixIn: 10.2.2.2.
				}
				if ( isset( $attr['agregate'] ) && ( ! empty( $attr['agregate'] ) ) ) {
					$resource_id .= ';' . $attr['agregate'];
				}
				if ( isset( $attr['aggregate'] ) && ( ! empty( $attr['aggregate'] ) ) ) {                               // FixIn: 8.3.3.8.
					$resource_id .= ';' . $attr['aggregate'];
				}
				// Escape any XSS in aggregate parameter.
				$resource_id = str_replace( ',', ';', wpbc_clean_digit_or_csd( $resource_id ) );

				if ( isset( $attr['startmonth'] ) ) { // Set start month of calendar, fomrat: '2011-1'
					$start_month_calendar = explode( '-', $attr['startmonth'] );
					if ( ( is_array( $start_month_calendar ) ) && ( count( $start_month_calendar ) > 1 ) ) {
					} else {
						$start_month_calendar = false;
					}
				}
				if ( isset( $attr['options'] ) ) {
					$bk_otions = $attr['options'];
				}


				$shortcode_params = array(
					'resource_id'                     => $resource_id,
					'cal_count'                       => $cal_count,
					'is_echo'                         => 0,
					'start_month_calendar'            => $start_month_calendar,
					'bk_otions'                       => $bk_otions,
				);

				if ( ! empty( $attr['calendar_dates_start'] ) ) {
					$shortcode_params['calendar_dates_start'] = wpbc_sanitize_date( $attr['calendar_dates_start'] );
				}
				if ( ! empty( $attr['calendar_dates_end'] ) ) {
					$shortcode_params['calendar_dates_end'] = wpbc_sanitize_date( $attr['calendar_dates_end'] );
				}

				$res = $this->wpbc_process__availability_calendar( $shortcode_params );


		        $start_script_code = "<div id='calendar_booking_unselectable".$resource_id."'></div>";
			    return "<div class='wpbc_only_calendar wpbc_container'>" . $start_script_code . $res . '</div>';        // FixIn: 8.0.1.2.
		    }

		    // Show only booking form, with already selected dates
		    function bookingform_shortcode($attr) {

			    if ( wpbc_is_on_edit_page() ) {
				    return wpbc_get_preview_for_shortcode( 'bookingform', $attr );      // FixIn: 9.9.0.39.
			    }

				$attr = wpbc_escape_shortcode_params( $attr );          //FixIn: 9.7.3.6.1

		        //if ( function_exists( 'wpbc_br_cache' ) ) $br_cache = wpbc_br_cache();  // Init booking resources cache

		        $my_boook_type = 1;
		        $my_booking_form = 'standard';
		        $my_boook_count = 1;
		        $my_selected_dates_without_calendar = '';

			    if ( isset( $attr['resource_id'] ) ) {
				    $attr['type'] = intval( $attr['resource_id'] );           // FixIn: 10.2.2.2.
			    }
			    if ( isset( $attr['type'] ) ) {
				    $my_boook_type = intval( $attr['type'] );                // FixIn: 10.2.2.2.
			    }
		        if ( isset( $attr['form_type'] ) )      { $my_booking_form = $attr['form_type'];                         }
		        if ( isset( $attr['selected_dates'] ) ) { $my_selected_dates_without_calendar = $attr['selected_dates']; }  //$my_selected_dates_without_calendar = '20.08.2010, 29.08.2010';

		        $res = $this->add_booking_form_action($my_boook_type,$my_boook_count, 0 , $my_booking_form, $my_selected_dates_without_calendar, false );

		        return $res;
		    }


    // Show booking form for editing
    function bookingedit_shortcode($attr) {

	    if ( wpbc_is_on_edit_page() ) {
		    return wpbc_get_preview_for_shortcode( 'bookingedit', $attr );      // FixIn: 9.9.0.39.
	    }

		$attr = wpbc_escape_shortcode_params( $attr );          //FixIn: 9.7.3.6.1


        //if ( function_exists( 'wpbc_br_cache' ) ) $br_cache = wpbc_br_cache();  // Init booking resources cache

	    // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
	    if ( isset( $_GET['wpbc_hash'] ) ) {

	    	if ( function_exists( 'wpbc_parse_one_way_hash' ) ) {

				$get_wpbc_hash = ( ( isset( $_GET['wpbc_hash'] ) ) ? sanitize_text_field( wp_unslash( $_GET['wpbc_hash'] ) ) : '' );  /* phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing */ /* FixIn: sanitize_unslash */

			    $one_way_hash_response = wpbc_parse_one_way_hash( $get_wpbc_hash );

			    return $one_way_hash_response;
		    }
	    }

        $my_boook_count = get_bk_option( 'booking_client_cal_count' );
        $my_boook_type = 1;
        $my_booking_form = 'standard';
        $bk_otions = array();
        if ( isset( $attr['nummonths'] ) )   { $my_boook_count = intval( $attr['nummonths'] );  }
		if ( isset( $attr['resource_id'] ) ) {  $attr['type'] = intval( $attr['resource_id']); }
        if ( isset( $attr['type'] ) )        { $my_boook_type = intval( $attr['type']);        }
        if ( isset( $attr['form_type'] ) )   { $my_booking_form = $attr['form_type']; }
		if ( isset( $attr['agregate'] ) && ( ! empty( $attr['agregate'] ) ) ) {  // FixIn: 7.0.1.26.
			$my_boook_type .= ';' . $attr['agregate'];
		}
		if ( isset( $attr['aggregate'] ) && ( ! empty( $attr['aggregate'] ) ) ) {
			$my_boook_type .= ';' . $attr['aggregate'];
		}
		// Escape any XSS in aggregate parameter.
		$my_boook_type = str_replace( ',', ';', wpbc_clean_digit_or_csd( $my_boook_type ) );

		if ( isset( $attr['options'] ) ) { $bk_otions = $attr['options']; }


        // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
        if (isset($_GET['booking_hash'])) {
			$get_booking_hash = ( ( isset( $_GET['booking_hash'] ) ) ? sanitize_text_field( wp_unslash( $_GET['booking_hash'] ) ) : '' );  /* phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing */ /* FixIn: sanitize_unslash */
            $my_booking_id_type = wpbc_hash__get_booking_id__resource_id( $get_booking_hash );
            if ($my_booking_id_type !== false) {
	            $my_edited_bk_id = $my_booking_id_type[0];
	            $my_boook_type   = $my_booking_id_type[1];
                if ($my_boook_type == '') return '<div class="wpbc_after_booking_thank_you_section"><div class="wpbc_ty__container"><div class="wpbc_ty__header"><strong>' . esc_html__('Oops!' ,'booking') . '</strong> ' . esc_html__('We could not find your booking. The link you used may be incorrect or has expired. If you need assistance, please contact our support team.' ,'booking') . '</div></div></div>';
            } else {
                return '<div class="wpbc_after_booking_thank_you_section"><div class="wpbc_ty__container"><div class="wpbc_ty__header"><strong>' . esc_html__('Oops!' ,'booking') . '</strong> ' . esc_html__('We could not find your booking. The link you used may be incorrect or has expired. If you need assistance, please contact our support team.' ,'booking') . '</div></div></div>';
            }

        } else {
            return __('This page can only be accessed through links in emails related to your booking.' ,'booking')
                    . ' <br/><em>'
                        /* translators: 1: ... */
                        . sprintf( __( 'Please check more about configuration at  %1$sthis page%2$s', 'booking' )
									, '<a href="https://wpbookingcalendar.com/faq/configure-editing-cancel-payment-bookings-for-visitors/" target="_blank">' , '</a>.')
                    . '</em>';
        }


        $res = $this->add_booking_form_action($my_boook_type,$my_boook_count, 0 , $my_booking_form, '', false, $bk_otions );

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
        if (isset($_GET['booking_pay'])) {
            // Payment form
			if ( 'On' == get_bk_option( 'booking_super_admin_receive_regular_user_payments' ) ){								// FixIn: 9.2.3.8.
				make_bk_action('make_force_using_this_user', -999 );      													// '-999' - This ID "by default" is the ID of super booking admin user
			}

			$get_booking_hash = ( ( isset( $_GET['booking_hash'] ) ) ? sanitize_text_field( wp_unslash( $_GET['booking_hash'] ) ) : '' );  /* phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing */ /* FixIn: sanitize_unslash */
			$res = wpbc_do_shortcode__booking_confirm( array(
																'booking_hash' => $get_booking_hash
															) );

			if ( 'On' == get_bk_option( 'booking_super_admin_receive_regular_user_payments' ) ){								// FixIn: 9.2.3.8.
				make_bk_action( 'finish_force_using_this_user' );
			}

        }

        return $res;
    }

    // Search form
    function bookingsearch_shortcode($attr) {

	    if ( ! class_exists( 'wpdev_bk_personal' ) ) {
		    return '<strong>' . esc_html__( 'This shortcode available in Pro versions,  only!', 'booking' ) . '</strong> ';
	    }

	    if ( wpbc_is_on_edit_page() ) {
		    return wpbc_get_preview_for_shortcode( 'bookingsearch', $attr );      // FixIn: 9.9.0.39.
	    }

		$attr = wpbc_escape_shortcode_params( $attr );          //FixIn: 9.7.3.6.1

	    $search_form = '';

	    if ( function_exists( 'wpbc_search_avy__show_search_form' ) ) {

			ob_start();

			$search_form_content = wpbc_search_avy__show_search_form( $attr );

			// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			echo $search_form_content;

		    $search_form = ob_get_clean();
	    }

        return $search_form ;
    }

	/**
	 * Search Results Shortcode   --   Show 'Search Results'    at      New Page
	 *
	 * @param $attr
	 *
	 * @return string
	 */
    function bookingsearchresults_shortcode($attr) {

		if ( ! class_exists( 'wpdev_bk_personal' ) ) {
			return '<strong>' . esc_html__('This shortcode available in Pro versions,  only!' ,'booking') . '</strong> ';
		}

	    if ( wpbc_is_on_edit_page() ) {
		    return wpbc_get_preview_for_shortcode( 'bookingsearchresults', $attr );                                     // FixIn: 9.9.0.39.
	    }

		$attr = wpbc_escape_shortcode_params( $attr );                                                                  //FixIn: 9.7.3.6.1

        //if ( function_exists( 'wpbc_br_cache' ) ) $br_cache = wpbc_br_cache();                                        // Init booking resources cache

	    $search_results_to_show = '';
	    if ( function_exists( 'wpbc_search_avy__show_search_results' ) ) {

		    ob_start();

		    wpbc_search_avy__show_search_results( $attr );                                                              // FixIn: 10.0.0.37.

		    $search_results_to_show .= ob_get_clean();
	    }

        return $search_results_to_show;
    }


    // Select Booking form using the selectbox
    function bookingselect_shortcode($attr) {

		if ( ! class_exists( 'wpdev_bk_personal' ) ) {
			return '<strong>' . esc_html__('This shortcode available in Pro versions,  only!' ,'booking') . '</strong> ';
		}

	    if ( wpbc_is_on_edit_page() ) {
		    return wpbc_get_preview_for_shortcode( 'bookingselect', $attr );      // FixIn: 9.9.0.39.
	    }

		$attr = wpbc_escape_shortcode_params( $attr );          //FixIn: 9.7.3.6.1

        //if ( function_exists( 'wpbc_br_cache' ) ) $br_cache = wpbc_br_cache();  // Init booking resources cache

        $search_form = apply_bk_filter('wpdev_get_booking_select_form','', $attr );

        return $search_form ;
    }

    // Select Booking form using the selectbox
    function bookingresource_shortcode($attr) {

		if ( ! class_exists( 'wpdev_bk_personal' ) ) {
			return '<strong>' . esc_html__('This shortcode available in Pro versions,  only!' ,'booking') . '</strong> ';
		}

	    if ( wpbc_is_on_edit_page() ) {
		    return wpbc_get_preview_for_shortcode( 'bookingresource', $attr );      // FixIn: 9.9.0.39.
	    }

		$attr = wpbc_escape_shortcode_params( $attr );          //FixIn: 9.7.3.6.1

        //if ( function_exists( 'wpbc_br_cache' ) ) $br_cache = wpbc_br_cache();  // Init booking resources cache

        $search_form = apply_bk_filter('wpbc_booking_resource_info','', $attr );

        return $search_form ;
    }


    // </editor-fold>
}