Browse Source

** Booking Activities 1.5.0 **

* Feature - Customizable booking forms !
* Feature - You can now delete your bookings and your booking groups from the booking list
* Feature - You can display past events on frontend, they can be bookable or not
* Feature - Responsive default calendar view: display day view for small calendars instead of week view (set the threshold in settings)
* Tweak - Add a "Product" column in booking list (if the reservation was made with WooCommerce)
* Tweak - Add a dismissible admin notice to inform that WooCommerce "guest checkout" option isn't supported
* Tweak - Use core dashicons instead of additional images in backend
* Tweak - When to load the events? setting now also apply to product variation if a default variation is set
* Fix - Booking groups sometimes not appearing in booking list
* Fix - Show / Hide columns according to page options in booking list after a row is refreshed
* Fix - Booking list pagination didn't allow to jump to a specific page
* Fix - Couldn't drag and drop activities in calendar editor with touch devices
* Fix - PHP warning during AJAX request which needs to create an instance of the Booking List
* Fix - PHP warning when deleting a non-booking order item in the admin panel
* Fix - PHP warning sometimes occurs before sending a notification
* Fix - If the snap frequency was 00:00, it wasn't possible to drop an event on the calendar editor
* Fix - Woocommerce 2.6 backward compatibility various checkout issues
* **Breaking change** - Refund actions in Booking Activities settings must be set again
develop 1.5.0
Yoan Cutillas 4 years ago
parent
commit
592e7dc97d
  1. 179
      booking-activities.php
  2. 79
      class/class-bookings-list.php
  3. 551
      class/class-forms-list.php
  4. 36
      controller/controller-booking-system.php
  5. 99
      controller/controller-bookings.php
  6. 1145
      controller/controller-forms.php
  7. 6
      controller/controller-notifications.php
  8. 43
      controller/controller-settings.php
  9. 87
      controller/controller-shortcodes.php
  10. 4
      controller/controller-templates.php
  11. 569
      controller/controller-woocommerce-backend.php
  12. 302
      controller/controller-woocommerce-bookings.php
  13. 73
      controller/controller-woocommerce-forms.php
  14. 311
      controller/controller-woocommerce-frontend.php
  15. 12
      controller/controller-woocommerce-notifications.php
  16. 124
      controller/controller-woocommerce-settings.php
  17. 66
      css/backend.css
  18. 2
      css/backend.min.css
  19. 32
      css/bookings.css
  20. 2
      css/bookings.min.css
  21. 105
      css/forms.css
  22. 1
      css/forms.min.css
  23. 26
      css/global.css
  24. 2
      css/global.min.css
  25. 56
      css/templates.css
  26. 2
      css/templates.min.css
  27. 9
      css/woocommerce.css
  28. 3
      css/woocommerce.min.css
  29. 656
      functions/functions-booking-system.php
  30. 95
      functions/functions-bookings.php
  31. 1442
      functions/functions-forms.php
  32. 355
      functions/functions-global.php
  33. 45
      functions/functions-notifications.php
  34. 116
      functions/functions-settings.php
  35. 89
      functions/functions-template.php
  36. 21
      functions/functions-templates-forms-control.php
  37. 108
      functions/functions-woocommerce.php
  38. 55
      i18n-config.json
  39. BIN
      img/add.png
  40. BIN
      img/close.png
  41. BIN
      img/cross.png
  42. BIN
      img/gear.png
  43. BIN
      img/help.png
  44. BIN
      img/hide.png
  45. BIN
      img/show.png
  46. BIN
      img/tick.png
  47. BIN
      img/wc-integration.PNG
  48. 280
      js/backend-functions.js
  49. 2
      js/backend-functions.min.js
  50. 12
      js/booking-method-calendar.js
  51. 2
      js/booking-method-calendar.min.js
  52. 110
      js/booking-system-dialogs.js
  53. 2
      js/booking-system-dialogs.min.js
  54. 112
      js/booking-system-functions.js
  55. 2
      js/booking-system-functions.min.js
  56. 22
      js/booking-system.js
  57. 2
      js/booking-system.min.js
  58. 256
      js/bookings-dialogs.js
  59. 2
      js/bookings-dialogs.min.js
  60. 21
      js/bookings-functions.js
  61. 2
      js/bookings-functions.min.js
  62. 2
      js/bookings.js
  63. 419
      js/form-editor-dialogs.js
  64. 1
      js/form-editor-dialogs.min.js
  65. 237
      js/form-editor.js
  66. 1
      js/form-editor.min.js
  67. 422
      js/forms.js
  68. 1
      js/forms.min.js
  69. 35
      js/global-functions.js
  70. 2
      js/global-functions.min.js
  71. 4
      js/global-var.js
  72. 146
      js/shortcodes.js
  73. 1
      js/shortcodes.min.js
  74. 92
      js/templates-dialogs.js
  75. 2
      js/templates-dialogs.min.js
  76. 364
      js/templates-functions.js
  77. 2
      js/templates-functions.min.js
  78. 4
      js/templates.js
  79. 2
      js/templates.min.js
  80. 276
      js/woocommerce-backend.js
  81. 2
      js/woocommerce-backend.min.js
  82. 168
      js/woocommerce-frontend.js
  83. 2
      js/woocommerce-frontend.min.js
  84. 2860
      languages/booking-activities.pot
  85. 46
      languages/script-translation.php
  86. 77
      model/model-booking-system.php
  87. 148
      model/model-bookings.php
  88. 645
      model/model-forms.php
  89. 10
      model/model-global.php
  90. 110
      model/model-install.php
  91. 83
      model/model-templates.php
  92. 64
      model/model-woocommerce.php
  93. 67
      readme.txt
  94. 30
      view/view-backend-bookings-dialogs.php
  95. 15
      view/view-booking-system-dialogs.php
  96. 37
      view/view-bookings-dialogs.php
  97. 13
      view/view-bookings.php
  98. 739
      view/view-form-editor-dialogs.php
  99. 206
      view/view-form-editor.php
  100. 52
      view/view-form-list.php
  101. Some files were not shown because too many files have changed in this diff Show More

179
booking-activities.php

@ -2,8 +2,8 @@
/**
* 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, and yours!). Works great with WooCommerce.
* Version: 1.4.4
* Description: Booking system specialized in activities (sports, cultural, leisure, events...). Works great with WooCommerce.
* Version: 1.5.0
* Author: Booking Activities Team
* Author URI: https://booking-activities.fr/en/?utm_source=plugin&utm_medium=plugin&utm_content=header
* Text Domain: booking-activities
@ -38,14 +38,12 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
// GLOBALS AND CONSTANTS
if( ! defined( 'BOOKACTI_VERSION' ) ) { define( 'BOOKACTI_VERSION', '1.4.4' ); }
if( ! defined( 'BOOKACTI_VERSION' ) ) { define( 'BOOKACTI_VERSION', '1.5.0' ); }
if( ! defined( 'BOOKACTI_PLUGIN_NAME' ) ) { define( 'BOOKACTI_PLUGIN_NAME', 'booking-activities' ); }
if( ! defined( 'BOOKACTI_PLUGIN_BASENAME' ) ) { define( 'BOOKACTI_PLUGIN_BASENAME', plugin_basename( __FILE__ ) ); }
// HEADER STRINGS (For translation)
__( 'Booking Activities', BOOKACTI_PLUGIN_NAME );
__( 'Booking system specialized in activities (sports, cultural, leisure, events, and yours!). Works great with WooCommerce.', BOOKACTI_PLUGIN_NAME );
__( 'Booking system specialized in activities (sports, cultural, leisure, events...). Works great with WooCommerce.', BOOKACTI_PLUGIN_NAME );
// INCLUDE LANGUAGES FILES
@ -62,12 +60,14 @@ add_action( 'plugins_loaded', 'bookacti_load_textdomain' );
// INCLUDE PHP FUNCTIONS
include_once( 'functions/functions-global.php' );
include_once( 'functions/functions-booking-system.php' );
include_once( 'functions/functions-template.php' );
include_once( 'functions/functions-templates-forms-control.php' );
include_once( 'functions/functions-bookings.php' );
include_once( 'functions/functions-forms.php' );
include_once( 'functions/functions-settings.php' );
include_once( 'functions/functions-notifications.php' );
@ -76,8 +76,26 @@ include_once( 'controller/controller-booking-system.php' );
include_once( 'controller/controller-settings.php' );
include_once( 'controller/controller-notifications.php' );
include_once( 'controller/controller-bookings.php' );
include_once( 'controller/controller-forms.php' );
include_once( 'controller/controller-shortcodes.php' );
// INCLUDE DATABASE FUNCTIONS
require_once( 'model/model-global.php' );
require_once( 'model/model-install.php' );
require_once( 'model/model-templates.php' );
require_once( 'model/model-booking-system.php' );
require_once( 'model/model-bookings.php' );
require_once( 'model/model-forms.php' );
// INCLUDE CLASSES
if( is_admin() ) {
require_once( 'class/class-bookings-list.php' );
require_once( 'class/class-forms-list.php' );
}
// If woocommerce is active, include functions
if( bookacti_is_plugin_active( 'woocommerce/woocommerce.php' ) ) {
include_once( 'controller/controller-woocommerce-bookings.php' );
@ -85,28 +103,20 @@ if( bookacti_is_plugin_active( 'woocommerce/woocommerce.php' ) ) {
include_once( 'controller/controller-woocommerce-frontend.php' );
include_once( 'controller/controller-woocommerce-settings.php' );
include_once( 'controller/controller-woocommerce-notifications.php' );
include_once( 'controller/controller-woocommerce-forms.php' );
include_once( 'functions/functions-woocommerce.php' );
require_once( 'model/model-woocommerce.php' );
}
// INCLUDE DATABASE FUNCTIONS
require_once( 'model/model-global.php' );
require_once( 'model/model-install.php' );
require_once( 'model/model-templates.php' );
require_once( 'model/model-booking-system.php' );
require_once( 'model/model-bookings.php' );
require_once( 'model/model-woocommerce.php' );
// INCLUDE CLASSES
require_once( 'class/class-bookings-list.php' );
// INCLUDE SCRIPTS
// High priority scripts
add_action( 'admin_enqueue_scripts','bookacti_enqueue_high_priority_global_scripts', 10 );
add_action( 'wp_enqueue_scripts', 'bookacti_enqueue_high_priority_global_scripts', 10 );
/**
* Enqueue high priority scripts
* @global array $bookacti_translation_array
*/
function bookacti_enqueue_high_priority_global_scripts() {
// INCLUDE LIBRARIES
wp_enqueue_script( 'bookacti-js-moment', plugins_url( 'lib/fullcalendar/moment.min.js', __FILE__ ), array( 'jquery' ), BOOKACTI_VERSION, true );
@ -132,16 +142,21 @@ function bookacti_enqueue_high_priority_global_scripts() {
wp_enqueue_script ( 'bookacti-js-global-functions' );
wp_enqueue_script ( 'bookacti-js-booking-system-functions' );
}
add_action( 'admin_enqueue_scripts','bookacti_enqueue_high_priority_global_scripts', 10 );
add_action( 'wp_enqueue_scripts', 'bookacti_enqueue_high_priority_global_scripts', 10 );
// Normal priority scripts
add_action( 'admin_enqueue_scripts','bookacti_enqueue_global_scripts', 20 );
add_action( 'wp_enqueue_scripts', 'bookacti_enqueue_global_scripts', 20 );
/**
* Enqueue normal priority scripts
* @version 1.5.0
* @global array $bookacti_translation_array
*/
function bookacti_enqueue_global_scripts() {
// INCLUDE STYLESHEETS
wp_enqueue_style ( 'bookacti-css-global', plugins_url( 'css/global.min.css', __FILE__ ), array(), BOOKACTI_VERSION );
wp_enqueue_style ( 'bookacti-css-bookings', plugins_url( 'css/bookings.min.css', __FILE__ ), array(), BOOKACTI_VERSION );
wp_enqueue_style ( 'bookacti-css-forms', plugins_url( 'css/forms.min.css', __FILE__ ), array(), BOOKACTI_VERSION );
wp_enqueue_style ( 'bookacti-css-woocommerce', plugins_url( 'css/woocommerce.min.css', __FILE__ ), array(), BOOKACTI_VERSION );
wp_enqueue_style ( 'jquery-ui-bookacti-theme', plugins_url( 'lib/jquery-ui/themes/booking-activities/jquery-ui.min.css', __FILE__ ), array(), BOOKACTI_VERSION );
@ -151,6 +166,7 @@ function bookacti_enqueue_global_scripts() {
wp_register_script( 'bookacti-js-booking-method-calendar', plugins_url( 'js/booking-method-calendar.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-fullcalendar', 'bookacti-js-global-functions' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-bookings-functions', plugins_url( 'js/bookings-functions.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-fullcalendar', 'bookacti-js-global-functions', ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-bookings-dialogs', plugins_url( 'js/bookings-dialogs.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-global-functions', 'bookacti-js-moment', 'jquery-ui-dialog' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-forms', plugins_url( 'js/forms.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-functions', 'jquery-ui-dialog', 'password-strength-meter' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-woocommerce-global', plugins_url( 'js/woocommerce-global.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-global-functions', 'bookacti-js-moment', 'jquery-ui-dialog' ), BOOKACTI_VERSION, true );
// LOCALIZE SCRIPTS
@ -160,19 +176,26 @@ function bookacti_enqueue_global_scripts() {
wp_localize_script( 'bookacti-js-booking-method-calendar', 'bookacti_localized', $bookacti_translation_array );
wp_localize_script( 'bookacti-js-bookings-functions', 'bookacti_localized', $bookacti_translation_array );
wp_localize_script( 'bookacti-js-bookings-dialogs', 'bookacti_localized', $bookacti_translation_array );
wp_localize_script( 'bookacti-js-forms', 'bookacti_localized', $bookacti_translation_array );
wp_localize_script( 'bookacti-js-woocommerce-global', 'bookacti_localized', $bookacti_translation_array );
// ENQUEUE SCRIPTS
wp_enqueue_script ( 'bookacti-js-booking-system' );
wp_enqueue_script ( 'bookacti-js-booking-system-dialogs' );
wp_enqueue_script ( 'bookacti-js-booking-method-calendar' );
wp_enqueue_script ( 'bookacti-js-bookings-functions' );
wp_enqueue_script ( 'bookacti-js-bookings-dialogs' );
wp_enqueue_script ( 'bookacti-js-woocommerce-global' );
wp_enqueue_script( 'bookacti-js-booking-system' );
wp_enqueue_script( 'bookacti-js-booking-system-dialogs' );
wp_enqueue_script( 'bookacti-js-booking-method-calendar' );
wp_enqueue_script( 'bookacti-js-bookings-functions' );
wp_enqueue_script( 'bookacti-js-bookings-dialogs' );
wp_enqueue_script( 'bookacti-js-forms' );
wp_enqueue_script( 'bookacti-js-woocommerce-global' );
}
add_action( 'admin_enqueue_scripts','bookacti_enqueue_global_scripts', 20 );
add_action( 'wp_enqueue_scripts', 'bookacti_enqueue_global_scripts', 20 );
add_action( 'admin_enqueue_scripts','bookacti_enqueue_high_priority_backend_scripts', 15 );
/**
* Enqueue high priority scripts in backend only
* @global array $bookacti_translation_array
*/
function bookacti_enqueue_high_priority_backend_scripts() {
// INCLUDE JAVASCRIPT FILES
wp_register_script( 'bookacti-js-backend-functions', plugins_url( 'js/backend-functions.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'jquery-ui-dialog', 'jquery-ui-tabs', 'jquery-ui-tooltip' ), BOOKACTI_VERSION, true );
@ -180,15 +203,20 @@ function bookacti_enqueue_high_priority_backend_scripts() {
// LOCALIZE SCRIPTS
global $bookacti_translation_array;
wp_localize_script( 'bookacti-js-bookings', 'bookacti_localized', $bookacti_translation_array );
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' );
}
add_action( 'admin_enqueue_scripts','bookacti_enqueue_high_priority_backend_scripts', 15 );
add_action( 'admin_enqueue_scripts', 'bookacti_enqueue_backend_scripts', 30 );
/**
* Enqueue low priority scripts in backend only
* @version 1.5.0
* @global array $bookacti_translation_array
*/
function bookacti_enqueue_backend_scripts() {
// INCLUDE STYLESHEETS
@ -198,11 +226,13 @@ function bookacti_enqueue_backend_scripts() {
// INCLUDE JAVASCRIPT FILES
wp_register_script( 'bookacti-js-templates-forms-control', plugins_url( 'js/templates-forms-control.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-moment' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-templates-functions', plugins_url( 'js/templates-functions.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-fullcalendar', 'jquery-effects-highlight' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-templates-functions', plugins_url( 'js/templates-functions.min.js', __FILE__ ), array( 'jquery', 'jquery-touch-punch', 'bookacti-js-global-var', 'bookacti-js-fullcalendar', 'jquery-effects-highlight' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-templates-dialogs', plugins_url( 'js/templates-dialogs.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-global-functions', 'bookacti-js-backend-functions', 'bookacti-js-templates-forms-control', 'bookacti-js-moment', 'jquery-ui-dialog', 'jquery-ui-selectmenu' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-templates', plugins_url( 'js/templates.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-fullcalendar', 'bookacti-js-global-functions', 'bookacti-js-templates-functions', 'bookacti-js-templates-dialogs' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-woocommerce-backend', plugins_url( 'js/woocommerce-backend.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-moment' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-settings', plugins_url( 'js/settings.min.js', __FILE__ ), array( 'jquery' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-form-editor-dialogs', plugins_url( 'js/form-editor-dialogs.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-moment', 'jquery-ui-dialog', 'bookacti-js-backend-functions' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-form-editor', plugins_url( 'js/form-editor.min.js', __FILE__ ), array( 'jquery', 'jquery-touch-punch', 'bookacti-js-global-var', 'bookacti-js-booking-system-functions', 'jquery-ui-sortable', 'bookacti-js-forms', 'bookacti-js-form-editor-dialogs' ), BOOKACTI_VERSION, true );
// LOCALIZE SCRIPTS
global $bookacti_translation_array;
@ -210,7 +240,10 @@ function bookacti_enqueue_backend_scripts() {
wp_localize_script( 'bookacti-js-templates-functions', 'bookacti_localized', $bookacti_translation_array );
wp_localize_script( 'bookacti-js-templates-dialogs', 'bookacti_localized', $bookacti_translation_array );
wp_localize_script( 'bookacti-js-templates', 'bookacti_localized', $bookacti_translation_array );
wp_localize_script( 'bookacti-js-woocommerce-backend', 'bookacti_localized', $bookacti_translation_array );
wp_localize_script( 'bookacti-js-settings', 'bookacti_localized', $bookacti_translation_array );
wp_localize_script( 'bookacti-js-form-editor-dialogs', 'bookacti_localized', $bookacti_translation_array );
wp_localize_script( 'bookacti-js-form-editor', 'bookacti_localized', $bookacti_translation_array );
// ENQUEUE SCRIPTS
wp_enqueue_script ( 'bookacti-js-templates-forms-control' );
@ -219,31 +252,41 @@ function bookacti_enqueue_backend_scripts() {
wp_enqueue_script ( 'bookacti-js-templates' );
wp_enqueue_script ( 'bookacti-js-woocommerce-backend' );
wp_enqueue_script ( 'bookacti-js-settings' );
wp_enqueue_script ( 'bookacti-js-form-editor-dialogs' );
wp_enqueue_script ( 'bookacti-js-form-editor' );
}
add_action( 'admin_enqueue_scripts', 'bookacti_enqueue_backend_scripts', 30 );
add_action( 'wp_enqueue_scripts', 'bookacti_enqueue_frontend_scripts', 30 );
/**
* Enqueue low priority scripts in frontend only
* @since 1.5.0
* @global array $bookacti_translation_array
*/
function bookacti_enqueue_frontend_scripts() {
// INCLUDE STYLESHEETS
wp_enqueue_style ( 'bookacti-css-frontend', plugins_url( 'css/frontend.min.css', __FILE__ ), array(), BOOKACTI_VERSION );
// INCLUDE JAVASCRIPT FILES
wp_register_script( 'bookacti-js-shortcodes', plugins_url( 'js/shortcodes.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-moment' ), BOOKACTI_VERSION, true );
wp_register_script( 'bookacti-js-woocommerce-frontend', plugins_url( 'js/woocommerce-frontend.min.js', __FILE__ ), array( 'jquery', 'bookacti-js-global-var', 'bookacti-js-fullcalendar', 'bookacti-js-global-functions', 'bookacti-js-booking-method-calendar' ), BOOKACTI_VERSION, true );
// LOCALIZE SCRIPTS
global $bookacti_translation_array;
wp_localize_script( 'bookacti-js-shortcodes', 'bookacti_localized', $bookacti_translation_array );
wp_localize_script( 'bookacti-js-woocommerce-frontend', 'bookacti_localized', $bookacti_translation_array );
// ENQUEUE SCRIPTS
wp_enqueue_script ( 'bookacti-js-shortcodes' );
wp_enqueue_script ( 'bookacti-js-woocommerce-frontend' );
}
add_action( 'wp_enqueue_scripts', 'bookacti_enqueue_frontend_scripts', 30 );
// ACTIVATE
register_activation_hook( __FILE__, 'bookacti_activate' );
// ACTIVATE / DEACTIVATE / UPDATE / UNINSTALL
/**
* Activate Booking Activities
*/
function bookacti_activate() {
// Allow users to manage Bookings
@ -270,18 +313,22 @@ function bookacti_activate() {
// Flush rules after install
flush_rewrite_rules();
}
register_activation_hook( __FILE__, 'bookacti_activate' );
// DEACTIVATION
register_deactivation_hook( __FILE__, 'bookacti_deactivate' );
/**
* Deactivate Booking Activities
*/
function bookacti_deactivate() {
do_action( 'bookacti_deactivate' );
}
register_deactivation_hook( __FILE__, 'bookacti_deactivate' );
// UNINSTALL
register_uninstall_hook( __FILE__, 'bookacti_uninstall' );
/**
* Uninstall Booking Activities
*/
function bookacti_uninstall() {
//Deregister the hourly reccuring event
wp_clear_scheduled_hook( 'bookacti_hourly_event' );
@ -304,6 +351,7 @@ function bookacti_uninstall() {
// Clear any cached data that has been removed
wp_cache_flush();
}
register_uninstall_hook( __FILE__, 'bookacti_uninstall' );
/**
@ -320,9 +368,13 @@ function bookacti_check_version( $from_activate = false ) {
add_action( 'init', 'bookacti_check_version', 5 );
// ADMIN MENU
/**
* Create the Admin Menu
* @version 1.5.0
*/
function bookacti_create_menu() {
// Add a menu and submenus
@ -330,28 +382,61 @@ function bookacti_create_menu() {
add_menu_page( __( 'Booking Activities', BOOKACTI_PLUGIN_NAME ), _x( 'Booking Activities', 'Name of the tab in the menu', BOOKACTI_PLUGIN_NAME ), 'bookacti_manage_booking_activities', 'booking-activities', null, $icon_url, '56.5' );
add_submenu_page( 'booking-activities', _x( 'Booking Activities', 'Landing page title', BOOKACTI_PLUGIN_NAME ), _x( 'Home', 'Landing page tab name', BOOKACTI_PLUGIN_NAME ),'bookacti_manage_booking_activities', 'booking-activities', 'bookacti_landing_page' );
add_submenu_page( 'booking-activities', __( 'Calendar editor', BOOKACTI_PLUGIN_NAME ), __( 'Calendar editor', BOOKACTI_PLUGIN_NAME ), 'bookacti_manage_templates', 'bookacti_calendars', 'bookacti_templates_page' );
add_submenu_page( 'booking-activities', __( 'Booking forms', BOOKACTI_PLUGIN_NAME ), __( 'Booking forms', BOOKACTI_PLUGIN_NAME ), 'bookacti_manage_forms', 'bookacti_forms', 'bookacti_forms_page' );
add_submenu_page( 'booking-activities', __( 'Bookings', BOOKACTI_PLUGIN_NAME ), __( 'Bookings', BOOKACTI_PLUGIN_NAME ), 'bookacti_manage_bookings', 'bookacti_bookings', 'bookacti_bookings_page' );
add_submenu_page( 'booking-activities', __( 'Settings', BOOKACTI_PLUGIN_NAME ), __( 'Settings', BOOKACTI_PLUGIN_NAME ), 'bookacti_manage_booking_activities_settings', 'bookacti_settings', 'bookacti_settings_page' );
}
add_action( 'admin_menu', 'bookacti_create_menu' );
// Landing Page
/**
* Include content of Booking Activities landing page
*/
function bookacti_landing_page() {
include_once( 'view/view-landing.php' );
}
// Page content of Booking top-level menu
/**
* Include content of Calendar editor top-level menu page
*/
function bookacti_templates_page() {
include_once( 'view/view-templates.php' );
}
// Page content of the first Booking submenu
/**
* Include content of Forms top-level menu page
* @since 1.5.0
*/
function bookacti_forms_page() {
$can_create_form = current_user_can( 'bookacti_create_forms' );
$can_edit_form = current_user_can( 'bookacti_edit_forms' );
$load_form_editor = false;
if( ! empty( $_GET[ 'action' ] ) ) {
if( ( $_GET[ 'action' ] === 'new' && $can_create_form )
|| ( $_GET[ 'action' ] === 'edit' && ! empty( $_GET[ 'form_id' ] ) && is_numeric( $_GET[ 'form_id' ] ) && $can_edit_form ) ) {
$load_form_editor = true;
}
}
if( $load_form_editor ) {
include_once( 'view/view-form-editor.php' );
} else {
include_once( 'view/view-form-list.php' );
}
}
/**
* Include content of Bookings top-level menu page
*/
function bookacti_bookings_page() {
include_once( 'view/view-bookings.php' );
}
// Page content of the settings submenu
/**
* Include content of Settings top-level menu page
*/
function bookacti_settings_page() {
include_once( 'view/view-settings.php' );
}

79
class/class-bookings-list.php

@ -22,9 +22,13 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
/**
* Set up the Booking list table
*
* @version 1.3.0
* @version 1.5.0
* @access public
*/
public function __construct(){
// This global variable is required to create screen
if( ! isset( $GLOBALS[ 'hook_suffix' ] ) ) { $GLOBALS[ 'hook_suffix' ] = null; }
parent::__construct( array(
/*translator: */
'singular' => 'booking', // Singular name of the listed records
@ -41,7 +45,8 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
/**
* Get booking list table columns
*
* @version 1.3.0
* @version 1.5.0
* @access public
* @return array
*/
public function get_columns(){
@ -51,6 +56,8 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
'cb' => '<input type="checkbox" />',
'id' => _x( 'id', 'An id is a unique identification number', BOOKACTI_PLUGIN_NAME ),
'customer' => __( 'Customer', BOOKACTI_PLUGIN_NAME ),
'email' => __( 'Email', BOOKACTI_PLUGIN_NAME ),
'phone' => __( 'Phone', BOOKACTI_PLUGIN_NAME ),
'state' => _x( 'Status', 'Booking status', BOOKACTI_PLUGIN_NAME ),
'payment_status'=> _x( 'Paid', 'Payment status column name', BOOKACTI_PLUGIN_NAME ),
'quantity' => _x( 'Qty', 'Short for "Quantity"', BOOKACTI_PLUGIN_NAME ),
@ -65,8 +72,9 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
/**
* Columns of the booking list
* You must use 'bookacti_booking_list_columns_order' php filter order your custom columns.
* You must use 'bookacti_fill_booking_list_entry' jquery hook to fill your custom columns.
* You must use 'bookacti_booking_list_columns_order' php filter to order your custom columns.
* You must use 'bookacti_booking_list_default_hidden_columns' php filter to hide your custom columns by default.
* You must use 'bookacti_booking_list_booking_columns' php filter to fill your custom columns.
*
* @param array $columns
*/
@ -80,6 +88,8 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
30 => 'state',
40 => 'payment_status',
50 => 'customer',
54 => 'email',
57 => 'phone',
60 => 'event_title',
70 => 'start_date',
80 => 'end_date',
@ -114,6 +124,7 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
* Get default hidden columns
*
* @since 1.3.0
* @access public
* @param array $hidden
* @param WP_Screen $screen
* @return array
@ -121,6 +132,8 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
public function get_default_hidden_columns( $hidden, $screen ) {
if( $screen->id == $this->screen->id ) {
$hidden = apply_filters( 'bookacti_booking_list_default_hidden_columns', array(
'email',
'phone',
'end_date',
'template_title',
'activity_title'
@ -134,6 +147,7 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
* Get sortable columns
*
* @since 1.3.0
* @access public
* @return array
*/
protected function get_sortable_columns() {
@ -157,6 +171,7 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
* Get the screen property
*
* @since 1.3.0
* @access public
* @return WP_Screen
*/
private function get_wp_screen() {
@ -171,6 +186,7 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
* Prepare the items to be displayed in the list
*
* @version 1.3.0
* @access public
* @param array $filters
* @param boolean $no_pagination
*/
@ -210,6 +226,7 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
* Fill columns
*
* @version 1.3.0
* @access public
* @param array $item
* @param string $column_name
* @return string
@ -222,18 +239,16 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
/**
* Get booking list items. Parameters can be passed in the URL.
*
* @version 1.4.0
* @param int $event_group_id
* @param int $event_id
* @param string $event_start
* @param string $event_end
* @param int $booking_group_id
* @version 1.5.0
* @access public
* @return array
*/
public function get_booking_list_items() {
// Request bookings corresponding to filters
if( $this->filters[ 'event_id' ] && ! $this->filters[ 'event_group_id' ] ) { $this->filters[ 'booking_group_id' ] = 'none'; }
if( ! $this->filters[ 'booking_group_id' ] ) { $this->filters[ 'group_by' ] = 'booking_group'; }
$bookings = bookacti_get_bookings( $this->filters );
// Retrieve booking groups data
@ -245,8 +260,18 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
foreach( $bookings as $booking ) {
if( ! in_array( $booking->user_id, $user_ids, true ) ){
$user_ids[] = $booking->user_id;
continue;
}
// If the booking group has a different user than the bookings of the group
if( ! $booking->group_id ) { continue; }
if( ! empty( $booking_groups[ $booking->group_id ] ) ) {
$booking_group = $booking_groups[ $booking->group_id ];
if( $booking_group->user_id !== $booking->user_id && ! in_array( $booking_group->user_id, $user_ids, true ) ) {
$user_ids[] = $booking_group->user_id;
}
}
}
$users = bookacti_get_users_data( array( 'include' => $user_ids ) );
// Get datetime format once for all (reduce SQL queries)
@ -286,7 +311,7 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
} else {
$raw_id = $booking->id;
$tr_class = $booking->group_id ? 'bookacti-single-booking bookacti-gouped-booking' : 'bookacti-single-booking';
$tr_class = $booking->group_id ? 'bookacti-single-booking bookacti-gouped-booking bookacti-booking-group-id-' . $booking->group_id : 'bookacti-single-booking';
$id = $booking->group_id ? $booking->id . '<span class="bookacti-booking-group-id" >' . $booking->group_id . '</span>' : $booking->id;
$user_id = $booking->user_id;
$state = bookacti_format_booking_state( $booking->state, true );
@ -302,26 +327,29 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
}
// Format customer column
if( is_numeric( $user_id ) ) {
if( $user_id && is_numeric( $user_id ) && ! empty( $users[ $user_id ] ) ) {
$user = $users[ $user_id ];
$customer = '<a '
. ' href="' . esc_url( get_admin_url() . 'user-edit.php?user_id=' . $user_id ) . '" '
. ' target="_blank" '
. ' >'
. esc_html( $user->user_login . ' (' . $user->user_email . ')' )
. $user->display_name
. ' </a>';
$email = ! empty( $user->user_email ) ? $user->user_email : '';
$phone = ! empty( $user->phone ) ? $user->phone : '';
} else {
$user = new stdClass();
$customer = esc_html( __( 'Unknown user', BOOKACTI_PLUGIN_NAME ) . ' (' . $user_id . ')' );
$email = '';
$phone = '';
}
$primary_data = array();
$booking_item = apply_filters( 'bookacti_booking_list_booking_columns', array(
'tr_class' => $tr_class,
'id' => $id,
'customer' => $customer,
'email' => $email,
'phone' => $phone,
'state' => $state,
'payment_status'=> $paid,
'quantity' => $quantity,
@ -363,6 +391,7 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
/**
* Format filters passed as argument or retrieved via POST or GET
* @access public
* @param array $filters
* @return array
*/
@ -415,6 +444,7 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
*
* @since 1.3.0
* @version 1.4.0
* @access public
* @return int
*/
public function get_total_items_count() {
@ -542,10 +572,27 @@ if( ! class_exists( 'Bookings_List_Table' ) ) {
* Get default primary column name
*
* @since 1.3.0
* @access public
* @return string
*/
public function get_default_primary_column_name() {
return apply_filters( 'bookacti_booking_list_primary_column', 'customer', $this->screen );
}
/**
* Display pagination inside a form to allow to jump to a page
* @since 1.5.0
* @param string $which
*/
protected function pagination( $which ) {
if( $which !== 'top' ) { parent::pagination( $which ); return; }
?>
<form action='<?php echo admin_url( 'admin.php' ); ?>' >
<input type='hidden' name='page' value='bookacti_bookings' />
<?php parent::pagination( $which ); ?>
</form>
<?php
}
}
}

551
class/class-forms-list.php

@ -0,0 +1,551 @@
<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) { exit; }
if( ! class_exists( 'WP_List_Table' ) ) {
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
if( ! class_exists( 'Forms_List_Table' ) ) {
/**
* Forms WP_List_Table
* @since 1.5.0
*/
class Forms_List_Table extends WP_List_Table {
public $items;
public $filters;
protected $screen;
/**
* Set up the Form list table
* @access public
*/
public function __construct(){
// This global variable is required to create screen
if( ! isset( $GLOBALS[ 'hook_suffix' ] ) ) { $GLOBALS[ 'hook_suffix' ] = null; }
parent::__construct( array(
/*translator: */
'singular' => 'form', // Singular name of the listed records
'plural' => 'forms', // Plural name of the listed records
'ajax' => false,
'screen' => null
));
// Hide default columns
add_filter( 'default_hidden_columns', array( $this, 'get_default_hidden_columns' ), 10, 2 );
}
/**
* Get form list table columns
* @access public
* @return array
*/
public function get_columns(){
// Set the columns
$columns = array(
'cb' => '<input type="checkbox" />',
'id' => _x( 'id', 'An id is a unique identification number', BOOKACTI_PLUGIN_NAME ),
'title' => __( 'Title', BOOKACTI_PLUGIN_NAME ),
'author' => __( 'Author', BOOKACTI_PLUGIN_NAME ),
'date' => __( 'Date', BOOKACTI_PLUGIN_NAME ),
'status' => _x( 'Status', 'Form status', BOOKACTI_PLUGIN_NAME ),
'shortcode' => __( 'Shortcode', BOOKACTI_PLUGIN_NAME ),
'active' => __( 'Active', BOOKACTI_PLUGIN_NAME )
);
/**
* Columns of the form list
* You must use 'bookacti_form_list_columns_order' php filter to order your custom columns.
* You must use 'bookacti_form_list_default_hidden_columns' php filter to hide your custom columns by default.
* You must use 'bookacti_form_list_form_columns' php filter to fill your custom columns.
*
* @param array $columns
*/
$columns = apply_filters( 'bookacti_form_list_columns', $columns );
// Sort the columns
$columns_order = array(
10 => 'cb',
20 => 'id',
30 => 'title',
40 => 'shortcode',
50 => 'author',
60 => 'date',
70 => 'status',
80 => 'active'
);
/**
* Columns order of the form list
* Order the columns given by the filter 'bookacti_form_list_columns'
*
* @param array $columns
*/
$columns_order = apply_filters( 'bookacti_form_list_columns_order', $columns_order );
ksort( $columns_order );
$displayed_columns = array();
foreach( $columns_order as $column_id ) {
$displayed_columns[ $column_id ] = $columns[ $column_id ];
}
// Return the columns
return $displayed_columns;
}
/**
* Get default hidden columns
* @access public
* @param array $hidden
* @param WP_Screen $screen
* @return array
*/
public function get_default_hidden_columns( $hidden, $screen ) {
if( $screen->id == $this->screen->id ) {
$hidden = apply_filters( 'bookacti_form_list_default_hidden_columns', array(
'status',
'active'
) );
}
return $hidden;
}
/**
* Get sortable columns
* @access public
* @return array
*/
protected function get_sortable_columns() {
return array(
'id' => array( 'id', true ),
'title' => array( 'title', false ),
'author'=> array( 'user_id', false ),
'date' => array( 'creation_date', false ),
'status'=> array( 'status', false )
);
}
/**
* Get the screen property
* @access public
* @return WP_Screen
*/
private function get_wp_screen() {
if( empty( $this->screen ) ) {
$this->screen = get_current_screen();
}
return $this->screen;
}
/**
* Prepare the items to be displayed in the list
* @access public
* @param array $filters
* @param boolean $no_pagination
*/
public function prepare_items( $filters = array(), $no_pagination = false ) {
$this->get_column_info();
$this->_column_headers[0] = $this->get_columns();
$this->filters = $this->format_filters( $filters );
if( ! $no_pagination ) {
// Get the number of forms to display per page
$screen = $this->get_wp_screen();
$screen_option = $screen->get_option( 'per_page', 'option' );
$per_page = intval( get_user_meta( get_current_user_id(), $screen_option, true ) );
if( empty ( $per_page ) || $per_page < 1 ) {
$per_page = $screen->get_option( 'per_page', 'default' );
}
// Set pagination
$this->set_pagination_args( array(
'total_items' => $this->get_total_items_count(),
'per_page' => $per_page
) );
$this->filters[ 'offset' ] = ( $this->get_pagenum() - 1 ) * $per_page;
$this->filters[ 'per_page' ] = $per_page;
}
$items = $this->get_form_list_items();
$this->items = $items;
}
/**
* Fill columns
* @access public
* @param array $item
* @param string $column_name
* @return string
*/
public function column_default( $item, $column_name ) {
return isset( $item[ $column_name ] ) ? $item[ $column_name ] : '';
}
/**
* Fill "Title" column and add action buttons
* @access public
* @param array $item
* @return string
*/
public function column_title( $item ) {
$form_id = $item[ 'id' ];
$actions = array();
if( current_user_can( 'bookacti_edit_forms' ) ) {
// Add the 'edit' action
if( $item[ 'active_raw' ] ) {
$actions[ 'edit' ] = '<a href="' . esc_url( get_admin_url() . 'admin.php?page=bookacti_forms&action=edit&form_id=' . $form_id ) . '" >'
. esc_html_x( 'Edit', 'forms', BOOKACTI_PLUGIN_NAME )
. '</a>';
}
if( current_user_can( 'bookacti_delete_forms' ) ) {
if( $item[ 'active_raw' ] ) {
// Add the 'trash' action
$actions[ 'trash' ] = '<a href="' . esc_url( wp_nonce_url( get_admin_url() . 'admin.php?page=bookacti_forms', 'trash-form_' . $form_id ) . '&action=trash&form_id=' . $form_id ) . '" >'
. esc_html_x( 'Trash', 'forms', BOOKACTI_PLUGIN_NAME )
. '</a>';
} else {
// Add the 'restore' action
$actions[ 'restore' ] = '<a href="' . esc_url( wp_nonce_url( get_admin_url() . 'admin.php?page=bookacti_forms', 'restore-form_' . $form_id ) . '&action=restore&form_id=' . $form_id ) . '" >'
. esc_html_x( 'Restore', 'forms', BOOKACTI_PLUGIN_NAME )
. '</a>';
// Add the 'delete' action
$actions[ 'delete' ] = '<a href="' . esc_url( wp_nonce_url( get_admin_url() . 'admin.php?page=bookacti_forms', 'delete-form_' . $form_id ) . '&status=trash&action=delete&form_id=' . $form_id ) . '" >'
. esc_html_x( 'Delete Permanently', 'forms', BOOKACTI_PLUGIN_NAME )
. '</a>';
}
}
}
$actions = apply_filters( 'bookacti_form_list_row_actions', $actions, $item );
// Add a span and a class to each action
foreach( $actions as $action_id => $link ) {
$actions[ $action_id ] = '<span class="' . $action_id . '">' . $link . '</span>';
}
return sprintf( '%1$s %2$s', $item[ 'title' ], $this->row_actions( $actions, false ) );
}
/**
* Get form list items. Parameters can be passed in the URL.
*
* @access public
* @return array
*/
public function get_form_list_items() {
// Request forms corresponding to filters
$forms = bookacti_get_forms( $this->filters );
$can_edit_forms = current_user_can( 'bookacti_edit_forms' );
// Build form list
$form_list_items = array();
foreach( $forms as $form ) {
// If the user is not allowed to manage this form, do not display it at all
if( ! bookacti_user_can_manage_form( $form->id ) ) { continue; }
$id = $form->id;
$title = ! empty( $form->title ) ? $form->title : __( 'Untitled', BOOKACTI_PLUGIN_NAME );
$active = $form->active ? __( 'Yes', BOOKACTI_PLUGIN_NAME ) : __( 'No', BOOKACTI_PLUGIN_NAME );
// Format title column
$title = esc_html( apply_filters( 'bookacti_translate_text', $title ) );
if( $can_edit_forms ) {
$title = '<a href="' . esc_url( get_admin_url() . 'admin.php?page=bookacti_forms&action=edit&form_id=' . $id ) . '" >'
. $title
. '</a>';
}
// Build shortcode
$shortcode = '[bookingactivities_form form="' . $id . '"]';
$shortcode = "<input type='text' onfocus='this.select();' readonly='readonly' value='" . $shortcode . "' class='large-text code'>";
// Author name
$user_object = get_user_by( 'id', $form->user_id );
$author = $user_object->display_name;
$form_item = apply_filters( 'bookacti_form_list_form_columns', array(
'id' => $id,
'title' => $title,
'shortcode' => $shortcode,
'author' => $author,
'date' => bookacti_format_datetime( $form->creation_date, __( 'F d, Y', BOOKACTI_PLUGIN_NAME ) ),
'status' => $form->status,
'active' => $active,
'active_raw' => $form->active,
'primary_data' => array()
), $form );
// Add info on the primary column to make them directly visible in responsive view
if( $form_item[ 'primary_data' ] ) {
$primary_column_name = $this->get_primary_column();
$primary_data = '<div class="bookacti-form-primary-data-container">';
foreach( $form_item[ 'primary_data' ] as $single_primary_data ) {
$primary_data .= '<span class="bookacti-form-primary-data">' . $single_primary_data . '</span>';
}
$primary_data .= '</div>';
$form_item[ $primary_column_name ] .= $primary_data;
}
$form_list_items[] = $form_item;
}
return $form_list_items;
}
/**
* Format filters passed as argument or retrieved via POST or GET
* @access public
* @param array $filters
* @return array
*/
public function format_filters( $filters = array() ) {
// Get filters from URL if no filter was directly passed
if( ! $filters ) {
$active = false;
if( isset( $_REQUEST[ 'active' ] ) ) { $active = ! $_REQUEST[ 'active' ] ? 0 : 1; }
$filters = array(
'id' => isset( $_REQUEST[ 'id' ] ) ? $_REQUEST[ 'id' ] : array(),
'title' => isset( $_REQUEST[ 'title' ] ) ? $_REQUEST[ 'activities' ] : '',
'user_id' => isset( $_REQUEST[ 'user_id' ] ) ? $_REQUEST[ 'user_id' ] : 0,
'status' => isset( $_REQUEST[ 'status' ] ) ? $_REQUEST[ 'status' ] : '',
'active' => $active,
'order_by' => isset( $_REQUEST[ 'orderby' ] ) ? $_REQUEST[ 'orderby' ] : array( 'id' ),
'order' => isset( $_REQUEST[ 'order' ] ) ? $_REQUEST[ 'order' ] : 'DESC'
);
}
// Format filters before making the request
$filters = bookacti_format_form_filters( $filters );
return $filters;
}
/**
* Get the total amount of forms according to filters
* @access public
* @return int
*/
public function get_total_items_count() {
return bookacti_get_number_of_form_rows( $this->filters );
}
/**
* Get the tbody element for the list table
* @access public
* @return string
*/
public function get_rows_or_placeholder() {
if ( $this->has_items() ) {
return $this->get_rows();
} else {
return '<tr class="no-items"><td class="colspanchange" colspan="' . esc_attr( $this->get_column_count() ) . '">' . esc_html__( 'No items found.', BOOKACTI_PLUGIN_NAME ) . '</td></tr>';
}
}
/**
* Generate the table rows
* @access public
* @return string
*/
public function get_rows() {
$rows = '';
foreach ( $this->items as $item ) {
$rows .= $this->get_single_row( $item );
}
return $rows;
}
/**
* Returns content for a single row of the table
* @access public
* @param array $item The current item
* @return string
*/
public function get_single_row( $item ) {
$row = '<tr>';
$row .= $this->get_single_row_columns( $item );
$row .= '</tr>';
return $row;
}
/**
* Returns the columns for a single row of the table
*
* @access public
* @param object $item The current item
*/
public function get_single_row_columns( $item ) {
list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
$returned_columns = '';
foreach ( $columns as $column_name => $column_display_name ) {
$classes = "$column_name column-$column_name";
if ( $primary === $column_name ) {
$classes .= ' has-row-actions column-primary';
}
if ( in_array( $column_name, $hidden, true ) ) {
$classes .= ' hidden';
}
// Comments column uses HTML in the display name with screen reader text.
// Instead of using esc_attr(), we strip tags to get closer to a user-friendly string.
$data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"';
$attributes = "class='$classes' $data";
if ( 'cb' === $column_name ) {
$returned_columns .= '<th scope="row" class="check-column">';
$returned_columns .= $this->column_cb( $item );
$returned_columns .= '</th>';
} elseif ( method_exists( $this, '_column_' . $column_name ) ) {
$returned_columns .= call_user_func(
array( $this, '_column_' . $column_name ),
$item,
$classes,
$data,
$primary
);
} elseif ( method_exists( $this, 'column_' . $column_name ) ) {
$returned_columns .= "<td $attributes>";
$returned_columns .= call_user_func( array( $this, 'column_' . $column_name ), $item );
$returned_columns .= $this->handle_row_actions( $item, $column_name, $primary );
$returned_columns .= "</td>";
} else {
$returned_columns .= "<td $attributes>";
$returned_columns .= $this->column_default( $item, $column_name );
$returned_columns .= $this->handle_row_actions( $item, $column_name, $primary );
$returned_columns .= "</td>";
}
}
return $returned_columns;
}
/**
* Display content for a single row of the table
*
* @access public
* @param array $item The current item
*/
public function single_row( $item ) {
echo '<tr>';
$this->single_row_columns( $item );
echo '</tr>';
}
/**
* Get an associative array ( id => link ) with the list of views available on this table
* @return array
*/
protected function get_views() {
$published_current = 'current';
$trash_current = '';
if( isset( $_REQUEST[ 'status' ] ) && $_REQUEST[ 'status' ] === 'trash' ) {
$published_current = '';
$trash_current = 'current';
}
$filters = bookacti_format_form_filters();
$published_filter = $filters; $published_filter[ 'status' ] = array( 'publish' );
$trash_filter = $filters; $trash_filter[ 'status' ] = array( 'trash' );
$published_count = bookacti_get_number_of_form_rows( $published_filter );
$trash_count = bookacti_get_number_of_form_rows( $trash_filter );
return array(
'published' => '<a href="' . esc_url( get_admin_url() . 'admin.php?page=bookacti_forms' ) . '" class="' . $published_current . '" >' . esc_html_x( 'Published', 'forms', BOOKACTI_PLUGIN_NAME ) . ' <span class="count">(' . $published_count . ')</span></a>',
'trash' => '<a href="' . esc_url( get_admin_url() . 'admin.php?page=bookacti_forms&status=trash' ) . '" class="' . $trash_current . '" >' . esc_html_x( 'Trash', 'forms', BOOKACTI_PLUGIN_NAME ) . ' <span class="count">(' . $trash_count . ')</span></a>'
);
}
/**
* Generate row actions div
* @access protected
* @param array $actions
* @param bool $always_visible
* @return string
*/
protected function row_actions( $actions, $always_visible = false ) {
$action_count = count( $actions );
$i = 0;
if( ! $action_count ) { return ''; }
$class_visible = $always_visible ? 'visible' : '';
$out = '<div class="row-actions ' . esc_attr( $class_visible ) . '">';
foreach ( $actions as $action => $link ) {
++$i;
$sep = $i == $action_count ? '' : ' | ';
$out .= $link . $sep;
}
$out .= '</div>';
return $out;
}
/**
* Get default primary column name
*
* @access public
* @return string
*/
public function get_default_primary_column_name() {
return apply_filters( 'bookacti_form_list_primary_column', 'title', $this->screen );
}
/**
* Display pagination inside a form to allow to jump to a page
* @param string $which
*/
protected function pagination( $which ) {
if( $which !== 'top' ) { parent::pagination( $which ); return; }
?>
<form action='<?php echo admin_url( 'admin.php' ); ?>' >
<input type='hidden' name='page' value='bookacti_forms' />
<?php parent::pagination( $which ); ?>
</form>
<?php
}
}
}

36
controller/controller-booking-system.php

@ -66,7 +66,7 @@ add_action( 'wp_ajax_nopriv_bookactiFetchEvents', 'bookacti_controller_fetch_eve
* Reload booking system with new attributes via AJAX
*
* @since 1.1.0
* @version 1.4.3
* @version 1.5.0
*/
function bookacti_controller_reload_booking_system() {
@ -94,8 +94,11 @@ function bookacti_controller_reload_booking_system() {
if( $is_nonce_valid && $is_allowed ) {
$template_data = bookacti_get_mixed_template_data( $attributes[ 'calendars' ], $attributes[ 'past_events' ] );
$events_interval = bookacti_get_new_interval_of_events( $template_data, array(), false, $attributes[ 'past_events' ] );
if( empty( $attributes[ 'template_data' ] ) ) {
$attributes[ 'template_data' ] = bookacti_get_mixed_template_data( $attributes[ 'calendars' ], $attributes[ 'past_events' ] );
}
$events_interval = bookacti_get_new_interval_of_events( $attributes[ 'template_data' ], array(), false, $attributes[ 'past_events' ] );
// Get HTML elements used by the booking method
$html_elements = bookacti_get_booking_method_html( $attributes[ 'method' ], $attributes );
@ -109,7 +112,7 @@ function bookacti_controller_reload_booking_system() {
$events = array( 'events' => array(), 'data' => array() );
if( $attributes[ 'group_categories' ] !== false ) {
$groups_data = bookacti_get_groups_of_events( $attributes[ 'calendars' ], $attributes[ 'group_categories' ], $attributes[ 'past_events' ] );
$groups_data = bookacti_get_groups_of_events( $attributes[ 'calendars' ], $attributes[ 'group_categories' ], $attributes[ 'past_events' ], $attributes[ 'template_data' ] );
$categories_data = bookacti_get_group_categories( $attributes[ 'calendars' ], $attributes[ 'group_categories' ] );
foreach( $groups_data as $group_id => $group_data ) { $groups_ids[] = $group_id; }
@ -144,7 +147,7 @@ function bookacti_controller_reload_booking_system() {
'groups_events' => $groups_events,
'groups_data' => $groups_data,
'group_categories_data' => $categories_data,
'template_data' => $template_data
'template_data' => $attributes[ 'template_data' ]
) );
} else {
@ -158,30 +161,21 @@ add_action( 'wp_ajax_nopriv_bookactiReloadBookingSystem', 'bookacti_controller_r
/**
* AJAX Controller - Get booking numbers for a given template and / or event
*
* @version 1.3.2
* @version 1.5.0
*/
function bookacti_controller_get_booking_numbers() {
$template_ids = isset( $_POST['template_ids'] ) ? intval( $_POST['template_ids'] ) : array();
$event_ids = isset( $_POST['event_ids'] ) ? intval( $_POST['event_ids'] ) : array();
// Check nonce and capabilities
$is_nonce_valid = check_ajax_referer( 'bookacti_get_booking_numbers', 'nonce', false );
if( $is_nonce_valid ) {
$booking_numbers = bookacti_get_number_of_bookings_by_events( $template_ids, $event_ids );
if( count( $booking_numbers ) > 0 ) {
wp_send_json( array( 'status' => 'success', 'bookings' => $booking_numbers ) );
} else if( count( $booking_numbers ) === 0 ) {
wp_send_json( array( 'status' => 'no_bookings' ) );
} else {
wp_send_json( array( 'status' => 'failed', 'error' => 'unknown' ) );
}
$booking_numbers = bookacti_get_number_of_bookings_by_events( $template_ids, $event_ids );
if( count( $booking_numbers ) > 0 ) {
wp_send_json( array( 'status' => 'success', 'bookings' => $booking_numbers ) );
} else if( count( $booking_numbers ) === 0 ) {
wp_send_json( array( 'status' => 'no_bookings' ) );
} else {
wp_send_json( array( 'status' => 'failed', 'error' => 'not_allowed' ) );
wp_send_json( array( 'status' => 'failed', 'error' => 'unknown' ) );
}
}
add_action( 'wp_ajax_bookactiGetBookingNumbers', 'bookacti_controller_get_booking_numbers' );

99
controller/controller-bookings.php

@ -35,7 +35,6 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
// BOOKING ACTIONS
// SINGLE BOOKING
/**
* AJAX Controller - Cancel a booking
@ -333,9 +332,52 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
}
add_action( 'wp_ajax_bookactiRescheduleBooking', 'bookacti_controller_reschedule_booking' );
add_action( 'wp_ajax_nopriv_bookactiRescheduleBooking', 'bookacti_controller_reschedule_booking' );
/**
* AJAX Controller - Delete a booking
* @since 1.5.0
*/
function bookacti_controller_delete_booking() {
$booking_id = intval( $_POST[ 'booking_id' ] );
// Check nonce
if( ! check_ajax_referer( 'bookacti_delete_booking', 'nonce_delete_booking', false ) ) {
bookacti_send_json_invalid_nonce( 'delete_booking' );
}
// Check capabilities
if( ! current_user_can( 'bookacti_delete_bookings' ) || ! bookacti_user_can_manage_booking( $booking_id ) ) {
bookacti_send_json_not_allowed( 'delete_booking' );
}
do_action( 'bookacti_before_delete_booking', $booking_id );
$deleted = bookacti_delete_booking( $booking_id );
if( ! $deleted ) {
$return_array = array(
'status' => 'failed',
'error' => 'not_deleted',
'message' => esc_html__( 'An error occurred while trying to delete the booking.', BOOKACTI_PLUGIN_NAME )
);
bookacti_send_json( $return_array, 'delete_booking' );
}
// Delete booking metadata, if any
bookacti_delete_metadata( 'booking', $booking_id );
do_action( 'bookacti_booking_deleted', $booking_id );
$return_array = array( 'status' => 'success' );
bookacti_send_json( $return_array, 'delete_booking' );
}
add_action( 'wp_ajax_bookactiDeleteBooking', 'bookacti_controller_delete_booking' );
// BOOKING GROUPS
/**
@ -584,7 +626,56 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
wp_send_json( array( 'status' => 'success', 'row' => $row, 'grouped_booking_rows' => $rows, 'active_changed' => $active_changed ) );
}
add_action( 'wp_ajax_bookactiChangeBookingGroupState', 'bookacti_controller_change_booking_group_state' );
/**
* AJAX Controller - Delete a booking group
* @since 1.5.0
*/
function bookacti_controller_delete_booking_group() {
$booking_group_id = intval( $_POST[ 'booking_id' ] );
// Check nonce
if( ! check_ajax_referer( 'bookacti_delete_booking', 'nonce_delete_booking', false ) ) {
bookacti_send_json_invalid_nonce( 'delete_booking_group' );
}
// Check capabilities
if( ! current_user_can( 'bookacti_delete_bookings' ) || ! bookacti_user_can_manage_booking_group( $booking_group_id ) ) {
bookacti_send_json_not_allowed( 'delete_booking_group' );
}
do_action( 'bookacti_before_delete_booking_group', $booking_group_id );
$bookings_deleted = bookacti_delete_booking_group_bookings( $booking_group_id );
if( $bookings_deleted === false ) {
$return_array = array(
'status' => 'failed',
'error' => 'grouped_bookings_not_deleted',
'message' => esc_html__( 'An error occurred while trying to delete the bookings of the group.', BOOKACTI_PLUGIN_NAME )
);
bookacti_send_json( $return_array, 'delete_booking_group' );
}
$group_deleted = bookacti_delete_booking_group( $booking_group_id );
if( ! $group_deleted ) {
$return_array = array(
'status' => 'failed',
'error' => 'not_deleted',
'message' => esc_html__( 'An error occurred while trying to delete the booking group.', BOOKACTI_PLUGIN_NAME )
);
bookacti_send_json( $return_array, 'delete_booking_group' );
}
do_action( 'bookacti_booking_group_deleted', $booking_group_id );
$return_array = array( 'status' => 'success' );
bookacti_send_json( $return_array, 'delete_booking_group' );
}
add_action( 'wp_ajax_bookactiDeleteBookingGroup', 'bookacti_controller_delete_booking_group' );

1145
controller/controller-forms.php

File diff suppressed because it is too large Load Diff

6
controller/controller-notifications.php

@ -6,11 +6,13 @@ if ( ! defined( 'ABSPATH' ) ) { exit; }
* Send a notification to admin and customer when a new booking is made
*
* @since 1.2.2 (was bookacti_send_notification_admin_new_booking in 1.2.1)
* @version 1.5.0
* @param int $booking_id
* @param array $booking_form_values
* @param string $booking_type
* @param int $form_id
*/
function bookacti_send_notification_when_booking_is_made( $booking_id, $booking_form_values, $booking_type ) {
function bookacti_send_notification_when_booking_is_made( $booking_id, $booking_form_values, $booking_type, $form_id = 0 ) {
// Send a booking confirmation to the customer
$status = $booking_type === 'group' ? bookacti_get_booking_group_state( $booking_id ) : bookacti_get_booking_state( $booking_id );
bookacti_send_notification( 'customer_' . $status . '_booking', $booking_id, $booking_type );
@ -18,7 +20,7 @@ function bookacti_send_notification_when_booking_is_made( $booking_id, $booking_
// Alert administrators that a new booking has been made
bookacti_send_notification( 'admin_new_booking', $booking_id, $booking_type );
}
add_action( 'bookacti_booking_form_validated', 'bookacti_send_notification_when_booking_is_made', 10, 3 );
add_action( 'bookacti_booking_form_validated', 'bookacti_send_notification_when_booking_is_made', 10, 4 );

43
controller/controller-settings.php

@ -98,6 +98,14 @@ function bookacti_init_settings() {
'bookacti_general_settings',
'bookacti_settings_section_general'
);
add_settings_field(
'default_calendar_view_threshold',
__( 'Responsive calendar view threshold', BOOKACTI_PLUGIN_NAME ),
'bookacti_settings_field_default_calendar_view_threshold_callback',
'bookacti_general_settings',
'bookacti_settings_section_general'
);
@ -214,14 +222,18 @@ add_action( 'admin_init', 'bookacti_init_settings' );
* Add screen options
*
* @since 1.3.0
* @version 1.5.0
*/
function bookacti_add_screen_options() {
add_action( 'load-booking-activities_page_bookacti_bookings', 'bookacti_display_bookings_screen_options' );
add_action( 'load-booking-activities_page_bookacti_forms', 'bookacti_display_forms_screen_options' );
}
add_action( 'admin_menu', 'bookacti_add_screen_options', 20 );
/**
* Add booking page columns screen options
* @since 1.3.0
*/
function bookacti_add_booking_page_screen_option() {
new Bookings_List_Table();
@ -229,18 +241,29 @@ function bookacti_add_booking_page_screen_option() {
add_action( 'admin_head-booking-activities_page_bookacti_bookings', 'bookacti_add_booking_page_screen_option' );
/**
* Add form page columns screen options
* @since 1.5.0
*/
function bookacti_add_form_page_screen_option() {
if( empty( $_REQUEST[ 'action' ] ) || ! in_array( $_REQUEST[ 'action' ], array( 'edit', 'new' ), true ) ) {
new Forms_List_Table();
}
}
add_action( 'admin_head-booking-activities_page_bookacti_forms', 'bookacti_add_form_page_screen_option' );
/**
* Save screen options