示例#1
0
 /**
  * Send the Express Checkout NVP request
  *
  * @param $form_id
  * @throws Exception
  */
 public function send_EC_Request($form_id)
 {
     if (!session_id()) {
         @session_start();
     }
     if (!count($this->products)) {
         throw new Exception('Products not found!');
     }
     $total = 0;
     // create the data to send on PayPal
     $data = '&SOLUTIONTYPE=' . 'Sole' . '&PAYMENTREQUEST_0_PAYMENTACTION=' . 'Sale' . '&PAYMENTREQUEST_0_CURRENCYCODE=' . urlencode(get_option('ab_paypal_currency')) . '&RETURNURL=' . urlencode(add_query_arg(array('action' => 'ab-paypal-returnurl', 'ab_fid' => $form_id), AB_Utils::getCurrentPageURL())) . '&CANCELURL=' . urlencode(add_query_arg(array('action' => 'ab-paypal-cancelurl', 'ab_fid' => $form_id), AB_Utils::getCurrentPageURL()));
     foreach ($this->products as $k => $product) {
         $data .= "&L_PAYMENTREQUEST_0_NAME{$k}=" . urlencode($product->name) . "&L_PAYMENTREQUEST_0_DESC{$k}=" . urlencode($product->desc) . "&L_PAYMENTREQUEST_0_AMT{$k}=" . urlencode($product->price) . "&L_PAYMENTREQUEST_0_QTY{$k}=" . urlencode($product->qty);
         $total += $product->qty * $product->price;
     }
     $data .= "&PAYMENTREQUEST_0_AMT=" . urlencode($total) . "&PAYMENTREQUEST_0_ITEMAMT=" . urlencode($total);
     // send the request to PayPal
     $response = self::sendNvpRequest('SetExpressCheckout', $data);
     //Respond according to message we receive from Paypal
     if ("SUCCESS" == strtoupper($response["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($response["ACK"])) {
         $_SESSION['bookly'][$form_id]['paypal_response'] = array($response, $form_id);
         $paypalurl = 'https://www' . get_option('ab_paypal_ec_mode') . '.paypal.com/cgi-bin/webscr?cmd=_express-checkout&useraction=commit&token=' . urldecode($response["TOKEN"]);
         header('Location: ' . $paypalurl);
         exit;
     } else {
         header('Location: ' . wp_sanitize_redirect(add_query_arg(array('action' => 'ab-paypal-errorurl', 'ab_fid' => $form_id, 'error_msg' => $response["L_LONGMESSAGE0"]), AB_Utils::getCurrentPageURL())));
         exit;
     }
 }
 /**
  * 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);
 }
 /**
  * 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);
 }
 /**
  * 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($wpdb->prepare('
         SELECT
             IFNULL(`c`.`id`,0)    AS `category_id`,
             IFNULL(`c`.`name`,%s) AS `category_name`,
             `c`.`position`        AS `category_position`,
             `s`.`id`              AS `service_id`,
             `s`.`position`        AS `service_position`,
             `s`.`title`           AS `service_name`,
             `st`.`id`             AS `staff_id`,
             `st`.`position`       AS `staff_position`,
             `st`.`full_name`      AS `staff_name`,
             `ss`.`capacity`       AS `capacity`,
             `ss`.`price`          AS `price`
         FROM `' . AB_Service::getTableName() . '` `s`
             INNER JOIN `' . AB_StaffService::getTableName() . '` `ss` ON `s`.`id` = `ss`.`service_id`
             LEFT JOIN `' . AB_Category::getTableName() . '` `c`        ON `s`.`category_id` = `c`.`id`
             LEFT JOIN `' . AB_Staff::getTableName() . '` `st`          ON `ss`.`staff_id` = `st`.`id`
         ORDER BY `service_name`
     ', __('Uncategorized', 'bookly')), ARRAY_A);
     foreach ($rows as $row) {
         if (!isset($this->services[$row['service_id']])) {
             $this->services[$row['service_id']] = array('id' => $row['service_id'], 'name' => AB_Utils::getTranslatedString('service_' . $row['service_id'], $row['service_name']), 'category_id' => $row['category_id'], 'staff' => array(), 'max_capacity' => $row['capacity'], 'position' => $row['service_position']);
         } else {
             if ($this->services[$row['service_id']]['max_capacity'] < $row['capacity']) {
                 // Detect the max capacity for each service
                 //(it is the max capacity from all staff members who provides this service).
                 $this->services[$row['service_id']]['max_capacity'] = $row['capacity'];
             }
         }
         if (!isset($this->staff[$row['staff_id']])) {
             $this->staff[$row['staff_id']] = array('id' => $row['staff_id'], 'name' => AB_Utils::getTranslatedString('staff_' . $row['staff_id'], $row['staff_name']), 'services' => array(), 'position' => $row['staff_position']);
         }
         if ($row['category_id'] != '' && !isset($this->categories[$row['category_id']])) {
             $this->categories[$row['category_id']] = array('id' => $row['category_id'], 'name' => AB_Utils::getTranslatedString('category_' . $row['category_id'], $row['category_name']), 'services' => array(), 'position' => $row['category_position']);
         }
         if (!isset($this->services[$row['service_id']]['staff'][$row['staff_id']])) {
             $staff_member = $this->staff[$row['staff_id']];
             unset($staff_member['services']);
             if (self::isPaymentDisabled() == false) {
                 $staff_member['name'] .= ' (' . AB_Utils::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']];
             unset($service['staff']);
             $service['max_capacity'] = $row['capacity'];
             $this->staff[$row['staff_id']]['services'][$row['service_id']] = $service;
         }
         if (!isset($this->categories[intval($row['category_id'])]['staff'][$row['staff_id']])) {
             $staff_member = $this->staff[$row['staff_id']];
             unset($staff_member['services']);
             $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']];
             unset($service['staff']);
             $this->categories[intval($row['category_id'])]['services'][$row['service_id']] = $service;
         }
     }
 }
示例#5
0
            <li class="ab-step-tabs<?php 
    if ($booking_step >= 4) {
        ?>
 active<?php 
    }
    ?>
">
                <a href="javascript:void(0)">4. <?php 
    echo AB_Utils::getTranslatedOption('ab_appearance_text_step_payment');
    ?>
</a>
                <div class=step></div>
            </li>
            <li class="ab-step-tabs<?php 
    if ($booking_step >= 5) {
        ?>
 active<?php 
    }
    ?>
 ab-last">
                <a href="javascript:void(0)">5. <?php 
    echo AB_Utils::getTranslatedOption('ab_appearance_text_step_done');
    ?>
</a>
                <div class=step></div>
            </li>
        <?php 
}
?>
    </ul>
</div>
示例#6
0
    _e('Title', 'bookly');
    ?>
</th>
                <th width="80"><?php 
    _e('Duration', 'bookly');
    ?>
</th>
                <th width="80"><?php 
    _e('Price', 'bookly');
    ?>
</th>
                <th width="140"><?php 
    _e('Capacity', 'bookly');
    ?>
                <?php 
    AB_Utils::popover(__('The maximum number of customers allowed to book the service for the certain time period.', 'bookly'), 'width:16px;margin-left:0;');
    ?>
                <th><?php 
    _e('Staff', 'bookly');
    ?>
</th>
                <th><?php 
    _e('Category', 'bookly');
    ?>
</th>
                <th class="last">&nbsp;</th>
            </tr>
        </thead>
        <tbody>
        <?php 
    foreach ($service_collection as $i => $service) {
示例#7
0
                </td>
                <td>
                    <?php 
    echo $form->renderField('ab_settings_' . $day);
    ?>
                    <span>&nbsp;<?php 
    _e('to', 'bookly');
    ?>
&nbsp;</span>
                    <?php 
    echo $form->renderField('ab_settings_' . $day, false);
    ?>
                </td>
            </tr>
        <?php 
}
?>
        </tbody>
        <tr>
            <td></td>
            <td>
                <?php 
AB_Utils::submitButton();
?>
                <?php 
AB_Utils::resetButton('ab-hours-reset');
?>
            </td>
        </tr>
    </table>
</form>
示例#8
0
<div class="ab-payment-nav">
    <div style="margin-bottom: 15px!important;" class="ab-row-fluid"><?php 
_e($info_text, 'bookly');
?>
</div>
    <?php 
if ($_local) {
    ?>
        <div class="ab-row-fluid ab-list">
            <label>
                <input type="radio" class="ab-local-payment" checked="checked" name="payment-method-<?php 
    echo $form_id;
    ?>
" value="local"/>
                <?php 
    echo AB_Utils::getTranslatedOption('ab_appearance_text_label_pay_locally');
    ?>
            </label>
        </div>
    <?php 
}
?>

    <?php 
if ($_paypal) {
    ?>
        <div class="ab-row-fluid ab-list">
            <label>
                <input type="radio" class="ab-paypal-payment" <?php 
    checked(!$_local);
    ?>
示例#9
0
"<?php 
        selected($userData->get('time_from') == $key);
        ?>
><?php 
        echo $time;
        ?>
</option>
                                    <?php 
    }
    ?>
                                </select>
                            </div>
                        </div>
                        <div class="ab-left ab-time-to">
                            <label class="ab-bold"><?php 
    echo AB_Utils::getTranslatedOption('ab_appearance_text_label_finish_by');
    ?>
</label>
                            <div>
                                <select class="ab-select-time-to">
                                    <?php 
    foreach ($time_list as $key => $time) {
        ?>
                                        <option value="<?php 
        echo $key;
        ?>
"<?php 
        selected($userData->get('time_to') == $key);
        ?>
><?php 
        echo $time;
示例#10
0
    _e('Please add your staff members.', 'bookly');
    ?>
</li>
                    <li><?php 
    _e('Add services and assign them to the staff members you created earlier.', 'bookly');
    ?>
</li>
                </ol>
                <hr>
                <a class="btn btn-info" href="<?php 
    echo AB_Utils::escAdminUrl(AB_StaffController::page_slug);
    ?>
"><?php 
    _e('Add Staff Members', 'bookly');
    ?>
</a>
                <a class="btn btn-info" href="<?php 
    echo AB_Utils::escAdminUrl(AB_ServiceController::page_slug);
    ?>
"><?php 
    _e('Add Services', 'bookly');
    ?>
</a>
            <?php 
}
?>
        </div>
    </div>
</div>

示例#11
0
 /**
  * Returns a collection of Google calendar events
  *
  * @param DateTime $startDate
  * @return array|false
  */
 public function getCalendarEvents(DateTime $startDate)
 {
     // get all events from calendar, without timeMin filter (the end of the event can be later then the start of searched time period)
     $result = array();
     try {
         $calendar_access = $this->getCalendarAccess();
         $time_slot_length = AB_BookingConfiguration::getTimeSlotLength();
         $limit_events = get_option('ab_settings_google_limit_events');
         $timeMin = clone $startDate;
         $timeMin = $timeMin->modify('-1 day')->format(DateTime::RFC3339);
         $events = $this->service->events->listEvents($this->getCalendarID(), array('singleEvents' => true, 'orderBy' => 'startTime', 'timeMin' => $timeMin, 'maxResults' => $limit_events ?: self::EVENTS_PER_REQUEST));
         while (true) {
             foreach ($events->getItems() as $event) {
                 /** @var Google_Service_Calendar_Event $event */
                 if ($event->getStatus() !== 'cancelled') {
                     // Skip events created by Bookly in non freeBusyReader calendar.
                     if ($calendar_access != 'freeBusyReader') {
                         $ext_properties = $event->getExtendedProperties();
                         if ($ext_properties !== null) {
                             $private = $ext_properties->private;
                             if ($private !== null && array_key_exists('service_id', $private)) {
                                 continue;
                             }
                         }
                     }
                     // Get start/end dates of event and transform them into WP timezone (Google doesn't transform whole day events into our timezone).
                     $event_start = $event->getStart();
                     $event_end = $event->getEnd();
                     if ($event_start->dateTime == null) {
                         // All day event.
                         $eventStartDate = new DateTime($event_start->date, new DateTimeZone($this->getCalendarTimezone()));
                         $eventEndDate = new DateTime($event_end->date, new DateTimeZone($this->getCalendarTimezone()));
                     } else {
                         // Regular event.
                         $eventStartDate = new DateTime($event_start->dateTime);
                         $eventEndDate = new DateTime($event_end->dateTime);
                     }
                     $eventStartDate->setTimezone(new DateTimeZone(AB_Utils::getTimezoneString()));
                     $eventEndDate->setTimezone(new DateTimeZone(AB_Utils::getTimezoneString()));
                     // Check if event intersects with out datetime interval.
                     if ($eventEndDate > $startDate) {
                         // If event lasts for more than 1 day, then divide it.
                         for ($loop_start = $eventStartDate; $loop_start < $eventEndDate; $loop_start->modify('+1 day')->setTime(0, 0, 0)) {
                             // Start date.
                             if ($loop_start->format('Ymd') > $eventStartDate->format('Ymd')) {
                                 $start_date = $loop_start->format('Y-m-d 00:00:00');
                             } else {
                                 $start_date = $loop_start->format('Y-m-d H:i:s');
                             }
                             // End date.
                             if ($loop_start->format('Ymd') < $eventEndDate->format('Ymd')) {
                                 $end_date = '10_symbols 24:00:00';
                             } else {
                                 $loop_end = clone $eventEndDate;
                                 $end_date = $loop_end->getTimestamp();
                                 // Round end time to a multiple of the default time slot length.
                                 $extra = $end_date % $time_slot_length;
                                 if ($extra) {
                                     $end_date += $time_slot_length - $extra;
                                 }
                                 $loop_end->setTimestamp($end_date);
                                 $end_date = $loop_end->format('Y-m-d H:i:s');
                                 if (substr($end_date, 11) == '00:00:00') {
                                     // Set time to 24:00:00 (date part does not matter, it just needs to be 10 characters length).
                                     $end_date = '10_symbols 24:00:00';
                                 }
                             }
                             $result[] = array('staff_id' => $this->staff->get('id'), 'start_date' => $start_date, 'end_date' => $end_date, 'number_of_bookings' => 1, 'from_google' => true);
                         }
                     }
                 }
             }
             if (!$limit_events && $events->getNextPageToken()) {
                 $events = $this->service->events->listEvents($this->getCalendarID(), array('singleEvents' => true, 'orderBy' => 'startTime', 'timeMin' => $timeMin, 'pageToken' => $events->getNextPageToken()));
             } else {
                 break;
             }
         }
         return $result;
     } catch (Exception $e) {
         $this->errors[] = $e->getMessage();
     }
     return false;
 }
示例#12
0
         width="1" height="1">
</form>

<form class="ab-inline-block ab-ctext" action="<?php 
echo esc_url($action);
?>
" method="post">
    <input type="hidden" name="item_name" value="Bookly SMS">
    <input type="hidden" name="currency_code" value="USD">
    <input type="hidden" name="amount" value="100">
    <input type="hidden" name="return" value="<?php 
echo AB_Utils::escAdminUrl(AB_SmsController::page_slug, array('paypal_result' => 'success'));
?>
">
    <input type="hidden" name="cancel_return" value="<?php 
echo AB_Utils::escAdminUrl(AB_SmsController::page_slug, array('paypal_result' => 'cancel'));
?>
">
    <input type="hidden" name="cmd" value="_xclick">
    <input type="hidden" name="business" value="<?php 
echo esc_attr($business);
?>
">
    <input type="hidden" name="custom" value="<?php 
echo esc_attr($sms->getUserName());
?>
">
    <input type="hidden" name="no_shipping" value="1">
    <input type="hidden" name="handling" value="4.92">
    <input type="image"
           src="<?php 
示例#13
0
<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')) {
                                ?>
                                                <a class="ab-btn orange" href="<?php 
                                echo esc_attr(admin_url('admin-ajax.php') . '?action=ab_cancel_appointment&token=' . $a['token']);
                                ?>
">
                                                    <span class="ab_label"><?php 
                                _e('Cancel', 'bookly');
示例#14
0
 /**
  * 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);
 }
示例#15
0
 /**
  * Extend parent method to control access on staff member level.
  *
  * @param string $action
  * @return bool
  */
 protected function hasAccess($action)
 {
     if (parent::hasAccess($action)) {
         if (!AB_Utils::isCurrentUserAdmin()) {
             $staff = new AB_Staff();
             switch ($action) {
                 case 'executeEditStaff':
                 case 'executeDeleteStaffAvatar':
                 case 'executeStaffServices':
                 case 'executeStaffSchedule':
                 case 'executeStaffHolidays':
                     $staff->load($this->getParameter('id'));
                     break;
                 case 'executeStaffServicesUpdate':
                 case 'executeStaffHolidaysUpdate':
                     $staff->load($this->getParameter('staff_id'));
                     break;
                 case 'executeStaffScheduleHandleBreak':
                     $staffScheduleItem = new AB_StaffScheduleItem();
                     $staffScheduleItem->load($this->getParameter('staff_schedule_item_id'));
                     $staff->load($staffScheduleItem->get('staff_id'));
                     break;
                 case 'executeDeleteStaffScheduleBreak':
                     $break = new AB_ScheduleItemBreak();
                     $break->load($this->getParameter('id'));
                     $staffScheduleItem = new AB_StaffScheduleItem();
                     $staffScheduleItem->load($break->get('staff_schedule_item_id'));
                     $staff->load($staffScheduleItem->get('staff_id'));
                     break;
                 case 'executeStaffScheduleUpdate':
                     if ($this->hasParameter('days')) {
                         foreach ($this->getParameter('days') as $id => $day_index) {
                             $staffScheduleItem = new AB_StaffScheduleItem();
                             $staffScheduleItem->load($id);
                             $staff = new AB_Staff();
                             $staff->load($staffScheduleItem->get('staff_id'));
                             if ($staff->get('wp_user_id') != get_current_user_id()) {
                                 return false;
                             }
                         }
                     }
                     break;
                 default:
                     return false;
             }
             return $staff->get('wp_user_id') == get_current_user_id();
         }
         return true;
     }
     return false;
 }
示例#16
0
 /**
  * Show admin notice about purchase code and license.
  */
 public function showAdminNotice()
 {
     if (AB_Utils::isCurrentUserAdmin() && !get_user_meta(get_current_user_id(), 'ab_dismiss_admin_notice', true) && get_option('ab_envato_purchase_code') == '' && time() > get_option('ab_installation_time') + 604800) {
         $this->render('admin_notice');
     }
 }
示例#17
0
 /**
  * Process the Express Checkout RETURNURL
  */
 public function paypalResponseSuccess()
 {
     $form_id = $_GET['ab_fid'];
     $paypal = new AB_PayPal();
     if (isset($_GET["token"]) && isset($_GET["PayerID"])) {
         $token = $_GET["token"];
         $payer_id = $_GET["PayerID"];
         // send the request to PayPal
         $response = $paypal->sendNvpRequest('GetExpressCheckoutDetails', sprintf('&TOKEN=%s', $token));
         if (strtoupper($response["ACK"]) == "SUCCESS") {
             $data = sprintf('&TOKEN=%s&PAYERID=%s&PAYMENTREQUEST_0_PAYMENTACTION=Sale', $token, $payer_id);
             // response keys containing useful data to send via DoExpressCheckoutPayment operation
             $response_data_keys_pattern = sprintf('/^(%s)/', implode('|', array('PAYMENTREQUEST_0_AMT', 'PAYMENTREQUEST_0_ITEMAMT', 'PAYMENTREQUEST_0_CURRENCYCODE', 'L_PAYMENTREQUEST_0')));
             foreach ($response as $key => $value) {
                 // collect product data from response using defined response keys
                 if (preg_match($response_data_keys_pattern, $key)) {
                     $data .= sprintf('&%s=%s', $key, $value);
                 }
             }
             //We need to execute the "DoExpressCheckoutPayment" at this point to Receive payment from user.
             $response = $paypal->sendNvpRequest('DoExpressCheckoutPayment', $data);
             if ("SUCCESS" == strtoupper($response["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($response["ACK"])) {
                 // get transaction info
                 $response = $paypal->sendNvpRequest('GetTransactionDetails', "&TRANSACTIONID=" . urlencode($response["PAYMENTINFO_0_TRANSACTIONID"]));
                 if ("SUCCESS" == strtoupper($response["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($response["ACK"])) {
                     // need session to get Total and Token
                     $token = $_SESSION['bookly'][$form_id]['paypal_response'][0]['TOKEN'];
                     $userData = new AB_UserBookingData($form_id);
                     $userData->load();
                     if ($userData->get('service_id')) {
                         $appointment = $userData->save();
                         $customer_appointment = new AB_CustomerAppointment();
                         $customer_appointment->loadBy(array('appointment_id' => $appointment->get('id'), 'customer_id' => $userData->getCustomerId()));
                         $payment = new AB_Payment();
                         $payment->set('token', urldecode($token));
                         $payment->set('total', $userData->getFinalServicePrice() * $userData->get('number_of_persons'));
                         $payment->set('customer_appointment_id', $customer_appointment->get('id'));
                         $payment->set('transaction', urlencode($response["TRANSACTIONID"]));
                         $payment->set('created', current_time('mysql'));
                         $payment->save();
                         $userData->setPayPalStatus('success');
                     }
                     @wp_redirect(remove_query_arg(array('action', 'token', 'PayerID', 'ab_fid'), AB_Utils::getCurrentPageURL()));
                     exit(0);
                 } else {
                     header('Location: ' . wp_sanitize_redirect(add_query_arg(array('action' => 'ab-paypal-errorurl', 'ab_fid' => $form_id, 'error_msg' => $response["L_LONGMESSAGE0"]), AB_Utils::getCurrentPageURL())));
                     exit;
                 }
             } else {
                 header('Location: ' . wp_sanitize_redirect(add_query_arg(array('action' => 'ab-paypal-errorurl', 'ab_fid' => $form_id, 'error_msg' => $response["L_LONGMESSAGE0"]), AB_Utils::getCurrentPageURL())));
                 exit;
             }
         } else {
             header('Location: ' . wp_sanitize_redirect(add_query_arg(array('action' => 'ab-paypal-errorurl', 'ab_fid' => $form_id, 'error_msg' => 'Invalid token provided'), AB_Utils::getCurrentPageURL())));
             exit;
         }
     } else {
         throw new Exception('Token parameter not found!');
     }
 }
示例#18
0
 /**
  * Send email to $mail_to.
  *
  * @param AB_Notification $notification
  * @param AB_NotificationCodes $codes
  * @param string $mail_to
  * @param string $phone
  * @return bool
  */
 private static function _send(AB_Notification $notification, AB_NotificationCodes $codes, $mail_to, $phone = '')
 {
     $result = false;
     if ($notification->get('gateway') == 'email') {
         $message = $codes->replace($notification->get('message'));
         // Send email to recipient.
         $subject = $codes->replace($notification->get('subject'));
         $result = wp_mail($mail_to, $subject, wpautop($message), AB_Utils::getEmailHeaders());
         // Send copy to administrators.
         if ($notification->get('copy')) {
             $admin_emails = AB_Utils::getAdminEmails();
             if (!empty($admin_emails)) {
                 wp_mail($admin_emails, $subject, wpautop($message), AB_Utils::getEmailHeaders());
             }
         }
     } elseif ($notification->get('gateway') == 'sms') {
         $message = $codes->replace($notification->get('message'), 'sms');
         if (self::$sms_authorized === null) {
             self::$sms = new AB_SMS();
             self::$sms_authorized = self::$sms->loadProfile();
         }
         if (self::$sms_authorized) {
             if ($phone != '') {
                 $result = self::$sms->sendSms($phone, $message);
             }
             if ($notification->get('copy')) {
                 if ($administrator_phone = get_option('ab_sms_administrator_phone', '') != '') {
                     self::$sms->sendSms($administrator_phone, $message);
                 }
             }
         }
     }
     return $result;
 }
示例#19
0
                                        <a class="ab-popup-close ab-popup-close-icon" href="javascript:void(0)"></a>
                                    </div>
                                </div>
                            </div>
                        </td>
                        <td class="breaks">
                            <?php 
    include '_breaks.php';
    ?>
                        </td>
                    </tr>
                <?php 
}
?>
                <tr class="staff-schedule-item-row ab-last-row">
                    <td></td>
                    <td colspan="3">
                        <input type="hidden" name="action" value="ab_staff_schedule_update"/>
                        <?php 
AB_Utils::submitButton('ajax-send-staff-schedule');
?>
                        <?php 
AB_Utils::resetButton('ab-schedule-reset');
?>
                    </td>
                </tr>
                </tbody>
            </table>
        </div>
    </form>
</div>
示例#20
0
 /**
  * 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);
 }
示例#21
0
" />
                        <div class="ab-popup" style="display: none; margin-top: 10px;">
                            <div class="ab-arrow"></div>
                            <div class="ab-content">
                                <form method="post" id="new-category-form">
                                    <table class="form-horizontal">
                                        <tr>
                                            <td>
                                                <input class="form-control ab-clear-text" style="width: 170px" type="text" name="name" />
                                                <input type="hidden" name="action" value="ab_category_form" />
                                            </td>
                                        </tr>
                                        <tr>
                                            <td>
                                                <?php 
AB_Utils::submitButton();
?>
                                                <a class="ab-popup-close" href="#"><?php 
_e('Cancel', 'bookly');
?>
</a>
                                            </td>
                                        </tr>
                                    </table>
                                    <a class="ab-popup-close ab-popup-close-icon" href="#"></a>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="ab-right-content col-md-9 col-sm-9 col-xs-12 col-lg-9" id="ab_services_wrapper">
示例#22
0
        <div class="ab-formGroup ab-left">
            <label class="ab-formLabel"><?php 
echo AB_Utils::getTranslatedOption('ab_appearance_text_label_phone');
?>
</label>
            <div class="ab-formField">
                <input class="ab-formElement ab-user-phone" maxlength="30" type="tel" value="<?php 
echo esc_attr($userData->get('phone'));
?>
"/>
            </div>
            <div class="ab-user-phone-error ab-label-error ab-bold"></div>
        </div>
        <div class="ab-formGroup ab-left">
            <label class="ab-formLabel"><?php 
echo AB_Utils::getTranslatedOption('ab_appearance_text_label_email');
?>
</label>
            <div class="ab-formField" style="margin-right: 0">
                <input class="ab-formElement ab-user-email" maxlength="40" type="text" value="<?php 
echo esc_attr($userData->get('email'));
?>
"/>
            </div>
            <div class="ab-user-email-error ab-label-error ab-bold"></div>
        </div>
    </div>

    <?php 
foreach ($custom_fields as $custom_field) {
    ?>
 /**
  * Constructor
  */
 public function __construct()
 {
     date_default_timezone_set(AB_Utils::getTimezoneString());
     wp_load_translations_early();
     $now = new DateTime();
     $this->mysql_now = $now->format('Y-m-d H:i:s');
     $this->sms = new AB_SMS();
     $this->sms_authorized = $this->sms->loadProfile();
     $query = AB_Notification::query()->where('active', 1)->whereIn('type', array('staff_agenda', 'client_follow_up', 'client_reminder'));
     foreach ($query->find() as $notification) {
         $this->processNotification($notification);
     }
 }
示例#24
0
            </td>
            <td><input id="ab_settings_company_phone" class="form-control" type="text" name="ab_settings_company_phone" value="<?php 
echo esc_attr(get_option('ab_settings_company_phone'));
?>
" /></td>
        </tr>
        <tr>
            <td>
                <label for="ab_settings_company_website"><?php 
_e('Website', 'bookly');
?>
</label>
            </td>
            <td><input id="ab_settings_company_website" class="form-control" type="text" name="ab_settings_company_website" value="<?php 
echo esc_attr(get_option('ab_settings_company_website'));
?>
" /></td>
        </tr>
        <tr>
            <td></td>
            <td>
                <?php 
AB_Utils::submitButton();
?>
                <?php 
AB_Utils::resetButton('ab-settings-company-reset');
?>
            </td>
        </tr>
    </table>
</form>
示例#25
0
">
                </div>
                <div class="form-group">
                    <label for="new_password_repeat"><?php 
    _e('Repeat new password', 'bookly');
    ?>
</label>
                    <input type="password" class="form-control" id="new_password_repeat" placeholder="<?php 
    echo esc_attr(__('Repeat new password', 'bookly'));
    ?>
">
                </div>
            </div>
            <div class="modal-footer">
                <?php 
    AB_Utils::submitButton('ajax-send-change-password');
    ?>
                <button type="button" class="ab-reset-form" data-dismiss="modal"><?php 
    _e('Cancel', 'bookly');
    ?>
</button>
            </div>
            <input type="hidden" name="action" value="ab_change_password">
        </div>
    </div>
    </form>
</div>

<?php 
} else {
    ?>
示例#26
0
    ?>
</option>
                    <?php 
}
?>
                </select>
            </td>
        </tr>
        <tr class="ab-stripe">
            <td><label for="ab_stripe_secret_key"><?php 
_e('Secret Key', 'bookly');
?>
</label></td>
            <td><input id="ab_stripe_secret_key" class="form-control" type="text" size="33" name="ab_stripe_secret_key" value="<?php 
echo get_option('ab_stripe_secret_key');
?>
"/></td>
        </tr>
        <tr>
            <td colspan="2">
                <?php 
AB_Utils::submitButton();
?>
                <?php 
AB_Utils::resetButton('ab-payments-reset');
?>
            </td>
            <td></td>
        </tr>
    </table>
</form>
 /**
  * Export Appointment to CSV
  */
 public function executeExportToCSV()
 {
     $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');
     $delimiter = $this->getParameter('delimiter', ',');
     header('Content-Type: text/csv; charset=utf-8');
     header('Content-Disposition: attachment; filename=Appointments.csv');
     $header = array(__('Booking Time', 'bookly'), __('Staff Member', 'bookly'), __('Service', 'bookly'), __('Duration', 'bookly'), __('Price', 'bookly'), __('Customer', 'bookly'), __('Phone', 'bookly'), __('Email', 'bookly'));
     $custom_fields = array();
     $fields_data = json_decode(get_option('ab_custom_fields'));
     foreach ($fields_data as $field_data) {
         $custom_fields[$field_data->id] = '';
         $header[] = $field_data->label;
     }
     $output = fopen('php://output', 'w');
     fwrite($output, pack("CCC", 0xef, 0xbb, 0xbf));
     fputcsv($output, $header, $delimiter);
     $rows = AB_CustomerAppointment::query()->select('r.id,
            r.number_of_persons,
            r.coupon_discount,
            r.coupon_deduction,
            st.full_name  AS staff_name,
            s.title       AS service_title,
            s.duration    AS service_duration,
            c.name        AS customer_name,
            c.phone       AS customer_phone,
            c.email       AS customer_email,
            ss.price,
            a.start_date')->leftJoin('AB_Appointment', 'a', 'a.id = r.appointment_id')->leftJoin('AB_Service', 's', 's.id = a.service_id')->leftJoin('AB_Staff', 'st', 'st.id = a.staff_id')->leftJoin('AB_Customer', 'c', 'c.id = r.customer_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('a.start_date')->order(AB_Query::ORDER_DESCENDING)->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_data = array($row['start_date'], $row['staff_name'], $row['service_title'], AB_Service::durationToString($row['service_duration']), AB_Utils::formatPrice($row['price']), $row['customer_name'], $row['customer_phone'], $row['customer_email']);
         $customer_appointment = new AB_CustomerAppointment();
         $customer_appointment->load($row['id']);
         foreach ($customer_appointment->getCustomFields() as $custom_field) {
             $custom_fields[$custom_field['id']] = $custom_field['value'];
         }
         fputcsv($output, array_merge($row_data, $custom_fields), $delimiter);
         $custom_fields = array_map(function () {
             return '';
         }, $custom_fields);
     }
     fclose($output);
     exit;
 }
示例#28
0
</span>)
            <?php 
} else {
    ?>
                <?php 
    _e('Profile', 'bookly');
    ?>
            <?php 
}
?>
        </h3>
    </div>
    <div class="panel-body">
        <div class="row">
            <div id="ab-staff" class="ab-left-bar col-md-3 col-sm-3 col-xs-12 col-lg-3"<?php 
if (!AB_Utils::isCurrentUserAdmin()) {
    ?>
 style="display: none" <?php 
}
?>
>
                <ul id="ab-staff-list">
                    <?php 
if ($staff_members) {
    ?>
                        <?php 
    foreach ($staff_members as $staff) {
        ?>
                            <li class="ab-staff-member" id="ab-list-staff-<?php 
        echo $staff['id'];
        ?>
示例#29
0
        default:
            include '_codes.php';
    }
    ?>
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        <?php 
}
?>
        <div class="ab-notifications">
            <?php 
echo '<i>' . __('To send scheduled notifications please execute the following script hourly with your cron:', 'bookly') . '</i><br />';
echo '<b>php -f ' . realpath(AB_PATH . '/lib/utils/send_notifications_cron.php') . '</b>';
?>
        </div>
    </div>
    <div class="panel-footer">
        <?php 
AB_Utils::submitButton();
?>
        <?php 
AB_Utils::resetButton();
?>
    </div>
</div>
</form>
示例#30
0
 /**
  * Check if the current user has access to the action.
  *
  * Default access (if is not set with annotation for the controller or action) is "admin"
  * Access type:
  *  "admin"     - check if the current user is super admin
  *  "user"      - check if the current user is authenticated
  *  "anonymous" - anonymous user
  *
  * @param string $action
  * @return bool
  */
 protected function hasAccess($action)
 {
     $permissions = $this->getPermissions();
     $security = isset($permissions[$action]) ? $permissions[$action] : null;
     if (is_null($security)) {
         // Check if controller class has permission
         $security = isset($permissions['_this']) ? $permissions['_this'] : null;
         if (is_null($security)) {
             $security = 'admin';
         }
     }
     switch ($security) {
         case 'admin':
             return AB_Utils::isCurrentUserAdmin();
         case 'user':
             return is_user_logged_in();
         case 'anonymous':
             return true;
     }
     return false;
 }