user && $app->user == $user_id ) { $owner = true; } } // Then check cookie. Check is not so strict here, as he couldn't be seeing that cancel checkbox in the first place if ( ! $owner ) { $apps = Appointments_Sessions::get_current_visitor_appointments(); if ( in_array( $app_id, $apps ) ) { $owner = true; } } // Addons may want to do something here $owner = apply_filters( 'app_cancellation_owner', $owner, $app_id ); if ( !$owner ) { wp_send_json_error( esc_js(__('There is an issue with this appointment. Please refresh the page and try again. If problem persists, please contact website admin.','appointments') ) ); } $result = appointments_cancel_appointment( $app_id ); if ( is_wp_error( $result ) ) { wp_send_json_error( esc_js(__('Appointment could not be cancelled. Please refresh the page and try again.','appointments') ) ); } wp_send_json_success(); } /** * Track javascript errors * @since 1.0.3 */ function js_error() { // @TODO: Activate this again in future releases // if ( false && isset( $_POST['url'] ) ) { // $this->error_url = $_POST['url']; // $appointments->log( __('Javascript error on : ', 'appointments') . $this->error_url ); // die( json_encode( array( 'message' => '

' . // sprintf( __('[Appointments+] You have at least one javascript error on %s.
Error message: %s
File: %s
Line: %s', 'appointments'), $this->error_url, @$_POST['errorMessage'], @$_POST['file'], @$_POST['lineNumber']) . // '

') // ) // ); // } die(); } function inline_edit_save() { global $appointments, $wpdb, $current_user; check_ajax_referer( 'app-edit-appointment', 'nonce' ); $app_id = absint( $_POST["app_id"] ); $app = appointments_get_appointment( $app_id ); $app_orig_status = isset( $app->status ) ? $app->status : ''; $data = array(); $data['user'] = absint( $_POST['user'] ); $data['email'] = !empty($_POST['email']) && is_email($_POST['email']) ? $_POST['email'] : ''; $data['name'] = sanitize_text_field( $_POST['name'] ); $data['phone'] = sanitize_text_field( $_POST['phone'] ); $data['address'] = sanitize_text_field( $_POST['address'] ); $data['city'] = sanitize_text_field( $_POST['city'] ); $data['service'] = absint( $_POST['service'] ); $data['worker'] = absint( $_POST['worker'] ); $data['price'] = $_POST['price']; $data['note'] = $_POST['note']; $data['status'] = $_POST['status']; $data['date'] = $_POST['date']; $data['time'] = $_POST['time']; $resend = (bool)$_POST["resend"]; $data = apply_filters('app-appointment-inline_edit-save_data', $data); $error = apply_filters( 'appointments_inline_edit_error', false, $data, $_REQUEST ); if ( is_wp_error( $error ) ) { $result = array( 'app_id' => $app_id, 'message' => '' . _x( 'Error', 'Error while editing an appointment', 'appointments' ) . ': ' . $error->get_error_message() . '' ); wp_send_json( $result ); } elseif ( true === $error ) { // Unknown error $result = array( 'app_id' => $app_id, 'message' => '' . _x( 'Error', 'Error while editing an appointment', 'appointments' ) . ': ' . __( 'Record could not be saved OR you did not make any changes!', 'appointments' ) . '' ); wp_send_json( $result ); } do_action( 'appointments_inline_edit', $app_id, $data ); $update_result = $insert_result = false; if ( $app ) { // Update if ( ! $resend ) { // The appointments_update_appointment() will try send confirmation email. // Avoid sending if not requested add_filter( 'appointments_send_confirmation', '__return_false', 40 ); } $data['datetime'] = strtotime( $data['date'] . ' ' . $data['time'] . ':00' ); $update_result = appointments_update_appointment( $app_id, $data ); // Send confirmation email if requested in update (only for confirmed or similar statuses) $unconfirmable_statuses = array( 'removed', 'pending', 'completed' ); if( $app_orig_status != $data['status'] || in_array( $data['status'], $unconfirmable_statuses ) ){ $resend = false; } if ( $resend ) { appointments_send_confirmation( $app_id ); } } else { // Insert $data['date'] = strtotime( $data['date'] . ' ' . $data['time'] . ':00' ); if ( ! $resend ) { add_filter( 'appointments_send_confirmation', '__return_false', 50 ); } $app_id = appointments_insert_appointment( $data ); $insert_result = true; } do_action('app-appointment-inline_edit-after_save', $app_id, $data); do_action('app-appointment-inline_edit-before_response', $app_id, $data); $app = appointments_get_appointment( $app_id ); if ( ! $app ) { $insert_result = false; $update_result = false; } if ( $update_result ) { $app_orig_status = $app->status; $result = array( 'app_id' => $app->ID, 'message' => __('Changes saved.', 'appointments'), ); // Log change of status if ( $data['status'] != $app_orig_status ) { $appointments->log( sprintf( __('Status changed from %s to %s by %s for appointment ID:%d','appointments'), $app_orig_status, $data["status"], $current_user->user_login, $app->ID ) ); // Result includes reload of page to show updated statuses. $result[ 'reload' ] = true; } } else if ( $insert_result ) { $result = array( 'app_id' => $app->ID, 'message' => __('Changes saved.', 'appointments'), ); } else { $message = $resend && !empty($data['status']) && 'removed' != $data['status'] ? sprintf('%s', __('Confirmation message (re)sent', 'appointments')) : sprintf('%s', __('Record could not be saved OR you did not make any changes!', 'appointments')) ; $result = array( 'app_id' => $app_id, 'message' => $message, ); } $result = apply_filters('app-appointment-inline_edit-result', $result, $app_id, $data); die(json_encode($result)); } // Edit or create appointments function inline_edit() { $appointments = appointments(); check_ajax_referer( 'app-add-new', 'nonce' ); $app_id = absint( $_POST["app_id"] ); $app = false; if ( $app_id ) { $app = appointments_get_appointment( $app_id ); } if ( $app ) { $start_date_timestamp = date( "Y-m-d", $app->get_start_timestamp() ); $end_datetime = date_i18n( $appointments->datetime_format, strtotime( $app->end ) ); // Is this a registered user? if ( $app->user ) { $fields = array( 'name', 'email', 'phone', 'address', 'city' ); // Fill up the fields foreach ( $fields as $field ) { $value = get_user_meta( $app->user, 'app_' . $field, true ); if ( $value ) { $app->$field = $value; } } } } else { $app = array( 'ID' => 0, 'user' => 0, 'worker' => 0, 'location' => 0, 'service' => appointments_get_services_min_id(), 'price' => $appointments->get_price() ); // @TODO Remove this shit // Get first service and its price $_REQUEST['app_service_id'] = $app['service']; $_REQUEST['app_provider_id'] = 0; $app = new Appointments_Appointment( $app ); // Set start date as now + 60 minutes. $current_time = current_time( 'timestamp' ); $start_date_timestamp = date( "Y-m-d", $current_time + 60 * $appointments->get_min_time() ); $end_datetime = ''; } $column_length = isset( $_POST['col_len'] ) && is_numeric( $_POST['col_len'] ) ? absint( $_POST['col_len'] ) : 6; $columns = isset( $_POST['columns'] ) ? absint( $_POST['columns'] ) : $column_length; $dropdown_users = wp_dropdown_users( array( 'show_option_all' => __( 'Not registered user', 'appointments' ), 'show' => 'user_login', 'echo' => 0, 'selected' => $app->user, 'name' => 'user' ) ); $workers = appointments_get_workers(); $user_fields = array( 'name', 'email', 'phone', 'address', 'city' ); $options = appointments_get_options(); // Check if an admin min time (time base) is set. @since 1.0.2 $min_time = $options["admin_min_time"] ? $options["admin_min_time"] : $appointments->get_min_time(); $min_secs = 60 * apply_filters( 'app_admin_min_time', $min_time ); $services = appointments_get_services(); $notifications_sent = appointments_get_appointment_meta( $app_id, '_notifications_sent' ); $confirmation_sent = ( is_array( $notifications_sent ) && isset( $notifications_sent['confirmation'] ) && $notifications_sent['confirmation'] ); ob_start(); include( appointments_plugin_dir() . 'admin/views/inline-edit.php' ); wp_send_json( array( 'result' => ob_get_clean() ) ); } /** * Make checks on submitted fields and save appointment */ function post_confirmation() { global $appointments; $check_spam = $appointments->check_spam(); if (! $check_spam) { die(json_encode(array( "error" => apply_filters( 'app_spam_message', __( 'You have already applied for an appointment. Please wait until you hear from us.', 'appointments') ), ))); } /** * Check nonce */ $this->security_check_die( 'AppShortcodeConfirmation' ); global $current_user; $values = explode( ":", $_POST["value"] ); $location = $values[0]; $service = $values[1]; $worker = $values[2]; $start = $values[3]; $end = $values[4]; $post_id = $values[5]; if (is_user_logged_in()) { $user_id = $current_user->ID; $userdata = get_userdata( $current_user->ID ); $user_email = $userdata->email; $user_name = $userdata->display_name; if (!$user_name) { $first_name = get_user_meta($worker, 'first_name', true); $last_name = get_user_meta($worker, 'last_name', true); $user_name = $first_name . " " . $last_name; } if ("" == trim($user_name)) $user_name = $userdata->user_login; } else { $user_id = 0; $user_email = ''; $user_name = ''; } // A little trick to pass correct lsw variables to the get_price, is_busy and get_capacity functions $_REQUEST["app_location_id"] = $location; $_REQUEST["app_service_id"] = $service; $_REQUEST["app_provider_id"] = $worker; $appointments->get_lsw(); // Default status $status = 'pending'; if ('yes' != $appointments->options["payment_required"] && isset($appointments->options["auto_confirm"]) && 'yes' == $appointments->options["auto_confirm"]) { $status = 'confirmed'; } // We may have 2 prices now: 1) Service full price, 2) Amount that will be paid to Paypal $price = $appointments->get_price(); $price = apply_filters('app_post_confirmation_price', $price, $service, $worker, $start, $end); $paypal_price = $appointments->get_price(true); $paypal_price = apply_filters('app_post_confirmation_paypal_price', number_format( str_replace( ',', '', $paypal_price ), 2, ".", "" ), $service, $worker, $start, $end); // Break here - is the appointment free and, if so, shall we auto-confirm? if ( !(float)$price && !(float)$paypal_price // Free appointment ... && 'pending' === $status && "yes" === $appointments->options["payment_required"] // ... in a paid environment ... && (!empty($appointments->options["auto_confirm"]) && "yes" === $appointments->options["auto_confirm"]) // ... with auto-confirm activated ) { $status = defined('APP_CONFIRMATION_ALLOW_FREE_AUTOCONFIRM') && APP_CONFIRMATION_ALLOW_FREE_AUTOCONFIRM ? 'confirmed' : $status ; } $name = !empty($_POST['app_name']) ? sanitize_text_field($_POST["app_name"]) : $user_name ; $name_check = apply_filters( "app_name_check", true, $name ); if ( ! $name_check ) { $appointments->json_die( 'name' ); } $email = $user_email; if ( ! empty( $_POST['app_email'] ) ) { $_email = sanitize_email( $_POST['app_email'] ); if ( is_email( $_email ) ) { $email = $_email; } } if ( $appointments->options["ask_email"] && ! is_email( $email ) ) { $appointments->json_die( 'email' ); } $phone = !empty($_POST['app_phone']) ? sanitize_text_field($_POST["app_phone"]) : '' ; $phone_check = apply_filters("app_phone_check", true, $phone); if ( ! $phone_check ) { $appointments->json_die( 'phone' ); } $address = !empty($_POST['app_address']) ? sanitize_text_field($_POST["app_address"]) : '' ; $address_check = apply_filters("app_address_check", true, $address); if ( ! $address_check ) { $appointments->json_die( 'address' ); } $city = !empty($_POST['app_city']) ? sanitize_text_field($_POST["app_city"]) : '' ; $city_check = apply_filters("app_city_check", true, $city); if ( ! $city_check ) { $appointments->json_die( 'city' ); } $note = !empty($_POST['app_note']) ? sanitize_text_field($_POST["app_note"]) : '' ; $gcal = !empty($_POST['app_gcal']) ? $_POST['app_gcal'] : '' ; do_action('app-additional_fields-validate'); // It may be required to add additional data here $note = apply_filters('app_note_field', $note); $service_result = appointments_get_service( $service ); $duration = false; if ( $service_result !== null ) { $duration = $service_result->duration; } if ( ! $duration ) { // In minutes $duration = $appointments->get_min_time(); } $duration = apply_filters( 'app_post_confirmation_duration', $duration, $service, $worker, $user_id ); $args = array( 'worker_id' => $worker, 'service_id' => $service, 'location_id' => $location ); $is_busy = apppointments_is_range_busy( $start, $start + ( $duration * MINUTE_IN_SECONDS ), $args ); if ( $is_busy ) { die( json_encode( array( "error" => apply_filters( 'app_booked_message', __( 'We are sorry, but this time slot is no longer available. Please refresh the page and try another time slot. Thank you.', 'appointments' ) ), ) ) ); } if ( ! $worker ) { // Try to assign to first worker available if( $service ){ $workers = appointments_get_workers_by_service( $service ); } else{ $workers = appointments_get_all_workers(); } foreach ( $workers as $worker ) { $args['worker_id'] = $worker->ID; $is_busy = apppointments_is_range_busy( $start, $start + ( $duration * 60 ), $args ); if ( ! $is_busy ) { $worker = $worker->ID; break; } } } unset( $args ); $status = apply_filters('app_post_confirmation_status', $status, $price, $service, $worker, $user_id ); $args = array( 'user' => $user_id, 'name' => $name, 'email' => $email, 'phone' => $phone, 'address' => $address, 'city' => $city, 'location' => $location, 'service' => $service, 'worker' => $worker, 'price' => $price, 'status' => $status, 'date' => $start, 'note' => $note, 'duration' => $duration ); /** * Allow to filter arguments that will be passed to appointment insertion * * Return WP_Error or true to avoid appointment insert * * @param bool * @param array $args List of arguments that will be used to insert the appointment * @param array $_REQUEST Request list coming from form screen */ $args = apply_filters( 'appointments_post_confirmation_args', $args ); /** * Allow to filter errors in confirmation form right before the appointment is added * * Return WP_Error or true to avoid appointment insert * * @param bool * @param array $args List of arguments that will be used to insert the appointment * @param array $_REQUEST Request list coming from form screen */ $error = apply_filters( 'appointments_post_confirmation_error', false, $args, $_REQUEST ); if ( is_wp_error( $error ) ) { wp_send_json( array( 'error' => $error->get_error_message() ) ); } elseif ( true === $error ) { // Unknown error wp_send_json( array( 'error' => __( 'Appointment could not be saved. Please contact website admin.', 'appointments') ) ); } $insert_id = appointments_insert_appointment( $args ); appointments_clear_appointment_cache(); if (!$insert_id) { die(json_encode(array( "error" => __( 'Appointment could not be saved. Please contact website admin.', 'appointments'), ))); } // A new appointment is accepted, so clear cache appointments_clear_cache(); $apps = Appointments_Sessions::get_current_visitor_appointments(); $apps[] = $insert_id; Appointments_Sessions::set_visitor_appointments( $apps ); Appointments_Sessions::set_visitor_personal_data( array( "n" => $name, "e" => $email, "p" => $phone, "a" => $address, "c" => $city, "g" => $gcal ) ); // May be required to clean up or modify userdata cookie do_action( 'app_save_cookie', $insert_id, $apps ); // Save user data too if ( is_user_logged_in() && defined('APP_USE_LEGACY_USERDATA_OVERWRITING') && APP_USE_LEGACY_USERDATA_OVERWRITING ) { global $current_user; if ( $name ) update_user_meta( $current_user->ID, 'app_name', $name ); if ( $email ) update_user_meta( $current_user->ID, 'app_email', $email ); if ( $phone ) update_user_meta( $current_user->ID, 'app_phone', $phone ); if ( $address ) update_user_meta( $current_user->ID, 'app_address', $address ); if ( $city ) update_user_meta( $current_user->ID, 'app_city', $city ); do_action( 'app_save_user_meta', $current_user->ID, array( 'name'=>$name, 'email'=>$email, 'phone'=>$phone, 'address'=>$address, 'city'=>$city ) ); } // Send confirmation for pending, payment not required cases, if selected so if ( 'yes' != $appointments->options["payment_required"] && isset($appointments->options["send_notification"]) && 'yes' == $appointments->options["send_notification"] && 'pending' == $status ) { appointments_send_notification( $insert_id ); } // GCal button if (isset($appointments->options["gcal"]) && 'yes' == $appointments->options["gcal"] && $gcal) { $gcal_url = $appointments->gcal( $service, $start, $start + ($duration * 60 ), false, $address, $city ); } else { $gcal_url = ''; } $additional = array( 'mp' => 0, 'variation' => null, ); $additional = apply_filters('app-appointment-appointment_created', $additional, $insert_id, $post_id, $service, $worker, $start, $end); $mp = isset( $additional['mp'] ) ? $additional['mp'] : 0; $variation = isset( $additional['variation'] ) ? $additional['variation'] : 0; $gcal_same_window = ! empty( $appointments->options["gcal_same_window"] ) ? 1 : 0; if (isset( $appointments->options["payment_required"] ) && 'yes' == $appointments->options["payment_required"]) { die(json_encode(array( "cell" => $_POST["value"], "app_id" => $insert_id, "refresh" => 0, "price" => $paypal_price, "service_name" => stripslashes( $service_result->name ), 'gcal_url' => $gcal_url, 'gcal_same_window' => $gcal_same_window, 'mp' => $mp, 'variation' => $variation ))); } else { $result = array( "cell" => $_POST["value"], "app_id" => $insert_id, "refresh" => 1, 'gcal_url' => $gcal_url, 'gcal_same_window' => $gcal_same_window, ); wp_send_json( $result ); } } /** * IPN handling for Paypal */ function handle_paypal_return() { global $appointments; // PayPal IPN handling code $appointments->options = get_option( 'appointments_options' ); if ((isset($_POST['payment_status']) || isset($_POST['txn_type'])) && isset($_POST['custom'])) { if ($appointments->options['mode'] == 'live') { $domain = 'https://www.paypal.com'; } else { $domain = 'https://www.sandbox.paypal.com'; } $req = 'cmd=_notify-validate'; foreach ($_POST as $k => $v) { $req .= '&' . $k . '=' . $v; } $header = 'POST /cgi-bin/webscr HTTP/1.0' . "\r\n" . 'Content-Type: application/x-www-form-urlencoded' . "\r\n" . 'Content-Length: ' . strlen($req) . "\r\n" . "\r\n"; @set_time_limit(60); if ($conn = @fsockopen($domain, 80, $errno, $errstr, 30)) { fputs($conn, $header . $req); socket_set_timeout($conn, 30); $response = ''; $close_connection = false; while (true) { if (feof($conn) || $close_connection) { fclose($conn); break; } $st = @fgets($conn, 4096); if ($st === false) { $close_connection = true; continue; } $response .= $st; } $error = ''; $lines = explode("\n", str_replace("\r\n", "\n", $response)); // looking for: HTTP/1.1 200 OK if (count($lines) == 0) $error = 'Response Error: Header not found'; else if (substr($lines[0], -7) != ' 200 OK') $error = 'Response Error: Unexpected HTTP response'; else { // remove HTTP header while (count($lines) > 0 && trim($lines[0]) != '') array_shift($lines); // first line will be empty, second line will have the result if (count($lines) < 2) $error = 'Response Error: No content found in transaction response'; else if (strtoupper(trim($lines[1])) != 'VERIFIED') $error = 'Response Error: Unexpected transaction response'; } if ($error != '') { $appointments->log( $error ); exit; } } // We are using server time. Not Paypal time. $timestamp = $appointments->local_time; // process PayPal response switch ($_POST['payment_status']) { case 'Partially-Refunded': break; case 'In-Progress': break; case 'Completed': case 'Processed': // case: successful payment $amount = $_POST['mc_gross']; $currency = $_POST['mc_currency']; $args = array( 'app_ID' => $_POST['custom'], 'paypal_ID' => $_POST['txn_id'], 'stamp' => $timestamp, 'total_amount' => $amount, 'currency' => $currency, 'status' => $_POST['payment_status'], 'note' => '', ); $transaction = appointments_get_transaction( $_POST['custom'] ); if ( $transaction ) { appointments_update_transaction( $_POST['custom'], $args ); } else { appointments_insert_transaction( $args ); } if ( ! appointments_update_appointment_status( $_POST['custom'], 'paid' ) ) { // Something wrong. Warn admin $message = sprintf( __('Paypal confirmation arrived, but status could not be changed for some reason. Please check appointment with ID %s', 'appointments'), $_POST['custom'] ); wp_mail( $appointments->get_admin_email( ), __('Appointment status could not be changed','appointments'), $message, $appointments->message_headers() ); } break; case 'Reversed': // case: charge back $note = __('Last transaction has been reversed. Reason: Payment has been reversed (charge back)', 'appointments'); $amount = $_POST['mc_gross']; $currency = $_POST['mc_currency']; $args = array( 'app_ID' => $_POST['custom'], 'paypal_ID' => $_POST['txn_id'], 'stamp' => $timestamp, 'total_amount' => $amount, 'currency' => $currency, 'status' => $_POST['payment_status'], 'note' => $note, ); $transaction = appointments_get_transaction( $_POST['custom'] ); if ( $transaction ) { appointments_update_transaction( $_POST['custom'], $args ); } else { appointments_insert_transaction( $args ); } break; case 'Refunded': // case: refund $note = __('Last transaction has been reversed. Reason: Payment has been refunded', 'appointments'); $amount = $_POST['mc_gross']; $currency = $_POST['mc_currency']; $args = array( 'app_ID' => $_POST['custom'], 'paypal_ID' => $_POST['txn_id'], 'stamp' => $timestamp, 'total_amount' => $amount, 'currency' => $currency, 'status' => $_POST['payment_status'], 'note' => $note, ); $transaction = appointments_get_transaction( $_POST['custom'] ); if ( $transaction ) { appointments_update_transaction( $_POST['custom'], $args ); } else { appointments_insert_transaction( $args ); } break; case 'Denied': // case: denied $note = __('Last transaction has been reversed. Reason: Payment Denied', 'appointments'); $amount = $_POST['mc_gross']; $currency = $_POST['mc_currency']; $args = array( 'app_ID' => $_POST['custom'], 'paypal_ID' => $_POST['txn_id'], 'stamp' => $timestamp, 'total_amount' => $amount, 'currency' => $currency, 'status' => $_POST['payment_status'], 'note' => $note, ); $transaction = appointments_get_transaction( $_POST['custom'] ); if ( $transaction ) { appointments_update_transaction( $_POST['custom'], $args ); } else { appointments_insert_transaction( $args ); } break; case 'Pending': // case: payment is pending $pending_str = array( 'address' => __('Customer did not include a confirmed shipping address', 'appointments'), 'authorization' => __('Funds not captured yet', 'appointments'), 'echeck' => __('eCheck that has not cleared yet', 'appointments'), 'intl' => __('Payment waiting for aproval by service provider', 'appointments'), 'multi-currency' => __('Payment waiting for service provider to handle multi-currency process', 'appointments'), 'unilateral' => __('Customer did not register or confirm his/her email yet', 'appointments'), 'upgrade' => __('Waiting for service provider to upgrade the PayPal account', 'appointments'), 'verify' => __('Waiting for service provider to verify his/her PayPal account', 'appointments'), '*' => '' ); $reason = @$_POST['pending_reason']; $note = __('Last transaction is pending. Reason: ', 'appointments') . (isset($pending_str[$reason]) ? $pending_str[$reason] : $pending_str['*']); $amount = $_POST['mc_gross']; $currency = $_POST['mc_currency']; $args = array( 'app_ID' => $_POST['custom'], 'paypal_ID' => $_POST['txn_id'], 'stamp' => $timestamp, 'total_amount' => $amount, 'currency' => $currency, 'status' => $_POST['payment_status'], 'note' => $note, ); $transaction = appointments_get_transaction( $_POST['custom'] ); if ( ! $transaction ) { appointments_update_transaction( $_POST['custom'], $args ); } else { appointments_insert_transaction( $args ); } break; default: // case: various error cases } } else { // Did not find expected POST variables. Possible access attempt from a non PayPal site. // This is IPN response, so echoing will not help. Let's log it. $appointments->log( 'Error: Missing POST variables. Identification is not possible.' ); exit; } exit; } /** * Check and return necessary fields to the front end */ function pre_confirmation () { global $appointments; /** * Check nonce */ $this->security_check_die( 'AppShortcodeConfirmation' ); $values = explode( ":", $_POST["value"] ); $location = $values[0]; $service = $values[1]; $worker = $values[2]; $start = $values[3]; $end = $values[4]; // A little trick to pass correct lsw variables to the get_price, is_busy and get_capacity functions $_REQUEST["app_location_id"] = $location; $_REQUEST["app_service_id"] = $service; $_REQUEST["app_provider_id"] = $worker; $appointments->get_lsw(); // Alright, so before we go further, let's check if we can if (!is_user_logged_in() && (!empty($appointments->options['login_required']) && 'yes' == $appointments->options['login_required'])) { die(json_encode(array( 'error' => __('You need to login to make an appointment.', 'appointments'), ))); } $price = $appointments->get_price(); // It is possible to apply special discounts $price = apply_filters('app_display_amount', $price, $service, $worker); $price = apply_filters('app_pre_confirmation_price', $price, $service, $worker, $start, $end); $display_currency = !empty($appointments->options["currency"]) ? App_Template::get_currency_symbol($appointments->options["currency"]) : App_Template::get_currency_symbol('USD') ; $is_busy = $appointments->is_busy($start, $end, $appointments->get_capacity()); if ( $is_busy ) { die(json_encode(array( "error" => apply_filters( 'app_booked_message', __( 'We are sorry, but this time slot is no longer available. Please refresh the page and try another time slot. Thank you.', 'appointments') ) ))); } $service_obj = appointments_get_service($service); $service = ''; $start = ''; $end = ''; $price = $price > 0 ? '' : 0 ; $worker = !empty($worker) ? '' : '' ; $ask_name = !empty($appointments->options['ask_name']) ? 'ask' : '' ; $ask_email = !empty($appointments->options['ask_email']) ? 'ask' : '' ; $ask_phone = !empty($appointments->options['ask_phone']) ? 'ask' : '' ; $ask_address = !empty($appointments->options['ask_address']) ? 'ask' : '' ; $ask_city = !empty($appointments->options['ask_city']) ? 'ask' : '' ; $ask_note = !empty($appointments->options['ask_note']) ? 'ask' : '' ; $ask_gcal = isset( $appointments->options["gcal"] ) && 'yes' == $appointments->options["gcal"] ? 'ask' : '' ; $reply_array = array( 'service' => $service, 'worker' => $worker, 'start' => $start, 'end' => $end, 'price' => $price, 'name' => $ask_name, 'email' => $ask_email, 'phone' => $ask_phone, 'address' => $ask_address, 'city' => $ask_city, 'note' => $ask_note, 'gcal' => $ask_gcal ); $reply_array = apply_filters('app_pre_confirmation_reply', $reply_array); die(json_encode($reply_array)); } /** * Save a CSV file of all appointments * @since 1.0.9 */ function export(){ global $appointments; $type = ! empty( $_POST['export_type'] ) ? $_POST['export_type'] : 'all'; $apps = array(); $args = array(); if ( 'selected' == $type && ! empty( $_POST['app'] ) ) { // selected appointments if ( $_POST['app'] ) { $args = array( 'app_id' => array_map( 'absint', $_POST['app'] ) ); } } else if ( 'type' == $type ) { $status = ! empty( $_POST['status'] ) ? $_POST['status'] : false; if ( 'active' === $status ) { $args = array( 'status' => array( 'confirmed', 'paid' ) ); } else if ( $status ) { $args = array( 'status' => $status ); } } $args = apply_filters( 'app-export-appointment-args', $args ); $apps = appointments_get_appointments( $args ); if ( empty( $apps ) || ! is_array( $apps ) ) { die( __( 'Nothing to download!', 'appointments' ) ); } $file = fopen('php://temp/maxmemory:'. (12*1024*1024), 'r+'); // Add field names to the file $columns = array_map( 'strtolower', apply_filters( 'app-export-columns', $appointments->db->get_col_info() ) ); fputcsv( $file, $columns ); foreach ( $apps as $app ) { $raw = $app; array_walk( $app, array( &$this, 'export_helper' ) ); $app = $this->sort_app_columns( $app, $columns ); $app = apply_filters( 'app-export-appointment', $app, $raw ); if ( ! empty( $app ) ) { fputcsv( $file, (array)$app ); } } $filename = "appointments_".date('F')."_".date('d')."_".date('Y').".csv"; //serve the file rewind($file); ob_end_clean(); //kills any buffers set by other plugins header('Content-Description: File Transfer'); header('Content-Type: text/csv'); header('Content-Disposition: attachment; filename="'.$filename.'"'); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); $output = stream_get_contents($file); //$output = $output . "\xEF\xBB\xBF"; // UTF-8 BOM header('Content-Length: ' . strlen($output)); fclose($file); die($output); } /** * Sorting the appointment columns so they match the csv columns. Usefull when locations addon enabled * @since 2.2.1 */ function sort_app_columns( $app, $columns ){ $sorted_app = array(); $app_array = array_change_key_case( (array)$app, CASE_LOWER ); foreach( $columns as $column ){ if( isset( $app_array[ $column ] ) ){ $sorted_app[ $column ] = $app_array[ $column ]; } else{ $sorted_app[ $column ] = ''; } } return $sorted_app; } /** * Helper function for export * @since 1.0.9 */ function export_helper( &$value, $key ) { global $appointments; if ( 'created' == $key || 'start' == $key || 'end' == $key ) $value = mysql2date( $appointments->datetime_format, $value ); else if ( 'user' == $key && $value ) { $userdata = get_userdata( $value ); if ( $userdata ) $value = $userdata->user_login; } else if ( 'service' == $key ) $value = $appointments->get_service_name( $value ); else if ( 'worker' == $key ) $value = appointments_get_worker_name( $value ); } /** * Control csv columns * @since 1.9.4.1 */ function app_export_columns( $cols ){ // Do not include the Location column in the export CSV if the add-on is not active if( !class_exists( 'App_Locations_LocationsWorker' ) ){ foreach( $cols as $key => $col ) { if( $col == 'location' ) unset( $cols[ $key ] ); } } return $cols; } /** * return security message, when checks fails * @since 2.2.2.1 */ private function security_check_die( $action, $query_arg = 'nonce' ) { $check = check_ajax_referer( $action, $query_arg, false ); if ( false !== $check ) { return; } $data = array( "error" => apply_filters( 'app_spam_message', __( 'Sorry, there was a problem with your request!', 'appointments') ), ); $data = json_encode( $data ); die( $data ); } }