Browse Source

** Booking Activities 1.7.19 **

* Optimization - Dynamic user selectbox in booking list filters
* Optimization - Dynamic product selectbox in Calendar field settings, actions tab
* Tweak - Allow to perform the form action on event click even if there is no Submit button and if the calendar is not in a form
* Tweak - Error messages related to the picked event are removed when a new event is picked
* Fix - The "Events are bookable for up to" option didn't work
* Fix - WC product edit page: Activity tab didn't appear when Activity box was checked
* Fix - WC product edit page: Price warning didn't take the decimal separator into account
* Fix - Multisite: Wrong redirect after creating a booking form
* Fix - Bypass form manager checks for shop managers
* Fix - PHP Notice when creating a calendar or a booking form
* Fix - PHP Error when a user logs in and WC session doesn't exist
* Fix - Display Pack tooltip not displayed on unavailable events on mouseover
* Fix - Form action list didn't changed when calendars changed
develop
yoan_cutillas 2 years ago
parent
commit
7e0be3cf5a
  1. 19
      booking-activities.php
  2. 15
      controller/controller-forms.php
  3. 76
      controller/controller-settings.php
  4. 4
      controller/controller-templates.php
  5. 11
      controller/controller-woocommerce-backend.php
  6. 86
      controller/controller-woocommerce-forms.php
  7. 23
      controller/controller-woocommerce-frontend.php
  8. 13
      css/bookings.css
  9. 2
      css/bookings.min.css
  10. 3
      css/forms.css
  11. 2
      css/forms.min.css
  12. 9
      css/global.css
  13. 2
      css/global.min.css
  14. 20
      functions/functions-booking-system.php
  15. 18
      functions/functions-forms.php
  16. 112
      functions/functions-global.php
  17. 2
      functions/functions-settings.php
  18. 146
      functions/functions-woocommerce.php
  19. 53
      js/backend-functions.js
  20. 2
      js/backend-functions.min.js
  21. 11
      js/booking-system-functions.js
  22. 47
      js/booking-system.js
  23. 2
      js/booking-system.min.js
  24. 4
      js/bookings-functions.js
  25. 2
      js/bookings-functions.min.js
  26. 43
      js/form-editor.js
  27. 2
      js/form-editor.min.js
  28. 68
      js/forms.js
  29. 2
      js/forms.min.js
  30. 206
      js/global-functions.js
  31. 2
      js/global-functions.min.js
  32. 22
      js/woocommerce-backend.js
  33. 2
      js/woocommerce-backend.min.js
  34. 45
      js/woocommerce-frontend.js
  35. 2
      js/woocommerce-frontend.min.js
  36. 97
      js/woocommerce-global.js
  37. 2
      js/woocommerce-global.min.js
  38. 1174
      languages/booking-activities.pot
  39. 4
      languages/script-translation.php
  40. 1
      lib/select2/select2.min.css
  41. 2
      lib/select2/select2.min.js
  42. 51
      model/model-woocommerce.php
  43. 17
      readme.txt
  44. 10
      view/view-bookings.php
  45. 5
      view/view-form-editor-dialogs.php
  46. 5
      view/view-templates-dialogs.php

19
booking-activities.php

@ -3,7 +3,7 @@
* Plugin Name: Booking Activities
* Plugin URI: https://booking-activities.fr/en/?utm_source=plugin&utm_medium=plugin&utm_content=header
* Description: Booking system specialized in activities (sports, cultural, leisure, events...). Works great with WooCommerce.
* Version: 1.7.18
* Version: 1.7.19
* Author: Booking Activities Team
* Author URI: https://booking-activities.fr/en/?utm_source=plugin&utm_medium=plugin&utm_content=header
* Text Domain: booking-activities
@ -40,7 +40,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
// GLOBALS AND CONSTANTS
if( ! defined( 'BOOKACTI_VERSION' ) ) { define( 'BOOKACTI_VERSION', '1.7.18' ); }
if( ! defined( 'BOOKACTI_VERSION' ) ) { define( 'BOOKACTI_VERSION', '1.7.19' ); }
if( ! defined( 'BOOKACTI_PLUGIN_NAME' ) ) { define( 'BOOKACTI_PLUGIN_NAME', 'booking-activities' ); }
@ -121,7 +121,7 @@ if( bookacti_is_plugin_active( 'woocommerce/woocommerce.php' ) ) {
/**
* Enqueue high priority scripts
* @version 1.7.0
* @version 1.7.19
* @global array $bookacti_translation_array
*/
function bookacti_enqueue_high_priority_global_scripts() {
@ -137,7 +137,7 @@ function bookacti_enqueue_high_priority_global_scripts() {
// INCLUDE JAVASCRIPT FILES
wp_register_script( 'bookacti-js-global-var', plugins_url( 'js/global-var.min.js', __FILE__ ), array( 'jquery' ), BOOKACTI_VERSION, false ); // Load in header
wp_register_script( 'bookacti-js-global-functions', plugins_url( 'js/global-functions.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'jquery-ui-autocomplete', 'jquery-ui-tooltip' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-global-functions', plugins_url( 'js/global-functions.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'jquery-ui-tooltip' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-booking-system-functions', plugins_url( 'js/booking-system-functions.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-fullcalendar', 'jquery-effects-highlight' ), BOOKACTI_VERSION, true );
// LOCALIZE SCRIPTS
@ -220,13 +220,18 @@ add_action( 'wp_enqueue_scripts', 'bookacti_enqueue_global_scripts', 20 );
/**
* Enqueue high priority scripts in backend only
* @version 1.7.0
* @version 1.7.19
* @global array $bookacti_translation_array
*/
function bookacti_enqueue_high_priority_backend_scripts() {
// On backend, only include these scripts on Booking Activities pages
if( ! bookacti_is_booking_activities_screen() ) { return; }
// INCLUDE LIBRARIES
$select2_version = '4.0.13';
wp_enqueue_script( 'select2', plugins_url( 'lib/select2/select2.min.js', __FILE__ ), array( 'jquery' ), $select2_version, true );
wp_enqueue_style( 'select2', plugins_url( 'lib/select2/select2.min.css', __FILE__ ), array(), $select2_version );
// INCLUDE JAVASCRIPT FILES
wp_register_script( 'bookacti-js-backend-functions', plugins_url( 'js/backend-functions.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-global-functions', 'jquery-ui-dialog', 'jquery-ui-tabs', 'jquery-ui-tooltip' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-bookings', plugins_url( 'js/bookings.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-fullcalendar', 'bookacti-js-global-functions', 'bookacti-js-backend-functions' ), BOOKACTI_VERSION, true );
@ -236,8 +241,8 @@ function bookacti_enqueue_high_priority_backend_scripts() {
wp_localize_script( 'bookacti-js-bookings', 'bookacti_localized', $bookacti_translation_array );
// ENQUEUE SCRIPTS
wp_enqueue_script ( 'bookacti-js-backend-functions' );
wp_enqueue_script ( 'bookacti-js-bookings' );
wp_enqueue_script( 'bookacti-js-backend-functions' );
wp_enqueue_script( 'bookacti-js-bookings' );
}
add_action( 'admin_enqueue_scripts','bookacti_enqueue_high_priority_backend_scripts', 15 );

15
controller/controller-forms.php

@ -34,7 +34,7 @@ add_action( 'bookacti_display_form_field_calendar', 'bookacti_display_form_field
/**
* Display the form field 'login'
* @since 1.5.0
* @version 1.7.16
* @version 1.7.19
* @param string $html
* @param array $field
* @param string $instance_id
@ -42,13 +42,14 @@ add_action( 'bookacti_display_form_field_calendar', 'bookacti_display_form_field
* @return string
*/
function bookacti_display_form_field_login( $html, $field, $instance_id, $context ) {
$field_id = ! empty( $field[ 'id' ] ) ? esc_attr( $field[ 'id' ] ) : esc_attr( 'bookacti-form-field-' . $field[ 'type' ] . '-' . $field[ 'field_id' ] . '-' . $instance_id );
$field_class = 'bookacti-form-field-container';
if( ! empty( $field[ 'name' ] ) ) { $field_class .= ' bookacti-form-field-name-' . sanitize_title_with_dashes( esc_attr( $field[ 'name' ] ) ); }
if( ! empty( $field[ 'type' ] ) ) { $field_class .= ' bookacti-form-field-type-' . sanitize_title_with_dashes( esc_attr( $field[ 'type' ] ) ); }
if( ! empty( $field[ 'field_id' ] ) ) { $field_class .= ' bookacti-form-field-id-' . esc_attr( $field[ 'field_id' ] ); }
if( ! empty( $field[ 'class' ] ) ) { $field_class .= ' ' . esc_attr( $field[ 'class' ] ); }
ob_start();
?>
<div class='<?php echo $field_class; ?> bookacti-user-is-not-logged-in' id='<?php echo $field_id; ?>' >
@ -153,7 +154,7 @@ function bookacti_display_form_field_login( $html, $field, $instance_id, $contex
bookacti_display_field( $args );
if( empty( $field[ 'generate_password' ] ) && $field[ 'min_password_strength' ] > 1 ) {
wp_enqueue_script( 'password-strength-meter' );
if( wp_script_is( 'password-strength-meter', 'registered' ) ) { wp_enqueue_script( 'password-strength-meter' ); }
?>
<div class='bookacti-password-strength' style='display:none;'>
<span class='bookacti-password-strength-meter'></span>
@ -836,9 +837,9 @@ add_action( 'add_meta_boxes_booking-activities_page_bookacti_forms', 'bookacti_f
/*
* Allow metaboxes on for editor
* @since 1.5.0
* @version 1.7.19
*/
function bookacti_allow_meta_boxes_in_form_editor() {
if( empty( $_REQUEST[ 'action' ] ) || ! in_array( $_REQUEST[ 'action' ], array( 'edit', 'new' ), true ) ) { return; }
/* Trigger the add_meta_boxes hooks to allow meta boxes to be added */
@ -846,7 +847,7 @@ function bookacti_allow_meta_boxes_in_form_editor() {
do_action( 'add_meta_boxes', 'booking-activities_page_bookacti_forms', null );
/* Enqueue WordPress' script for handling the meta boxes */
wp_enqueue_script( 'postbox' );
if( wp_script_is( 'postbox', 'registered' ) ) { wp_enqueue_script( 'postbox' ); }
}
add_action( 'load-booking-activities_page_bookacti_forms', 'bookacti_allow_meta_boxes_in_form_editor' );
@ -877,7 +878,7 @@ add_action( 'admin_footer-booking-activities_page_bookacti_forms', 'bookacti_pri
/**
* Create a booking form from REQUEST parameters
* @since 1.5.0
* @version 1.7.17
* @version 1.7.19
*/
function bookacti_controller_create_form() {
if( empty( $_REQUEST[ 'action' ] ) || $_REQUEST[ 'action' ] !== 'new' ) { return; }
@ -907,7 +908,7 @@ function bookacti_controller_create_form() {
}
// Change current url to the edit url
$form_url = is_multisite() ? network_admin_url( 'admin.php?page=bookacti_forms&action=edit&form_id=' . $form_id ) : admin_url( 'admin.php?page=bookacti_forms&action=edit&form_id=' . $form_id );
$form_url = admin_url( 'admin.php?page=bookacti_forms&action=edit&form_id=' . $form_id );
header( 'Location: ' . $form_url );
}
add_action( 'load-booking-activities_page_bookacti_forms', 'bookacti_controller_create_form', 5 );

76
controller/controller-settings.php

@ -1030,4 +1030,78 @@ function bookacti_add_editable_extensions( $editable_extensions, $plugin ) {
$editable_extensions[] = 'log';
return $editable_extensions;
}
add_filter( 'editable_extensions', 'bookacti_add_editable_extensions', 10, 2 );
add_filter( 'editable_extensions', 'bookacti_add_editable_extensions', 10, 2 );
// AJAX SELECTBOXES
/**
* Search users for AJAX selectbox
* @since 1.7.19
*/
function bookacti_controller_search_select2_users() {
// Check nonce
$is_nonce_valid = check_ajax_referer( 'bookacti_query_select2_options', 'nonce', false );
if( ! $is_nonce_valid ) { bookacti_send_json_not_allowed( 'search_select2_users' ); }
// Check query
$term = isset( $_REQUEST[ 'term' ] ) ? sanitize_text_field( stripslashes( $_REQUEST[ 'term' ] ) ) : '';
if( ! $term ) { bookacti_send_json( array( 'status' => 'failed', 'error' => 'empty_query' ), 'search_select2_users' ); }
$defaults = array(
'name' => isset( $_REQUEST[ 'name' ] ) ? sanitize_title_with_dashes( stripslashes( $_REQUEST[ 'name' ] ) ) : '',
'id' => isset( $_REQUEST[ 'id' ] ) ? sanitize_title_with_dashes( stripslashes( $_REQUEST[ 'id' ] ) ) : '',
'search' => '*' . esc_attr( $term ) . '*',
'search_columns' => array( 'user_login', 'user_url', 'user_email', 'user_nicename', 'display_name' ),
'option_label' => array( 'first_name', ' ', 'last_name', ' (', 'user_login', ' / ', 'user_email', ')' ),
'allow_current' => 0,
'include' => array(), 'exclude' => array(),
'role' => array(), 'role__in' => array(), 'role__not_in' => array(),
'orderby' => 'display_name', 'order' => 'ASC'
);
$args = apply_filters( 'bookacti_ajax_select2_users_args', $defaults );
$users = bookacti_get_users_data( $args );
$options = array();
// Add "Current user" option
if( ! empty( $_REQUEST[ 'allow_current' ] ) ) {
$options[] = array( 'id' => 'current', 'text' => esc_html__( 'Current user', 'booking-activities' ) );
}
// Add user options
foreach( $users as $user ) {
// Build the option label based on the array
$label = '';
foreach( $args[ 'option_label' ] as $show ) {
// If the key contain "||" display the first not empty value
if( strpos( $show, '||' ) !== false ) {
$keys = explode( '||', $show );
$show = $keys[ 0 ];
foreach( $keys as $key ) {
if( ! empty( $user->{ $key } ) ) { $show = $key; break; }
}
}
// Display the value if the key exists, else display the key as is, as a separator
if( isset( $user->{ $show } ) ) {
$label .= $user->{ $show };
} else {
$label .= $show;
}
}
$options[] = array( 'id' => $user->ID, 'text' => esc_html( $label ) );
}
// Allow plugins to add their values
$select2_options = apply_filters( 'bookacti_ajax_select2_users_options', $options, $args );
if( ! $select2_options ) {
bookacti_send_json( array( 'status' => 'failed', 'error' => 'no_results' ), 'search_select2_users' );
}
bookacti_send_json( array( 'status' => 'success', 'options' => $select2_options ), 'search_select2_users' );
}
add_action( 'wp_ajax_bookactiSelect2Query_users', 'bookacti_controller_search_select2_users' );

4
controller/controller-templates.php

@ -705,7 +705,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
/**
* AJAX Controller - Create a new template
* @version 1.7.18
* @version 1.7.19
*/
function bookacti_controller_insert_template() {
// Check nonce and capabilities
@ -727,7 +727,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
bookacti_send_json( array( 'status' => 'failed' ), 'insert_template' );
}
$duplicated_template_id = intval( $_POST[ 'duplicated-template-id' ] );
$duplicated_template_id = ! empty( $_POST[ 'duplicated-template-id' ] ) ? intval( $_POST[ 'duplicated-template-id' ] ) : 0;
$managers_array = isset( $_POST[ 'template-managers' ] ) ? bookacti_ids_to_array( $_POST[ 'template-managers' ] ) : array();
$options_array = isset( $_POST[ 'templateOptions' ] ) && is_array( $_POST[ 'templateOptions' ] ) ? $_POST[ 'templateOptions' ] : array();

11
controller/controller-woocommerce-backend.php

@ -463,7 +463,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
/**
* Bypass template manager check for shop managers
*
* @version 1.7.19
* @param boolean $allowed
* @return boolean
*/
@ -472,10 +472,11 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
}
add_filter( 'bookacti_bypass_template_managers_check', 'bookacti_bypass_checks_for_shop_managers', 10, 1 );
add_filter( 'bookacti_bypass_activity_managers_check', 'bookacti_bypass_checks_for_shop_managers', 10, 1 );
add_filter( 'bookacti_bypass_form_managers_check', 'bookacti_bypass_checks_for_shop_managers', 10, 1 );
// CUSTOM PRODUCTS OPTIONS
/**

86
controller/controller-woocommerce-forms.php

@ -221,7 +221,7 @@ add_filter( 'bookacti_form_action_options', 'bookacti_add_wc_form_action_options
/**
* Add columns to the activity redirect URL table
* @since 1.7.0
* @version 1.7.10
* @version 1.7.19
* @param array $url_array
* @param array $params
* @return array
@ -232,9 +232,8 @@ function bookacti_add_wc_columns_to_activity_redirect_url_table( $url_array, $pa
// Get the product selectbox
$args = array(
'field_name' => 'product_by_activity[0]',
'selected' => '',
'show_option_none' => esc_html_x( 'None', 'About product', 'booking-activities' ),
'option_none_value' => '',
'allow_tags' => 0,
'allow_clear' => 1,
'echo' => 0
);
$default_product_selectbox = bookacti_display_product_selectbox( $args );
@ -267,22 +266,19 @@ add_filter( 'bookacti_activity_redirect_url_table', 'bookacti_add_wc_columns_to_
/**
* Add columns to the group category redirect URL table
* @since 1.7.0
* @version 1.7.10
* @since 1.7.19 (was bookacti_add_wc_columns_to_group_activity_redirect_url_table)
* @param array $url_array
* @param array $params
* @return array
*/
function bookacti_add_wc_columns_to_group_activity_redirect_url_table( $url_array, $params = array() ) {
function bookacti_add_wc_columns_to_group_category_redirect_url_table( $url_array, $params = array() ) {
$url_array[ 'head' ][ 'product' ] = esc_html__( 'Bound product', 'booking-activities' );
$args = array(
'field_name' => 'product_by_group_category[0]',
'selected' => '',
'show_option_none' => esc_html_x( 'None', 'About product', 'booking-activities' ),
'option_none_value' => '',
'echo' => 0,
'limit' => -1
'allow_tags' => 0,
'allow_clear' => 1,
'echo' => 0
);
$default_product_selectbox = bookacti_display_product_selectbox( $args );
@ -309,15 +305,69 @@ function bookacti_add_wc_columns_to_group_activity_redirect_url_table( $url_arra
return $url_array;
}
add_filter( 'bookacti_group_category_redirect_url_table', 'bookacti_add_wc_columns_to_group_activity_redirect_url_table', 10, 2 );
add_filter( 'bookacti_group_category_redirect_url_table', 'bookacti_add_wc_columns_to_group_category_redirect_url_table', 10, 2 );
/**
* Search products for AJAX selectbox
* @since 1.7.19
*/
function bookacti_controller_search_select2_products() {
// Check nonce
$is_nonce_valid = check_ajax_referer( 'bookacti_query_select2_options', 'nonce', false );
if( ! $is_nonce_valid ) { bookacti_send_json_not_allowed( 'search_select2_products' ); }
// Check query
$term = isset( $_REQUEST[ 'term' ] ) ? sanitize_text_field( stripslashes( $_REQUEST[ 'term' ] ) ) : '';
if( ! $term ) { bookacti_send_json( array( 'status' => 'failed', 'error' => 'empty_query' ), 'search_select2_products' ); }
$defaults = array(
'name' => isset( $_REQUEST[ 'name' ] ) ? sanitize_title_with_dashes( stripslashes( $_REQUEST[ 'name' ] ) ) : '',
'id' => isset( $_REQUEST[ 'id' ] ) ? sanitize_title_with_dashes( stripslashes( $_REQUEST[ 'id' ] ) ) : ''
);
$args = apply_filters( 'bookacti_ajax_select2_products_args', $defaults );
$products_titles = bookacti_get_products_titles( $term );
$options = array();
// Add products options
foreach( $products_titles as $product_id => $product ) {
$product_title = esc_html( apply_filters( 'bookacti_translate_text', $product[ 'title' ] ) );
if( empty( $product[ 'variations' ] ) ) {
$options[] = array( 'id' => $product_id, 'text' => $product_title );
} else {
$children_options = array();
foreach( $product[ 'variations' ] as $variation_id => $variation ) {
$variation_title = esc_html( apply_filters( 'bookacti_translate_text', $variation[ 'title' ] ) );
$formatted_variation_title = trim( preg_replace( '/,[\s\S]+?:/', ',', ',' . $variation_title ), ', ' );
$children_options[] = array( 'id' => $variation_id, 'text' => $formatted_variation_title );
}
$options[] = array( 'children' => $children_options, 'text' => $product_title );
}
}
// Allow plugins to add their values
$select2_options = apply_filters( 'bookacti_ajax_select2_products_options', $options, $args );
if( ! $select2_options ) {
bookacti_send_json( array( 'status' => 'failed', 'error' => 'no_results' ), 'search_select2_products' );
}
bookacti_send_json( array( 'status' => 'success', 'options' => $select2_options ), 'search_select2_products' );
}
add_action( 'wp_ajax_bookactiSelect2Query_products', 'bookacti_controller_search_select2_products' );
/**
* Add the product bound to the selected event to cart
* @since 1.7.0
* @version 1.7.17
* @version 1.7.19
*/
function bookacti_controller_add_bound_product_to_cart() {
// Check nonce
if( ! check_ajax_referer( 'bookacti_booking_form', 'nonce_booking_form', false ) ) {
bookacti_send_json_invalid_nonce( 'add_bound_product_to_cart' );
}
$form_id = intval( $_POST[ 'form_id' ] );
$group_id = $_POST[ 'bookacti_group_id' ] === 'single' ? 'single' : intval( $_POST[ 'bookacti_group_id' ] );
@ -475,11 +525,14 @@ add_filter( 'bookacti_product_booking_form_id', 'bookacti_change_product_form_id
/**
* Display WC user meta corresponding to the desired meta if it is empty
* @since 1.7.18
* @version 1.7.19
* @param array $args
* @param array $raw_args
* @return array
*/
function bookacti_display_wc_user_meta_in_user_selectbox( $args, $raw_args ) {
function bookacti_display_wc_user_meta_in_user_selectbox( $args, $raw_args = array() ) {
if( empty( $args[ 'option_label' ] ) ) { return $args; }
$wc_additional_option_labels = array(
'user_email'=> 'billing_email',
'first_name'=> 'billing_first_name||shipping_first_name',
@ -494,4 +547,5 @@ function bookacti_display_wc_user_meta_in_user_selectbox( $args, $raw_args ) {
}
return $args;
}
add_filter( 'bookacti_user_selectbox_args', 'bookacti_display_wc_user_meta_in_user_selectbox', 10, 2 );
add_filter( 'bookacti_user_selectbox_args', 'bookacti_display_wc_user_meta_in_user_selectbox', 10, 2 );
add_filter( 'bookacti_ajax_select2_users_args', 'bookacti_display_wc_user_meta_in_user_selectbox', 10, 1 );

23
controller/controller-woocommerce-frontend.php

@ -12,11 +12,12 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
/**
* Add woocommerce related translations
* @version 1.7.16
* @version 1.7.19
* @param array $translation_array
* @return array
*/
function bookacti_woocommerce_translation_array( $translation_array ) {
$translation_array[ 'empty_product_price' ] = esc_html__( 'You must set a price for your product, otherwise the booking form won’t appear on the product page.', 'booking-activities' );
$translation_array[ 'expired_min' ] = esc_html__( 'expired', 'booking-activities' );
$translation_array[ 'expired' ] = esc_html__( 'Expired', 'booking-activities' );
$translation_array[ 'in_cart' ] = esc_html__( 'In cart', 'booking-activities' );
@ -39,24 +40,24 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
/**
* Change 'user_id' of bookings from customer id to user id when he logs in
*
* @since 1.0.0
* @version 1.4.0
* @version 1.7.19
* @global WooCommerce $woocommerce
* @param string $user_login
* @param WP_User $user
*/
function bookacti_change_customer_id_to_user_id( $user_login, $user ) {
global $woocommerce;
$customer_id = $woocommerce->session->get_customer_id();
// Make sure the customer was not logged in (it could be a user switching between two accounts)
if( ! bookacti_user_id_exists( $customer_id ) ) {
// update customer id to user id
bookacti_update_bookings_user_id( $user->ID, $customer_id );
// Replace bookings customer ID with user ID
if( ! empty( $woocommerce->session ) && is_object( $woocommerce->session ) && method_exists( $woocommerce->session, 'get_customer_id' ) ) {
$customer_id = $woocommerce->session->get_customer_id();
// Make sure the customer was not logged in (it could be a user switching between two accounts)
if( ! bookacti_user_id_exists( $customer_id ) ) {
bookacti_update_bookings_user_id( $user->ID, $customer_id );
}
}
// Update the cart expiration date if the user is logged in
$is_per_product_expiration = bookacti_get_setting_value( 'bookacti_cart_settings', 'is_cart_expiration_per_product' );
if( ! $is_per_product_expiration ) {

13
css/bookings.css

@ -5,7 +5,6 @@
#bookacti-event-filter-container,
.bookacti-bookings-filter-container input,
.bookacti-bookings-filter-container select,
.bookacti-bookings-filter-container .bookacti-combobox,
.bookacti-bookings-filter-container button,
.bookacti-bookings-filter-container .button,
.bookacti-bookings-filter-container textarea { width: 150px; }
@ -17,12 +16,6 @@
#bookacti-pick-event-filter::before { font-family: 'dashicons'; content: "\f508"; margin-right: 4px; font-size: 1.2em; vertical-align: middle; }
#bookacti-unpick-events-filter { margin-top: 4px; }
#bookacti-customer-filter-container .bookacti-combobox { min-height: 28px; }
#bookacti-customer-filter-container .bookacti-combobox > * { background-color: #fff; border-color: #ddd; box-shadow: inset 0 1px 0 rgba(0,0,0,.07); }
#bookacti-customer-filter-container .ui-button.bookacti-combobox-toggle { width: 20px; min-height: 28px; border-left: none; }
#bookacti-customer-filter-container .bookacti-combobox-input { padding: 2px 6px; min-width: 0; max-width: 132px; min-height: 28px; border-right: none; border-bottom-right-radius: 0; border-top-right-radius: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#bookacti-customer-filter-container .bookacti-combobox-toggle.ui-state-hover .ui-icon { background-image: url(../lib/jquery-ui/themes/booking-activities/images/ui-icons_565d61_256x240.png); }
#bookacti-submit-filter-container input { overflow: hidden; text-overflow: ellipsis; }
.bookacti-submit-filter-centered { display: block; margin: 20px auto; }
.bookacti-submit-filter-centered .bookacti-bookings-filter-title { display: none; }
@ -257,14 +250,10 @@ tr.bookacti-booking-list-selected-row { background-color: rgba( 65, 143,
/* Wordpress breakpoint for responsive WP List Table */
@media screen and ( max-width: 782px ) {
/* Backend booking list filters */
#bookacti-bookings-filters-container { width: 100%; text-align: center; }
.bookacti-bookings-filter-title { text-align: left; }
#wpbody .bookacti-bookings-filter-content select[multiple] { height: 75px; }
#bookacti-customer-filter-container .bookacti-combobox { min-height: 36px; }
#bookacti-customer-filter-container .ui-button.bookacti-combobox-toggle { min-height: 36px; }
#bookacti-customer-filter-container .bookacti-combobox-input { min-height: 36px; position: absolute; left: 0; }
/* Backend booking list */
.bookacti-booking-primary-data-container { display: inline-block; }
@ -320,6 +309,4 @@ tr.bookacti-booking-list-selected-row { background-color: rgba( 65, 143,
.bookacti-bookings-filter-content input,
.bookacti-bookings-filter-content a { width: 100%; }
#wpbody .bookacti-bookings-filter-content select[multiple] { height: 60px; }
#bookacti-customer-filter-container .bookacti-combobox-input { max-width: none; }
#bookacti-customer-filter-container .ui-button.bookacti-combobox-toggle { width: 32px; }
}

2
css/bookings.min.css

File diff suppressed because one or more lines are too long

3
css/forms.css

@ -74,8 +74,6 @@ body.booking-activities_page_bookacti_forms label[for='bookacti_form_publish-hid
.bookacti-form-dialog form fieldset > div:last-child,
.bookacti-form-dialog form > div:last-child { margin-bottom: 0; }
.bookacti-form-dialog .bookacti-combobox-input { min-width: 150px; width: 150px; }
.bookacti-activities-actions-options-table,
.bookacti-group-categories-actions-options-table { display: none; }
.bookacti-activities-actions-options-table h4,
@ -98,7 +96,6 @@ body.booking-activities_page_bookacti_forms label[for='bookacti_form_publish-hid
/***** FORMS FIELDS FORMATING *****/
.bookacti-form-field-container { margin-bottom: 20px; }
.bookacti-form-field-container:not(.bookacti-form-field-type-calendar) { overflow: hidden; }
.bookacti-form-field-label,
.bookacti-form-field-content { display: inline-block; vertical-align: middle; margin: 0; }
.bookacti-form-field-label { width: 160px; padding-right: 10px; }

2
css/forms.min.css

File diff suppressed because one or more lines are too long

9
css/global.css

@ -2,12 +2,9 @@
/** GLOBAL **/
/* Combobox */
/* Select2 */
.bookacti-user-selectbox { width: 100%; }
.bookacti-combobox { position: relative; display: inline-block; vertical-align: middle; width: auto; min-height: 40px; }
.ui-button.bookacti-combobox-toggle { position: absolute; display: inline-block; top: 0; right: -1px; padding: 0; margin: 0; width: 32px; min-height: 40px; box-sizing: border-box; border-bottom-right-radius: 3px; border-top-right-radius: 3px; }
.bookacti-combobox-input { margin: 0; margin-right: -1px; padding: 5px 10px; min-width: 200px; min-height: 40px; width: auto; border-radius: 3px; }
.bookacti-combobox-list { max-height: 200px; max-width: 480px; overflow-y: auto; overflow-x: hidden; }
.bookacti-select2-dropdown { z-index: 10001; }
/* Radio box */
.bookacti-custom-radio-button { display: inline-block; margin: 0 0.5em 0.5em 0; }
@ -103,7 +100,7 @@
/* Events */
.bookacti-calendar .fc-event { overflow: hidden; }
.bookacti-calendar .fc-event:not(.bookacti-event-unavailable) { cursor: pointer; }
.bookacti-event-unavailable { opacity: 0.5; z-index: -1 !important; }
.bookacti-event-unavailable { opacity: 0.5; }
.bookacti-picked-event .fc-bg { opacity: 0.5; transition: opacity 0.2s; }
.bookacti-picked-event { border-width: 2px; z-index: 15 !important; transition: border 0.2s; }

2
css/global.min.css

File diff suppressed because one or more lines are too long

20
functions/functions-booking-system.php

@ -510,7 +510,7 @@ function bookacti_get_calendar_field_booking_system_attributes( $calendar_field
// Transform the Calendar field settings to Booking system attributes
$booking_system_atts_raw= array_merge( $calendar_field, $availability_period, array( 'picked_events' => $picked_events, 'display_data' => $display_data ) );
$booking_system_atts = bookacti_format_booking_system_attributes( $booking_system_atts_raw );
return apply_filters( 'bookacti_calendar_field_booking_system_attributes', $booking_system_atts, $calendar_field );
}
@ -640,7 +640,7 @@ function bookacti_format_booking_system_url_attributes( $atts = array() ) {
/**
* Get booking system fields default data
* @since 1.5.0
* @version 1.7.17
* @version 1.7.19
* @param array $fields
* @return array
*/
@ -660,7 +660,6 @@ function bookacti_get_booking_system_fields_default_data( $fields = array() ) {
$defaults[ 'calendars' ] = array(
'name' => 'calendars',
'type' => 'select',
'id' => '_bookacti_template',
'multiple' => 'maybe',
'options' => $templates_options,
'value' => '',
@ -720,7 +719,6 @@ function bookacti_get_booking_system_fields_default_data( $fields = array() ) {
$defaults[ 'groups_only' ] = array(
'type' => 'checkbox',
'name' => 'groups_only',
'id' => '_bookacti_groups_only',
'value' => 0,
'title' => esc_html__( 'Groups only', 'booking-activities' ),
'tip' => esc_html__( 'Display only groups of events if checked. Else, also display the other single events (if any).', 'booking-activities' )
@ -775,12 +773,10 @@ function bookacti_get_booking_system_fields_default_data( $fields = array() ) {
'name' => 'user_id',
'options' => array(
'name' => 'user_id',
'id' => 'user_id',
'show_option_all' => esc_html__( 'All', 'booking-activities' ),
'show_option_current' => esc_html__( 'Current user', 'booking-activities' ),
'option_label' => array( 'user_login', ' (', 'user_email', ')' ),
'selected' => 0,
'echo' => true
'allow_current' => 1,
'echo' => 1
),
'title' => esc_html__( 'Customer', 'booking-activities' ),
'tip' => esc_html__( 'Retrieve events booked by the selected user only.', 'booking-activities' ) . ' ' . esc_html__( '"Booked only" option must be activated.', 'booking-activities' )
@ -1640,7 +1636,7 @@ function bookacti_get_calendar_field_availability_period( $calendar_field ) {
/**
* Get availability period according to relative and absolute dates
* @since 1.5.9
* @version 1.7.17
* @version 1.7.19
* @param array $absolute_period
* @param array $relative_period
* @param boolean $bypass_relative_period
@ -1663,7 +1659,7 @@ function bookacti_get_availability_period( $absolute_period = array(), $relative
$relative_start_time = clone $current_time;
$relative_start_time->add( new DateInterval( 'P' . $relative_period_start . 'D' ) );
$relative_start_date = $relative_start_time->format( 'Y-m-d' );
if( strtotime( $relative_start_date ) > strtotime( $absolute_period[ 'start' ] ) ) {
if( strtotime( $relative_start_date ) > strtotime( $calendar_start_date ) ) {
$calendar_start_date = $relative_start_date;
}
}
@ -1671,14 +1667,14 @@ function bookacti_get_availability_period( $absolute_period = array(), $relative
$relative_end_time = clone $current_time;
$relative_end_time->add( new DateInterval( 'P' . $relative_period_end . 'D' ) );
$relative_end_date = $relative_end_time->format( 'Y-m-d' );
if( strtotime( $relative_end_date ) < strtotime( $absolute_period[ 'end' ] ) ) {
if( strtotime( $relative_end_date ) < strtotime( $calendar_end_date ) ) {
$calendar_end_date = $relative_end_date;
}
}
}
$availability_period = array( 'start' => $calendar_start_date, 'end' => $calendar_end_date );
return apply_filters( 'bookacti_availability_period', $availability_period, $absolute_period, $relative_period );
}

18
functions/functions-forms.php

@ -185,7 +185,7 @@ function bookacti_sanitize_form_data( $raw_form_data ) {
/**
* Display a booking form
* @version 1.7.7
* @version 1.7.19
* @param int $form_id
* @param string $instance_id
* @param string $context
@ -237,12 +237,12 @@ function bookacti_display_form( $form_id, $instance_id = '', $context = 'display
// Add form container only if there is a "submit" button
if( $is_form ) { ?>
<form <?php echo $form_attributes_str; ?>>
<input type='hidden' name='action' value='bookactiSubmitBookingForm' />
<input type='hidden' name='nonce_booking_form' value='<?php echo wp_create_nonce( 'bookacti_booking_form' ); ?>' />
<?php } else { ?>
<div <?php echo $form_attributes_str; ?>>
<?php } ?>
<input type='hidden' name='form_id' value='<?php echo $form_id; ?>' />
<input type='hidden' name='action' value='bookactiSubmitBookingForm' />
<input type='hidden' name='nonce_booking_form' value='<?php echo wp_create_nonce( 'bookacti_booking_form' ); ?>' />
<?php
do_action( 'bookacti_form_before', $form, $instance_id, $context );
@ -744,7 +744,7 @@ function bookacti_format_form_field_data( $raw_field_data ) {
/**
* Sanitize field data according to its type
* @since 1.5.0
* @version 1.7.17
* @version 1.7.19
* @param array|string $raw_field_data
* @return array|false
*/
@ -764,6 +764,7 @@ function bookacti_sanitize_form_field_data( $raw_field_data ) {
if( $raw_field_data[ 'name' ] === 'calendar' ) {
$booleans_to_check = array( 'groups_only', 'groups_single_events', 'bookings_only', 'past_events', 'past_events_bookable' );
foreach( $booleans_to_check as $key ) {
if( ! isset( $raw_field_data[ $key ] ) ) { $field_meta[ $key ] = $default_meta[ $key ]; continue; }
$field_meta[ $key ] = in_array( $raw_field_data[ $key ], array( 1, '1', true, 'true', 'yes', 'ok' ), true ) ? 1 : 0;
}
@ -783,7 +784,7 @@ function bookacti_sanitize_form_field_data( $raw_field_data ) {
$field_meta[ 'group_categories' ] = $group_categories && is_array( $group_categories ) ? $group_categories : ( $had_group_categories ? array( 'none' ) : array() );
$field_meta[ 'status' ] = isset( $raw_field_data[ 'status' ] ) && is_array( $raw_field_data[ 'status' ] ) ? array_intersect( $raw_field_data[ 'status' ], array_keys( bookacti_get_booking_state_labels() ) ) : $default_meta[ 'status' ];
$field_meta[ 'user_id' ] = isset( $raw_field_data[ 'user_id' ] ) && is_numeric( $raw_field_data[ 'user_id' ] ) ? intval( $raw_field_data[ 'user_id' ] ) : ( in_array( $raw_field_data[ 'user_id' ], array( 0, '0', 'current' ), true ) ? $raw_field_data[ 'user_id' ] : $default_meta[ 'user_id' ] );
$field_meta[ 'user_id' ] = isset( $raw_field_data[ 'user_id' ] ) && is_numeric( $raw_field_data[ 'user_id' ] ) ? intval( $raw_field_data[ 'user_id' ] ) : ( isset( $raw_field_data[ 'user_id' ] ) && in_array( $raw_field_data[ 'user_id' ], array( 0, '0', 'current' ), true ) ? $raw_field_data[ 'user_id' ] : $default_meta[ 'user_id' ] );
$field_meta[ 'method' ] = isset( $raw_field_data[ 'method' ] ) && in_array( $raw_field_data[ 'method' ], array_keys( bookacti_get_available_booking_methods() ), true ) ? $raw_field_data[ 'method' ] : $default_meta[ 'method' ];
@ -1553,10 +1554,9 @@ function bookacti_format_form_filters( $filters = array() ) {
/**
* Display 'managers' metabox content for forms
* @since 1.5.0
* @version 1.7.12
* @version 1.7.19
*/
function bookacti_display_form_managers_meta_box( $form ) {
// Get current form managers option list
$managers_already_added = array();
$manager_ids = bookacti_get_form_managers( $form[ 'form_id' ] );
@ -1576,8 +1576,8 @@ function bookacti_display_form_managers_meta_box( $form ) {
// Get available form managers option list
$in_roles = apply_filters( 'bookacti_managers_roles', array() );
$not_in_roles = apply_filters( 'bookacti_managers_roles_exceptions', is_multisite() ? array() : array( 'administrator' ) );
$user_query = new WP_User_Query( array( 'blog_id' => is_multisite() ? 0 : get_current_blog_id(), 'role__in' => $in_roles, 'role__not_in' => $not_in_roles ) );
$not_in_roles = apply_filters( 'bookacti_managers_roles_exceptions', array( 'administrator' ) );
$user_query = new WP_User_Query( array( 'role__in' => $in_roles, 'role__not_in' => $not_in_roles ) );
$users = $user_query->get_results();
$available_managers_options_list = '';
if ( ! empty( $users ) ) {

112
functions/functions-global.php

@ -1073,91 +1073,89 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
/**
* Create a user selectbox
* @since 1.3.0
* @version 1.7.18
* @version 1.7.19
* @param array $raw_args
* @return string|void
*/
function bookacti_display_user_selectbox( $raw_args ) {
$defaults = array(
'show_option_all' => '',
'show_option_none' => '', 'option_none_value' => -1,
'show_option_self' => '', 'option_self_value' => '',
'show_option_current' => '', 'option_current_value' => 'current',
'option_label' => array( 'display_name' ), 'echo' => 1,
'allow_tags' => 0, 'allow_clear' => 1, 'allow_current' => 0,
'option_label' => array( 'display_name' ), 'ajax' => 1, 'echo' => 1,
'selected' => 0, 'name' => 'user_id', 'class' => '', 'id' => '',
'include' => array(), 'exclude' => array(),
'role' => array(), 'role__in' => array(), 'role__not_in' => array(),
'orderby' => 'display_name', 'order' => 'ASC'
);
$args = apply_filters( 'bookacti_user_selectbox_args', wp_parse_args( $raw_args, $defaults ), $raw_args );
$users = bookacti_get_users_data( $args );
$args = apply_filters( 'bookacti_user_selectbox_args', wp_parse_args( $raw_args, $defaults ), $raw_args );
$users = ! $args[ 'ajax' ] ? bookacti_get_users_data( $args ) : array();
$args[ 'class' ] = $args[ 'ajax' ] ? 'bookacti-select2-ajax ' . trim( $args[ 'class' ] ) : 'bookacti-select2-no-ajax ' . trim( $args[ 'class' ] );
if( $args[ 'ajax' ] && $args[ 'selected' ] ) {
$user = get_user_by( 'id', $args[ 'selected' ] );
if( $user ) { $users[] = $user; }
}
ob_start();
?>
<input type='hidden' name='<?php echo $args[ 'name' ]; ?>' value='' />
<select <?php if( $args[ 'id' ] ) { echo 'id="' . $args[ 'id' ] . '"'; } ?> name='<?php echo $args[ 'name' ]; ?>' class='bookacti-user-selectbox <?php echo $args[ 'class' ]; ?>' >
<option value='' ><?php echo esc_html__( 'Search for a customer', 'booking-activities' ); ?></option>
<select <?php if( $args[ 'id' ] ) { echo 'id="' . $args[ 'id' ] . '"'; } ?>
name='<?php echo $args[ 'name' ]; ?>'
class='bookacti-user-selectbox <?php echo $args[ 'class' ]; ?>'
data-tags='<?php echo ! empty( $args[ 'allow_tags' ] ) ? 1 : 0; ?>'
data-allow-clear='<?php echo ! empty( $args[ 'allow_clear' ] ) ? 1 : 0; ?>'
data-placeholder='<?php esc_html_e( 'Search for a customer', 'booking-activities' ); ?>'
data-type='users' >
<option><!-- Used for the placeholder --></option>
<?php
if( $args[ 'show_option_all' ] ) {
$_selected = selected( 0, $args[ 'selected' ], false );
?><option value='0' <?php echo $_selected ?> ><?php echo $args[ 'show_option_all' ]; ?></option><?php
}
if( $args[ 'show_option_none' ] ) {
$_selected = selected( $args[ 'option_none_value' ], $args[ 'selected' ], false );
?><option value='<?php echo esc_attr( $args[ 'option_none_value' ] ); ?>' <?php echo $_selected ?> ><?php echo $args[ 'show_option_none' ]; ?></option><?php
if( $args[ 'allow_current' ] ) {
$_selected = selected( 'current', $args[ 'selected' ], false );
?><option value='current' <?php echo $_selected ?> ><?php esc_html_e( 'Current user', 'booking-activities' ); ?></option><?php
}
if( $args[ 'show_option_current' ] ) {
$_selected = selected( $args[ 'option_current_value' ], $args[ 'selected' ], false );
?><option value='<?php echo esc_attr( $args[ 'option_current_value' ] ); ?>' <?php echo $_selected ?> ><?php echo $args[ 'show_option_current' ]; ?></option><?php
}
if( $args[ 'show_option_self' ] ) {
$_selected = selected( $args[ 'option_self_value' ], $args[ 'selected' ], false );
?><option value='<?php echo esc_attr( $args[ 'option_self_value' ] ); ?>' class='bookacti-variable-value' <?php echo $_selected ?> ><?php echo $args[ 'option_self_value' ] ? $args[ 'option_self_value' ] : $args[ 'show_option_self' ]; ?></option><?php
}
do_action( 'bookacti_add_user_selectbox_options', $args, $users );
$is_selected = false;
if( $users ) {
foreach( $users as $user ) {
$_selected = selected( $user->ID, $args[ 'selected' ], false );
if( $_selected ) { $is_selected = true; }
// Build the option label based on the array
$label = '';
foreach( $args[ 'option_label' ] as $show ) {
// If the key contain "||" display the first not empty value
if( strpos( $show, '||' ) !== false ) {
$keys = explode( '||', $show );
$show = $keys[ 0 ];
foreach( $keys as $key ) {
if( ! empty( $user->{ $key } ) ) { $show = $key; break; }
}
}
foreach( $users as $user ) {
$_selected = selected( $user->ID, $args[ 'selected' ], false );
// Build the option label based on the array
$label = '';
foreach( $args[ 'option_label' ] as $show ) {
// If the key contain "||" display the first not empty value
if( strpos( $show, '||' ) !== false ) {
$keys = explode( '||', $show );
$show = $keys[ 0 ];
foreach( $keys as $key ) {
if( ! empty( $user->{ $key } ) ) { $show = $key; break; }
// Display the value if the key exists, else display the key as is, as a separator
if( isset( $user->{ $show } ) ) {
$label .= $user->{ $show };
} else {
$label .= $show;
}
}
// Display the value if the key exists, else display the key as is, as a separator
if( isset( $user->{ $show } ) ) {
$label .= $user->{ $show };
} else {
$label .= $show;
}
?>
<option value='<?php echo $user->ID; ?>' <?php echo $_selected ?> ><?php echo esc_html( $label ); ?></option>
<?php
}
?>
<option value='<?php echo $user->ID; ?>' <?php echo $_selected ?> ><?php echo esc_html( $label ); ?></option>
<?php
}
if( $args[ 'allow_tags' ] && $args[ 'selected' ] !== '' && ! $is_selected ) {
?><option value='<?php echo esc_attr( $args[ 'selected' ] ); ?>' selected="selected"><?php echo esc_html( $args[ 'selected' ] ); ?></option><?php
}
?>
</select>
<?php
$output = ob_get_clean();
// Return the output...
if( ! $args[ 'echo' ] ) { return $output; }
// ...or echo
echo $output;
}
@ -1658,7 +1656,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
/**
* Get users metadata
* @version 1.7.1
* @version 1.7.19
* @param array $args
* @return array
*/
@ -1671,7 +1669,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
'date_query' => array(),
'orderby' => 'login', 'order' => 'ASC', 'offset' => '',
'number' => '', 'paged' => '', 'count_total' => false,
'search' => '', 'fields' => 'all'
'search' => '', 'search_columns' => array(), 'fields' => 'all'
);
$args = apply_filters( 'bookacti_users_data_args', wp_parse_args( $args, $defaults ), $args );

2
functions/functions-settings.php

@ -310,7 +310,7 @@ function bookacti_settings_section_licenses_callback() { }
$selected_timezone = bookacti_get_setting_value( 'bookacti_general_settings', 'timezone' );
// Display selectbox
echo '<select name="bookacti_general_settings[timezone]" >';
echo '<select name="bookacti_general_settings[timezone]" class="bookacti-select2-no-ajax">';
foreach( $timezones as $region => $list ) {
echo '<optgroup label="' . $region . '" >';
foreach( $list as $timezone => $name ) {

146
functions/functions-woocommerce.php

@ -1691,67 +1691,77 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
/**
* Display a products selectbox
* @since 1.7.0
* @version 1.7.10
* @param array $args
* @param array $products_titles
* @version 1.7.19
* @param array $raw_args
* @return string
*/
function bookacti_display_product_selectbox( $args = array(), $products_titles = array() ) {
function bookacti_display_product_selectbox( $raw_args = array() ) {
$defaults = array(
'field_name' => 'product_id',
'selected' => '',
'id' => '',
'class' => '',
'show_option_none' => '',
'option_none_value' => 'none',
'allow_tags' => 0,
'allow_clear' => 1,
'ajax' => 1,
'echo' => 1
);
$r = wp_parse_args( $args, $defaults );
$args = apply_filters( 'bookacti_product_selectbox_args', wp_parse_args( $raw_args, $defaults ), $raw_args );
if( ! $products_titles ) { $products_titles = bookacti_get_products_titles(); }
$products_titles = ! $args[ 'ajax' ] ? bookacti_get_products_titles() : ( $args[ 'selected' ] ? bookacti_get_products_titles( $args[ 'selected' ] ) : array() );
$args[ 'class' ] = $args[ 'ajax' ] ? 'bookacti-select2-ajax ' . trim( $args[ 'class' ] ) : 'bookacti-select2-no-ajax ' . trim( $args[ 'class' ] );
ob_start();
?>
<select name='<?php echo $r[ 'field_name' ]; ?>' class='bookacti-wc-products-selectbox <?php echo $r[ 'class' ]; ?>'>
<select <?php if( $args[ 'id' ] ) { echo 'id="' . $args[ 'id' ] . '"'; } ?>
name='<?php echo $args[ 'field_name' ]; ?>'
class='bookacti-wc-products-selectbox <?php echo $args[ 'class' ]; ?>'
data-tags='<?php echo ! empty( $args[ 'allow_tags' ] ) ? 1 : 0; ?>'
data-allow-clear='<?php echo ! empty( $args[ 'allow_clear' ] ) ? 1 : 0; ?>'
data-placeholder='<?php esc_html_e( 'Search for a product', 'booking-activities' ); ?>'
data-type='products' >
<option><!-- Used for the placeholder --></option>
<?php
// Display 'none' value
if( ! empty( $r[ 'show_option_none' ] ) ) {
?>
<option value='<?php echo esc_attr( $r[ 'option_none_value' ] ); ?>'><?php echo $r[ 'show_option_none' ]; ?></option>
<?php
}
do_action( 'bookacti_add_product_selectbox_options', $args, $products_titles );
foreach( $products_titles as $product_id => $product ) {
// Display simple products options
if( empty( $product[ 'variations' ] ) ) {
?>
<option class='bookacti-wc-product-option' value='<?php echo esc_attr( $product_id ); ?>' <?php selected( $product_id, $r[ 'selected' ] ); ?>><?php echo apply_filters( 'bookacti_translate_text', $product[ 'title' ] ); ?></option>
<?php
// Display variations options
} else {
?>
<optgroup class='bookacti-wc-variable-product-option-group' label='<?php echo esc_attr( apply_filters( 'bookacti_translate_text', $product[ 'title' ] ) ); ?>'>
<?php
foreach( $product[ 'variations' ] as $variation_id => $variation ) {
$variation_title = apply_filters( 'bookacti_translate_text', $variation[ 'title' ] );
$strpos = strpos( $variation_title, ' - ' );
if( $strpos !== false ) { $strpos += 3; } else { $strpos = 0; }
?>
<option class='bookacti-wc-product-variation-option' value='<?php echo esc_attr( $variation_id ); ?>' <?php selected( $variation_id, $r[ 'selected' ] ); ?>><?php echo substr( $variation_title, $strpos ); ?></option>
<?php
}
$is_selected = false;
if( $products_titles ) {
foreach( $products_titles as $product_id => $product ) {
// Display simple products options
if( empty( $product[ 'variations' ] ) ) {
$_selected = selected( $product_id, $args[ 'selected' ] );
if( $_selected ) { $is_selected = true; }
?><option class='bookacti-wc-product-option' value='<?php echo esc_attr( $product_id ); ?>' <?php echo $_selected; ?>><?php echo esc_html( apply_filters( 'bookacti_translate_text', $product[ 'title' ] ) ); ?></option><?php
// Display variations options
} else {
?>
</optgroup>
<?php
<optgroup class='bookacti-wc-variable-product-option-group' label='<?php echo esc_attr( apply_filters( 'bookacti_translate_text', $product[ 'title' ] ) ); ?>'>
<?php
foreach( $product[ 'variations' ] as $variation_id => $variation ) {
$_selected = selected( $variation_id, $args[ 'selected' ] );
if( $_selected ) { $is_selected = true; }
$variation_title = esc_html( apply_filters( 'bookacti_translate_text', $variation[ 'title' ] ) );
$formatted_variation_title = trim( preg_replace( '/,[\s\S]+?:/', ',', ',' . $variation_title ), ', ' );
?><option class='bookacti-wc-product-variation-option' value='<?php echo esc_attr( $variation_id ); ?>' <?php echo $_selected; ?>><?php echo $formatted_variation_title; ?></option><?php
}
?>
</optgroup>
<?php
}
}
}
if( $args[ 'allow_tags' ] && $args[ 'selected' ] !== '' && ! $is_selected ) {
?><option value='<?php echo esc_attr( $args[ 'selected' ] ); ?>' selected="selected"><?php echo esc_html( $args[ 'selected' ] ); ?></option><?php
}
?>
</select>
<?php
$selectbox = ob_get_clean();
if( empty( $r[ 'echo' ] ) ) { return $selectbox; }
echo $selectbox;
$output = ob_get_clean();
if( empty( $args[ 'echo' ] ) ) { return $output; }
echo $output;
}
@ -2431,47 +2441,29 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
/**
* Setting for: Bookings page in My Account
* @since 1.7.16
* @version 1.7.19
*/
function bookacti_settings_wc_my_account_bookings_page_id_callback() {
wp_enqueue_script( 'wc-enhanced-select' );
wp_enqueue_style( 'woocommerce_admin_styles' );
$args = array(
'name' => 'bookacti_account_settings[wc_my_account_bookings_page_id]',
'id' => 'wc_my_account_bookings_page_id',
'type' => 'single_select_page',
'default' => '',
'class' => 'wc-enhanced-select-nostd',
'sort_column' => 'menu_order',
'sort_order' => 'ASC',
'show_option_no_change' => esc_html__( 'Disabled' ),
'show_option_none' => esc_html__( 'Default booking list', 'booking-activities' ),
'option_none_value' => 0,
'selected' => bookacti_get_setting_value( 'bookacti_account_settings', 'wc_my_account_bookings_page_id' ),
$options = array(
'-1' => esc_html__( 'Disabled' ),
'0' => esc_html__( 'Default booking list', 'booking-activities' ),
);
wp_dropdown_pages( $args );
bookacti_help_tip( esc_html__( 'Select the page to display in the "Bookings" tab of the "My account" area. You can also display the default booking list, or completely disable this tab.', 'booking-activities' ) );
}
/**
* Select the default value when no page is selected in "Bookings page in My Account" setting
* This function is necessary since wp_dropdown_pages ignore the "selected" parameter for both "no_changes" and "none" options
* @since 1.7.16
* @param string $output
* @param array $parsed_args
* @param array $pages
* @return string
*/
function bookacti_settings_wc_my_account_bookings_page_id_select_default_value( $output, $parsed_args, $pages ) {
if( $parsed_args[ 'id' ] !== 'wc_my_account_bookings_page_id' ) { return $output; }
if( intval( $parsed_args[ 'selected' ] ) > 0 ) { return $output; }
$search = '<option value="' . intval( $parsed_args[ 'selected' ] ) . '"';
$replace= $search . ' selected';
$pages = get_pages( array( 'sort_column' => 'menu_order', 'sort_order' => 'ASC' ) );
foreach( $pages as $page ) {
$options[ $page->ID ] = apply_filters( 'bookacti_translate_text', $page->post_title );
}
return str_replace( $search, $replace, $output );
$args = array(
'type' => 'select',
'name' => 'bookacti_account_settings[wc_my_account_bookings_page_id]',
'id' => 'wc_my_account_bookings_page_id',
'class' => 'bookacti-select2-no-ajax',
'options' => $options,
'value' => bookacti_get_setting_value( 'bookacti_account_settings', 'wc_my_account_bookings_page_id' ),
'tip' => esc_html__( 'Select the page to display in the "Bookings" tab of the "My account" area. You can also display the default booking list, or completely disable this tab.', 'booking-activities' )
);
bookacti_display_field( $args );
}
add_filter( 'wp_dropdown_pages', 'bookacti_settings_wc_my_account_bookings_page_id_select_default_value', 10, 3 );

53
js/backend-functions.js

@ -1,5 +1,4 @@
$j( document ).ready( function() {
// Update multilangual fields with Qtranslate X
$j( '.qtranxs-translatable' ).on( 'keyup', function() {
bookacti_update_qtx_field( this );
@ -18,19 +17,6 @@ $j( document ).ready( function() {
bookacti_switch_select_to_multiple( this );
});
//Show or hide activities depending on the selected template
// On load
if( $j( '#_bookacti_template' ).length ) {
var template_ids = $j( '#_bookacti_template' ).val();
var options = $j( '[data-bookacti-show-if-templates]' );
bookacti_show_hide_template_related_options( template_ids, options );
}
// On change
$j( '#_bookacti_template' ).on( 'change', function(){
var template_ids = $j( this ).val();
var options = $j( '[data-bookacti-show-if-templates]' );
bookacti_show_hide_template_related_options( template_ids, options );
});
// Tooltip
bookacti_init_tooltip();
@ -46,6 +32,38 @@ $j( document ).ready( function() {
window.location.replace( url );
});
/**
* Init select2
* @since 1.7.19
*/
bookacti_select2_init();
/**
* Allow select2 to work in a jquery-ui dialog
* @since 1.7.19
*/
$j( '.bookacti-backend-dialog' ).dialog({
autoOpen: false,
open: function() {
if( $j.ui && $j.ui.dialog && ! $j.ui.dialog.prototype._allowInteractionRemapped && $j( this ).closest( '.ui-dialog' ).length ) {
if( $j.ui.dialog.prototype._allowInteraction ) {
$j.ui.dialog.prototype._allowInteraction = function( e ) {
if( $j( e.target ).closest( '.select2-drop' ).length ) { return true; }
if( typeof ui_dialog_interaction === 'undefined' ) { return true; }
return ui_dialog_interaction.apply( this, arguments );
};
$j.ui.dialog.prototype._allowInteractionRemapped = true;
} else {
$j.error( 'You must upgrade jQuery UI or else.' );
}
}
},
_allowInteraction: function( event ) {
return ! ( ( ! $j( event.target ).is( '.select2-input' ) ) || this._super( event ) );
}
});
});
@ -163,7 +181,7 @@ function bookacti_empty_all_dialog_forms( scope ) {
/**
* Fill custom settings fields in a form
* @version 1.7.17
* @version 1.7.19
* @param {array} fields
* @param {string} field_prefix
* @param {qtring} scope
@ -226,11 +244,6 @@ function bookacti_fill_fields_from_array( fields, field_prefix, scope ) {
} else if( $j( scope + 'select[name="' + field_name + '"]' ).length ) {
$j( scope + 'select[name="' + field_name + '"] option[value="' + value + '"]' ).prop( 'selected', true );
$j( scope + 'select[name="' + field_name + '"]' ).trigger( 'change' );
// Update user-selectbox
if( $j( scope + 'select[name="' + field_name + '"].bookacti-user-selectbox' ).length ) {
var new_value = $j( scope + 'select[name="' + field_name + '"].bookacti-user-selectbox option:selected' ).html();
$j( scope + 'select[name="' + field_name + '"].bookacti-user-selectbox' ).siblings( '.bookacti-combobox' ).find( '.bookacti-combobox-input' ).val( new_value );
}
// Select multiple
} else if( $j( scope + 'select[name="' + field_name + '[]"]' ).length ) {

2
js/backend-functions.min.js

File diff suppressed because one or more lines are too long

11
js/booking-system-functions.js

@ -509,9 +509,14 @@ function bookacti_fill_booking_system_fields( booking_system, event, group_id )
}
// Pick all events of a group onto the calendar
/**
* Pick all events of a group onto the calendar
* @version 1.7.19
* @param {dom_element} booking_system
* @param {int|string} group_id
* @param {object} event
*/
function bookacti_pick_events_of_group( booking_system, group_id, event ) {
group_id = $j.isArray( group_id ) && group_id.length === 1 ? group_id[ 0 ] : group_id;
group_id = $j.isNumeric( group_id ) || group_id === 'single' ? group_id : false;
@ -525,7 +530,7 @@ function bookacti_pick_events_of_group( booking_system, group_id, event ) {
// Empty the picked events and refresh them
bookacti_unpick_all_events( booking_system );
// Pick a single event or the whol group
// Pick a single event or the whole group
if( group_id === 'single' ) {
bookacti_pick_event( booking_system, event );
} else {

47
js/booking-system.js

@ -1,8 +1,18 @@
$j( document ).ready( function() {
/**
* Remove error messages after pciking new events
* @since 1.7.19
*/
$j( 'body' ).on( 'bookacti_events_picked', '.bookacti-booking-system', function( e, group_id, event ) {
if( $j( this ).siblings( '.bookacti-notices' ).length ) {
$j( this ).siblings( '.bookacti-notices' ).empty();
}
});
/**
* Init actions to perfoms when the user picks an event
* @version 1.7.10
* @version 1.7.19
*/
$j( 'body' ).on( 'bookacti_events_picked', '.bookacti-booking-system', function( e, group_id, event ){
// Retrieve the info required to show the desired events
@ -26,8 +36,14 @@ $j( document ).ready( function() {
if( group_id === 'single' && attributes[ 'when_perform_form_action' ] === 'on_event_click' ) {
if( attributes[ 'form_action' ] === 'redirect_to_url' ) {
bookacti_redirect_to_activity_url( booking_system, event );
} else if( attributes[ 'form_action' ] === 'default' && $j( this ).closest( 'form' ).length ) {
$j( this ).closest( 'form' ).find( '[type="submit"]' ).trigger( 'click' );
} else if( attributes[ 'form_action' ] === 'default' ) {
if( ! booking_system.closest( 'form' ).length && booking_system.closest( '.bookacti-form-fields' ).length ) {
booking_system.closest( '.bookacti-form-fields' ).wrap( '<form id="bookacti-temporary-form"></form>' );
}
if( booking_system.closest( 'form' ).length ) {
bookacti_submit_booking_form( booking_system.closest( 'form' ) );
return;
}
}
}
}
@ -39,7 +55,7 @@ $j( document ).ready( function() {
/**
* Init actions to perfoms when the user picks a group of events
* @version 1.7.10
* @version 1.7.19
*/
$j( 'body' ).on( 'bookacti_group_of_events_chosen', '.bookacti-booking-system', function( e, group_id, event ) {
// Retrieve the info required to show the desired events
@ -56,8 +72,14 @@ $j( document ).ready( function() {
} else if( $j.isNumeric( group_id ) ) {
bookacti_redirect_to_group_category_url( booking_system, group_id );
}
} else if( attributes[ 'form_action' ] === 'default' && $j( this ).closest( 'form' ).length ) {
$j( this ).closest( 'form' ).find( '[type="submit"]' ).trigger( 'click' );
} else if( attributes[ 'form_action' ] === 'default' ) {
if( ! booking_system.closest( 'form' ).length && booking_system.closest( '.bookacti-form-fields' ).length ) {
booking_system.closest( '.bookacti-form-fields' ).wrap( '<form id="bookacti-temporary-form"></form>' );
}
if( booking_system.closest( 'form' ).length ) {
bookacti_submit_booking_form( booking_system.closest( 'form' ) );
return;
}
}
}
}
@ -66,6 +88,19 @@ $j( document ).ready( function() {
});
/**
* Remove temporary form after submit
* @since 1.7.19
* @param {object} response
* @param {object} form_data_object
*/
$j( 'body' ).on( 'bookacti_booking_form_submitted', 'form#bookacti-temporary-form', function( e, response, form_data_object ) {
if( $j( this ).find( '.bookacti-form-fields' ).length ) {
$j( this ).find( '.bookacti-form-fields' ).unwrap( 'form#bookacti-temporary-form' );
}
});
/**
* Do not init reschedule booking system automatically
* @since 1.7.0

2
js/booking-system.min.js

@ -1 +1 @@
$j(document).ready(function(){$j("body").on("bookacti_events_picked",".bookacti-booking-system",function(i,h,g){var b=$j(this);var a=b.attr("id");var c=bookacti.booking_system[a];bookacti_fill_booking_system_fields(b,g,h);bookacti_fill_picked_events_list(b);if(!$j(this).closest("#bookacti-form-editor-page-form").length){var d=bookacti_get_event_group_ids(b,g);var f=false;if($j.isArray(d)&&((d.length>1)||(d.length===1&&c.groups_single_events))){f=true}if(!f){if(h==="single"&&c.when_perform_form_action==="on_event_click"){if(c.form_action==="redirect_to_url"){bookacti_redirect_to_activity_url(b,g)}else{if(c.form_action==="default"&&$j(this).closest("form").length){$j(this).closest("form").find('[type="submit"]').trigger("click")}}}}}b.trigger("bookacti_events_picked_after",[h,g])});$j("body").on("bookacti_group_of_events_chosen",".bookacti-booking-system",function(g,f,d){var b=$j(this);var a=b.attr("id");var c=bookacti.booking_system[a];if(!$j(this).closest("#bookacti-form-editor-page-form").length){if(c.when_perform_form_action==="on_event_click"){if(c.form_action==="redirect_to_url"){if(f==="single"){bookacti_redirect_to_activity_url(b,d)}else{if($j.isNumeric(f)){bookacti_redirect_to_group_category_url(b,f)}}}else{if(c.form_action==="default"&&$j(this).closest("form").length){$j(this).closest("form").find('[type="submit"]').trigger("click")}}}}b.trigger("bookacti_group_of_events_chosen_after",[f,d])});$j("body").on("bookacti_init_booking_sytem",".bookacti-booking-system#bookacti-booking-system-reschedule",function(c,b,a){b.load=false});if($j(".bookacti-booking-system").length){bookacti_init_booking_system_dialogs();$j(".bookacti-booking-system").each(function(){var b=$j(this);var a=b.attr("id");var c=bookacti.booking_system[a];if(typeof bookacti.booking_system[a]["loading_number"]==="undefined"){bookacti.booking_system[a]["loading_number"]=0}if(typeof bookacti.booking_system[a]["picked_events"]==="undefined"){bookacti.booking_system[a]["picked_events"]=[]}var d={load:true,auto_load:c.auto_load?true:false};b.trigger("bookacti_init_booking_sytem",[d,c]);if(d.load){if(d.auto_load){bookacti_booking_method_set_up(b,false);b.find(".bookacti-loading-alt").remove()}else{bookacti_reload_booking_system(b,true)}}})}});
$j(document).ready(function(){$j("body").on("bookacti_events_picked",".bookacti-booking-system",function(c,b,a){if($j(this).siblings(".bookacti-notices").length){$j(this).siblings(".bookacti-notices").empty()}});$j("body").on("bookacti_events_picked",".bookacti-booking-system",function(i,h,g){var b=$j(this);var a=b.attr("id");var c=bookacti.booking_system[a];bookacti_fill_booking_system_fields(b,g,h);bookacti_fill_picked_events_list(b);if(!$j(this).closest("#bookacti-form-editor-page-form").length){var d=bookacti_get_event_group_ids(b,g);var f=false;if($j.isArray(d)&&((d.length>1)||(d.length===1&&c.groups_single_events))){f=true}if(!f){if(h==="single"&&c.when_perform_form_action==="on_event_click"){if(c.form_action==="redirect_to_url"){bookacti_redirect_to_activity_url(b,g)}else{if(c.form_action==="default"){if(!b.closest("form").length&&b.closest(".bookacti-form-fields").length){b.closest(".bookacti-form-fields").wrap('<form id="bookacti-temporary-form"></form>')}if(b.closest("form").length){bookacti_submit_booking_form(b.closest("form"));return}}}}}}b.trigger("bookacti_events_picked_after",[h,g])});$j("body").on("bookacti_group_of_events_chosen",".bookacti-booking-system",function(g,f,d){var b=$j(this);var a=b.attr("id");var c=bookacti.booking_system[a];if(!$j(this).closest("#bookacti-form-editor-page-form").length){if(c.when_perform_form_action==="on_event_click"){if(c.form_action==="redirect_to_url"){if(f==="single"){bookacti_redirect_to_activity_url(b,d)}else{if($j.isNumeric(f)){bookacti_redirect_to_group_category_url(b,f)}}}else{if(c.form_action==="default"){if(!b.closest("form").length&&b.closest(".bookacti-form-fields").length){b.closest(".bookacti-form-fields").wrap('<form id="bookacti-temporary-form"></form>')}if(b.closest("form").length){bookacti_submit_booking_form(b.closest("form"));return}}}}}b.trigger("bookacti_group_of_events_chosen_after",[f,d])});$j("body").on("bookacti_booking_form_submitted","form#bookacti-temporary-form",function(b,a,c){if($j(this).find(".bookacti-form-fields").length){$j(this).find(".bookacti-form-fields").unwrap("form#bookacti-temporary-form")}});$j("body").on("bookacti_init_booking_sytem",".bookacti-booking-system#bookacti-booking-system-reschedule",function(c,b,a){b.load=false});if($j(".bookacti-booking-system").length){bookacti_init_booking_system_dialogs();$j(".bookacti-booking-system").each(function(){var b=$j(this);var a=b.attr("id");var c=bookacti.booking_system[a];if(typeof bookacti.booking_system[a]["loading_number"]==="undefined"){bookacti.booking_system[a]["loading_number"]=0}if(typeof bookacti.booking_system[a]["picked_events"]==="undefined"){bookacti.booking_system[a]["picked_events"]=[]}var d={load:true,auto_load:c.auto_load?true:false};b.trigger("bookacti_init_booking_sytem",[d,c]);if(d.load){if(d.auto_load){bookacti_booking_method_set_up(b,false);b.find(".bookacti-loading-alt").remove()}else{bookacti_reload_booking_system(b,true)}}})}});

4
js/bookings-functions.js

@ -27,13 +27,13 @@ $j( document ).ready( function() {
/**
* Init booking filter action
* @version 1.6.0
* @version 1.7.19
*/
function bookacti_init_booking_filters_actions() {
// Display or hide activities filter according to selected templates
bookacti_update_template_related_filters();
$j( '#bookacti-booking-filter-templates, #bookacti-booking-filter-status, #bookacti-booking-filter-customer' ).on( 'change bookacti_customers_selectbox_changed', function() {
$j( '#bookacti-booking-filter-templates, #bookacti-booking-filter-status, #bookacti-booking-filter-customer' ).on( 'change', function() {
// Show / Hide activities filter
bookacti_update_template_related_filters();

2
js/bookings-functions.min.js

File diff suppressed because one or more lines are too long

43
js/form-editor.js

@ -44,18 +44,33 @@ $j( document ).ready( function() {
});
/**
* Show or hide activities depending on the selected template - On load
* @version 1.7.19
*/
if( $j( '#bookacti-calendars' ).length ) {
var template_ids = $j( '#bookacti-calendars' ).val();
var options = $j( '[data-bookacti-show-if-templates]' );
bookacti_show_hide_template_related_options( template_ids, options );
}
/**
* Add / remove activity row in the "redirect URL" table according to the currently selected activities
* @since 1.7.0
* @version 1.7.17
* @version 1.7.19
*/
$j( '#bookacti-form-field-dialog-calendar' ).on( 'change', 'select#bookacti-activities', function( e ){
var activities = $j( this ).val();
$j( '#bookacti-form-field-dialog-calendar' ).on( 'change', 'select#bookacti-calendars, select#bookacti-activities', function( e ){
var template_ids = $j( '#bookacti-calendars' ).val();
var options = $j( '[data-bookacti-show-if-templates]' );
bookacti_show_hide_template_related_options( template_ids, options );
var activities = $j( 'select#bookacti-activities' ).val();
// If all activities, take them all
if( activities === 'all' ) {
activities = [];
$j( this ).find( 'option:not(:disabled)' ).each( function() {
$j( 'select#bookacti-activities' ).find( 'option:not(:disabled)' ).each( function() {
var activity_id = $j( this ).attr( 'value' );
if( $j.isNumeric( activity_id ) ) {
activities.push( activity_id );
@ -83,18 +98,22 @@ $j( document ).ready( function() {
row.find( ':input' ).prop( 'disabled', false );
row.show();
return true; // continue
// If the row doesn't exists, create it
// If the row doesn't exist, create it
} else {
tbody.find( 'tr:first' ).clone().appendTo( tbody );
tbody.find( 'tr:last .select2' ).remove();
tbody.find( 'tr:last :input' ).each( function() {
var field_name_raw = $j( this ).attr( 'name' );
var field_name = field_name_raw.substring( 0, field_name_raw.lastIndexOf( '[' ) );
$j( this ).attr( 'name', field_name + '[' + activity_id + ']' );
$j( this ).removeClass( 'select2-hidden-accessible' );
});
tbody.find( 'tr:last td.bookacti-column-activity' ).<