From a2804962942f4d00a8aeae24dbaf7bbfa9e1aa03 Mon Sep 17 00:00:00 2001 From: Alex Tselegidis Date: Thu, 28 Oct 2021 14:01:17 +0200 Subject: [PATCH] Updated all the main controllers to work with the updated code. --- application/controllers/Appointments.php | 304 +++--- application/controllers/Backend.php | 206 ++-- application/controllers/Backend_api.php | 1240 +++++++++------------- application/controllers/Captcha.php | 12 +- application/controllers/Consents.php | 26 +- application/controllers/Console.php | 43 +- application/controllers/Errors.php | 15 +- application/controllers/Google.php | 138 +-- application/controllers/Installation.php | 61 +- application/controllers/Privacy.php | 29 +- application/controllers/User.php | 151 ++- 11 files changed, 1004 insertions(+), 1221 deletions(-) diff --git a/application/controllers/Appointments.php b/application/controllers/Appointments.php index b3be8488..89f926e4 100755 --- a/application/controllers/Appointments.php +++ b/application/controllers/Appointments.php @@ -12,7 +12,9 @@ * ---------------------------------------------------------------------------- */ /** - * Appointments Controller + * Appointments controller + * + * Handles the appointment related operations. * * @package Controllers */ @@ -24,19 +26,20 @@ class Appointments extends EA_Controller { { parent::__construct(); - $this->load->helper('installation'); - $this->load->helper('google_analytics'); $this->load->model('appointments_model'); $this->load->model('providers_model'); $this->load->model('admins_model'); $this->load->model('secretaries_model'); + $this->load->model('service_categories_model'); $this->load->model('services_model'); $this->load->model('customers_model'); $this->load->model('settings_model'); + $this->load->library('timezones'); $this->load->library('synchronization'); $this->load->library('notifications'); $this->load->library('availability'); + $this->load->driver('cache', ['adapter' => 'file']); } @@ -44,40 +47,40 @@ class Appointments extends EA_Controller { * Default callback method of the application. * * This method creates the appointment book wizard. If an appointment hash is provided then it means that the - * customer followed the appointment manage link that was send with the book success email. + * customer followed the appointment manage link that was sent with the book success email. * * @param string $appointment_hash The appointment hash identifier. */ - public function index($appointment_hash = '') + public function index(string $appointment_hash = '') { try { if ( ! is_app_installed()) { - redirect('installation/index'); + redirect('installation'); return; } $available_services = $this->services_model->get_available_services(); $available_providers = $this->providers_model->get_available_providers(); - $company_name = $this->settings_model->get_setting('company_name'); - $book_advance_timeout = $this->settings_model->get_setting('book_advance_timeout'); - $date_format = $this->settings_model->get_setting('date_format'); - $time_format = $this->settings_model->get_setting('time_format'); - $first_weekday = $this->settings_model->get_setting('first_weekday'); - $require_phone_number = $this->settings_model->get_setting('require_phone_number'); - $show_field['phone-number'] = $this->settings_model->get_setting('show_phone_number'); - $show_field['address'] = $this->settings_model->get_setting('show_address'); - $show_field['city'] = $this->settings_model->get_setting('show_city'); - $show_field['zip-code'] = $this->settings_model->get_setting('show_zip_code'); - $show_field['notes'] = $this->settings_model->get_setting('show_notes'); - $display_cookie_notice = $this->settings_model->get_setting('display_cookie_notice'); - $cookie_notice_content = $this->settings_model->get_setting('cookie_notice_content'); - $display_terms_and_conditions = $this->settings_model->get_setting('display_terms_and_conditions'); - $terms_and_conditions_content = $this->settings_model->get_setting('terms_and_conditions_content'); - $display_privacy_policy = $this->settings_model->get_setting('display_privacy_policy'); - $privacy_policy_content = $this->settings_model->get_setting('privacy_policy_content'); - $display_any_provider = $this->settings_model->get_setting('display_any_provider'); + $company_name = setting('company_name'); + $book_advance_timeout = setting('book_advance_timeout'); + $date_format = setting('date_format'); + $time_format = setting('time_format'); + $first_weekday = setting('first_weekday'); + $require_phone_number = setting('require_phone_number'); + $show_field['phone-number'] = setting('show_phone_number'); + $show_field['address'] = setting('show_address'); + $show_field['city'] = setting('show_city'); + $show_field['zip-code'] = setting('show_zip_code'); + $show_field['notes'] = setting('show_notes'); + $display_cookie_notice = setting('display_cookie_notice'); + $cookie_notice_content = setting('cookie_notice_content'); + $display_terms_and_conditions = setting('display_terms_and_conditions'); + $terms_and_conditions_content = setting('terms_and_conditions_content'); + $display_privacy_policy = setting('display_privacy_policy'); + $privacy_policy_content = setting('privacy_policy_content'); + $display_any_provider = setting('display_any_provider'); $timezones = $this->timezones->to_array(); // Remove the data that are not needed inside the $available_providers array. @@ -100,7 +103,7 @@ class Appointments extends EA_Controller { // Load the appointments data and enable the manage mode of the page. $manage_mode = TRUE; - $results = $this->appointments_model->get_batch(['hash' => $appointment_hash]); + $results = $this->appointments_model->get(['hash' => $appointment_hash]); if (empty($results)) { @@ -118,10 +121,11 @@ class Appointments extends EA_Controller { // If the requested appointment begin date is lower than book_advance_timeout. Display a message to the // customer. - $startDate = strtotime($results[0]['start_datetime']); + $start_datetime = strtotime($results[0]['start_datetime']); + $limit = strtotime('+' . $book_advance_timeout . ' minutes', strtotime('now')); - if ($startDate < $limit) + if ($start_datetime < $limit) { $hours = floor($book_advance_timeout / 60); $minutes = ($book_advance_timeout % 60); @@ -133,13 +137,17 @@ class Appointments extends EA_Controller { ]), 'message_icon' => base_url('assets/img/error.png') ]; + $this->load->view('appointments/message', $view); + return; } $appointment = $results[0]; - $provider = $this->providers_model->get_row($appointment['id_users_provider']); - $customer = $this->customers_model->get_row($appointment['id_users_customer']); + + $provider = $this->providers_model->find($appointment['id_users_provider']); + + $customer = $this->customers_model->find($appointment['id_users_customer']); $customer_token = md5(uniqid(mt_rand(), TRUE)); @@ -182,9 +190,9 @@ class Appointments extends EA_Controller { 'display_any_provider' => $display_any_provider, ]; } - catch (Exception $exception) + catch (Throwable $e) { - $variables['exceptions'][] = $exception; + $variables['exceptions'][] = $e; } $this->load->view('appointments/book', $variables); @@ -199,44 +207,42 @@ class Appointments extends EA_Controller { * * @param string $appointment_hash This appointment hash identifier. */ - public function cancel($appointment_hash) + public function cancel(string $appointment_hash) { try { - // Check whether the appointment hash exists in the database. - $appointments = $this->appointments_model->get_batch(['hash' => $appointment_hash]); + $occurrences = $this->appointments_model->get(['hash' => $appointment_hash]); - if (empty($appointments)) + if (empty($occurrences)) { throw new Exception('No record matches the provided hash.'); } - $appointment = $appointments[0]; - $provider = $this->providers_model->get_row($appointment['id_users_provider']); - $customer = $this->customers_model->get_row($appointment['id_users_customer']); - $service = $this->services_model->get_row($appointment['id_services']); + $appointment = $occurrences[0]; + + $provider = $this->providers_model->find($appointment['id_users_provider']); + + $customer = $this->customers_model->find($appointment['id_users_customer']); + + $service = $this->services_model->find($appointment['id_services']); $settings = [ - 'company_name' => $this->settings_model->get_setting('company_name'), - 'company_email' => $this->settings_model->get_setting('company_email'), - 'company_link' => $this->settings_model->get_setting('company_link'), - 'date_format' => $this->settings_model->get_setting('date_format'), - 'time_format' => $this->settings_model->get_setting('time_format') + 'company_name' => setting('company_name'), + 'company_email' => setting('company_email'), + 'company_link' => setting('company_link'), + 'date_format' => setting('date_format'), + 'time_format' => setting('time_format') ]; - // Remove the appointment record from the data. - if ( ! $this->appointments_model->delete($appointment['id'])) - { - throw new Exception('Appointment could not be deleted from the database.'); - } + $this->appointments_model->delete($appointment['id']); $this->synchronization->sync_appointment_deleted($appointment, $provider); + $this->notifications->notify_appointment_deleted($appointment, $service, $provider, $customer, $settings); } - catch (Exception $exception) + catch (Throwable $e) { - // Display the error message to the customer. - $exceptions[] = $exception; + $exceptions[] = $e; } $view = [ @@ -254,34 +260,34 @@ class Appointments extends EA_Controller { } /** - * GET an specific appointment book and redirect to the success screen. + * Display the appointment registration success page. * * @param string $appointment_hash The appointment hash identifier. * * @throws Exception */ - public function book_success($appointment_hash) + public function book_success(string $appointment_hash) { - $appointments = $this->appointments_model->get_batch(['hash' => $appointment_hash]); + $occurrences = $this->appointments_model->get(['hash' => $appointment_hash]); - if (empty($appointments)) + if (empty($occurrences)) { redirect('appointments'); // The appointment does not exist. return; } - $appointment = $appointments[0]; + $appointment = $occurrences[0]; + unset($appointment['notes']); - $customer = $this->customers_model->get_row($appointment['id_users_customer']); + $customer = $this->customers_model->find($appointment['id_users_customer']); - $provider = $this->providers_model->get_row($appointment['id_users_provider']); + $provider = $this->providers_model->find($appointment['id_users_provider']); - $service = $this->services_model->get_row($appointment['id_services']); + $service = $this->services_model->find($appointment['id_services']); - $company_name = $this->settings_model->get_setting('company_name'); + $company_name = setting('company_name'); - // Get any pending exceptions. $exceptions = $this->session->flashdata('book_success'); $view = [ @@ -313,20 +319,18 @@ class Appointments extends EA_Controller { } /** - * Get the available appointment hours for the given date. + * Get the available appointment hours for the selected date. * * This method answers to an AJAX request. It calculates the available hours for the given service, provider and * date. - * - * Outputs a JSON string with the availabilities. */ public function ajax_get_available_hours() { try { - $provider_id = $this->input->post('provider_id'); - $service_id = $this->input->post('service_id'); - $selected_date = $this->input->post('selected_date'); + $provider_id = request('provider_id'); + $service_id = request('service_id'); + $selected_date = request('selected_date'); // Do not continue if there was no provider selected (more likely there is no provider in the system). if (empty($provider_id)) @@ -340,46 +344,46 @@ class Appointments extends EA_Controller { // If manage mode is TRUE then the following we should not consider the selected appointment when // calculating the available time periods of the provider. - $exclude_appointment_id = $this->input->post('manage_mode') === 'true' ? $this->input->post('appointment_id') : NULL; + $exclude_appointment_id = request('manage_mode') === 'true' ? request('appointment_id') : NULL; // If the user has selected the "any-provider" option then we will need to search for an available provider // that will provide the requested service. - $service = $this->services_model->get_row($service_id); - + $service = $this->services_model->find($service_id); + if ($provider_id === ANY_PROVIDER) { - $providers = $this->providers_model->get_batch(); - - $available_hours = []; - - foreach($providers as $provider) + $providers = $this->providers_model->get(); + + $available_hours = []; + + foreach ($providers as $provider) { - if (!in_array($service_id, $provider['services'])) + if ( ! in_array($service_id, $provider['services'])) { - continue; + continue; } - - $provider_available_hours = $this->availability->get_available_hours($selected_date, $service, $provider, $exclude_appointment_id); - + + $provider_available_hours = $this->availability->get_available_hours($selected_date, $service, $provider, $exclude_appointment_id); + $available_hours = array_merge($available_hours, $provider_available_hours); } - $response = array_unique(array_values($available_hours)); + $response = array_unique(array_values($available_hours)); } else { - $provider = $this->providers_model->get_row($provider_id); + $provider = $this->providers_model->find($provider_id); $response = $this->availability->get_available_hours($selected_date, $service, $provider, $exclude_appointment_id); } } - catch (Exception $exception) + catch (Throwable $e) { $this->output->set_status_header(500); $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] + 'message' => $e->getMessage(), + 'trace' => config('debug') ? $e->getTrace() : [] ]; } @@ -393,19 +397,19 @@ class Appointments extends EA_Controller { * * This method will return the database ID of the provider with the most available periods. * - * @param int $service_id The requested service ID. - * @param string $date The date to be searched (Y-m-d). - * @param string $hour The hour to be searched (H:i). + * @param int $service_id Service ID + * @param string $date Selected date (Y-m-d). + * @param string|null $hour Selected hour (H:i). * * @return int Returns the ID of the provider that can provide the service at the selected date. * * @throws Exception */ - protected function search_any_provider($service_id, $date, $hour = null) + protected function search_any_provider(int $service_id, string $date, string $hour = NULL): int { $available_providers = $this->providers_model->get_available_providers(); - $service = $this->services_model->get_row($service_id); + $service = $this->services_model->find($service_id); $provider_id = NULL; @@ -420,9 +424,10 @@ class Appointments extends EA_Controller { // Check if the provider is available for the requested date. $available_hours = $this->availability->get_available_hours($date, $service, $provider); - if (count($available_hours) > $max_hours_count && (empty($hour) || in_array($hour, $available_hours, false))) + if (count($available_hours) > $max_hours_count && (empty($hour) || in_array($hour, $available_hours, FALSE))) { $provider_id = $provider['id']; + $max_hours_count = count($available_hours); } } @@ -435,24 +440,37 @@ class Appointments extends EA_Controller { /** * Register the appointment to the database. - * - * Outputs a JSON string with the appointment ID. */ public function ajax_register_appointment() { try { - $post_data = $this->input->post('post_data'); - $captcha = $this->input->post('captcha'); + $post_data = request('post_data'); + $captcha = request('captcha'); $manage_mode = filter_var($post_data['manage_mode'], FILTER_VALIDATE_BOOLEAN); $appointment = $post_data['appointment']; $customer = $post_data['customer']; - if (!array_key_exists('address', $customer)){ $customer['address'] = ""; } - if (!array_key_exists('city', $customer)){ $customer['city'] = ""; } - if (!array_key_exists('zip_code', $customer)){ $customer['zip_code'] = ""; } - if (!array_key_exists('notes', $customer)){ $customer['notes'] = ""; } - if (!array_key_exists('phone_number', $customer)){ $customer['address'] = ""; } + if ( ! array_key_exists('address', $customer)) + { + $customer['address'] = ''; + } + if ( ! array_key_exists('city', $customer)) + { + $customer['city'] = ''; + } + if ( ! array_key_exists('zip_code', $customer)) + { + $customer['zip_code'] = ''; + } + if ( ! array_key_exists('notes', $customer)) + { + $customer['notes'] = ''; + } + if ( ! array_key_exists('phone_number', $customer)) + { + $customer['address'] = ''; + } // Check appointment availability before registering it to the database. $appointment['id_users_provider'] = $this->check_datetime_availability(); @@ -462,14 +480,16 @@ class Appointments extends EA_Controller { throw new Exception(lang('requested_hour_is_unavailable')); } - $provider = $this->providers_model->get_row($appointment['id_users_provider']); - $service = $this->services_model->get_row($appointment['id_services']); + $provider = $this->providers_model->find($appointment['id_users_provider']); - $require_captcha = $this->settings_model->get_setting('require_captcha'); - $captcha_phrase = $this->session->userdata('captcha_phrase'); + $service = $this->services_model->find($appointment['id_services']); + + $require_captcha = (bool)setting('require_captcha'); + + $captcha_phrase = session('captcha_phrase'); // Validate the CAPTCHA string. - if ($require_captcha === '1' && $captcha_phrase !== $captcha) + if ($require_captcha && $captcha_phrase !== $captcha) { $this->output ->set_content_type('application/json') @@ -491,23 +511,24 @@ class Appointments extends EA_Controller { } // Save customer language (the language which is used to render the booking page). - $customer['language'] = config('language'); - $customer_id = $this->customers_model->add($customer); + $customer['language'] = session('language') ?? config('language'); + $customer_id = $this->customers_model->save($customer); $appointment['id_users_customer'] = $customer_id; - $appointment['is_unavailable'] = (int)$appointment['is_unavailable']; // needs to be type casted - $appointment['id'] = $this->appointments_model->add($appointment); - $appointment['hash'] = $this->appointments_model->get_value('hash', $appointment['id']); + $appointment['is_unavailable'] = (int)$appointment['is_unavailable']; + $appointment['id'] = $this->appointments_model->save($appointment); + $appointment['hash'] = $this->appointments_model->value($appointment['id'], 'hash'); $settings = [ - 'company_name' => $this->settings_model->get_setting('company_name'), - 'company_link' => $this->settings_model->get_setting('company_link'), - 'company_email' => $this->settings_model->get_setting('company_email'), - 'date_format' => $this->settings_model->get_setting('date_format'), - 'time_format' => $this->settings_model->get_setting('time_format') + 'company_name' => setting('company_name'), + 'company_link' => setting('company_link'), + 'company_email' => setting('company_email'), + 'date_format' => setting('date_format'), + 'time_format' => setting('time_format') ]; $this->synchronization->sync_appointment_saved($appointment, $service, $provider, $customer, $settings, $manage_mode); + $this->notifications->notify_appointment_saved($appointment, $service, $provider, $customer, $settings, $manage_mode); $response = [ @@ -515,13 +536,13 @@ class Appointments extends EA_Controller { 'appointment_hash' => $appointment['hash'] ]; } - catch (Exception $exception) + catch (Throwable $e) { $this->output->set_status_header(500); $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] + 'message' => $e->getMessage(), + 'trace' => config('debug') ? $e->getTrace() : [] ]; } @@ -533,24 +554,27 @@ class Appointments extends EA_Controller { /** * Check whether the provider is still available in the selected appointment date. * - * It might be times where two or more customers select the same appointment date and time. This shouldn't be - * allowed to happen, so one of the two customers will eventually get the preferred date and the other one will have - * to choose for another date. Use this method just before the customer confirms the appointment details. If the - * selected date was taken in the mean time, the customer must be prompted to select another time for his - * appointment. + * It is possible that two or more customers select the same appointment date and time concurrently. The app won't + * allow this to happen, so one of the two will eventually get the selected date and the other one will have + * to choose for another one. + * + * Use this method just before the customer confirms the appointment registration. If the selected date was reserved + * in the meanwhile, the customer must be prompted to select another time. * * @return int Returns the ID of the provider that is available for the appointment. * * @throws Exception */ - protected function check_datetime_availability() + protected function check_datetime_availability(): ?int { - $post_data = $this->input->post('post_data'); + $post_data = request('post_data'); $appointment = $post_data['appointment']; $appointment_start = new DateTime($appointment['start_datetime']); + $date = $appointment_start->format('Y-m-d'); + $hour = $appointment_start->format('H:i'); if ($appointment['id_users_provider'] === ANY_PROVIDER) @@ -560,11 +584,11 @@ class Appointments extends EA_Controller { return $appointment['id_users_provider']; } - $service = $this->services_model->get_row($appointment['id_services']); + $service = $this->services_model->find($appointment['id_services']); - $exclude_appointment_id = isset($appointment['id']) ? $appointment['id'] : NULL; + $exclude_appointment_id = $appointment['id'] ?? NULL; - $provider = $this->providers_model->get_row($appointment['id_users_provider']); + $provider = $this->providers_model->find($appointment['id_users_provider']); $available_hours = $this->availability->get_available_hours($date, $service, $provider, $exclude_appointment_id); @@ -597,11 +621,11 @@ class Appointments extends EA_Controller { { try { - $provider_id = $this->input->get('provider_id'); - $service_id = $this->input->get('service_id'); - $appointment_id = $this->input->get_post('appointment_id'); - $manage_mode = $this->input->get_post('manage_mode'); - $selected_date_string = $this->input->get('selected_date'); + $provider_id = request('provider_id'); + $service_id = request('service_id'); + $appointment_id = request('appointment_id'); + $manage_mode = filter_var(request('manage_mode'), FILTER_VALIDATE_BOOLEAN); + $selected_date_string = request('selected_date'); $selected_date = new DateTime($selected_date_string); $number_of_days_in_month = (int)$selected_date->format('t'); $unavailable_dates = []; @@ -613,7 +637,7 @@ class Appointments extends EA_Controller { $exclude_appointment_id = $manage_mode ? $appointment_id : NULL; // Get the service record. - $service = $this->services_model->get_row($service_id); + $service = $this->services_model->find($service_id); for ($i = 1; $i <= $number_of_days_in_month; $i++) { @@ -629,7 +653,7 @@ class Appointments extends EA_Controller { // Finding at least one slot of availability. foreach ($provider_ids as $current_provider_id) { - $provider = $this->providers_model->get_row($current_provider_id); + $provider = $this->providers_model->find($current_provider_id); $available_hours = $this->availability->get_available_hours( $current_date->format('Y-m-d'), @@ -653,13 +677,13 @@ class Appointments extends EA_Controller { $response = $unavailable_dates; } - catch (Exception $exception) + catch (Throwable $e) { $this->output->set_status_header(500); $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] + 'message' => $e->getMessage(), + 'trace' => config('debug') ? $e->getTrace() : [] ]; } @@ -677,7 +701,7 @@ class Appointments extends EA_Controller { * * @return array Returns the ID of the provider that can provide the requested service. */ - protected function search_providers_by_service($service_id) + protected function search_providers_by_service(int $service_id): array { $available_providers = $this->providers_model->get_available_providers(); $provider_list = []; diff --git a/application/controllers/Backend.php b/application/controllers/Backend.php index 85cddc8a..a597a08a 100755 --- a/application/controllers/Backend.php +++ b/application/controllers/Backend.php @@ -12,9 +12,9 @@ * ---------------------------------------------------------------------------- */ /** - * Backend Controller + * Backend controller * - * @property CI_Session $session + * Handles the backend related operations. * * @package Controllers */ @@ -26,64 +26,65 @@ class Backend extends EA_Controller { { parent::__construct(); - $this->load->model('appointments_model'); - $this->load->model('providers_model'); - $this->load->model('services_model'); - $this->load->model('customers_model'); - $this->load->model('settings_model'); - $this->load->model('roles_model'); - $this->load->model('user_model'); - $this->load->model('secretaries_model'); $this->load->model('admins_model'); - $this->load->library('timezones'); + $this->load->model('appointments_model'); + $this->load->model('customers_model'); + $this->load->model('providers_model'); + $this->load->model('roles_model'); + $this->load->model('secretaries_model'); + $this->load->model('service_categories_model'); + $this->load->model('services_model'); + $this->load->model('settings_model'); + $this->load->model('users_model'); + + $this->load->library('accounts'); $this->load->library('migration'); + $this->load->library('timezones'); } /** * Display the main backend page. * - * This method displays the main backend page. All users login permission can view this page which displays a + * This method displays the main backend page. All login permission can view this page which displays a * calendar with the events of the selected provider or service. If a user has more privileges he will see more * menus at the top of the page. * * @param string $appointment_hash Appointment edit dialog will appear when the page loads (default ''). - * - * @throws Exception */ - public function index($appointment_hash = '') + public function index(string $appointment_hash = '') { - $this->session->set_userdata('dest_url', site_url('backend/index' . (! empty($appointment_hash) ? '/' . $appointment_hash : ''))); + session(['dest_url' => site_url('backend/index' . (! empty($appointment_hash) ? '/' . $appointment_hash : ''))]); - if ( ! $this->has_privileges(PRIV_APPOINTMENTS)) + if ( ! $this->has_permissions(PRIV_APPOINTMENTS)) { return; } - $calendar_view_query_param = $this->input->get('view'); + $calendar_view_query_param = request('view'); - $user_id = $this->session->userdata('user_id'); + $user_id = session('user_id'); - $user = $this->user_model->get_user($user_id); + $user = $this->users_model->find($user_id); $view['base_url'] = config('base_url'); $view['page_title'] = lang('calendar'); - $view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id')); + $view['user_display_name'] = $this->accounts->get_user_display_name($user_id); $view['active_menu'] = PRIV_APPOINTMENTS; - $view['date_format'] = $this->settings_model->get_setting('date_format'); - $view['time_format'] = $this->settings_model->get_setting('time_format'); - $view['first_weekday'] = $this->settings_model->get_setting('first_weekday'); - $view['company_name'] = $this->settings_model->get_setting('company_name'); - $view['require_phone_number'] = $this->settings_model->get_setting('require_phone_number'); + $view['date_format'] = setting('date_format'); + $view['time_format'] = setting('time_format'); + $view['first_weekday'] = setting('first_weekday'); + $view['company_name'] = setting('company_name'); + $view['require_phone_number'] = setting('require_phone_number'); $view['available_providers'] = $this->providers_model->get_available_providers(); $view['available_services'] = $this->services_model->get_available_services(); - $view['customers'] = $this->customers_model->get_batch(); + $view['customers'] = $this->customers_model->get(); $view['calendar_view'] = ! empty($calendar_view_query_param) ? $calendar_view_query_param : $user['settings']['calendar_view']; $view['timezones'] = $this->timezones->to_array(); $this->set_user_data($view); - if ($this->session->userdata('role_slug') === DB_SLUG_SECRETARY) + if (session('role_slug') === DB_SLUG_SECRETARY) { - $secretary = $this->secretaries_model->get_row($this->session->userdata('user_id')); + $secretary = $this->secretaries_model->find(session('user_id')); $view['secretary_providers'] = $secretary['providers']; } else @@ -91,12 +92,12 @@ class Backend extends EA_Controller { $view['secretary_providers'] = []; } - $results = $this->appointments_model->get_batch(['hash' => $appointment_hash]); + $results = $this->appointments_model->get(['hash' => $appointment_hash]); if ($appointment_hash !== '' && count($results) > 0) { $appointment = $results[0]; - $appointment['customer'] = $this->customers_model->get_row($appointment['id_users_customer']); + $appointment['customer'] = $this->customers_model->find($appointment['id_users_customer']); $view['edit_appointment'] = $appointment; // This will display the appointment edit dialog on page load. } else @@ -115,43 +116,40 @@ class Backend extends EA_Controller { * The backend page requires different privileges from the users to display pages. Not all pages are available to * all users. For example secretaries should not be able to edit the system users. * - * @param string $page This argument must match the roles field names of each section (eg "appointments", "users" - * ...). - * @param bool $redirect If the user has not the required privileges (either not logged in or insufficient role - * privileges) then the user will be redirected to another page. Set this argument to FALSE when using ajax (default - * true). + * @param string $page This argument must match the roles field names of each section (e.g. "appointments"). + * @param bool $redirect If the user has not the required privileges either not logged in or insufficient + * permissions then the user will be redirected to another page. * - * @return bool Returns whether the user has the required privileges to view the page or not. If the user is not - * logged in then he will be prompted to log in. If he hasn't the required privileges then an info message will be - * displayed. + * @return bool Returns whether the user has the required privileges to view the page or not. */ - protected function has_privileges($page, $redirect = TRUE) + protected function has_permissions(string $page, bool $redirect = TRUE): bool { // Check if user is logged in. - $user_id = $this->session->userdata('user_id'); + $user_id = session('user_id'); - if ($user_id == FALSE) + if ( ! $user_id) { - // User not logged in, display the login view. if ($redirect) { - header('Location: ' . site_url('user/login')); + redirect('user/login'); } + return FALSE; } // Check if the user has the required privileges for viewing the selected page. - $role_slug = $this->session->userdata('role_slug'); + $role_slug = session('role_slug'); - $role_privileges = $this->db->get_where('roles', ['slug' => $role_slug])->row_array(); + $role_permissions = $this->db->get_where('roles', ['slug' => $role_slug])->row_array(); - if ($role_privileges[$page] < PRIV_VIEW) + if ($role_permissions[$page] < PRIV_VIEW) { // User does not have the permission to view the page. if ($redirect) { - header('Location: ' . site_url('user/no_privileges')); + redirect('user/no_permissions'); } + return FALSE; } @@ -163,13 +161,13 @@ class Backend extends EA_Controller { * * @param array $view Contains the view data. */ - protected function set_user_data(&$view) + protected function set_user_data(array &$view) { - $view['user_id'] = $this->session->userdata('user_id'); - $view['user_email'] = $this->session->userdata('user_email'); - $view['timezone'] = $this->session->userdata('timezone'); - $view['role_slug'] = $this->session->userdata('role_slug'); - $view['privileges'] = $this->roles_model->get_privileges($this->session->userdata('role_slug')); + $view['user_id'] = session('user_id'); + $view['user_email'] = session('user_email'); + $view['timezone'] = session('timezone'); + $view['role_slug'] = session('role_slug'); + $view['privileges'] = $this->roles_model->get_permissions_by_slug(session('role_slug')); } /** @@ -179,30 +177,30 @@ class Backend extends EA_Controller { */ public function customers() { - $this->session->set_userdata('dest_url', site_url('backend/customers')); + session(['dest_url' => site_url('backend/customers')]); - if ( ! $this->has_privileges(PRIV_CUSTOMERS)) + if ( ! $this->has_permissions(PRIV_CUSTOMERS)) { return; } $view['base_url'] = config('base_url'); $view['page_title'] = lang('customers'); - $view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id')); + $view['user_display_name'] = $this->accounts->get_user_display_name(session('user_id')); $view['active_menu'] = PRIV_CUSTOMERS; - $view['company_name'] = $this->settings_model->get_setting('company_name'); - $view['date_format'] = $this->settings_model->get_setting('date_format'); - $view['time_format'] = $this->settings_model->get_setting('time_format'); - $view['first_weekday'] = $this->settings_model->get_setting('first_weekday'); - $view['require_phone_number'] = $this->settings_model->get_setting('require_phone_number'); - $view['customers'] = $this->customers_model->get_batch(); + $view['company_name'] = setting('company_name'); + $view['date_format'] = setting('date_format'); + $view['time_format'] = setting('time_format'); + $view['first_weekday'] = setting('first_weekday'); + $view['require_phone_number'] = setting('require_phone_number'); + $view['customers'] = $this->customers_model->get(); $view['available_providers'] = $this->providers_model->get_available_providers(); $view['available_services'] = $this->services_model->get_available_services(); $view['timezones'] = $this->timezones->to_array(); - if ($this->session->userdata('role_slug') === DB_SLUG_SECRETARY) + if (session('role_slug') === DB_SLUG_SECRETARY) { - $secretary = $this->secretaries_model->get_row($this->session->userdata('user_id')); + $secretary = $this->secretaries_model->find(session('user_id')); $view['secretary_providers'] = $secretary['providers']; } else @@ -227,23 +225,23 @@ class Backend extends EA_Controller { */ public function services() { - $this->session->set_userdata('dest_url', site_url('backend/services')); + session(['dest_url' => site_url('backend/services')]); - if ( ! $this->has_privileges(PRIV_SERVICES)) + if ( ! $this->has_permissions(PRIV_SERVICES)) { return; } $view['base_url'] = config('base_url'); $view['page_title'] = lang('services'); - $view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id')); + $view['user_display_name'] = $this->accounts->get_user_display_name(session('user_id')); $view['active_menu'] = PRIV_SERVICES; - $view['company_name'] = $this->settings_model->get_setting('company_name'); - $view['date_format'] = $this->settings_model->get_setting('date_format'); - $view['time_format'] = $this->settings_model->get_setting('time_format'); - $view['first_weekday'] = $this->settings_model->get_setting('first_weekday'); - $view['services'] = $this->services_model->get_batch(); - $view['categories'] = $this->services_model->get_all_categories(); + $view['company_name'] = setting('company_name'); + $view['date_format'] = setting('date_format'); + $view['time_format'] = setting('time_format'); + $view['first_weekday'] = setting('first_weekday'); + $view['services'] = $this->services_model->get(); + $view['categories'] = $this->service_categories_model->get(); $view['timezones'] = $this->timezones->to_array(); $this->set_user_data($view); @@ -260,26 +258,26 @@ class Backend extends EA_Controller { */ public function users() { - $this->session->set_userdata('dest_url', site_url('backend/users')); + session(['dest_url' => site_url('backend/users')]); - if ( ! $this->has_privileges(PRIV_USERS)) + if ( ! $this->has_permissions(PRIV_USERS)) { return; } $view['base_url'] = config('base_url'); $view['page_title'] = lang('users'); - $view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id')); + $view['user_display_name'] = $this->accounts->get_user_display_name(session('user_id')); $view['active_menu'] = PRIV_USERS; - $view['company_name'] = $this->settings_model->get_setting('company_name'); - $view['date_format'] = $this->settings_model->get_setting('date_format'); - $view['time_format'] = $this->settings_model->get_setting('time_format'); - $view['first_weekday'] = $this->settings_model->get_setting('first_weekday'); - $view['admins'] = $this->admins_model->get_batch(); - $view['providers'] = $this->providers_model->get_batch(); - $view['secretaries'] = $this->secretaries_model->get_batch(); - $view['services'] = $this->services_model->get_batch(); - $view['working_plan'] = $this->settings_model->get_setting('company_working_plan'); + $view['company_name'] = setting('company_name'); + $view['date_format'] = setting('date_format'); + $view['time_format'] = setting('time_format'); + $view['first_weekday'] = setting('first_weekday'); + $view['admins'] = $this->admins_model->get(); + $view['providers'] = $this->providers_model->get(); + $view['secretaries'] = $this->secretaries_model->get(); + $view['services'] = $this->services_model->get(); + $view['working_plan'] = setting('company_working_plan'); $view['timezones'] = $this->timezones->to_array(); $view['working_plan_exceptions'] = '{}'; $this->set_user_data($view); @@ -294,34 +292,36 @@ class Backend extends EA_Controller { * * This page will display the user settings (name, password etc). If current user is an administrator, then he will * be able to make change to the current Easy!Appointment installation (core settings like company name, book - * timeout etc). + * timeout). */ public function settings() { - $this->session->set_userdata('dest_url', site_url('backend/settings')); - if ( ! $this->has_privileges(PRIV_SYSTEM_SETTINGS, FALSE) - && ! $this->has_privileges(PRIV_USER_SETTINGS)) + session(['dest_url' => site_url('backend/settings')]); + + if ( + ! $this->has_permissions(PRIV_SYSTEM_SETTINGS, FALSE) + && ! $this->has_permissions(PRIV_USER_SETTINGS)) { return; } - $user_id = $this->session->userdata('user_id'); + $user_id = session('user_id'); $view['base_url'] = config('base_url'); $view['page_title'] = lang('settings'); - $view['user_display_name'] = $this->user_model->get_user_display_name($user_id); + $view['user_display_name'] = $this->accounts->get_user_display_name($user_id); $view['active_menu'] = PRIV_SYSTEM_SETTINGS; - $view['company_name'] = $this->settings_model->get_setting('company_name'); - $view['date_format'] = $this->settings_model->get_setting('date_format'); - $view['first_weekday'] = $this->settings_model->get_setting('first_weekday'); - $view['time_format'] = $this->settings_model->get_setting('time_format'); - $view['role_slug'] = $this->session->userdata('role_slug'); - $view['system_settings'] = $this->settings_model->get_settings(); - $view['user_settings'] = $this->user_model->get_user($user_id); + $view['company_name'] = setting('company_name'); + $view['date_format'] = setting('date_format'); + $view['first_weekday'] = setting('first_weekday'); + $view['time_format'] = setting('time_format'); + $view['role_slug'] = session('role_slug'); + $view['system_settings'] = $this->settings_model->get(); + $view['user_settings'] = $this->users_model->find($user_id); $view['timezones'] = $this->timezones->to_array(); // book_advance_timeout preview - $book_advance_timeout = $this->settings_model->get_setting('book_advance_timeout'); + $book_advance_timeout = setting('book_advance_timeout'); $hours = floor($book_advance_timeout / 60); $minutes = $book_advance_timeout % 60; $view['book_advance_timeout_preview'] = sprintf('%02d:%02d', $hours, $minutes); @@ -346,7 +346,7 @@ class Backend extends EA_Controller { { try { - if ( ! $this->has_privileges(PRIV_SYSTEM_SETTINGS, TRUE)) + if ( ! $this->has_permissions(PRIV_SYSTEM_SETTINGS)) { throw new Exception('You do not have the required privileges for this task!'); } @@ -358,9 +358,9 @@ class Backend extends EA_Controller { $view = ['success' => TRUE]; } - catch (Exception $exception) + catch (Throwable $e) { - $view = ['success' => FALSE, 'exception' => $exception->getMessage()]; + $view = ['success' => FALSE, 'exception' => $e->getMessage()]; } $this->load->view('general/update', $view); diff --git a/application/controllers/Backend_api.php b/application/controllers/Backend_api.php index 4a188199..f80cf25b 100755 --- a/application/controllers/Backend_api.php +++ b/application/controllers/Backend_api.php @@ -11,14 +11,10 @@ * @since v1.0.0 * ---------------------------------------------------------------------------- */ -use EA\Engine\Notifications\Email as EmailClient; -use EA\Engine\Types\Email; -use EA\Engine\Types\Text; - /** - * Backend API Controller + * Backend API controller * - * Contains all the backend AJAX callbacks. + * Handles the backend API related operations. * * @package Controllers */ @@ -26,10 +22,10 @@ class Backend_api extends EA_Controller { /** * @var array */ - protected $privileges; + protected $permissions; /** - * Class Constructor + * Backend_api constructor. */ public function __construct() { @@ -42,18 +38,22 @@ class Backend_api extends EA_Controller { $this->load->model('providers_model'); $this->load->model('roles_model'); $this->load->model('secretaries_model'); + $this->load->model('service_categories_model'); $this->load->model('services_model'); $this->load->model('settings_model'); - $this->load->model('user_model'); + $this->load->model('users_model'); + $this->load->library('google_sync'); $this->load->library('ics_file'); $this->load->library('notifications'); $this->load->library('synchronization'); $this->load->library('timezones'); - if ($this->session->userdata('role_slug')) + $role_slug = session('role_slug'); + + if ($role_slug) { - $this->privileges = $this->roles_model->get_privileges($this->session->userdata('role_slug')); + $this->permissions = $this->roles_model->get_permissions_by_slug($role_slug); } } @@ -66,16 +66,17 @@ class Backend_api extends EA_Controller { { try { - $start_date = $this->input->post('startDate') . ' 00:00:00'; - $end_date = $this->input->post('endDate') . ' 23:59:59'; + $start_date = request('startDate') . ' 00:00:00'; + + $end_date = request('endDate') . ' 23:59:59'; $response = [ - 'appointments' => $this->appointments_model->get_batch([ + 'appointments' => $this->appointments_model->get([ 'is_unavailable' => FALSE, 'start_datetime >=' => $start_date, 'end_datetime <=' => $end_date ]), - 'unavailability_events' => $this->appointments_model->get_batch([ + 'unavailability_events' => $this->appointments_model->get([ 'is_unavailable' => TRUE, 'start_datetime >=' => $start_date, 'end_datetime <=' => $end_date @@ -84,14 +85,16 @@ class Backend_api extends EA_Controller { foreach ($response['appointments'] as &$appointment) { - $appointment['provider'] = $this->providers_model->get_row($appointment['id_users_provider']); - $appointment['service'] = $this->services_model->get_row($appointment['id_services']); - $appointment['customer'] = $this->customers_model->get_row($appointment['id_users_customer']); + $appointment['provider'] = $this->providers_model->find($appointment['id_users_provider']); + $appointment['service'] = $this->services_model->find($appointment['id_services']); + $appointment['customer'] = $this->customers_model->find($appointment['id_users_customer']); } - unset ($appointment); - $user_id = $this->session->userdata('user_id'); - $role_slug = $this->session->userdata('role_slug'); + unset($appointment); + + $user_id = session('user_id'); + + $role_slug = session('role_slug'); // If the current user is a provider he must only see his own appointments. if ($role_slug === DB_SLUG_PROVIDER) @@ -116,7 +119,8 @@ class Backend_api extends EA_Controller { // If the current user is a secretary he must only see the appointments of his providers. if ($role_slug === DB_SLUG_SECRETARY) { - $providers = $this->secretaries_model->get_row($user_id)['providers']; + $providers = $this->secretaries_model->find($user_id)['providers']; + foreach ($response['appointments'] as $index => $appointment) { if ( ! in_array((int)$appointment['id_users_provider'], $providers)) @@ -134,47 +138,42 @@ class Backend_api extends EA_Controller { } } - $this->output->set_output(json_encode($response)); + json_response($response); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** * Get the registered appointments for the given date period and record. * - * This method returns the database appointments and unavailable periods for the - * user selected date period and record type (provider or service). + * This method returns the database appointments and unavailable periods for the user selected date period and + * record type (provider or service). */ public function ajax_get_calendar_appointments() { try { - if ($this->privileges[PRIV_APPOINTMENTS]['view'] == FALSE) + if ($this->permissions[PRIV_APPOINTMENTS]['view'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - if ( ! $this->input->post('filter_type')) + $filter_type = request('filter_type'); + + if ( ! $filter_type) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['appointments' => []])); + json_response([ + 'appointments' => [], + 'unavailables' => [] + ]); + return; } - if ($this->input->post('filter_type') == FILTER_TYPE_PROVIDER) + if ($filter_type == FILTER_TYPE_PROVIDER) { $where_id = 'id_users_provider'; } @@ -184,9 +183,9 @@ class Backend_api extends EA_Controller { } // Get appointments - $record_id = $this->db->escape($this->input->post('record_id')); - $start_date = $this->db->escape($this->input->post('start_date')); - $end_date = $this->db->escape(date('Y-m-d', strtotime($this->input->post('end_date') . ' +1 day'))); + $record_id = $this->db->escape(request('record_id')); + $start_date = $this->db->escape(request('start_date')); + $end_date = $this->db->escape(date('Y-m-d', strtotime(request('end_date') . ' +1 day'))); $where_clause = $where_id . ' = ' . $record_id . ' AND ((start_datetime > ' . $start_date . ' AND start_datetime < ' . $end_date . ') @@ -195,19 +194,19 @@ class Backend_api extends EA_Controller { AND is_unavailable = 0 '; - $response['appointments'] = $this->appointments_model->get_batch($where_clause); + $response['appointments'] = $this->appointments_model->get($where_clause); foreach ($response['appointments'] as &$appointment) { - $appointment['provider'] = $this->providers_model->get_row($appointment['id_users_provider']); - $appointment['service'] = $this->services_model->get_row($appointment['id_services']); - $appointment['customer'] = $this->customers_model->get_row($appointment['id_users_customer']); + $appointment['provider'] = $this->providers_model->find($appointment['id_users_provider']); + $appointment['service'] = $this->services_model->find($appointment['id_services']); + $appointment['customer'] = $this->customers_model->find($appointment['id_users_customer']); } // Get unavailable periods (only for provider). $response['unavailables'] = []; - if ($this->input->post('filter_type') == FILTER_TYPE_PROVIDER) + if ($filter_type == FILTER_TYPE_PROVIDER) { $where_clause = $where_id . ' = ' . $record_id . ' AND ((start_datetime > ' . $start_date . ' AND start_datetime < ' . $end_date . ') @@ -216,31 +215,20 @@ class Backend_api extends EA_Controller { AND is_unavailable = 1 '; - $response['unavailables'] = $this->appointments_model->get_batch($where_clause); + $response['unavailables'] = $this->appointments_model->get($where_clause); } foreach ($response['unavailables'] as &$unavailable) { - $unavailable['provider'] = $this->providers_model->get_row($unavailable['id_users_provider']); + $unavailable['provider'] = $this->providers_model->find($unavailable['id_users_provider']); } - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); + json_response($response); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -251,77 +239,82 @@ class Backend_api extends EA_Controller { try { // Save customer changes to the database. - if ($this->input->post('customer_data')) - { - $customer = json_decode($this->input->post('customer_data'), TRUE); + $customer_data = request('customer_data'); - $required_privileges = ( ! isset($customer['id'])) - ? $this->privileges[PRIV_CUSTOMERS]['add'] - : $this->privileges[PRIV_CUSTOMERS]['edit']; - if ($required_privileges == FALSE) + if ($customer_data) + { + $customer = json_decode($customer_data, TRUE); + + $required_permissions = ( ! isset($customer['id'])) + ? $this->permissions[PRIV_CUSTOMERS]['add'] + : $this->permissions[PRIV_CUSTOMERS]['edit']; + + if ($required_permissions == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $customer['id'] = $this->customers_model->add($customer); + $customer['id'] = $this->customers_model->save($customer); } // Save appointment changes to the database. - if ($this->input->post('appointment_data')) - { - $appointment = json_decode($this->input->post('appointment_data'), TRUE); + $appointment_data = request('appointment_data'); - $required_privileges = ( ! isset($appointment['id'])) - ? $this->privileges[PRIV_APPOINTMENTS]['add'] - : $this->privileges[PRIV_APPOINTMENTS]['edit']; - if ($required_privileges == FALSE) + $manage_mode = ! empty($appointment_data['id']); + + if ($appointment_data) + { + $appointment = json_decode($appointment_data, TRUE); + + $required_permissions = ( ! isset($appointment['id'])) + ? $this->permissions[PRIV_APPOINTMENTS]['add'] + : $this->permissions[PRIV_APPOINTMENTS]['edit']; + + if ($required_permissions == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $manage_mode = isset($appointment['id']); - - // If the appointment does not contain the customer record id, then it means that is is going to be - // inserted. Get the customer's record ID. + // If the appointment does not contain the customer record id, then it means that is going to be + // inserted. if ( ! isset($appointment['id_users_customer'])) { - $appointment['id_users_customer'] = $customer['id']; + $appointment['id_users_customer'] = $customer['id'] ?? $customer_data['id']; } - $appointment['id'] = $this->appointments_model->add($appointment); + $appointment['id'] = $this->appointments_model->save($appointment); } - $appointment = $this->appointments_model->get_row($appointment['id']); - $provider = $this->providers_model->get_row($appointment['id_users_provider']); - $customer = $this->customers_model->get_row($appointment['id_users_customer']); - $service = $this->services_model->get_row($appointment['id_services']); + if (empty($appointment['id'])) + { + throw new RuntimeException('The appointment ID is not available.'); + } + + $appointment = $this->appointments_model->find($appointment['id']); + $provider = $this->providers_model->find($appointment['id_users_provider']); + $customer = $this->customers_model->find($appointment['id_users_customer']); + $service = $this->services_model->find($appointment['id_services']); $settings = [ - 'company_name' => $this->settings_model->get_setting('company_name'), - 'company_link' => $this->settings_model->get_setting('company_link'), - 'company_email' => $this->settings_model->get_setting('company_email'), - 'date_format' => $this->settings_model->get_setting('date_format'), - 'time_format' => $this->settings_model->get_setting('time_format') + 'company_name' => setting('company_name'), + 'company_link' => setting('company_link'), + 'company_email' => setting('company_email'), + 'date_format' => setting('date_format'), + 'time_format' => setting('time_format') ]; $this->synchronization->sync_appointment_saved($appointment, $service, $provider, $customer, $settings, $manage_mode); + $this->notifications->notify_appointment_saved($appointment, $service, $provider, $customer, $settings, $manage_mode); - $response = AJAX_SUCCESS; + json_response([ + 'success' => TRUE, + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -335,118 +328,106 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_APPOINTMENTS]['delete'] == FALSE) + if (cannot('delete', 'appointments')) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - if ( ! $this->input->post('appointment_id')) + $appointment_id = request('appointment_id'); + + if (empty($appointment_id)) { throw new Exception('No appointment id provided.'); } // Store appointment data for later use in this method. - $appointment = $this->appointments_model->get_row($this->input->post('appointment_id')); - $provider = $this->providers_model->get_row($appointment['id_users_provider']); - $customer = $this->customers_model->get_row($appointment['id_users_customer']); - $service = $this->services_model->get_row($appointment['id_services']); + $appointment = $this->appointments_model->find($appointment_id); + $provider = $this->providers_model->find($appointment['id_users_provider']); + $customer = $this->customers_model->find($appointment['id_users_customer']); + $service = $this->services_model->find($appointment['id_services']); $settings = [ - 'company_name' => $this->settings_model->get_setting('company_name'), - 'company_email' => $this->settings_model->get_setting('company_email'), - 'company_link' => $this->settings_model->get_setting('company_link'), - 'date_format' => $this->settings_model->get_setting('date_format'), - 'time_format' => $this->settings_model->get_setting('time_format') + 'company_name' => setting('company_name'), + 'company_email' => setting('company_email'), + 'company_link' => setting('company_link'), + 'date_format' => setting('date_format'), + 'time_format' => setting('time_format') ]; // Delete appointment record from the database. - $this->appointments_model->delete($this->input->post('appointment_id')); + $this->appointments_model->delete($appointment_id); $this->notifications->notify_appointment_deleted($appointment, $service, $provider, $customer, $settings); $this->synchronization->sync_appointment_deleted($appointment, $provider); - if (empty($warnings)) - { - $response = AJAX_SUCCESS; - } - else - { - $response = ['warnings' => $warnings]; - } + json_response([ + 'success' => TRUE, + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** * Disable a providers sync setting. * - * This method deletes the "google_sync" and "google_token" settings from the database. After that the provider's - * appointments will be no longer synced with google calendar. + * This method deletes the "google_sync" and "google_token" settings from the database. + * + * After that the provider's appointments will be no longer synced with Google Calendar. */ public function ajax_disable_provider_sync() { try { - if ( ! $this->input->post('provider_id')) + $provider_id = request('provider_id'); + + if ( ! $provider_id) { throw new Exception('Provider id not specified.'); } - if ($this->privileges[PRIV_USERS]['edit'] == FALSE - && $this->session->userdata('user_id') != $this->input->post('provider_id')) + $user_id = session('user_id'); + + if ( + $this->permissions[PRIV_USERS]['edit'] === FALSE + && (int)$user_id !== (int)$provider_id) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $this->providers_model->set_setting('google_sync', FALSE, $this->input->post('provider_id')); - $this->providers_model->set_setting('google_token', NULL, $this->input->post('provider_id')); - $this->appointments_model->clear_google_sync_ids($this->input->post('provider_id')); + $this->providers_model->set_setting($provider_id, 'google_sync', FALSE); - $response = AJAX_SUCCESS; + $this->providers_model->set_setting($provider_id, 'google_token', NULL); + + $this->appointments_model->clear_google_sync_ids($provider_id); + + json_response([ + 'success' => TRUE, + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** * Filter the customer records with the given key string. - * - * Outputs the search results. */ public function ajax_filter_customers() { try { - if ($this->privileges[PRIV_CUSTOMERS]['view'] == FALSE) + if ($this->permissions[PRIV_CUSTOMERS]['view'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $key = $this->db->escape_str($this->input->post('key')); + $key = $this->db->escape_str(request('key')); + $key = strtoupper($key); $where = @@ -461,43 +442,36 @@ class Backend_api extends EA_Controller { $order_by = 'first_name ASC, last_name ASC'; - $limit = $this->input->post('limit'); + $limit = request('limit'); if ($limit === NULL) { $limit = 1000; } - $customers = $this->customers_model->get_batch($where, $limit, NULL, $order_by); + $customers = $this->customers_model->get($where, $limit, NULL, $order_by); foreach ($customers as &$customer) { - $appointments = $this->appointments_model->get_batch(['id_users_customer' => $customer['id']]); + $appointments = $this->appointments_model->get(['id_users_customer' => $customer['id']]); foreach ($appointments as &$appointment) { - $appointment['service'] = $this->services_model->get_row($appointment['id_services']); - $appointment['provider'] = $this->providers_model->get_row($appointment['id_users_provider']); + $this->appointments_model->attach($appointment, [ + 'service', + 'provider', + ]); } $customer['appointments'] = $appointments; } - $response = $customers; + json_response($customers); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -508,32 +482,31 @@ class Backend_api extends EA_Controller { try { // Check privileges - $unavailable = json_decode($this->input->post('unavailable'), TRUE); + $unavailable = json_decode(request('unavailable'), TRUE); - $required_privileges = ( ! isset($unavailable['id'])) - ? $this->privileges[PRIV_APPOINTMENTS]['add'] - : $this->privileges[PRIV_APPOINTMENTS]['edit']; - if ($required_privileges == FALSE) + $required_permissions = ( ! isset($unavailable['id'])) + ? $this->permissions[PRIV_APPOINTMENTS]['add'] + : $this->permissions[PRIV_APPOINTMENTS]['edit']; + + if ( ! $required_permissions) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $provider = $this->providers_model->get_row($unavailable['id_users_provider']); + $provider = $this->providers_model->find($unavailable['id_users_provider']); // Add appointment $unavailable['id'] = $this->appointments_model->add_unavailable($unavailable); - $unavailable = $this->appointments_model->get_row($unavailable['id']); // fetch all inserted data + $unavailable = $this->appointments_model->find($unavailable['id']); // fetch all inserted data // Google Sync try { - $google_sync = $this->providers_model->get_setting('google_sync', - $unavailable['id_users_provider']); + $google_sync = $this->providers_model->get_setting($unavailable['id_users_provider'], 'google_sync'); if ($google_sync) { - $google_token = json_decode($this->providers_model->get_setting('google_token', - $unavailable['id_users_provider'])); + $google_token = json_decode($this->providers_model->get_setting($unavailable['id_users_provider'], 'google_token')); $this->google_sync->refresh_token($google_token->refresh_token); @@ -549,39 +522,20 @@ class Backend_api extends EA_Controller { } } } - catch (Exception $exception) + catch (Throwable $e) { - $warnings[] = $exception; + $warnings[] = $e; } - if (isset($warnings)) - { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['warnings' => $warnings])); - } - else - { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); - } - - $response = AJAX_SUCCESS; + json_response([ + 'success' => TRUE, + 'warnings' => $warnings ?? [] + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -591,55 +545,47 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_APPOINTMENTS]['delete'] == FALSE) + if ($this->permissions[PRIV_APPOINTMENTS]['delete'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $unavailable = $this->appointments_model->get_row($this->input->post('unavailable_id')); - $provider = $this->providers_model->get_row($unavailable['id_users_provider']); + $unavailable_id = request('unavailable_id'); + + $unavailable = $this->appointments_model->find($unavailable_id); + + $provider = $this->providers_model->find($unavailable['id_users_provider']); - // Delete unavailable $this->appointments_model->delete_unavailable($unavailable['id']); // Google Sync try { - $google_sync = $this->providers_model->get_setting('google_sync', $provider['id']); + $google_sync = $this->providers_model->get_setting($provider['id'], 'google_sync'); + if ($google_sync == TRUE) { - $google_token = json_decode($this->providers_model->get_setting('google_token', $provider['id'])); + $google_token = json_decode($this->providers_model->get_setting($provider['id'], 'google_token')); + $this->google_sync->refresh_token($google_token->refresh_token); + $this->google_sync->delete_unavailable($provider, $unavailable['id_google_calendar']); } } - catch (Exception $exception) + catch (Throwable $e) { - $warnings[] = $exception; + $warnings[] = $e; } - if (empty($warnings)) - { - $response = AJAX_SUCCESS; - } - else - { - $response = ['warnings' => $warnings]; - } + json_response([ + 'success' => TRUE, + 'warnings' => $warnings ?? [] + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -649,86 +595,59 @@ class Backend_api extends EA_Controller { { try { - // Check privileges - $required_privileges = $this->privileges[PRIV_USERS]['edit']; + $required_permissions = $this->permissions[PRIV_USERS]['edit']; - if ($required_privileges == FALSE) + if ( ! $required_permissions) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $date = $this->input->post('date'); - $working_plan_exception = $this->input->post('working_plan_exception'); - $provider_id = $this->input->post('provider_id'); + $date = request('date'); - $success = $this->providers_model->save_working_plan_exception($date, $working_plan_exception, $provider_id); + $working_plan_exception = request('working_plan_exception'); - if ($success) - { - $response = AJAX_SUCCESS; - } - else - { - $response = ['warnings' => 'Error on saving working plan exception.']; - } + $provider_id = request('provider_id'); + + $this->providers_model->save_working_plan_exception($provider_id, $date, $working_plan_exception); + + json_response([ + 'success' => TRUE, + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** - * Delete an working plan exceptions time period to database. + * Delete a working plan exceptions time period to database. */ public function ajax_delete_working_plan_exception() { try { - // Check privileges - $required_privileges = $this->privileges[PRIV_USERS]['edit']; + $required_permissions = $this->permissions[PRIV_USERS]['edit']; - if ($required_privileges == FALSE) + if ( ! $required_permissions) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $date = $this->input->post('date'); - $provider_id = $this->input->post('provider_id'); + $date = request('date'); - $success = $this->providers_model->delete_working_plan_exception($date, $provider_id); + $provider_id = request('provider_id'); - if ($success) - { - $response = AJAX_SUCCESS; - } - else - { - $response = ['warnings' => 'Error on deleting working plan exception.']; - } + $this->providers_model->delete_working_plan_exception($provider_id, $date); + + json_response([ + 'success' => TRUE + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -738,36 +657,28 @@ class Backend_api extends EA_Controller { { try { - $customer = json_decode($this->input->post('customer'), TRUE); + $customer = json_decode(request('customer'), TRUE); - $required_privileges = ( ! isset($customer['id'])) - ? $this->privileges[PRIV_CUSTOMERS]['add'] - : $this->privileges[PRIV_CUSTOMERS]['edit']; - if ($required_privileges == FALSE) + $required_permissions = ( ! isset($customer['id'])) + ? $this->permissions[PRIV_CUSTOMERS]['add'] + : $this->permissions[PRIV_CUSTOMERS]['edit']; + + if ( ! $required_permissions) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $customer_id = $this->customers_model->add($customer); + $customer_id = $this->customers_model->save($customer); - $response = [ - 'status' => AJAX_SUCCESS, + json_response([ + 'success' => TRUE, 'id' => $customer_id - ]; + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -777,28 +688,19 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_CUSTOMERS]['delete'] == FALSE) + if ($this->permissions[PRIV_CUSTOMERS]['delete'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $this->customers_model->delete($this->input->post('customer_id')); + $this->customers_model->delete(request('customer_id')); - $response = AJAX_SUCCESS; + response(); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -808,35 +710,28 @@ class Backend_api extends EA_Controller { { try { - $service = json_decode($this->input->post('service'), TRUE); + $service = json_decode(request('service'), TRUE); - $required_privileges = ( ! isset($service['id'])) - ? $this->privileges[PRIV_SERVICES]['add'] - : $this->privileges[PRIV_SERVICES]['edit']; - if ($required_privileges == FALSE) + $required_permissions = ( ! isset($service['id'])) + ? $this->permissions[PRIV_SERVICES]['add'] + : $this->permissions[PRIV_SERVICES]['edit']; + + if ( ! $required_permissions) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $service_id = $this->services_model->add($service); - $response = [ - 'status' => AJAX_SUCCESS, + $service_id = $this->services_model->save($service); + + json_response([ + 'success' => TRUE, 'id' => $service_id - ]; + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -846,28 +741,23 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_SERVICES]['delete'] == FALSE) + if ($this->permissions[PRIV_SERVICES]['delete'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $result = $this->services_model->delete($this->input->post('service_id')); + $service_id = request('service_id'); - $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; + $this->services_model->delete($service_id); + + json_response([ + 'success' => TRUE, + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -877,33 +767,26 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_SERVICES]['view'] == FALSE) + if ($this->permissions[PRIV_SERVICES]['view'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $key = $this->db->escape_str($this->input->post('key')); + $key = $this->db->escape_str(request('key')); $where = '(name LIKE "%' . $key . '%" OR duration LIKE "%' . $key . '%" OR ' . 'price LIKE "%' . $key . '%" OR currency LIKE "%' . $key . '%" OR ' . 'description LIKE "%' . $key . '%")'; - $response = $this->services_model->get_batch($where); + $services = $this->services_model->get($where); + + json_response($services); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -913,36 +796,28 @@ class Backend_api extends EA_Controller { { try { - $category = json_decode($this->input->post('category'), TRUE); + $category = json_decode(request('category'), TRUE); - $required_privileges = ( ! isset($category['id'])) - ? $this->privileges[PRIV_SERVICES]['add'] - : $this->privileges[PRIV_SERVICES]['edit']; - if ($required_privileges == FALSE) + $required_permissions = ( ! isset($category['id'])) + ? $this->permissions[PRIV_SERVICES]['add'] + : $this->permissions[PRIV_SERVICES]['edit']; + + if ( ! $required_permissions) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $category_id = $this->services_model->add_category($category); + $category_id = $this->service_categories_model->save($category); - $response = [ - 'status' => AJAX_SUCCESS, + json_response([ + 'success' => TRUE, 'id' => $category_id - ]; + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -952,28 +827,23 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_SERVICES]['delete'] == FALSE) + if ($this->permissions[PRIV_SERVICES]['delete'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $result = $this->services_model->delete_category($this->input->post('category_id')); + $service_category_id = request('category_id'); - $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; + $this->service_categories_model->delete($service_category_id); + + json_response([ + 'success' => TRUE + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -983,30 +853,23 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_SERVICES]['view'] == FALSE) + if ($this->permissions[PRIV_SERVICES]['view'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $key = $this->db->escape_str($this->input->post('key')); + $key = $this->db->escape_str(request('key')); $where = '(name LIKE "%' . $key . '%" OR description LIKE "%' . $key . '%")'; - $response = $this->services_model->get_all_categories($where); + $service_categories = $this->service_categories_model->get($where); + + json_response($service_categories); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1016,12 +879,12 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_USERS]['view'] == FALSE) + if ($this->permissions[PRIV_USERS]['view'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $key = $this->db->escape_str($this->input->post('key')); + $key = $this->db->escape_str(request('key')); $where = '(first_name LIKE "%' . $key . '%" OR last_name LIKE "%' . $key . '%" ' . @@ -1030,21 +893,14 @@ class Backend_api extends EA_Controller { 'OR city LIKE "%' . $key . '%" OR state LIKE "%' . $key . '%" ' . 'OR zip_code LIKE "%' . $key . '%" OR notes LIKE "%' . $key . '%")'; - $response = $this->admins_model->get_batch($where); + $admins = $this->admins_model->get($where); + + json_response($admins); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1054,36 +910,27 @@ class Backend_api extends EA_Controller { { try { - $admin = json_decode($this->input->post('admin'), TRUE); + $admin = json_decode(request('admin'), TRUE); - $required_privileges = ( ! isset($admin['id'])) - ? $this->privileges[PRIV_USERS]['add'] - : $this->privileges[PRIV_USERS]['edit']; - if ($required_privileges == FALSE) + $required_permissions = ( ! isset($admin['id'])) + ? $this->permissions[PRIV_USERS]['add'] + : $this->permissions[PRIV_USERS]['edit']; + if ( ! $required_permissions) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $admin_id = $this->admins_model->add($admin); + $admin_id = $this->admins_model->save($admin); - $response = [ - 'status' => AJAX_SUCCESS, + json_response([ + 'success' => TRUE, 'id' => $admin_id - ]; + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1093,28 +940,23 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_USERS]['delete'] == FALSE) + if ($this->permissions[PRIV_USERS]['delete'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $result = $this->admins_model->delete($this->input->post('admin_id')); + $admin_id = request('admin_id'); - $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; + $this->admins_model->delete($admin_id); + + json_response([ + 'success' => TRUE + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1124,12 +966,12 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_USERS]['view'] == FALSE) + if ($this->permissions[PRIV_USERS]['view'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $key = $this->db->escape_str($this->input->post('key')); + $key = $this->db->escape_str(request('key')); $where = '(first_name LIKE "%' . $key . '%" OR last_name LIKE "%' . $key . '%" ' . @@ -1138,21 +980,14 @@ class Backend_api extends EA_Controller { 'OR city LIKE "%' . $key . '%" OR state LIKE "%' . $key . '%" ' . 'OR zip_code LIKE "%' . $key . '%" OR notes LIKE "%' . $key . '%")'; - $response = $this->providers_model->get_batch($where); + $providers = $this->providers_model->get($where); + + json_response($providers); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1162,42 +997,33 @@ class Backend_api extends EA_Controller { { try { - $provider = json_decode($this->input->post('provider'), TRUE); + $provider = json_decode(request('provider'), TRUE); - $required_privileges = ( ! isset($provider['id'])) - ? $this->privileges[PRIV_USERS]['add'] - : $this->privileges[PRIV_USERS]['edit']; - if ($required_privileges == FALSE) + $required_permissions = ( ! isset($provider['id'])) + ? $this->permissions[PRIV_USERS]['add'] + : $this->permissions[PRIV_USERS]['edit']; + + if ( ! $required_permissions) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - if ( ! isset($provider['settings']['working_plan'])) + if (empty($provider['settings']['working_plan'])) { - $provider['settings']['working_plan'] = $this->settings_model - ->get_setting('company_working_plan'); + $provider['settings']['working_plan'] = setting('company_working_plan'); } - $provider_id = $this->providers_model->add($provider); + $provider_id = $this->providers_model->save($provider); - $response = [ - 'status' => AJAX_SUCCESS, + json_response([ + 'success' => TRUE, 'id' => $provider_id - ]; + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1207,28 +1033,23 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_USERS]['delete'] == FALSE) + if ($this->permissions[PRIV_USERS]['delete'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $result = $this->providers_model->delete($this->input->post('provider_id')); + $provider_id = request('provider_id'); - $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; + $this->providers_model->delete($provider_id); + + json_response([ + 'success' => TRUE + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1238,12 +1059,12 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_USERS]['view'] == FALSE) + if ($this->permissions[PRIV_USERS]['view'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $key = $this->db->escape_str($this->input->post('key')); + $key = $this->db->escape_str(request('key')); $where = '(first_name LIKE "%' . $key . '%" OR last_name LIKE "%' . $key . '%" ' . @@ -1252,21 +1073,14 @@ class Backend_api extends EA_Controller { 'OR city LIKE "%' . $key . '%" OR state LIKE "%' . $key . '%" ' . 'OR zip_code LIKE "%' . $key . '%" OR notes LIKE "%' . $key . '%")'; - $response = $this->secretaries_model->get_batch($where); + $secretaries = $this->secretaries_model->get($where); + + json_response($secretaries); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1276,36 +1090,27 @@ class Backend_api extends EA_Controller { { try { - $secretary = json_decode($this->input->post('secretary'), TRUE); + $secretary = json_decode(request('secretary'), TRUE); - $required_privileges = ( ! isset($secretary['id'])) - ? $this->privileges[PRIV_USERS]['add'] - : $this->privileges[PRIV_USERS]['edit']; - if ($required_privileges == FALSE) + $required_permissions = ( ! isset($secretary['id'])) + ? $this->permissions[PRIV_USERS]['add'] + : $this->permissions[PRIV_USERS]['edit']; + if ( ! $required_permissions) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $secretary_id = $this->secretaries_model->add($secretary); + $secretary_id = $this->secretaries_model->save($secretary); - $response = [ - 'status' => AJAX_SUCCESS, + json_response([ + 'success' => TRUE, 'id' => $secretary_id - ]; + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1315,28 +1120,23 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_USERS]['delete'] == FALSE) + if ($this->permissions[PRIV_USERS]['delete'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $result = $this->secretaries_model->delete($this->input->post('secretary_id')); + $secretary_id = request('secretary_id'); - $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; + $this->secretaries_model->delete($secretary_id); + + json_response([ + 'success' => TRUE + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1346,71 +1146,77 @@ class Backend_api extends EA_Controller { { try { - if ($this->input->post('type') == SETTINGS_SYSTEM) + $type = request('type'); + + if ($type == SETTINGS_SYSTEM) { - if ($this->privileges[PRIV_SYSTEM_SETTINGS]['edit'] == FALSE) + if ($this->permissions[PRIV_SYSTEM_SETTINGS]['edit'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $settings = json_decode($this->input->post('settings', FALSE), TRUE); + $settings = json_decode(request('settings', FALSE), TRUE); + + // Check if phone number settings are valid. + + $phone_number_required = FALSE; + + $phone_number_shown = FALSE; - //check if phone number settings are valid - $phone_number_required = false; - $phone_number_shown = false; foreach ($settings as $setting) { - if ($setting['name'] == "require_phone_number"){ + if ($setting['name'] === 'require_phone_number') + { $phone_number_required = $setting['value']; } - if ($setting['name'] == "show_phone_number"){ + if ($setting['name'] === 'show_phone_number') + { $phone_number_shown = $setting['value']; } } - if ($phone_number_required && !$phone_number_shown){//we have settings that break the appointments field. - throw new Exception("You cannot hide the phone number in the booking form while it's also required!"); + if ($phone_number_required && ! $phone_number_shown) + { + throw new RuntimeException('You cannot hide the phone number in the booking form while it\'s also required!'); } - $this->settings_model->save_settings($settings); - } - else - { - if ($this->input->post('type') == SETTINGS_USER) + foreach ($settings as $setting) { - if ($this->privileges[PRIV_USER_SETTINGS]['edit'] == FALSE) + $existing_setting = $this->settings_model->query()->where('name', $setting['name'])->get()->row_array(); + + if ( ! empty($existing_setting)) { - throw new Exception('You do not have the required privileges for this task.'); + $setting['id'] = $existing_setting['id']; } - $settings = json_decode($this->input->post('settings'), TRUE); - - $this->user_model->save_user($settings); - - $this->session->set_userdata([ - 'user_email' => $settings['email'], - 'username' => $settings['settings']['username'], - 'timezone' => $settings['timezone'], - ]); + $this->settings_model->save($setting); } } + else if ($type == SETTINGS_USER) + { + if ($this->permissions[PRIV_USER_SETTINGS]['edit'] == FALSE) + { + throw new Exception('You do not have the required permissions for this task.'); + } - $response = AJAX_SUCCESS; + $settings = json_decode(request('settings'), TRUE); + + $this->users_model->save($settings); + + session([ + 'user_email' => $settings['email'], + 'username' => $settings['settings']['username'], + 'timezone' => $settings['timezone'], + ]); + } + + response(); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1422,24 +1228,21 @@ class Backend_api extends EA_Controller { { // We will only use the function in the admins_model because it is sufficient for the rest user types for // now (providers, secretaries). - $is_valid = $this->admins_model->validate_username($this->input->post('username'), - $this->input->post('user_id')); - $response = $is_valid; + $username = request('username'); + + $user_id = request('user_id'); + + $is_valid = $this->admins_model->validate_username($username, $user_id); + + json_response([ + 'is_valid' => $is_valid, + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1456,7 +1259,7 @@ class Backend_api extends EA_Controller { foreach (config('available_languages') as $lang) { - if ($lang == $this->input->post('language')) + if ($lang == request('language')) { $found = TRUE; break; @@ -1465,31 +1268,27 @@ class Backend_api extends EA_Controller { if ( ! $found) { - throw new Exception('Translations for the given language does not exist (' . $this->input->post('language') . ').'); + throw new Exception('Translations for the given language does not exist (' . request('language') . ').'); } - $this->session->set_userdata('language', $this->input->post('language')); - $this->config->set_item('language', $this->input->post('language')); + $language = request('language'); - $response = AJAX_SUCCESS; + session(['language' => $language]); + + config(['language' => $language]); + + json_response([ + 'success' => TRUE + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** - * This method will return a list of the available google calendars. + * This method will return a list of the available Google Calendars. * * The user will need to select a specific calendar from this list to sync his appointments with. Google access must * be already granted for the specific provider. @@ -1498,42 +1297,37 @@ class Backend_api extends EA_Controller { { try { - if ( ! $this->input->post('provider_id')) + if ( ! request('provider_id')) { throw new Exception('Provider id is required in order to fetch the google calendars.'); } // Check if selected provider has sync enabled. - $google_sync = $this->providers_model->get_setting('google_sync', $this->input->post('provider_id')); + $provider_id = request('provider_id'); - if ($google_sync) + $google_sync = $this->providers_model->get_setting($provider_id, 'google_sync'); + + if ( ! $google_sync) { - $google_token = json_decode($this->providers_model->get_setting('google_token', - $this->input->post('provider_id'))); - $this->google_sync->refresh_token($google_token->refresh_token); + json_response([ + 'success' => FALSE + ]); - $calendars = $this->google_sync->get_google_calendars(); + return; + } - $response = $calendars; - } - else - { - $response = AJAX_FAILURE; - } + $google_token = json_decode($this->providers_model->get_setting($provider_id, 'google_token')); + + $this->google_sync->refresh_token($google_token->refresh_token); + + $calendars = $this->google_sync->get_google_calendars(); + + json_response($calendars); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1545,30 +1339,27 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_USERS]['edit'] == FALSE - && $this->session->userdata('user_id') != $this->input->post('provider_id')) + $provider_id = request('provider_id'); + + $user_id = session('user_id'); + + if ($this->permissions[PRIV_USERS]['edit'] == FALSE && (int)$user_id !== (int)$provider_id) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $result = $this->providers_model->set_setting('google_calendar', $this->input->post('calendar_id'), - $this->input->post('provider_id')); + $calendar_id = request('calendar_id'); - $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; + $this->providers_model->set_setting($provider_id, 'google_calendar', $calendar_id); + + json_response([ + 'success' => TRUE + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -1578,34 +1369,25 @@ class Backend_api extends EA_Controller { { try { - if ($this->privileges[PRIV_SYSTEM_SETTINGS]['edit'] == FALSE) + if ($this->permissions[PRIV_SYSTEM_SETTINGS]['edit'] == FALSE) { - throw new Exception('You do not have the required privileges for this task.'); + throw new Exception('You do not have the required permissions for this task.'); } - $working_plan = $this->input->post('working_plan'); + $working_plan = request('working_plan'); - $providers = $this->providers_model->get_batch(); + $providers = $this->providers_model->get(); foreach ($providers as $provider) { - $this->providers_model->set_setting('working_plan', $working_plan, $provider['id']); + $this->providers_model->set_setting($provider['id'], 'working_plan', $working_plan); } - $response = AJAX_SUCCESS; + response(); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } } diff --git a/application/controllers/Captcha.php b/application/controllers/Captcha.php index 20695c94..ad379388 100644 --- a/application/controllers/Captcha.php +++ b/application/controllers/Captcha.php @@ -11,8 +11,12 @@ * @since v1.0.0 * ---------------------------------------------------------------------------- */ +use Gregwar\Captcha\CaptchaBuilder; + /** - * Captcha Controller + * Captcha controller + * + * Handles the captcha operations. * * @package Controllers */ @@ -22,10 +26,10 @@ class Captcha extends EA_Controller { */ public function index() { - header('Content-type: image/jpeg'); - $builder = new Gregwar\Captcha\CaptchaBuilder; + $builder = new CaptchaBuilder; $builder->build(); - $this->session->set_userdata('captcha_phrase', $builder->getPhrase()); + session(['captcha_phrase' => $builder->getPhrase()]); + header('Content-type: image/jpeg'); $builder->output(); } } diff --git a/application/controllers/Consents.php b/application/controllers/Consents.php index 4ffbb985..4ba9d9b5 100644 --- a/application/controllers/Consents.php +++ b/application/controllers/Consents.php @@ -12,7 +12,7 @@ * ---------------------------------------------------------------------------- */ /** - * Class Consent + * Consents controller * * Handles user consent related operations. * @@ -25,39 +25,31 @@ class Consents extends EA_Controller { public function __construct() { parent::__construct(); + $this->load->model('consents_model'); } /** - * Save the user's consent. + * Save (insert or update) the consent */ public function ajax_save_consent() { try { - $consent = $this->input->post('consent'); + $consent = request('consent'); $consent['ip'] = $this->input->ip_address(); - $consent['id'] = $this->consents_model->add($consent); + $consent['id'] = $this->consents_model->save($consent); - $response = [ + json_response([ 'success' => TRUE, 'id' => $consent['id'] - ]; + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } } diff --git a/application/controllers/Console.php b/application/controllers/Console.php index b2acee33..cba17f09 100644 --- a/application/controllers/Console.php +++ b/application/controllers/Console.php @@ -14,9 +14,9 @@ require_once __DIR__ . '/Google.php'; /** - * Class Console + * Console controller * - * CLI commands of Easy!Appointments, can only be executed from a terminal and not with a direct request. + * Handles all the Console related operations. */ class Console extends EA_Controller { /** @@ -32,8 +32,9 @@ class Console extends EA_Controller { parent::__construct(); $this->load->dbutil(); - $this->load->helper('file'); + $this->load->library('migration'); + $this->load->model('admins_model'); $this->load->model('customers_model'); $this->load->model('providers_model'); @@ -53,8 +54,10 @@ class Console extends EA_Controller { public function install() { $this->migrate('fresh'); + $this->seed(); - $this->output->set_output(PHP_EOL . '⇾ Installation completed, login with "administrator" / "administrator".' . PHP_EOL . PHP_EOL); + + response(PHP_EOL . '⇾ Installation completed, login with "administrator" / "administrator".' . PHP_EOL . PHP_EOL); } /** @@ -75,9 +78,9 @@ class Console extends EA_Controller { * * @param string $type */ - public function migrate($type = '') + public function migrate(string $type = '') { - if ($type === 'fresh' && $this->migration->version(0) === FALSE) + if ($type === 'fresh' && ! $this->migration->version(0)) { show_error($this->migration->error_string()); } @@ -100,12 +103,14 @@ class Console extends EA_Controller { public function seed() { // Settings - $this->settings_model->set_setting('company_name', 'Company Name'); - $this->settings_model->set_setting('company_email', 'info@example.org'); - $this->settings_model->set_setting('company_link', 'https://example.org'); + setting([ + 'company_name' => 'Company Name', + 'company_email' => 'info@example.org', + 'company_link' => 'https://example.org', + ]); // Admin - $this->admins_model->add([ + $this->admins_model->save([ 'first_name' => 'John', 'last_name' => 'Doe', 'email' => 'john@example.org', @@ -119,7 +124,7 @@ class Console extends EA_Controller { ]); // Service - $service_id = $this->services_model->add([ + $service_id = $this->services_model->save([ 'name' => 'Service', 'duration' => '30', 'price' => '0', @@ -129,7 +134,7 @@ class Console extends EA_Controller { ]); // Provider - $this->providers_model->add([ + $this->providers_model->save([ 'first_name' => 'Jane', 'last_name' => 'Doe', 'email' => 'jane@example.org', @@ -140,7 +145,7 @@ class Console extends EA_Controller { 'settings' => [ 'username' => 'janedoe', 'password' => 'janedoe', - 'working_plan' => $this->settings_model->get_setting('company_working_plan'), + 'working_plan' => setting('company_working_plan'), 'notifications' => TRUE, 'google_sync' => FALSE, 'sync_past_days' => 30, @@ -150,7 +155,7 @@ class Console extends EA_Controller { ]); // Customer - $this->customers_model->add([ + $this->customers_model->save([ 'first_name' => 'James', 'last_name' => 'Doe', 'email' => 'james@example.org', @@ -161,7 +166,7 @@ class Console extends EA_Controller { /** * Create a backup file. * - * Use this method to backup your Easy!Appointments data. + * Use this method to back up your Easy!Appointments data. * * Usage: * @@ -173,11 +178,11 @@ class Console extends EA_Controller { */ public function backup() { - $path = isset($GLOBALS['argv'][3]) ? $GLOBALS['argv'][3] : APPPATH . '/../storage/backups'; + $path = $GLOBALS['argv'][3] ?? APPPATH . '/../storage/backups'; if ( ! file_exists($path)) { - throw new Exception('The backup path does not exist™: ' . $path); + throw new Exception('The backup path does not exist: ' . $path); } if ( ! is_writable($path)) @@ -207,7 +212,7 @@ class Console extends EA_Controller { */ public function sync() { - $providers = $this->providers_model->get_batch(); + $providers = $this->providers_model->get(); foreach ($providers as $provider) { @@ -252,6 +257,6 @@ class Console extends EA_Controller { '', ]; - $this->output->set_output(implode(PHP_EOL, $help)); + response(implode(PHP_EOL, $help)); } } diff --git a/application/controllers/Errors.php b/application/controllers/Errors.php index afbbf17e..04b92c93 100644 --- a/application/controllers/Errors.php +++ b/application/controllers/Errors.php @@ -12,15 +12,20 @@ * ---------------------------------------------------------------------------- */ /** - * Errors Controller + * Errors controller + * + * Handles the app error related operations. * * @package Controllers */ class Errors extends EA_Controller { + /** + * Errors constructor. + */ public function __construct() { parent::__construct(); - $this->load->helper('google_analytics'); + $this->load->model('settings_model'); } @@ -37,8 +42,8 @@ class Errors extends EA_Controller { */ public function error404() { - $view['company_name'] = $this->settings_model->get_setting('company_name'); - - $this->load->view('general/error404', $view); + $this->load->view('general/error404', [ + 'company_name' => setting('company_name') + ]); } } diff --git a/application/controllers/Google.php b/application/controllers/Google.php index 5cfc5b68..08c79bfb 100644 --- a/application/controllers/Google.php +++ b/application/controllers/Google.php @@ -12,9 +12,9 @@ * ---------------------------------------------------------------------------- */ /** - * Google Controller + * Google controller * - * This controller handles the Google Calendar synchronization operations. + * Handles the Google Calendar synchronization related operations. * * @package Controllers */ @@ -42,18 +42,10 @@ class Google extends EA_Controller { { try { + /** @var EA_Controller $CI */ $CI = get_instance(); - // The user must be logged in. - if ($CI->session->userdata('user_id') == FALSE && is_cli() === FALSE) - { - return; - } - - if ($provider_id === NULL) - { - throw new Exception('Provider id not specified.'); - } + $CI->load->library('google_sync'); $CI->load->model('appointments_model'); $CI->load->model('providers_model'); @@ -61,38 +53,54 @@ class Google extends EA_Controller { $CI->load->model('customers_model'); $CI->load->model('settings_model'); - $provider = $CI->providers_model->get_row($provider_id); + $user_id = session('user_id'); - // Check whether the selected provider has google sync enabled. - $google_sync = $CI->providers_model->get_setting('google_sync', $provider['id']); + if ( ! $user_id && ! is_cli()) + { + return; + } + + if ( ! $provider_id) + { + throw new InvalidArgumentException('No provider ID provided.'); + } + + $provider = $CI->providers_model->find($provider_id); + + // Check whether the selected provider has the Google Sync enabled. + $google_sync = $CI->providers_model->get_setting($provider['id'], 'google_sync'); if ( ! $google_sync) { throw new Exception('The selected provider has not the google synchronization setting enabled.'); } - $google_token = json_decode($CI->providers_model->get_setting('google_token', $provider['id'])); - $CI->load->library('google_sync'); + $google_token = json_decode($CI->providers_model->get_setting($provider['id'], 'google_token')); + + $CI->google_sync->refresh_token($google_token->refresh_token); // Fetch provider's appointments that belong to the sync time period. - $sync_past_days = $CI->providers_model->get_setting('sync_past_days', $provider['id']); - $sync_future_days = $CI->providers_model->get_setting('sync_future_days', $provider['id']); + $sync_past_days = $CI->providers_model->get_setting($provider['id'], 'sync_past_days'); + + $sync_future_days = $CI->providers_model->get_setting($provider['id'], 'sync_future_days'); + $start = strtotime('-' . $sync_past_days . ' days', strtotime(date('Y-m-d'))); + $end = strtotime('+' . $sync_future_days . ' days', strtotime(date('Y-m-d'))); - $where_clause = [ + $where = [ 'start_datetime >=' => date('Y-m-d H:i:s', $start), 'end_datetime <=' => date('Y-m-d H:i:s', $end), 'id_users_provider' => $provider['id'] ]; - $appointments = $CI->appointments_model->get_batch($where_clause); + $appointments = $CI->appointments_model->get($where); - $company_settings = [ - 'company_name' => $CI->settings_model->get_setting('company_name'), - 'company_link' => $CI->settings_model->get_setting('company_link'), - 'company_email' => $CI->settings_model->get_setting('company_email') + $settings = [ + 'company_name' => setting('company_name'), + 'company_link' => setting('company_link'), + 'company_email' => setting('company_email') ]; $provider_timezone = new DateTimeZone($provider['timezone']); @@ -102,8 +110,8 @@ class Google extends EA_Controller { { if ($appointment['is_unavailable'] == FALSE) { - $service = $CI->services_model->get_row($appointment['id_services']); - $customer = $CI->customers_model->get_row($appointment['id_users_customer']); + $service = $CI->services_model->find($appointment['id_services']); + $customer = $CI->customers_model->find($appointment['id_users_customer']); } else { @@ -114,14 +122,15 @@ class Google extends EA_Controller { // If current appointment not synced yet, add to Google Calendar. if ($appointment['id_google_calendar'] == NULL) { - $google_event = $CI->google_sync->add_appointment($appointment, $provider, - $service, $customer, $company_settings); + $google_event = $CI->google_sync->add_appointment($appointment, $provider, $service, $customer, $settings); + $appointment['id_google_calendar'] = $google_event->id; - $CI->appointments_model->add($appointment); // Save the Google Calendar ID. + + $CI->appointments_model->save($appointment); // Save the Google Calendar ID. } else { - // Appointment is synced with google calendar. + // Appointment is synced with Google Calendar. try { $google_event = $CI->google_sync->get_event($provider, $appointment['id_google_calendar']); @@ -134,33 +143,31 @@ class Google extends EA_Controller { // If Google Calendar event is different from Easy!Appointments appointment then update // Easy!Appointments record. $is_different = FALSE; - $appt_start = strtotime($appointment['start_datetime']); - $appt_end = strtotime($appointment['end_datetime']); + $appointment_start = strtotime($appointment['start_datetime']); + $appointment_end = strtotime($appointment['end_datetime']); $event_start = new DateTime($google_event->getStart()->getDateTime()); $event_start->setTimezone($provider_timezone); $event_end = new DateTime($google_event->getEnd()->getDateTime()); $event_end->setTimezone($provider_timezone); - - if ($appt_start != $event_start->getTimestamp() || $appt_end != $event_end->getTimestamp() - || $appointment['notes'] !== $google_event->getDescription()) - { - $is_different = TRUE; - } + $is_different = $appointment_start !== $event_start->getTimestamp() + || $appointment_end !== $event_end->getTimestamp() + || $appointment['notes'] !== $google_event->getDescription(); if ($is_different) { $appointment['start_datetime'] = $event_start->format('Y-m-d H:i:s'); $appointment['end_datetime'] = $event_end->format('Y-m-d H:i:s'); $appointment['notes'] = $google_event->getDescription(); - $CI->appointments_model->add($appointment); + $CI->appointments_model->save($appointment); } } - catch (Exception $exception) + catch (Throwable $e) { - // Appointment not found on Google Calendar, delete from Easy!Appoinmtents. + // Appointment not found on Google Calendar, delete from Easy!Appointments. $CI->appointments_model->delete($appointment['id']); + $appointment['id_google_calendar'] = NULL; } } @@ -168,6 +175,7 @@ class Google extends EA_Controller { // Add Google Calendar events that do not exist in Easy!Appointments. $google_calendar = $provider['settings']['google_calendar']; + $google_events = $CI->google_sync->get_sync_events($google_calendar, $start, $end); foreach ($google_events->getItems() as $google_event) @@ -197,14 +205,13 @@ class Google extends EA_Controller { $event_end->setTimezone($provider_timezone); } - $results = $CI->appointments_model->get_batch(['id_google_calendar' => $google_event->getId()]); + $results = $CI->appointments_model->get(['id_google_calendar' => $google_event->getId()]); if ( ! empty($results)) { continue; } - // Record doesn't exist in the Easy!Appointments, so add the event now. $appointment = [ 'start_datetime' => $event_start->format('Y-m-d H:i:s'), @@ -218,24 +225,17 @@ class Google extends EA_Controller { 'id_services' => NULL, ]; - $CI->appointments_model->add($appointment); + $CI->appointments_model->save($appointment); } - $response = AJAX_SUCCESS; + json_response([ + 'success' => TRUE + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $CI->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $CI->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } /** @@ -246,10 +246,10 @@ class Google extends EA_Controller { * * @param int $provider_id The provider id, for whom the sync authorization is made. */ - public function oauth($provider_id) + public function oauth(int $provider_id) { // Store the provider id for use on the callback function. - $this->session->set_userdata('oauth_provider_id', $provider_id); + session(['oauth_provider_id' => $provider_id]); // Redirect browser to google user content page. header('Location: ' . $this->google_sync->get_auth_url()); @@ -268,11 +268,12 @@ class Google extends EA_Controller { */ public function oauth_callback() { - $code = $this->input->get('code'); + $code = request('code'); if (empty($code)) { - $this->output->set_output('Code authorization failed.'); + response('Code authorization failed.'); + return; } @@ -280,24 +281,23 @@ class Google extends EA_Controller { if (empty($token)) { - $this->output->set_output('Token authorization failed.'); + response('Token authorization failed.'); + return; } // Store the token into the database for future reference. - $oauth_provider_id = $this->session->userdata('oauth_provider_id'); + $oauth_provider_id = session('oauth_provider_id'); if ($oauth_provider_id) { - $this->providers_model->set_setting('google_sync', TRUE, $oauth_provider_id); - $this->providers_model->set_setting('google_token', json_encode($token), $oauth_provider_id); - $this->providers_model->set_setting('google_calendar', 'primary', $oauth_provider_id); + $this->providers_model->set_setting($oauth_provider_id, 'google_sync', TRUE); + $this->providers_model->set_setting($oauth_provider_id, 'google_token', json_encode($token)); + $this->providers_model->set_setting($oauth_provider_id, 'google_calendar', 'primary'); } else { - $this->output->set_output('Sync provider id not specified.'); + response('Sync provider id not specified.'); } } - - } diff --git a/application/controllers/Installation.php b/application/controllers/Installation.php index c6ccd3aa..b9e7517a 100644 --- a/application/controllers/Installation.php +++ b/application/controllers/Installation.php @@ -12,9 +12,9 @@ * ---------------------------------------------------------------------------- */ /** - * Installation Controller + * Installation controller * - * This controller will handle the installation procedure of Easy!Appointments. + * Handles the installation related operations. * * @package Controllers */ @@ -25,14 +25,14 @@ class Installation extends EA_Controller { public function __construct() { parent::__construct(); + $this->load->model('admins_model'); $this->load->model('settings_model'); $this->load->model('services_model'); $this->load->model('providers_model'); $this->load->model('customers_model'); + $this->load->library('migration'); - $this->load->helper('installation'); - $this->load->helper('string'); } /** @@ -42,7 +42,7 @@ class Installation extends EA_Controller { { if (is_app_installed()) { - redirect('appointments'); + redirect(''); return; } @@ -63,8 +63,8 @@ class Installation extends EA_Controller { return; } - $admin = $this->input->post('admin'); - $company = $this->input->post('company'); + $admin = request('admin'); + $company = request('company'); if ( ! $this->migration->current()) { @@ -78,21 +78,25 @@ class Installation extends EA_Controller { $admin['settings']['notifications'] = TRUE; $admin['settings']['calendar_view'] = CALENDAR_VIEW_DEFAULT; unset($admin['username'], $admin['password']); - $admin['id'] = $this->admins_model->add($admin); + $admin['id'] = $this->admins_model->save($admin); - $this->session->set_userdata('user_id', $admin['id']); - $this->session->set_userdata('user_email', $admin['email']); - $this->session->set_userdata('role_slug', DB_SLUG_ADMIN); - $this->session->set_userdata('timezone', $admin['timezone']); - $this->session->set_userdata('username', $admin['settings']['username']); + session([ + 'user_id' => $admin['id'], + 'user_email' => $admin['email'], + 'role_slug' => DB_SLUG_ADMIN, + 'timezone' => $admin['timezone'], + 'username' => $admin['settings']['username'] + ]); // Save company settings - $this->settings_model->set_setting('company_name', $company['company_name']); - $this->settings_model->set_setting('company_email', $company['company_email']); - $this->settings_model->set_setting('company_link', $company['company_link']); + setting([ + 'company_name' => $company['company_name'], + 'company_email' => $company['company_email'], + 'company_link' => $company['company_link'], + ]); // Service - $service_id = $this->services_model->add([ + $service_id = $this->services_model->save([ 'name' => 'Service', 'duration' => '30', 'price' => '0', @@ -102,7 +106,7 @@ class Installation extends EA_Controller { ]); // Provider - $this->providers_model->add([ + $this->providers_model->save([ 'first_name' => 'Jane', 'last_name' => 'Doe', 'email' => 'jane@example.org', @@ -113,7 +117,7 @@ class Installation extends EA_Controller { 'settings' => [ 'username' => 'janedoe', 'password' => 'janedoe', - 'working_plan' => $this->settings_model->get_setting('company_working_plan'), + 'working_plan' => setting('company_working_plan'), 'notifications' => TRUE, 'google_sync' => FALSE, 'sync_past_days' => 30, @@ -123,27 +127,20 @@ class Installation extends EA_Controller { ]); // Customer - $this->customers_model->add([ + $this->customers_model->save([ 'first_name' => 'James', 'last_name' => 'Doe', 'email' => 'james@example.org', 'phone_number' => '+1 (000) 000-0000', ]); - $response = AJAX_SUCCESS; + json_response([ + 'success' => true + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } } diff --git a/application/controllers/Privacy.php b/application/controllers/Privacy.php index bb92b5f1..f3ec359a 100644 --- a/application/controllers/Privacy.php +++ b/application/controllers/Privacy.php @@ -12,7 +12,9 @@ * ---------------------------------------------------------------------------- */ /** - * Class Privacy + * Privacy controller + * + * Handles the privacy related operations. * * @package Controllers */ @@ -23,18 +25,20 @@ class Privacy extends EA_Controller { public function __construct() { parent::__construct(); + $this->load->driver('cache', ['adapter' => 'file']); + $this->load->model('customers_model'); } /** - * Remove all customer data (including appointments from the system). + * Remove all customer data (including appointments) from the system. */ public function ajax_delete_personal_information() { try { - $customer_token = $this->input->post('customer_token'); + $customer_token = request('customer_token'); if (empty($customer_token)) { @@ -45,28 +49,19 @@ class Privacy extends EA_Controller { if (empty($customer_id)) { - throw new InvalidArgumentException('Customer ID could not be found, please reload the page ' + throw new InvalidArgumentException('Customer ID does not exist, please reload the page ' . 'and try again.'); } $this->customers_model->delete($customer_id); - $response = [ + json_response([ 'success' => TRUE - ]; + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } } diff --git a/application/controllers/User.php b/application/controllers/User.php index 11ba6547..a54c6c05 100644 --- a/application/controllers/User.php +++ b/application/controllers/User.php @@ -16,7 +16,9 @@ use EA\Engine\Types\Email; use EA\Engine\Types\NonEmptyText; /** - * User Controller + * User controller + * + * Handles the user related operations. * * @package Controllers */ @@ -27,38 +29,28 @@ class User extends EA_Controller { public function __construct() { parent::__construct(); - $this->load->model('settings_model'); - $this->load->model('user_model'); + + $this->load->library('accounts'); } /** - * Default Method - * - * The default method will redirect the browser to the user/login URL. + * Redirect to the login page. */ public function index() { - header('Location: ' . site_url('user/login')); + redirect('user/login'); } /** * Display the login page. - * - * @throws Exception */ public function login() { - $view['base_url'] = config('base_url'); - $view['dest_url'] = $this->session->userdata('dest_url'); - - if ( ! $view['dest_url']) - { - $view['dest_url'] = site_url('backend'); - } - - $view['company_name'] = $this->settings_model->get_setting('company_name'); - - $this->load->view('user/login', $view); + $this->load->view('user/login', [ + 'base_url' => config('base_url'), + 'company_name' => setting('company_name'), + 'dest_url' => session('dest_url', site_url('backend')) + ]); } /** @@ -66,62 +58,57 @@ class User extends EA_Controller { */ public function logout() { - $this->session->unset_userdata('user_id'); - $this->session->unset_userdata('user_email'); - $this->session->unset_userdata('role_slug'); - $this->session->unset_userdata('username'); - $this->session->unset_userdata('dest_url'); + $this->session->sess_destroy(); - $view['base_url'] = config('base_url'); - $view['company_name'] = $this->settings_model->get_setting('company_name'); - $this->load->view('user/logout', $view); + $this->load->view('user/logout', [ + 'base_url' => config('base_url'), + 'company_name' => setting('company_name') + ]); } /** - * Display the "forgot password" page. - * @throws Exception + * Display the password recovery page. */ public function forgot_password() { - $view['base_url'] = config('base_url'); - $view['company_name'] = $this->settings_model->get_setting('company_name'); - $this->load->view('user/forgot_password', $view); + $this->load->view('user/forgot_password', [ + 'base_url' => config('base_url'), + 'company_name' => setting('company_name') + ]); } /** - * Display the "not authorized" page. - * @throws Exception + * Display the no-permissions page. */ - public function no_privileges() + public function no_permissions() { - $view['base_url'] = config('base_url'); - $view['company_name'] = $this->settings_model->get_setting('company_name'); - $this->load->view('user/no_privileges', $view); + $this->load->view('user/no_privileges', [ + 'base_url' => config('base_url'), + 'company_name' => setting('company_name') + ]); } /** - * Check whether the user has entered the correct login credentials. - * - * The session data of a logged in user are the following: - * - 'user_id' - * - 'user_email' - * - 'role_slug' - * - 'dest_url' + * Validate the login credentials and if successful, log the user in. */ public function ajax_check_login() { try { - if ( ! $this->input->post('username') || ! $this->input->post('password')) + if ( ! request('username') || ! request('password')) { throw new Exception('Invalid credentials given!'); } - $user_data = $this->user_model->check_login($this->input->post('username'), $this->input->post('password')); + $username = request('username'); + + $password = request('password'); + + $user_data = $this->accounts->check_login($username, $password); if ($user_data) { - $this->session->set_userdata($user_data); // Save data on user's session. + session($user_data); // Save data in the session. $response = AJAX_SUCCESS; } @@ -130,13 +117,13 @@ class User extends EA_Controller { $response = AJAX_FAILURE; } } - catch (Exception $exception) + catch (Throwable $e) { $this->output->set_status_header(500); $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] + 'message' => $e->getMessage(), + 'trace' => config('debug') ? $e->getTrace() : [] ]; } @@ -146,59 +133,51 @@ class User extends EA_Controller { } /** - * Regenerate a new password for the current user, only if the username and - * email address given correspond to an existing user in db. - * - * Required POST Parameters: - * - * - string $_POST['username'] Username to be validated. - * - string $_POST['email'] Email to be validated. + * Recover the user password and notify the user via email. */ public function ajax_forgot_password() { try { - if ( ! $this->input->post('username') || ! $this->input->post('email')) + $username = request('username'); + + if (empty($username)) { - throw new Exception('You must enter a valid username and email address in ' - . 'order to get a new password!'); + throw new InvalidArgumentException('No username value provided.'); } - $new_password = $this->user_model->regenerate_password( - $this->input->post('username'), - $this->input->post('email') + $email = request('email'); + + if (empty($email)) + { + throw new InvalidArgumentException('No email value provided.'); + } + + $new_password = $this->accounts->regenerate_password( + $username, + $email ); - if ($new_password != FALSE) + if ($new_password) { - $this->config->load('email'); - $email = new EmailClient($this, $this->config->config); - $company_settings = [ - 'company_name' => $this->settings_model->get_setting('company_name'), - 'company_link' => $this->settings_model->get_setting('company_link'), - 'company_email' => $this->settings_model->get_setting('company_email') + $settings = [ + 'company_name' => setting('company_name'), + 'company_link' => setting('company_link'), + 'company_email' => setting('company_email') ]; - $email->send_password(new NonEmptyText($new_password), new Email($this->input->post('email')), - $company_settings); + $email->send_password(new NonEmptyText($new_password), new Email(request('email')), $settings); } - $response = $new_password != FALSE ? AJAX_SUCCESS : AJAX_FAILURE; + json_response([ + 'success' => TRUE + ]); } - catch (Exception $exception) + catch (Throwable $e) { - $this->output->set_status_header(500); - - $response = [ - 'message' => $exception->getMessage(), - 'trace' => config('debug') ? $exception->getTrace() : [] - ]; + json_exception($e); } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } }