Skip to content

Instantly share code, notes, and snippets.

@panoslyrakis
Created May 15, 2017 08:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save panoslyrakis/162dd2c34569ad36a223c9688380a3eb to your computer and use it in GitHub Desktop.
Save panoslyrakis/162dd2c34569ad36a223c9688380a3eb to your computer and use it in GitHub Desktop.
Add capacity control to services of WPMUDEV Appointments+ plugin
<?php
/*
Plugin Name: Appointments capacity control
Plugin URI: https://premium.wpmudev.org/
Description: Add capacity control to services
Author: Panos Lyrakis @ WPMUDEV
Author URI: https://premium.wpmudev.org/
License: GPLv2 or later
*/
/*
Requires to modify function apppointments_is_range_busy()
and add the following somwhere on the beginning :
=============
$force_availability = apply_filters( 'app-force_availability', false, $start, $end, $args );
if( $force_availability ){
$is_busy = apply_filters( 'app-is_busy_custom', false, $start, $end, $args );
return $is_busy;
}
============
*/
if( ! class_exists( 'WPMUDEV_App_Capacity_Control' ) ){
class WPMUDEV_App_Capacity_Control{
private static $_instance = null;
public $version;
public static function get_instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new WPMUDEV_App_Capacity_Control();
}
return self::$_instance;
}
private function __construct(){
add_filter( 'app-force_availability', array( $this, 'force_availability' ), 10, 4 );
add_filter( 'app-is_busy_custom', array( $this, 'is_busy' ), 10, 4 );
add_filter( 'app_additional_fields', array( $this, 'additional_field'), 10 );
add_action( 'wpmudev_appointments_insert_appointment', array( $this, 'save_additional_fields' ), 10 );
add_action( 'wp_ajax_pre_confirmation_slot_capacity', array( $this, 'ajax_slot_capacity' ) );
add_action( 'wp_ajax_nopriv_pre_confirmation_slot_capacity', array( $this, 'ajax_slot_capacity' ) );
/*
//TODO
add_filter('app_notification_message', array($this, 'expand_email_macros'), 10, 3);
add_filter('app_confirmation_message', array($this, 'expand_email_macros'), 10, 3);
add_filter('app_reminder_message', array($this, 'expand_email_macros'), 10, 3);
add_filter('app_removal_notification_message', array($this, 'expand_email_macros'), 10, 3);
*/
}
public function force_availability( $force_it, $start, $end, $args ){
return true;
}
public function is_busy( $is_busy, $start, $end, $args ){
$service_id = (int)$args['service_id'];
$start = date( 'Y-m-d H:i:s', $start );
$end = date( 'Y-m-d H:i:s', $end );
$av_args = array(
'service_id' => $service_id,
'start' => $start,
'end' => $end
);
$service_capacity = $this->get_availability( $av_args );
return ! $service_capacity > 0;
}
public function get_availability( $args ){
global $wpdb;
$service_id = (int)$args['service_id'];
$service = appointments_get_service( $service_id );
$service_capacity = (int)$service->capacity; //appointments_get_service_capacity( $service_id ); //(int)$args[ 'capacity' ];
/*
$service_id = (int)$args['service_id'];
$start = (int)$args['start'];
$end = (int)$args['end'];
$un_args = array(
'service_id' => $service_id,
'start' => $start,
'end' => $end
);
*/
$unavail = self::get_unavail( $args );
if( is_numeric( $unavail ) && $unavail > 0 ){
$workers_count = count( appointments_get_workers_by_service( $service_id ) );
$service_capacity = $workers_count * $service_capacity;
$service_capacity -= $unavail;
//return ! $service_capacity > 0;
}
//return false;
return $service_capacity;
}
public static function get_unavail( $args ){
global $wpdb;
$service_id = $args[ 'service_id' ];
$start = $args[ 'start' ];
$end = $args[ 'end' ];
$booked_query = "SELECT SUM( app_meta.meta_value ) AS unavail FROM {$wpdb->prefix}app_appointments as app
LEFT JOIN {$wpdb->prefix}app_appointmentmeta AS app_meta ON app.ID = app_meta.app_appointment_id
WHERE
app.service={$service_id} AND app.status IN( 'pending','confirmed', 'paid' ) AND ( ( app.start BETWEEN '{$start}' AND '{$end}' ) OR ( app.end BETWEEN '{$start}' AND '{$end}' ) ) AND app_meta.meta_key = 'app_item_count'";
return $wpdb->get_var( $booked_query );
}
public function ajax_slot_capacity(){
$service_id = (int)$_POST[ 'service_id' ];
$start = date('Y-m-d H:i:s', $_POST[ 'start' ] );
$end = date('Y-m-d H:i:s', $_POST[ 'end' ] );
$args = array(
'service_id' => $service_id,
'start' => $start,
'end' => $end
);
$availability = $this->get_availability( $args );
$response = array( 'capacity' => $availability );
wp_send_json( $response );
}
public function additional_field( $fields_html ){
global $wpdb;
//$services_capacities = $wpdb->get_results( "SELECT ID, capacity FROM {$wpdb->prefix}app_services", ARRAY_A );
ob_start();
?>
<div class="appointments-capacity-field">
<label>
<span>Select number</span>
<select name="app-service-capacity-select" id="app-service-capacity-select"></select>
</label>
</div>
<script type="text/javascript">
(function($){
$(document).ready(function(){
$.ajaxSetup({
beforeSend: function (jqxhr, settings) {
settings.data += '&' + encodeURIComponent( 'app-service-capacity-select' ) + '=' + encodeURIComponent( $( '#app-service-capacity-select' ).val() );
}
});
//var services_capacities = JSON.parse( '<?php //echo json_encode( $services_capacities ); ?>' );
var $body = $('body');
var capacity_selector = $( '#app-service-capacity-select' );
$body.on( 'click', '.app_timetable_cell.free, .app_week_timetable_cell.free', function( $element ) {
/*if( ! isNaN( selected_service ) ){
return;
}*/
var confirmation_btn = $( '.appointments-confirmation-button' );
var selected_slot_meta = $( this ).find( '.appointments_take_appointment' ).val();
var selected_meta_parts = selected_slot_meta.split(':');
var selected_service = selected_meta_parts[1];
var start = selected_meta_parts[3];
var end = selected_meta_parts[4];
var cap_data = {
action : "pre_confirmation_slot_capacity",
nonce : AppShortcodeConfirmation.nonce,
service_id : selected_service,
start : start,
end : end
};
confirmation_btn.hide( 300 );
$.post( AppShortcodeConfirmation.ajaxurl, cap_data, function( response ) {
var capacity = 1;
if ( response && response.error ) {
//Just do nothing and leave capacity to 1
//console.log( 'No capacity response' );
}
else{
capacity = response.capacity;
}
var selector_options = '';
for( var c = 1; c <= capacity; c++ ){
selector_options += '<option value="' + c + '">' + c + '</option>';
}
capacity_selector.append( selector_options );
confirmation_btn.show( 300 );
}, 'json');
/*$.each(services_capacities, function(i,item){
if( item.ID == selected_service ){
capacity = item.capacity;
}
});*/
} );
});
})(jQuery);
</script>
<?php
$capacity_selector = ob_get_clean();
return $fields_html . $capacity_selector;
}
public function save_additional_fields( $app_id ){
if( ! isset( $_REQUEST[ 'app-service-capacity-select' ] ) || ! is_numeric( $_REQUEST[ 'app-service-capacity-select' ] ) ){
return;
}
$capacity_selected = (int)$_REQUEST['app-service-capacity-select'];
update_metadata( 'app_appointment', $app_id, 'app_item_count', $capacity_selected );
}
}
add_action( 'plugins_loaded', function(){
$GLOBALS['WPMUDEV_App_Capacity_Control'] = WPMUDEV_App_Capacity_Control::get_instance();
}, 10 );
}
@panoslyrakis
Copy link
Author

panoslyrakis commented May 15, 2017

In order the above to work on Appointments+ version 2.1.0 you need to modify file
includes/helpers.php
and add the following at the beginning of function apppointments_is_range_busy():

$force_availability = apply_filters( 'app-force_availability', false, $start, $end, $args ); if( $force_availability ){ $is_busy = apply_filters( 'app-is_busy_custom', false, $start, $end, $args ); return $is_busy; }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment