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;
     }
 }
Beispiel #6
0
 /**
  * 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;
 }
Beispiel #11
0
}
// 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>&nbsp;<?php 
    _e('to', 'bookly');
    ?>
Beispiel #12
0
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')));
         }
     }
 }
Beispiel #14
0
                <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;
 }
Beispiel #18
0
 /**
  * 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();
 }
Beispiel #19
0
 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);
     }
 }
Beispiel #20
0
?>
,
            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 
Beispiel #21
0
            <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>
Beispiel #22
0
                        <?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')) {