/**
  * Get list of customers.
  */
 public function executeGetCustomers()
 {
     $wpdb = $this->getWpdb();
     $response = array('status' => 'ok', 'data' => 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')) ? $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 = $wpdb->get_var('SELECT COUNT(*) FROM `ab_customer`');
     $pages = ceil($total / $items_per_page);
     if ($page < 1 || $page > $pages) {
         $page = 1;
     }
     if ($total) {
         $query = "SELECT `c`.*, MAX(`a`.`start_date`) AS `last_appointment`, COUNT(`a`.`id`) AS `total_appointments`,  COALESCE(SUM(`p`.`total`),0) AS `payments`\n                        FROM `ab_customer` `c`\n                        LEFT JOIN `ab_customer_appointment` `ca` ON `ca`.`customer_id` = `c`.`id`\n                        LEFT JOIN `ab_appointment` `a` ON `a`.`id` = `ca`.`appointment_id`\n                        LEFT JOIN `ab_payment` `p` ON `p`.`appointment_id` = `a`.`id` and `p`.`customer_id`  = `c`.`id`";
         // WHERE
         if ($filter !== '') {
             $query .= " WHERE `c`.`name` LIKE '%{$filter}%' OR `c`.`phone` LIKE '%{$filter}%' OR `c`.`email` LIKE '%{$filter}%'";
         }
         // GROUP BY
         $query .= ' GROUP BY `c`.`id`';
         // ORDER BY
         $query .= " ORDER BY {$sort} {$order}";
         // LIMIT
         $start = ($page - 1) * $items_per_page;
         $query .= " LIMIT {$start}, {$items_per_page}";
         $data = $wpdb->get_results($query);
         array_walk($data, function ($row) {
             $row->last_appointment = AB_CommonUtils::getFormattedDateTime($row->last_appointment);
             $row->payments = AB_CommonUtils::formatPrice($row->payments);
         });
         // Populate response.
         $response['data']['customers'] = $data;
         $response['data']['total'] = $total;
         $response['data']['pages'] = $pages;
         $response['data']['active_page'] = $page;
     }
     echo json_encode($response);
     exit(0);
 }
 /**
  * Constructor.
  */
 public function __construct()
 {
     global $wpdb;
     // Select all services (with categories and staff members)
     // which have at least one staff member assigned.
     $rows = $wpdb->get_results('
         SELECT
             `c`.`id`         AS `category_id`,
             `c`.`name`       AS `category_name`,
             `s`.`id`         AS `service_id`,
             `s`.`title`      AS `service_name`,
             `st`.`id`        AS `staff_id`,
             `st`.`full_name` AS `staff_name`,
             `ss`.`price`     AS `price`
         FROM `ab_service` `s`
             INNER JOIN `ab_staff_service` `ss` ON `s`.`id` = `ss`.`service_id`
             LEFT JOIN `ab_category` `c`        ON `s`.`category_id` = `c`.`id`
             LEFT JOIN `ab_staff` `st`          ON `ss`.`staff_id` = `st`.`id`
         ORDER BY `service_name`
     ', ARRAY_A);
     foreach ($rows as $row) {
         if (!isset($this->services[$row['service_id']])) {
             $this->services[$row['service_id']] = array('id' => $row['service_id'], 'name' => $row['service_name'], 'category_id' => $row['category_id'], 'staff' => array());
         }
         if (!isset($this->staff[$row['staff_id']])) {
             $this->staff[$row['staff_id']] = array('id' => $row['staff_id'], 'name' => $row['staff_name'], 'category_id' => $row['category_id'], 'service_id' => $row['service_id']);
         }
         if ($row['category_id'] && !isset($this->categories[$row['category_id']])) {
             $this->categories[$row['category_id']] = array('id' => $row['category_id'], 'name' => $row['category_name'], 'services' => array());
         } else {
             if (!$row['category_id'] && !isset($this->categories[0])) {
                 $this->categories[0] = array('id' => 0, 'name' => __('Uncategorized', 'ab'), 'services' => array());
             }
         }
         if (!isset($this->services[$row['service_id']]['staff'][$row['staff_id']])) {
             $staff_member = $this->staff[$row['staff_id']];
             $staff_member['categories'] = array();
             $staff_member['services'] = array();
             if (self::isPaymentDisabled() == false) {
                 $staff_member['name'] .= ' (' . AB_CommonUtils::formatPrice($row['price']) . ')';
             }
             $this->services[$row['service_id']]['staff'][$row['staff_id']] = $staff_member;
         }
         if (!isset($this->staff[$row['staff_id']]['services'][$row['service_id']])) {
             $service = $this->services[$row['service_id']];
             $service['staff'] = array();
             $this->staff[$row['staff_id']]['services'][$row['service_id']] = $service;
         }
         if (!isset($this->staff[$row['staff_id']]['categories'][$row['category_id']])) {
             $category = $this->categories[$row['category_id']];
             $category['services'] = array();
             $category['staff'] = array();
             $this->staff[$row['staff_id']]['categories'][$row['category_id']] = $category;
         }
         if (!isset($this->categories[intval($row['category_id'])]['staff'][$row['staff_id']])) {
             $staff_member = $this->staff[$row['staff_id']];
             $staff_member['categories'] = array();
             $staff_member['services'] = array();
             $this->categories[intval($row['category_id'])]['staff'][$row['staff_id']] = $staff_member;
         }
         if (!isset($this->categories[intval($row['category_id'])]['services'][$row['service_id']])) {
             $service = $this->services[$row['service_id']];
             $service['staff'] = array();
             $this->categories[intval($row['category_id'])]['services'][$row['service_id']] = $service;
         }
     }
 }
 /**
  * Render info text into a variable.
  *
  * @param int $booking_step
  * @param AB_UserBookingData $userData
  * @param int $preset_price
  *
  * @return string
  */
 private function _prepareInfoText($booking_step, $userData, $preset_price = null)
 {
     if ($userData->hasData()) {
         $service_name = $userData->getServiceName();
         $category_name = $userData->getCategoryName();
         $staff_name = $userData->getStaffName();
         $price = $preset_price === null ? $userData->getServicePrice() : $preset_price;
         // Convenient Time
         if ($booking_step === 2) {
             $replacement = array('[[STAFF_NAME]]' => '<b>' . $staff_name . '</b>', '[[SERVICE_NAME]]' => '<b>' . $service_name . '</b>', '[[CATEGORY_NAME]]' => '<b>' . $category_name . '</b>');
             return str_replace(array_keys($replacement), array_values($replacement), nl2br(esc_html(get_option('ab_appearance_text_info_second_step'))));
         }
         // Your Details
         if ($booking_step === 3) {
             if (get_option('ab_settings_use_client_time_zone') && $this->getParameter('client_time_zone_offset')) {
                 $service_time = date_i18n(get_option('time_format'), strtotime($userData->getBookedDatetime()) - ($this->getParameter('client_time_zone_offset') + get_option('gmt_offset') * 60) * 60);
             } else {
                 $service_time = date_i18n(get_option('time_format'), strtotime($userData->getBookedDatetime()));
             }
             $service_date = date_i18n(get_option('date_format'), strtotime($userData->getBookedDatetime()));
             $replacement = array('[[STAFF_NAME]]' => '<b>' . $staff_name . '</b>', '[[SERVICE_NAME]]' => '<b>' . $service_name . '</b>', '[[CATEGORY_NAME]]' => '<b>' . $category_name . '</b>', '[[SERVICE_TIME]]' => '<b>' . $service_time . '</b>', '[[SERVICE_DATE]]' => '<b>' . $service_date . '</b>', '[[SERVICE_PRICE]]' => '<b>' . AB_CommonUtils::formatPrice($price) . '</b>');
             return str_replace(array_keys($replacement), array_values($replacement), nl2br(esc_html(get_option('ab_appearance_text_info_third_step'))));
         }
         // Coupon Text
         if ($booking_step === 4) {
             $replacement = array('[[SERVICE_PRICE]]' => '<b>' . AB_CommonUtils::formatPrice($price) . '</b>');
             return str_replace(array_keys($replacement), array_values($replacement), nl2br(esc_html(get_option('ab_appearance_text_info_coupon'))));
         }
     }
     return '';
 }