function tutorial2() { global $appointments; //load the file if (!class_exists('Pointer_Tutorial')) { require_once $appointments->plugin_dir . '/includes/external/pointer-tutorials.php'; } //create our tutorial, with default redirect prefs $tutorial = new Pointer_Tutorial('app_tutorial2', true, false); //add our textdomain that matches the current plugin $tutorial->set_textdomain = 'appointments'; //add the capability a user must have to view the tutorial $tutorial->set_capability = App_Roles::get_capability('manage_options', App_Roles::CTX_TUTORIAL); $tutorial->add_icon($appointments->plugin_url . '/images/large-greyscale.png'); $appointments_page = admin_url('admin.php?page=appointments'); $tutorial->add_step($appointments_page, 'toplevel_page_appointments', '.info-button', __('Appointment List', 'appointments'), array('content' => '<p>' . esc_js(__('Appointment records are grouped by their statuses. You can see these groupings by clicking the Info icon.', 'appointments')) . '</p>', 'position' => array('edge' => 'right', 'align' => 'center'))); $tutorial->add_step($appointments_page, 'toplevel_page_appointments', '.add-new-h2', __('Entering a Manual Appointment', 'appointments'), array('content' => '<p>' . esc_js(__('When you received appointments from your clients, they will be added to this page automatically. But you can always add a new appointment manually. Please click ADD NEW link and then click Next.', 'appointments')) . '</p>', 'position' => array('edge' => 'left', 'align' => 'top'))); $tutorial->add_step($appointments_page, 'toplevel_page_appointments', 'select[name="status"]', __('Entering Data for the New Appointment', 'appointments'), array('content' => '<p>' . esc_js(__('As you can see, you can enter all parameters here. Enter some random values and select status as PENDING, for this example. Then click Next', 'appointments')) . '</p>', 'position' => array('edge' => 'right', 'align' => 'center'))); $tutorial->add_step($appointments_page, 'toplevel_page_appointments', 'input[name="resend"]', __('Sending Confirmation emails Manually', 'appointments'), array('content' => '<p>' . esc_js(__('If you require payment, confirmation email is automatically sent after a Paypal payment. However if you are confirming appointments manually, you should check this checkbox for a confirmation email to be sent. You can also use this option for resending the confirmation email, e.g. after rescheduling an appointment.', 'appointments')) . '</p>', 'position' => array('edge' => 'right', 'align' => 'center'))); $tutorial->add_step($appointments_page, 'toplevel_page_appointments', '.save', __('Entering Data for the New Appointment', 'appointments'), array('content' => '<p>' . esc_js(__('Save and then click Next.', 'appointments')) . '</p>', 'position' => array('edge' => 'right', 'align' => 'center'))); $tutorial->add_step($appointments_page, 'toplevel_page_appointments', '.error', __('Entering Data for the New Appointment', 'appointments'), array('content' => '<p>' . esc_js(__('The result is shown here. Normally you should get a success message. Otherwise it means that you have a javascript problem on admin side.', 'appointments')) . '</p>', 'position' => array('edge' => 'left', 'align' => 'center'))); $tutorial->add_step($appointments_page, 'toplevel_page_appointments', '.info-button', __('Save New Appointment', 'appointments'), array('content' => '<p>' . esc_js(__('As we added this appointment as "Pending" we will see it under Pending appointments. Click Pending appointments and then click Next.', 'appointments')) . '</p>', 'position' => array('edge' => 'left', 'align' => 'center'))); $tutorial->add_step($appointments_page . '&type=pending', 'toplevel_page_appointments', '.info-button', __('Editing an Appointment', 'appointments'), array('content' => '<p>' . esc_js(__('You can edit any appointment record. Just hover on the record and then click See Details and Edit', 'appointments')) . '</p>', 'position' => array('edge' => 'left', 'align' => 'center'))); $tutorial->add_step($appointments_page . '&type=pending', 'toplevel_page_appointments', '.cancel', _x('Cancel', 'Drop current action', 'appointments'), array('content' => '<p>' . esc_js(__('It is always possible to Cancel. Please note that these records are NOT saved until you click the Save button. Thanks for using Appointments+', 'appointments')) . '</p>', 'position' => array('edge' => 'left', 'align' => 'center'))); if (isset($_GET["tutorial"]) && 'restart2' == $_GET["tutorial"]) { $tutorial->restart(); } //start the tutorial $tutorial->initialize(); return $tutorial; }
public function add_script() { if (!current_user_can(App_Roles::get_capability('manage_options', App_Roles::CTX_PAGE_APPOINTMENTS))) { return false; } $key = esc_js(self::HB_KEY); $tpl = json_encode($this->_get_pending_template()); echo <<<EO_AAPC_JS <script> ;(function (\$) { if (typeof(wp) === "undefined") return false; function update_interface (data) { \tvar root = \$("#toplevel_page_appointments"), \t\ttarget = root.find(".wp-menu-name"), \t\tcount = data.count || 0 \t; \tif (!target.length) return false; \ttarget.find(".awaiting-mod").remove(); \tif (count > 0) target.append({$tpl}.replace(/%d/g, count)); } function set_heartbeat () { \twp.heartbeat.enqueue('{$key}', {count: "pending"}, false); } function init () { \tset_heartbeat(); \t\$(document).on('heartbeat-tick.{$key}', function (e, data) { \t\tset_heartbeat(); \t\tif (data && data.hasOwnProperty && data.hasOwnProperty('{$key}')) { \t\t\tupdate_interface(data['{$key}']); \t\t} \t}); } \$(init); })(jQuery); </script> EO_AAPC_JS; }
public function process_shortcode($args = array(), $content = '') { extract(wp_parse_args($args, $this->_defaults_to_args())); global $wpdb, $current_user, $bp, $appointments; $statuses = explode(',', $status); if (!is_array($statuses) || empty($statuses)) { return; } if (!trim($order_by)) { $order_by = 'ID'; } $stat = ''; foreach ($statuses as $s) { // Allow only defined stats if (array_key_exists(trim($s), App_Template::get_status_names())) { $stat .= " status='" . trim($s) . "' OR "; } } $stat = rtrim($stat, "OR "); // If this is a client shortcode if (!$provider) { if (isset($_COOKIE["wpmudev_appointments"])) { $apps = unserialize(stripslashes($_COOKIE["wpmudev_appointments"])); } else { $apps = array(); } if (!is_array($apps)) { return; } $provider_or_client = __('Provider', 'appointments'); $q = ''; if ($strict) { // Strict matching if (is_user_logged_in()) { $q = "user={$current_user->ID}"; // If the user is logged in, show just those apps } else { // Otherwise, deal with the cookie-cached ones $apps = array_values(array_filter(array_map('intval', $apps))); if (!empty($apps)) { $q = "ID IN(" . join(',', $apps) . ")"; } } } else { // Non-strict matching foreach ($apps as $app_id) { if (is_numeric($app_id)) { $q .= " ID=" . $app_id . " OR "; } } $q = rtrim($q, "OR "); // But he may as well has appointments added manually (requires being registered user) if (is_user_logged_in()) { $q .= " OR user="******" OR"); } } if ($q && $stat) { $results = $wpdb->get_results("SELECT * FROM " . $appointments->app_table . " WHERE (" . $q . ") AND (" . $stat . ") ORDER BY " . $appointments->sanitize_order_by($order_by)); } else { $results = false; } } else { $provider_or_client = __('Client', 'appointments'); // If no id is given, get current user if (!$provider_id) { $provider_id = $current_user->ID; } // Special case: If this is a single provider website, show staff appointments in his schedule too $workers = $appointments->get_workers(); if (App_Roles::current_user_can('manage_options', App_Roles::CTX_STAFF) && ($workers && count($workers) == 1 || !$workers)) { $provider_id .= ' OR worker=0'; } $results = $wpdb->get_results("SELECT * FROM " . $appointments->app_table . " WHERE (worker=" . $provider_id . ") AND (" . $stat . ") ORDER BY " . $order_by . " "); } // Can worker confirm pending appointments? if ($_allow_confirm && $appointments->is_worker($current_user->ID) && isset($appointments->options['allow_worker_confirm']) && 'yes' == $appointments->options['allow_worker_confirm']) { $allow_confirm = true; } else { $allow_confirm = false; } // Can client cancel appointments? if ($allow_cancel && !$provider && isset($appointments->options['allow_cancel']) && 'yes' == $appointments->options['allow_cancel']) { $a_cancel = true; } else { $a_cancel = false; } $ret = ''; $ret .= '<div class="appointments-my-appointments">'; // Make this a form for BP if confirmation is allowed, but not on admin side user profile page if ($this->_can_display_editable($allow_confirm)) { $ret .= '<form method="post">'; } $ret .= $title; $ret = apply_filters('app_my_appointments_before_table', $ret); $ret .= '<table class="my-appointments tablesorter"><thead>'; $ret .= apply_filters('app_my_appointments_column_name', '<th class="my-appointments-service">' . __('Service', 'appointments') . '</th><th class="my-appointments-worker">' . $provider_or_client . '</th><th class="my-appointments-date">' . __('Date/time', 'appointments') . '</th><th class="my-appointments-status">' . __('Status', 'appointments') . '</th>'); $colspan = 4; if ($allow_confirm) { $ret .= '<th class="my-appointments-confirm">' . __('Confirm', 'appointments') . '</th>'; $colspan++; } if ($a_cancel) { $ret .= '<th class="my-appointments-cancel">' . _x('Cancel', 'Discard existing info', 'appointments') . '</th>'; $colspan++; } if ($gcal && 'yes' == $appointments->options['gcal']) { $ret .= '<th class="my-appointments-gcal"> </th>'; $colspan++; } $ret .= '</thead><tbody>'; if ($results) { foreach ($results as $r) { $ret .= '<tr><td>'; $ret .= $appointments->get_service_name($r->service) . '</td>'; $ret .= apply_filters('app-shortcode-my_appointments-after_service', '', $r); $ret .= '<td>'; if (!$provider) { $ret .= $appointments->get_worker_name($r->worker) . '</td>'; } else { $ret .= $appointments->get_client_name($r->ID) . '</td>'; } $ret .= apply_filters('app-shortcode-my_appointments-after_worker', '', $r); $ret .= '<td>'; $ret .= date_i18n($appointments->datetime_format, strtotime($r->start)) . '</td>'; $ret .= apply_filters('app-shortcode-my_appointments-after_date', '', $r); $ret .= '<td>'; $ret .= App_Template::get_status_name($r->status); $ret .= '</td>'; $ret .= apply_filters('app-shortcode-my_appointments-after_status', '', $r); // If allowed so, a worker can confirm an appointment himself if ($allow_confirm) { if ('pending' == $r->status) { $is_readonly = ''; } else { $is_readonly = ' readonly="readonly"'; } $ret .= '<td><input class="app-my-appointments-confirm" type="checkbox" name="app_confirm[' . $r->ID . ']" ' . $is_readonly . ' /></td>'; } // If allowed so, a client can cancel an appointment if ($a_cancel) { // We don't want completed appointments to be cancelled $stat = $r->status; $in_allowed_stat = apply_filters('app_cancel_allowed_status', 'pending' == $stat || 'confirmed' == $stat || 'paid' == $stat, $stat, $r->ID); if ($in_allowed_stat) { $is_readonly = ''; } else { $is_readonly = ' readonly="readonly"'; } $ret .= '<td><input class="app-my-appointments-cancel" type="checkbox" name="app_cancel[' . $r->ID . ']" ' . $is_readonly . ' /></td>'; } if ($gcal && 'yes' == $appointments->options['gcal']) { if (isset($appointments->options["gcal_same_window"]) && $appointments->options["gcal_same_window"]) { $target = '_self'; } else { $target = '_blank'; } $ret .= '<td><a title="' . __('Click to submit this appointment to your Google Calendar account', 'appointments') . '" href="' . $appointments->gcal($r->service, strtotime($r->start, $appointments->local_time), strtotime($r->end, $appointments->local_time), true, $r->address, $r->city) . '" target="' . $target . '">' . $appointments->gcal_image . '</a></td>'; } $ret .= apply_filters('app_my_appointments_add_cell', '', $r); $ret .= '</tr>'; } } else { $ret .= '<tr><td colspan="' . $colspan . '">' . __('No appointments', 'appointments') . '</td></tr>'; } $ret .= '</tbody></table>'; $ret = apply_filters('app_my_appointments_after_table', $ret, $results); if ($this->_can_display_editable($allow_confirm)) { $ret .= '<div class="submit">' . '<input type="submit" name="app_bp_settings_submit" value="' . esc_attr(__('Submit Confirm', 'appointments')) . '" class="auto">' . '<input type="hidden" name="app_bp_settings_user" value="' . esc_attr($bp->displayed_user->id) . '">' . wp_nonce_field('app_bp_settings_submit', 'app_bp_settings_submit', true, false) . '</div>'; $ret .= '</form>'; } $ret .= '</div>'; $sorter = 'usLongDate'; $dateformat = 'us'; // Search for formats where day is at the beginning if (stripos(str_replace(array('/', '-'), '', $appointments->date_format), 'dmY') !== false) { $sorter = 'shortDate'; $dateformat = 'uk'; } // Sort table from front end if ($_tablesorter && file_exists($appointments->plugin_dir . '/js/jquery.tablesorter.min.js')) { $appointments->add2footer(' $(".my-appointments").tablesorter({ dateFormat: "' . $dateformat . '", headers: { 2: { sorter:"' . $sorter . '" } } }); $("th.my-appointments-gcal,th.my-appointments-confirm,th.my-appointments-cancel").removeClass("header"); $(".app-my-appointments-cancel").change( function() { if ( $(this).is(":checked") ) { var cancel_box = $(this); if ( !confirm("' . esc_js(__("Are you sure to cancel the selected appointment?", "appointments")) . '") ) { cancel_box.attr("checked", false); return false; } else{ var cancel_id = $(this).attr("name").replace("app_cancel[","").replace("]",""); if (cancel_id) { var cancel_data = {action: "cancel_app", app_id: cancel_id, cancel_nonce: "' . wp_create_nonce() . '"}; $.post(_appointments_data.ajax_url, cancel_data, function(response) { if (response && response.error ) { cancel_box.attr("disabled",true); alert(response.error); } else if (response && response.success) { alert("' . esc_js(__("Selected appointment cancelled.", "appointments")) . '"); cancel_box.closest("tr").css("opacity","0.3"); cancel_box.attr("disabled",true); } else { cancel_box.attr("disabled",true); alert("' . esc_js(__("A connection error occurred.", "appointments")) . '"); } }, "json"); } } } });'); } return $ret; }
public function save_settings($options) { if (empty($_POST['action_app']) || 'save_locations' != $_POST['action_app']) { return false; } if (!App_Roles::current_user_can('manage_options', App_Roles::CTX_PAGE_SETTINGS)) { return false; } if (!wp_verify_nonce($_POST['app_nonce'], 'update_app_settings')) { return false; } if (empty($_POST['locations'])) { return false; } $options = get_option('appointments_options', array()); $raw = stripslashes_deep($_POST['locations']); $data = array(); foreach ($raw as $json) { $item = @json_decode($json, true); if (empty($item)) { continue; } $data[] = $item; } $this->_locations->populate_from_storage($data); $this->_locations->update(); $settings = stripslashes_deep($_POST['locations_settings']); $options['locations_settings'] = !empty($settings) ? $settings : array(); $options = apply_filters('app-locations-before_save', $options); update_option('appointments_options', $options); wp_redirect(add_query_arg('saved', 1)); die; }
/** * Admin settings HTML code */ function settings() { if (!App_Roles::current_user_can('manage_options', App_Roles::CTX_PAGE_SETTINGS)) { wp_die(__('You do not have sufficient permissions to access this page.', 'appointments')); } $this->get_lsw(); global $wpdb; ?> <div class="wrap"> <div class="icon32" style="margin:10px 0 0 0"><img src="<?php echo $this->plugin_url . '/images/general.png'; ?> " /></div> <h2><?php echo __('Appointments+ Settings', 'appointments'); ?> </h2> <h3 class="nav-tab-wrapper"> <?php $tab = !empty($_GET['tab']) ? $_GET['tab'] : 'main'; $tabs = array('gcal' => __('Google Calendar', 'appointments'), 'working_hours' => __('Working Hours', 'appointments'), 'exceptions' => __('Exceptions', 'appointments'), 'services' => __('Services', 'appointments'), 'workers' => __('Service Providers', 'appointments'), 'addons' => __('Add-ons', 'appointments'), 'log' => __('Logs', 'appointments')); $tabhtml = array(); // If someone wants to remove or add a tab $tabs = apply_filters('appointments_tabs', $tabs); $class = 'main' == $tab ? ' nav-tab-active' : ''; $tabhtml[] = ' <a href="' . admin_url('admin.php?page=app_settings') . '" class="nav-tab' . $class . '">' . __('General', 'appointments') . '</a>'; foreach ($tabs as $stub => $title) { $class = $stub == $tab ? ' nav-tab-active' : ''; $tabhtml[] = ' <a href="' . admin_url('admin.php?page=app_settings&tab=' . $stub) . '" class="nav-tab' . $class . '" id="app_tab_' . $stub . '">' . $title . '</a>'; } echo implode("\n", $tabhtml); ?> </h3> <div class="clear"></div> <?php App_Template::admin_settings_tab($tab); ?> </div> <?php }
public function show_settings() { $roles = App_Roles::get_all_wp_roles(); $contexts = App_Roles::get_all_contexts(); $count = 1; ?> <div class="postbox"> <h3 class='hndle'><span><?php _e('Appointments role access', 'appointments'); ?> </span></h3> <div class="inside"> <table class="form-table"><tr> <?php foreach ($contexts as $ctx => $ctx_label) { ?> <?php if (App_Roles::CTX_GLOBAL == $ctx) { continue; } ?> <?php $context_roles = !empty($this->_data['roles'][$ctx]) ? $this->_data['roles'][$ctx] : array(); ?> <td> <table class="widefat"> <thead><tr><th><?php echo $ctx_label; ?> </th></tr></thead> <tbody><tr><td> <select name="roles[<?php esc_attr_e($ctx); ?> ][]" multiple="multiple"> <option value="" <?php echo empty($context_roles) ? 'selected="selected"' : ''; ?> ><?php _e('Default', 'appointments'); ?> </option> <?php foreach ($roles as $role => $label) { ?> <option value="<?php esc_attr_e($role); ?> " <?php echo in_array($role, $context_roles) ? 'selected="selected"' : ''; ?> ><?php echo $label; ?> </option> <?php } ?> </select> </td></tr></tbody> </table> </td> <?php if ($count == 2) { echo '</tr><tr>'; $count = 0; } $count++; ?> <?php } ?> </tr></table> </div> </div> <?php }
/** * Find worker name given his ID * @return string */ function get_worker_name($worker = 0, $php = true) { global $current_user; $user_name = ''; if (0 == $worker) { // Show different text to authorized people if (is_admin() || App_Roles::current_user_can('manage_options', App_Roles::CTX_STAFF) || appointments_is_worker($current_user->ID)) { $user_name = __('Our staff', 'my-plugin'); } else { $user_name = __('A specialist', 'my-plugin'); } } else { $userdata = get_userdata($worker); if (is_object($userdata) && !empty($userdata->app_name)) { $user_name = $userdata->app_name; } if (empty($user_name)) { if (!$php) { $user_name = $userdata->user_login; } else { $user_name = $userdata->display_name; } if (!$user_name) { $first_name = get_user_meta($worker, 'first_name', true); $last_name = get_user_meta($worker, 'last_name', true); $user_name = $first_name . " " . $last_name; } if ("" == trim($user_name)) { $user_name = $userdata->user_login; } } } return apply_filters('app_get_worker_name', $user_name, $worker); }