public function index() { /** @var WP_Locale $wp_locale */ global $wp_locale; $this->enqueueStyles(array('backend' => array('css/bookly.main-backend.css', 'bootstrap/css/bootstrap.min.css', 'css/daterangepicker.css', 'css/bootstrap-select.min.css'))); $this->enqueueScripts(array('backend' => array('bootstrap/js/bootstrap.min.js' => array('jquery'), 'js/moment.min.js', 'js/daterangepicker.js' => array('jquery'), 'js/bootstrap-select.min.js'))); wp_localize_script('ab-daterangepicker.js', 'BooklyL10n', array('today' => __('Today', 'bookly'), 'yesterday' => __('Yesterday', 'bookly'), 'last_7' => __('Last 7 Days', 'bookly'), 'last_30' => __('Last 30 Days', 'bookly'), 'this_month' => __('This Month', 'bookly'), 'last_month' => __('Last Month', 'bookly'), 'custom_range' => __('Custom Range', 'bookly'), 'apply' => __('Apply', 'bookly'), 'cancel' => __('Cancel', 'bookly'), 'to' => __('To', 'bookly'), 'from' => __('From', 'bookly'), 'months' => array_values($wp_locale->month), 'days' => array_values($wp_locale->weekday_abbrev), 'startOfWeek' => (int) get_option('start_of_week'), 'mjsDateFormat' => AB_DateTimeUtils::convertFormat('date', AB_DateTimeUtils::FORMAT_MOMENT_JS))); $request = array('range' => date('Y-m-d', strtotime('-30 days')) . ' - ' . date('Y-m-d'), 'order_by' => 'created', 'sort_order' => 'desc'); $this->collection = $this->createQuery($request)->fetchArray(); $payments = array(); $customers = array(); $providers = array(); $services = array(); foreach ($this->collection as $key => $value) { $payments[] = $value['type']; $customers[] = $value['customer']; $providers[] = $value['provider']; $services[] = $value['service']; } $this->types = array_unique($payments); $this->customers = array_unique($customers); $this->providers = array_unique($providers); $this->services = array_unique($services); $this->render('index'); }
/** * Default Action */ public function index() { /** @var WP_Locale $wp_locale */ global $wp_locale; $this->enqueueStyles(array('frontend' => array('css/intlTelInput.css', 'css/ladda.min.css', 'css/bookly-main.css', 'css/ab-columnizer.css', 'css/picker.classic.css', 'css/picker.classic.date.css', 'css/ab-picker.css'), 'backend' => array('css/bookly.main-backend.css', 'bootstrap/css/bootstrap.min.css', 'bootstrap/css/bootstrap-editable.css'), 'wp' => array('wp-color-picker'), 'module' => array('css/appearance.css'))); $this->enqueueScripts(array('backend' => array('bootstrap/js/bootstrap.min.js' => array('jquery'), 'bootstrap/js/bootstrap-editable.min.js' => array('jquery')), 'frontend' => array('js/picker.js' => array('jquery'), 'js/picker.date.js' => array('jquery'), 'js/spin.min.js' => array('jquery'), 'js/ladda.min.js' => array('jquery'), 'js/intlTelInput.min.js' => array('ab-picker.date.js')), 'wp' => array('wp-color-picker'), 'module' => array('js/appearance.js' => array('jquery')))); wp_localize_script('ab-picker.date.js', 'BooklyL10n', array('today' => __('Today', 'bookly'), 'months' => array_values($wp_locale->month), 'days' => array_values($wp_locale->weekday_abbrev), 'nextMonth' => __('Next month', 'bookly'), 'prevMonth' => __('Previous month', 'bookly'), 'date_format' => AB_DateTimeUtils::convertFormat('date', AB_DateTimeUtils::FORMAT_PICKADATE), 'start_of_week' => (int) get_option('start_of_week'), 'intlTelInput_utils' => plugins_url('intlTelInput.utils.js', AB_PATH . '/frontend/resources/js/intlTelInput.utils.js'))); // Initialize steps (tabs). $this->steps = array(1 => get_option('ab_appearance_text_step_service'), 2 => get_option('ab_appearance_text_step_time'), 3 => get_option('ab_appearance_text_step_details'), 4 => get_option('ab_appearance_text_step_payment'), 5 => get_option('ab_appearance_text_step_done')); // Render general layout. $this->render('index'); }
/** * Get list of appointments. */ public function executeGetAppointments() { $response = array('appointments' => array(), 'total' => 0, 'pages' => 0, 'active_page' => 0); $page = intval($this->getParameter('page')); $sort = in_array($this->getParameter('sort'), array('staff_name', 'service_title', 'start_date', 'price')) ? $this->getParameter('sort') : 'start_date'; $order = in_array($this->getParameter('order'), array('asc', 'desc')) ? $this->getParameter('order') : 'asc'; $start_date = new DateTime($this->getParameter('date_start')); $start_date = $start_date->format('Y-m-d H:i:s'); $end_date = new DateTime($this->getParameter('date_end')); $end_date = $end_date->modify('+1 day')->format('Y-m-d H:i:s'); $items_per_page = 20; $total = AB_Appointment::query()->whereBetween('start_date', $start_date, $end_date)->count(); $pages = ceil($total / $items_per_page); if ($page < 1 || $page > $pages) { $page = 1; } if ($total) { $query = AB_CustomerAppointment::query('ca')->select('ca.id, ca.number_of_persons, ca.coupon_discount, ca.coupon_deduction, ca.appointment_id, st.full_name AS staff_name, s.title AS service_title, s.duration AS service_duration, c.name AS customer_name, a.start_date, ss.price')->leftJoin('AB_Appointment', 'a', 'a.id = ca.appointment_id')->leftJoin('AB_Service', 's', 's.id = a.service_id')->leftJoin('AB_Customer', 'c', 'c.id = ca.customer_id')->leftJoin('AB_Staff', 'st', 'st.id = a.staff_id')->leftJoin('AB_StaffService', 'ss', 'ss.staff_id = st.id AND ss.service_id = s.id')->whereBetween('a.start_date', $start_date, $end_date)->sortBy($sort)->order($order); // LIMIT. $start = ($page - 1) * $items_per_page; $query->offset($start)->limit($items_per_page); $rows = $query->fetchArray(); foreach ($rows as &$row) { if ($row['coupon_discount'] or $row['coupon_deduction']) { $coupon = new AB_Coupon(); $coupon->set('discount', $row['coupon_discount']); $coupon->set('deduction', $row['coupon_deduction']); $row['price'] = $coupon->apply($row['price']); } $row['price'] *= $row['number_of_persons']; $row['price'] = AB_Utils::formatPrice($row['price']); $row['start_date'] = AB_DateTimeUtils::formatDateTime($row['start_date']); $row['service_duration'] = AB_Service::durationToString($row['service_duration']); } // Populate response. $response['appointments'] = $rows; $response['total'] = $total; $response['pages'] = $pages; $response['active_page'] = $page; } wp_send_json_success($response); }
/** * Do replacements. * * @param $text * @param string $type * * @return string */ public function replace($text, $type = 'email') { // Company logo as <img> tag. $company_logo = ''; if (get_option('ab_settings_company_logo_url') != '') { $company_logo = sprintf('<img src="%s" alt="%s" />', esc_attr(get_option('ab_settings_company_logo_url')), esc_attr(get_option('ab_settings_company_name'))); } // Staff photo as <img> tag. $staff_photo = ''; if ($this->data['staff_photo'] != '') { $staff_photo = sprintf('<img src="%s" alt="%s" />', esc_attr($this->get('staff_photo')), esc_attr($this->get('staff_name'))); } // Cancel appointment URL and <a> tag. $cancel_appointment_url = admin_url('admin-ajax.php') . '?action=ab_cancel_appointment&token=' . $this->get('appointment_token'); $cancel_appointment = sprintf('<a href="%1$s">%1$s</a>', $cancel_appointment_url); // Codes. $codes = array('[[APPOINTMENT_TIME]]' => AB_DateTimeUtils::formatTime($this->get('appointment_datetime')), '[[APPOINTMENT_DATE]]' => AB_DateTimeUtils::formatDate($this->get('appointment_datetime')), '[[CUSTOM_FIELDS]]' => $this->get('custom_fields'), '[[CUSTOM_FIELDS_2C]]' => $this->get('custom_fields_2c'), '[[CLIENT_NAME]]' => $this->get('client_name'), '[[CLIENT_PHONE]]' => $this->get('client_phone'), '[[CLIENT_EMAIL]]' => $this->get('client_email'), '[[SERVICE_NAME]]' => $this->get('service_name'), '[[SERVICE_PRICE]]' => AB_Utils::formatPrice($this->get('service_price')), '[[STAFF_EMAIL]]' => $this->get('staff_email'), '[[STAFF_NAME]]' => $this->get('staff_name'), '[[STAFF_PHONE]]' => $this->get('staff_phone'), '[[STAFF_PHOTO]]' => $staff_photo, '[[CANCEL_APPOINTMENT]]' => $cancel_appointment, '[[CANCEL_APPOINTMENT_URL]]' => $cancel_appointment_url, '[[CATEGORY_NAME]]' => $this->get('category_name'), '[[COMPANY_ADDRESS]]' => $type == 'email' ? nl2br(get_option('ab_settings_company_address')) : get_option('ab_settings_company_address'), '[[COMPANY_LOGO]]' => $company_logo, '[[COMPANY_NAME]]' => get_option('ab_settings_company_name'), '[[COMPANY_PHONE]]' => get_option('ab_settings_company_phone'), '[[COMPANY_WEBSITE]]' => get_option('ab_settings_company_website'), '[[NEXT_DAY_AGENDA]]' => $this->get('next_day_agenda'), '[[TOMORROW_DATE]]' => date_i18n(get_option('date_format'), strtotime($this->get('appointment_datetime'))), '[[TOTAL_PRICE]]' => AB_Utils::formatPrice($this->get('service_price') * $this->get('number_of_persons')), '[[NUMBER_OF_PERSONS]]' => $this->get('number_of_persons'), '[[SITE_ADDRESS]]' => $this->get('site_address'), '[[NEW_USERNAME]]' => $this->get('new_username'), '[[NEW_PASSWORD]]' => $this->get('new_password')); return strtr($text, $codes); }
/** * Constructor. * * @param array $options */ public function __construct(array $options = array()) { // Handle widget options. $options = array_merge(array('use_empty' => true, 'empty_value' => null, 'exclude_last_slot' => false), $options); // Insert empty value if required. if ($options['use_empty']) { $this->values[null] = $options['empty_value']; } $ts_length = AB_BookingConfiguration::getTimeSlotLength(); $time_start = AB_StaffScheduleItem::WORKING_START_TIME; $time_end = AB_StaffScheduleItem::WORKING_END_TIME; if ($options['exclude_last_slot']) { $time_end -= $ts_length; } // Run the loop. while ($time_start <= $time_end) { $this->values[AB_DateTimeUtils::buildTimeString($time_start)] = AB_DateTimeUtils::formatTime($time_start); $time_start += $ts_length; } }
/** * Get array with appointments data for customer profile. * * @return array */ public function getAppointmentsForProfile() { $records = array(); if ($this->get('id')) { $result = $this->wpdb->get_results($this->wpdb->prepare('SELECT `c`.`name` `category`, `sv`.`title` `service`, `s`.`full_name` `staff`, `a`.`start_date` `start_date`, `ss`.`price` `price`, `ca`.`number_of_persons` `number_of_persons`, `ca`.`coupon_discount` `coupon_discount`, `ca`.`coupon_deduction` `coupon_deduction`, `ca`.`time_zone_offset` `time_zone_offset`, `ca`.`token` `token` FROM `' . AB_Appointment::getTableName() . '` `a` LEFT JOIN `' . AB_Staff::getTableName() . '` `s` ON `s`.`id` = `a`.`staff_id` LEFT JOIN `' . AB_Service::getTableName() . '` `sv` ON `sv`.`id` = `a`.`service_id` LEFT JOIN `' . AB_Category::getTableName() . '` `c` ON `c`.`id` = `sv`.`category_id` LEFT JOIN `' . AB_StaffService::getTableName() . '` `ss` ON `ss`.`staff_id` = `a`.`staff_id` AND `ss`.`service_id` = `a`.`service_id` INNER JOIN `' . AB_CustomerAppointment::getTableName() . '` `ca` ON `ca`.`appointment_id` = `a`.`id` AND `ca`.`customer_id` = %d', $this->get('id')), ARRAY_A); if ($result) { foreach ($result as $row) { if ($row['time_zone_offset'] !== null) { $row['start_date'] = AB_DateTimeUtils::applyTimeZoneOffset($row['start_date'], $row['time_zone_offset']); } if ($row['coupon_discount'] or $row['coupon_deduction']) { $coupon = new AB_Coupon(); $coupon->set('discount', $row['coupon_discount']); $coupon->set('deduction', $row['coupon_deduction']); $row['price'] = $coupon->apply($row['price']); } $row['price'] *= $row['number_of_persons']; unset($row['time_zone_offset'], $row['coupon_discount'], $row['coupon_deduction'], $row['number_of_persons']); $records[] = $row; } } } return $records; }
/** * @param string $field_name * @param bool $is_start * @return string */ public function renderField($field_name = 'ab_settings_monday', $is_start = true) { $ts_length = AB_BookingConfiguration::getTimeSlotLength(); $time_output = AB_StaffScheduleItem::WORKING_START_TIME; $time_end = AB_StaffScheduleItem::WORKING_END_TIME; $option_name = $field_name . ($is_start ? '_start' : '_end'); $class_name = $is_start ? 'select_start' : 'select_end'; $selected_value = get_option($option_name); $output = "<select class='form-control ab-auto-w {$class_name}' name={$option_name}>"; if ($is_start) { $output .= "<option value=''>" . __('OFF', 'bookly') . "</option>"; $time_end -= $ts_length; } while ($time_output <= $time_end) { $value = AB_DateTimeUtils::buildTimeString($time_output, false); $op_name = AB_DateTimeUtils::formatTime($time_output); $output .= "<option value='{$value}'" . selected($value, $selected_value, false) . ">{$op_name}</option>"; $time_output += $ts_length; } $output .= '</select>'; return $output; }
/** * Get list of customers. */ public function executeGetCustomers() { $wpdb = $this->getWpdb(); $response = array('customers' => array(), 'total' => 0, 'pages' => 0, 'active_page' => 0); $page = intval($this->getParameter('page')); $sort = in_array($this->getParameter('sort'), array('name', 'phone', 'email', 'notes', 'last_appointment', 'total_appointments', 'payments', 'wp_user')) ? $this->getParameter('sort') : 'name'; $order = in_array($this->getParameter('order'), array('asc', 'desc')) ? $this->getParameter('order') : 'asc'; $filter = $wpdb->_real_escape($this->getParameter('filter')); $items_per_page = 20; $total = AB_Customer::query()->count(); $pages = ceil($total / $items_per_page); if ($page < 1 || $page > $pages) { $page = 1; } if ($total) { $query = AB_Customer::query('c')->select('c.*, MAX(a.start_date) AS last_appointment, COUNT(a.id) AS total_appointments, COALESCE(SUM(p.total),0) AS payments, wpu.display_name AS wp_user')->leftJoin('AB_CustomerAppointment', 'ca', 'ca.customer_id = c.id')->leftJoin('AB_Appointment', 'a', 'a.id = ca.appointment_id')->leftJoin('AB_Payment', 'p', 'p.customer_appointment_id = ca.id')->tableJoin($wpdb->users, 'wpu', 'wpu.ID = c.wp_user_id'); // WHERE if ($filter !== '') { $query->whereLike('c.name', "%{$filter}%")->whereLike('c.phone', "%{$filter}%", 'OR')->whereLike('c.email', "%{$filter}%", 'OR'); } $data = $query->groupBy('c.id')->sortBy($sort)->order($order)->limit($items_per_page)->offset(($page - 1) * $items_per_page)->fetchArray(); array_walk($data, function (&$row) { if ($row['last_appointment']) { $row['last_appointment'] = AB_DateTimeUtils::formatDateTime($row['last_appointment']); } $row['payments'] = AB_Utils::formatPrice($row['payments']); }); // Populate response. $response['customers'] = $data; $response['total'] = $total; $response['pages'] = $pages; $response['active_page'] = $page; } wp_send_json_success($response); }
/** * Send scheduled notifications. * * @param int $type (C_NEXT_DAY_APPOINTMENT|C_FOLLOW_UP_ACTION) * @param AB_Notification $notification * @param AB_CustomerAppointment $ca * @return bool */ public static function sendFromCron($type, AB_Notification $notification, AB_CustomerAppointment $ca) { $result = false; list($codes, $staff, $appointment, $customer) = self::_prepareData($ca); switch ($type) { case self::CRON_NEXT_DAY_APPOINTMENT: // Client time zone offset. if ($ca->get('time_zone_offset') !== null) { $codes->set('appointment_datetime', AB_DateTimeUtils::applyTimeZoneOffset($appointment->get('start_date'), $ca->get('time_zone_offset'))); } // Send email notification to client. $result = self::_send($notification, $codes, $customer->get('email'), $customer->get('phone')); break; case self::CRON_FOLLOW_UP_EMAIL: // Client time zone offset. if ($ca->get('time_zone_offset') !== null) { $codes->set('appointment_datetime', AB_DateTimeUtils::applyTimeZoneOffset($appointment->get('start_date'), $ca->get('time_zone_offset'))); } // Send email notification to client. $result = self::_send($notification, $codes, $customer->get('email'), $customer->get('phone')); break; } return $result; }
/** * Get item data for cart. * * @param $other_data * @param $cart_item * * @return array */ function getItemData($other_data, $cart_item) { if (isset($cart_item['bookly'])) { $info_name = get_option('ab_woocommerce_cart_info_name'); $info_value = get_option('ab_woocommerce_cart_info_value'); $staff = new AB_Staff(); $staff->load($cart_item['bookly']['staff_ids'][0]); $service = new AB_Service(); $service->load($cart_item['bookly']['service_id']); $info_value = strtr($info_value, array('[[APPOINTMENT_TIME]]' => AB_DateTimeUtils::formatTime($cart_item['bookly']['appointment_datetime']), '[[APPOINTMENT_DATE]]' => AB_DateTimeUtils::formatDate($cart_item['bookly']['appointment_datetime']), '[[CATEGORY_NAME]]' => $service->getCategoryName(), '[[SERVICE_NAME]]' => $service->getTitle(), '[[SERVICE_PRICE]]' => $service->get('price'), '[[STAFF_NAME]]' => $staff->get('full_name'))); $other_data[] = array('name' => $info_name, 'value' => $info_value); } return $other_data; }
} // Exit if accessed directly $start_of_week = (int) get_option('start_of_week'); ?> <form method="post" action="<?php echo esc_url(add_query_arg('type', '_hours')); ?> " class="ab-settings-form" id="business-hours"> <?php $form = new AB_BusinessHoursForm(); ?> <table class="form-inline"> <tbody> <?php for ($i = 0; $i < 7; $i++) { $day = strtolower(AB_DateTimeUtils::getWeekDayByNumber(($i + $start_of_week) % 7)); ?> <tr> <td> <label><?php _e(ucfirst($day)); ?> </label> </td> <td> <?php echo $form->renderField('ab_settings_' . $day); ?> <span> <?php _e('to', 'bookly'); ?>
esc_attr_e(get_option('ab_appearance_text_label_finish_by'), 'ab'); ?> " class="ab_editable" id="ab-text-label-finish_by" data-type="text" data-pk="1"><?php esc_html_e(get_option('ab_appearance_text_label_finish_by'), 'ab'); ?> </label> <div> <select class="select-list ab-select-time-to"> <?php for ($i = 28800; $i <= 64800; $i += 3600) { ?> <option<?php selected($i == 64800); ?> ><?php echo AB_DateTimeUtils::formatTime($i); ?> </option> <?php } ?> </select> </div> </div> </div> </div> <div class="ab-row-fluid ab-nav-steps last-row ab-clear"> <button class="ab-right ab-mobile-prev-step ab-btn ab-none ladda-button"> <span><?php _e('Back', 'bookly'); ?>
public function executeStaffScheduleHandleBreak() { $start_time = $this->getParameter('start_time'); $end_time = $this->getParameter('end_time'); $working_start = $this->getParameter('working_start'); $working_end = $this->getParameter('working_end'); if (strtotime(date('Y-m-d ' . $start_time)) >= strtotime(date('Y-m-d ' . $end_time))) { wp_send_json(array('success' => false, 'error_msg' => __('The start time must be less than the end one', 'bookly'))); } $staffScheduleItem = new AB_StaffScheduleItem(); $staffScheduleItem->load($this->getParameter('staff_schedule_item_id')); $break_id = $this->getParameter('break_id', 0); $in_working_time = $working_start <= $start_time && $start_time <= $working_end && $working_start <= $end_time && $end_time <= $working_end; if (!$in_working_time || !$staffScheduleItem->isBreakIntervalAvailable($start_time, $end_time, $break_id)) { wp_send_json(array('success' => false, 'error_msg' => __('The requested interval is not available', 'bookly'))); } $formatted_interval_start = AB_DateTimeUtils::formatTime($start_time); $formatted_interval_end = AB_DateTimeUtils::formatTime($end_time); $formatted_interval = $formatted_interval_start . ' - ' . $formatted_interval_end; if ($break_id) { $break = new AB_ScheduleItemBreak(); $break->load($break_id); $break->set('start_time', $start_time); $break->set('end_time', $end_time); $break->save(); wp_send_json(array('success' => true, 'new_interval' => $formatted_interval)); } else { $this->form = new AB_StaffScheduleItemBreakForm(); $this->form->bind($this->getPostParameters()); $staffScheduleItemBreak = $this->form->save(); if ($staffScheduleItemBreak) { $breakStart = new AB_TimeChoiceWidget(array('use_empty' => false)); $break_start_choices = $breakStart->render('', $start_time, array('class' => 'break-start', 'data-default_value' => AB_StaffScheduleItem::WORKING_START_TIME)); $breakEnd = new AB_TimeChoiceWidget(array('use_empty' => false)); $break_end_choices = $breakEnd->render('', $end_time, array('class' => 'break-end', 'data-default_value' => date('H:i:s', strtotime(AB_StaffScheduleItem::WORKING_START_TIME . ' + 1 hour')))); wp_send_json(array('success' => true, 'item_content' => $this->render('_break', array('staff_schedule_item_break_id' => $staffScheduleItemBreak->get('id'), 'formatted_interval' => $formatted_interval, 'break_start_choices' => $break_start_choices, 'break_end_choices' => $break_end_choices), false))); } else { wp_send_json(array('success' => false, 'error_msg' => __('Error adding the break interval', 'bookly'))); } } }
<tbody> <?php foreach ($schedule_items as $item) { ?> <?php $day_is_not_available = null === $item->get('start_time'); ?> <tr data-id="<?php echo $item->get('day_index'); ?> " data-staff_schedule_item_id="<?php echo $item->get('id'); ?> " class="staff-schedule-item-row"> <td class="first"><label><?php _e(AB_DateTimeUtils::getWeekDayByNumber($item->get('day_index') - 1)); ?> </label></td> <td class="working-intervals"> <?php $workingStart = new AB_TimeChoiceWidget(array('empty_value' => __('OFF', 'bookly'), 'exclude_last_slot' => true)); $working_start_choices = $workingStart->render("start_time[{$item->get('day_index')}]", $item->get('start_time'), array('class' => 'working-start form-control')); $workingEnd = new AB_TimeChoiceWidget(array('use_empty' => false)); $working_end_choices_attributes = array('class' => 'working-end form-control hide-on-non-working-day'); if ($day_is_not_available) { $working_end_choices_attributes['style'] = 'display:none'; } $working_end_choices = $workingEnd->render("end_time[{$item->get('day_index')}]", $item->get('end_time'), $working_end_choices_attributes); echo $working_start_choices . ' <span class="hide-on-non-working-day"' . ($day_is_not_available ? ' style="display: none"' : '') . '>' . __('to', 'bookly') . '</span> ' . $working_end_choices; ?> <input type="hidden" name="days[<?php
/** * Get data needed for appointment form initialisation. */ public function executeGetDataForAppointmentForm() { $result = array('staff' => array(), 'customers' => array(), 'custom_fields' => array(), 'time' => array(), 'time_interval' => get_option('ab_settings_time_slot_length') * 60); // Staff list. $staff_members = AB_Utils::isCurrentUserAdmin() ? AB_Staff::query()->sortBy('position')->find() : AB_Staff::query()->where('wp_user_id', get_current_user_id())->find(); /** @var AB_Staff $staff_member */ foreach ($staff_members as $staff_member) { $services = array(); foreach ($staff_member->getStaffServices() as $staff_service) { $services[] = array('id' => $staff_service->service->get('id'), 'title' => sprintf('%s (%s)', $staff_service->service->get('title'), AB_Service::durationToString($staff_service->service->get('duration'))), 'duration' => $staff_service->service->get('duration'), 'capacity' => $staff_service->get('capacity')); } $result['staff'][] = array('id' => $staff_member->get('id'), 'full_name' => $staff_member->get('full_name'), 'services' => $services); } // Customers list. foreach (AB_Customer::query()->sortBy('name')->find() as $customer) { $name = $customer->get('name'); if ($customer->get('email') != '' || $customer->get('phone') != '') { $name .= ' (' . trim($customer->get('email') . ', ' . $customer->get('phone'), ', ') . ')'; } $result['customers'][] = array('id' => $customer->get('id'), 'name' => $name, 'custom_fields' => array(), 'number_of_persons' => 1); } // Time list. $ts_length = AB_BookingConfiguration::getTimeSlotLength(); $time_start = AB_StaffScheduleItem::WORKING_START_TIME; $time_end = AB_StaffScheduleItem::WORKING_END_TIME; // Run the loop. while ($time_start <= $time_end) { $result['time'][] = array('value' => AB_DateTimeUtils::buildTimeString($time_start, false), 'title' => AB_DateTimeUtils::formatTime($time_start)); $time_start += $ts_length; } wp_send_json($result); }
/** * Render info text into a variable. * * @param string $text * @param AB_UserBookingData $userData * @param int $preset_price * * @return string */ private function _prepareInfoText($text, $userData, $preset_price = null) { if (empty($this->replacement)) { $service = $userData->getService(); $category_name = $service->getCategoryName(); $staff_name = $userData->getStaffName(); $price = $preset_price === null ? $userData->getServicePrice() : $preset_price; $number_of_persons = $userData->get('number_of_persons'); $service_date = AB_DateTimeUtils::formatDate($userData->get('appointment_datetime')); if (get_option('ab_settings_use_client_time_zone')) { $service_time = AB_DateTimeUtils::formatTime(AB_DateTimeUtils::applyTimeZoneOffset($userData->get('appointment_datetime'), $userData->get('time_zone_offset'))); } else { $service_time = AB_DateTimeUtils::formatTime($userData->get('appointment_datetime')); } $this->replacement = array('[[STAFF_NAME]]' => '<b>' . $staff_name . '</b>', '[[SERVICE_NAME]]' => '<b>' . $service->get('title') . '</b>', '[[CATEGORY_NAME]]' => '<b>' . $category_name . '</b>', '[[NUMBER_OF_PERSONS]]' => '<b>' . $number_of_persons . '</b>', '[[SERVICE_TIME]]' => '<b>' . $service_time . '</b>', '[[SERVICE_DATE]]' => '<b>' . $service_date . '</b>', '[[SERVICE_PRICE]]' => '<b>' . AB_Utils::formatPrice($price) . '</b>', '[[TOTAL_PRICE]]' => '<b>' . AB_Utils::formatPrice($price * $number_of_persons) . '</b>', '[[LOGIN_FORM]]' => get_current_user_id() == 0 ? $this->render('_login_form', array(), false) : ''); } return strtr(nl2br($text), $this->replacement); }
/** * Fetches ids of the available days + the available time range * For the 1st step of the booking wizard * * @return array */ public function fetchAvailableWorkDaysAndTime() { /** @var WP_Locale $wp_locale */ global $wp_locale; $schedule_items = AB_StaffScheduleItem::query('ssi')->select('GROUP_CONCAT( DISTINCT ssi.day_index ORDER BY ssi.day_index ) AS available_day_ids, SUBSTRING_INDEX(MIN(ssi.start_time), \':\', 2) AS min_start_time, SUBSTRING_INDEX(MAX(ssi.end_time), \':\', 2) AS max_end_time')->whereNot('ssi.start_time', null)->fetchArray(); $data = current($schedule_items); $result = array('available_days' => array(), 'time_range' => array()); if ($data['available_day_ids']) { $wp_week_start_day = (int) get_option('start_of_week'); $available_day_ids = explode(',', $data['available_day_ids']); $week_days = array_values($wp_locale->weekday_abbrev); if ($wp_week_start_day >= $available_day_ids[0]) { $list_start = array_slice($week_days, $wp_week_start_day, 7, TRUE); $list_end = array_slice($week_days, 0, $wp_week_start_day, TRUE); $week_days = $list_start + $list_end; } foreach ($week_days as $day_id => $day_name) { if (in_array($day_id + 1, $available_day_ids)) { $result['available_days'][$day_id + 1] = $day_name; } } } if ($data['min_start_time'] && $data['max_end_time']) { $start_timestamp = strtotime(sprintf("1970-01-01 %s", $data['min_start_time'])); $end_timestamp = strtotime(sprintf("1970-01-01 %s", $data['max_end_time'])); $now_timestamp = $start_timestamp; $now_timestamp_print = $start_timestamp; $end_timestamp_print = $end_timestamp; if ($this->client_timezone_offset !== false) { $now_timestamp_print -= ($this->client_timezone_offset + get_option('gmt_offset')) * 3600; $end_timestamp_print -= ($this->client_timezone_offset + get_option('gmt_offset')) * 3600; } while ($now_timestamp <= $end_timestamp) { $result['time_range'][AB_DateTimeUtils::buildTimeString($now_timestamp, false)] = AB_DateTimeUtils::formatTime($now_timestamp_print); // The next value will be rounded to integer number of hours, i.e. e.g. 8:00, 9:00, 10:00 and so on. $now_timestamp = $this->roundTime($now_timestamp + 30 * 60); $now_timestamp_print = $this->roundTime($now_timestamp_print + 30 * 60); } // The last value should always be the end time. $result['time_range'][AB_DateTimeUtils::buildTimeString($end_timestamp, false)] = AB_DateTimeUtils::formatTime($end_timestamp_print); } return $result; }
/** * Get SMS list. * * @param null $start_date * @param null $end_date * @return array|mixed */ public function getSmsList($start_date = null, $end_date = null) { if ($this->token) { $response = $this->sendGetRequest(self::GET_SMS_LIST, array('start_date' => $start_date, 'end_date' => $end_date)); if ($response) { array_walk($response->list, function (&$item) { $date_time = AB_DateTimeUtils::UTCToWPTimeZone($item->datetime); $item->date = AB_DateTimeUtils::formatDate($date_time); $item->time = AB_DateTimeUtils::formatTime($date_time); $item->message = nl2br($item->message); $item->phone = '+' . $item->phone; $item->charge = rtrim($item->charge, '0'); switch ($item->status) { case 1: case 10: $item->status = __('Queued', 'bookly'); $item->charge = '$' . $item->charge; break; case 2: case 16: $item->status = __('Error', 'bookly'); $item->charge = ''; break; case 3: $item->status = __('Out of credit', 'bookly'); $item->charge = ''; break; case 4: $item->status = __('Country out of service', 'bookly'); $item->charge = ''; break; case 11: $item->status = __('Sending', 'bookly'); $item->charge = '$' . $item->charge; break; case 12: $item->status = __('Sent', 'bookly'); $item->charge = '$' . $item->charge; break; case 13: $item->status = __('Delivered', 'bookly'); $item->charge = '$' . $item->charge; break; case 14: $item->status = __('Failed', 'bookly'); $item->charge = '$' . $item->charge; break; case 15: $item->status = __('Undelivered', 'bookly'); $item->charge = '$' . $item->charge; break; default: $item->status = __('Error', 'bookly'); $item->charge = ''; } }); return $response; } } return array(); }
public function executeGetSmsList() { $sms = new AB_SMS(); if ($this->hasParameter('range')) { $dates = explode(' - ', $this->getParameter('range'), 2); $start = AB_DateTimeUtils::applyTimeZoneOffset($dates[0], 0); $end = AB_DateTimeUtils::applyTimeZoneOffset(date('Y-m-d', strtotime('+1 day', strtotime($dates[1]))), 0); } else { $start = AB_DateTimeUtils::applyTimeZoneOffset(date('Y-m-d', strtotime('first day of this month')), 0); $end = AB_DateTimeUtils::applyTimeZoneOffset(date('Y-m-d', strtotime('first day of next month')), 0); } $list = $sms->getSmsList($start, $end); if (empty($list)) { wp_send_json_error(); } else { wp_send_json($list); } }
?> , form_id : <?php echo json_encode($form_id); ?> , start_of_week : <?php echo (int) get_option('start_of_week'); ?> , date_min : <?php echo json_encode(AB_BookingConfiguration::getDateMin()); ?> , date_format : <?php echo json_encode(AB_DateTimeUtils::convertFormat('date', AB_DateTimeUtils::FORMAT_PICKADATE)); ?> , custom_fields : <?php echo get_option('ab_custom_fields'); ?> , show_calendar : <?php echo intval(get_option('ab_appearance_show_calendar')); ?> , woocommerce : <?php echo intval(get_option('ab_woocommerce') && get_option('ab_woocommerce_product') && class_exists('WooCommerce')); ?> , woocommerce_cart_url : <?php
<span style="display: <?php echo $display; ?> "> <?php _e('breaks:', 'bookly'); ?> </span> </td> <td class="breaks-list-content"> <?php foreach ($breaks_list as $break_interval) { ?> <?php $formatted_interval_start = AB_DateTimeUtils::formatTime($break_interval['start_time']); $formatted_interval_end = AB_DateTimeUtils::formatTime($break_interval['end_time']); $formatted_interval = $formatted_interval_start . ' - ' . $formatted_interval_end; if (isset($default_breaks)) { $default_breaks['breaks'][] = array('start_time' => $break_interval['start_time'], 'end_time' => $break_interval['end_time'], 'staff_schedule_item_id' => $break_interval['staff_schedule_item_id']); } $breakStart = new AB_TimeChoiceWidget(array('use_empty' => false)); $break_start_choices = $breakStart->render('', $break_interval['start_time'], array('class' => 'break-start form-control')); $breakEnd = new AB_TimeChoiceWidget(array('use_empty' => false)); $break_end_choices = $breakEnd->render('', $break_interval['end_time'], array('class' => 'break-end form-control')); $this->render('_break', array('staff_schedule_item_break_id' => $break_interval['id'], 'formatted_interval' => $formatted_interval, 'break_start_choices' => $break_start_choices, 'break_end_choices' => $break_end_choices)); ?> <?php } ?> </td> </tr>
<?php foreach ($columns as $column) { ?> <?php switch ($column) { case 'date': ?> <td class="ab-column-date"><?php echo AB_DateTimeUtils::formatDate($a['start_date']); ?> </td><?php break; case 'time': ?> <td class="ab-column-time"><?php echo AB_DateTimeUtils::formatTime($a['start_date']); ?> </td><?php break; case 'price': ?> <td class="ab-column-price"><?php echo AB_Utils::formatPrice($a['price']); ?> </td><?php break; case 'cancel': ?> <td class="ab-column-cancel"> <?php if ($a['start_date'] > current_time('mysql')) {