From 39956c6b37bd1f03164a4db78555d65ac7e8408f Mon Sep 17 00:00:00 2001 From: Alex Tselegidis Date: Wed, 22 Apr 2020 21:48:56 +0200 Subject: [PATCH] Major refactoring and improvements to the application API code. --- application/config/autoload.php | 2 +- application/config/config.php | 2 +- application/config/google.php | 17 + application/controllers/Appointments.php | 1221 +++++++++-------- application/controllers/Backend.php | 182 +-- application/controllers/Backend_api.php | 1107 ++++++++------- application/controllers/Captcha.php | 24 +- application/controllers/Consents.php | 58 +- application/controllers/Errors.php | 33 +- application/controllers/Google.php | 105 +- application/controllers/Installation.php | 79 +- application/controllers/Privacy.php | 52 +- application/controllers/User.php | 93 +- .../controllers/api/v1/API_V1_Controller.php | 18 +- application/controllers/api/v1/Admins.php | 42 +- .../controllers/api/v1/Appointments.php | 38 +- .../controllers/api/v1/Availabilities.php | 37 +- application/controllers/api/v1/Categories.php | 42 +- application/controllers/api/v1/Customers.php | 42 +- application/controllers/api/v1/Providers.php | 38 +- .../controllers/api/v1/Secretaries.php | 42 +- application/controllers/api/v1/Services.php | 42 +- application/controllers/api/v1/Settings.php | 34 +- .../controllers/api/v1/Unavailabilities.php | 42 +- application/helpers/asset_helper.php | 12 +- application/helpers/config_helper.php | 2 +- .../helpers/custom_exceptions_helper.php | 55 +- .../helpers/data_validation_helper.php | 5 +- application/helpers/general_helper.php | 21 +- .../helpers/google_analytics_helper.php | 14 +- application/helpers/installation_helper.php | 15 +- application/helpers/render_helper.php | 2 +- application/libraries/Google_sync.php | 57 +- application/libraries/Ics_file.php | 10 +- .../migrations/001_specific_calendar_sync.php | 15 +- .../002_add_google_analytics_setting.php | 36 +- ...003_add_customer_notifications_setting.php | 35 +- .../004_add_date_format_setting.php | 37 +- .../005_add_require_captcha_setting.php | 36 +- .../006_add_calendar_view_setting.php | 16 +- .../007_add_service_availabilities_type.php | 16 +- .../008_add_service_attendants_number.php | 16 +- .../migrations/009_change_column_types.php | 16 +- .../010_add_time_format_setting.php | 32 +- ...11_remove_prefix_from_fkey_constraints.php | 16 +- application/migrations/012_legal_contents.php | 16 +- .../013_add_weekday_start_setting.php | 32 +- .../014_add_appointment_location_column.php | 16 +- .../015_add_user_extra_working_plan.php | 22 +- .../016_add_require_phone_number_setting.php | 32 +- .../migrations/017_add_api_token_setting.php | 36 +- .../migrations/018_add_timezone_columns.php | 16 +- .../019_add_display_any_provider_setting.php | 16 +- application/models/Admins_model.php | 333 ++--- application/models/Appointments_model.php | 286 ++-- application/models/Consents_model.php | 5 +- application/models/Customers_model.php | 219 +-- application/models/Providers_model.php | 548 ++++---- application/models/Roles_model.php | 5 +- application/models/Secretaries_model.php | 480 +++---- application/models/Services_model.php | 204 +-- application/models/Settings_model.php | 5 +- application/models/Timezones_model.php | 88 +- application/models/User_model.php | 41 +- application/views/appointments/book.php | 6 +- .../views/appointments/book_success.php | 12 +- application/views/appointments/message.php | 4 +- application/views/backend/calendar.php | 2 +- application/views/backend/footer.php | 6 +- application/views/backend/header.php | 2 +- application/views/backend/settings.php | 6 +- .../views/emails/appointment_details.php | 2 +- .../views/emails/delete_appointment.php | 2 +- application/views/emails/new_password.php | 2 +- application/views/errors/cli/index.html | 2 +- application/views/errors/html/index.html | 4 +- application/views/general/error404.php | 2 +- application/views/general/installation.php | 2 +- application/views/general/update.php | 2 +- application/views/index.html | 4 +- application/views/user/forgot_password.php | 2 +- application/views/user/login.php | 6 +- application/views/user/logout.php | 2 +- application/views/user/no_privileges.php | 2 +- assets/js/frontend_book_api.js | 2 +- 85 files changed, 3623 insertions(+), 2707 deletions(-) create mode 100644 application/config/google.php diff --git a/application/config/autoload.php b/application/config/autoload.php index 00dbce27..1d600e7d 100644 --- a/application/config/autoload.php +++ b/application/config/autoload.php @@ -81,7 +81,7 @@ $autoload['helper'] = ['custom_exceptions', 'url', 'file', 'language', 'asset', | */ -$autoload['config'] = []; +$autoload['config'] = ['google', 'email']; /* diff --git a/application/config/config.php b/application/config/config.php index 1b8369de..a1f46617 100644 --- a/application/config/config.php +++ b/application/config/config.php @@ -10,7 +10,7 @@ */ $config['version'] = '1.4.0'; // This must be changed manually. $config['release_label'] = 'Dev'; // Leave empty for no title or add Alpha, Beta etc ... -$config['google_sync_feature'] = Config::GOOGLE_SYNC_FEATURE; +$config['debug'] = Config::DEBUG_MODE; /* |-------------------------------------------------------------------------- diff --git a/application/config/google.php b/application/config/google.php new file mode 100644 index 00000000..2e1c4955 --- /dev/null +++ b/application/config/google.php @@ -0,0 +1,17 @@ +load->library('session'); $this->load->helper('installation'); - - // Set user's selected language. - if ($this->session->userdata('language')) - { - $this->config->set_item('language', $this->session->userdata('language')); - $this->lang->load('translations', $this->session->userdata('language')); - } - else - { - $this->lang->load('translations', $this->config->item('language')); // default - } - - // Common helpers $this->load->helper('google_analytics'); - } - - /** - * 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. - * - * @param string $appointment_hash DB appointment hash of an existing record (default ''). - */ - public function index($appointment_hash = '') - { - if ( ! is_ea_installed()) - { - redirect('installation/index'); - return; - } - $this->load->model('appointments_model'); $this->load->model('providers_model'); $this->load->model('services_model'); @@ -70,8 +61,37 @@ class Appointments extends CI_Controller { $this->load->model('settings_model'); $this->load->model('timezones_model'); + if ($this->session->userdata('language')) + { + // Set the user's selected language. + $this->config->set_item('language', $this->session->userdata('language')); + $this->lang->load('translations', $this->session->userdata('language')); + } + else + { + // Set the default language. + $this->lang->load('translations', $this->config->item('language')); + } + } + + /** + * 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. + * + * @param string $appointment_hash The appointment hash identifier. + */ + public function index($appointment_hash = '') + { try { + if ( ! is_ea_installed()) + { + redirect('installation/index'); + 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'); @@ -101,8 +121,8 @@ class Appointments extends CI_Controller { $available_providers[$index] = $stripped_data; } - // If an appointment hash is provided then it means that the customer - // is trying to edit a registered appointment record. + // If an appointment hash is provided then it means that the customer is trying to edit a registered + // appointment record. if ($appointment_hash !== '') { // Load the appointments data and enable the manage mode of the page. @@ -110,16 +130,17 @@ class Appointments extends CI_Controller { $results = $this->appointments_model->get_batch(['hash' => $appointment_hash]); - if (count($results) === 0) + if (empty($results)) { - // The requested appointment doesn't exist in the database. Display - // a message to the customer. - $view = [ - 'message_title' => $this->lang->line('appointment_not_found'), - 'message_text' => $this->lang->line('appointment_does_not_exist_in_db'), + // The requested appointment doesn't exist in the database. Display a message to the customer. + $variables = [ + 'message_title' => lang('appointment_not_found'), + 'message_text' => lang('appointment_does_not_exist_in_db'), 'message_icon' => base_url('assets/img/error.png') ]; - $this->load->view('appointments/message', $view); + + $this->load->view('appointments/message', $variables); + return; } @@ -127,16 +148,16 @@ class Appointments extends CI_Controller { $provider = $this->providers_model->get_row($appointment['id_users_provider']); $customer = $this->customers_model->get_row($appointment['id_users_customer']); - $customer_token = md5(uniqid(mt_rand(), true)); + $customer_token = md5(uniqid(mt_rand(), TRUE)); $this->load->driver('cache', ['adapter' => 'file']); - - $this->cache->save('customer-token-' . $customer_token, $customer['id'], 600); // save for 10 minutes + // Save the token for 10 minutes. + $this->cache->save('customer-token-' . $customer_token, $customer['id'], 600); } else { - // The customer is going to book a new appointment so there is no - // need for the manage functionality to be initialized. + // The customer is going to book a new appointment so there is no need for the manage functionality to + // be initialized. $manage_mode = FALSE; $customer_token = FALSE; $appointment = []; @@ -145,7 +166,7 @@ class Appointments extends CI_Controller { } // Load the book appointment view. - $view = [ + $variables = [ 'available_services' => $available_services, 'available_providers' => $available_providers, 'company_name' => $company_name, @@ -168,12 +189,12 @@ class Appointments extends CI_Controller { 'display_any_provider' => $display_any_provider, ]; } - catch (Exception $exc) + catch (Exception $exception) { - $view['exceptions'][] = $exc; + $variables['exceptions'][] = $exception; } - $this->load->view('appointments/book', $view); + $this->load->view('appointments/book', $variables); } /** @@ -181,33 +202,28 @@ class Appointments extends CI_Controller { * * This method removes an appointment from the company's schedule. In order for the appointment to be deleted, the * hash string must be provided. The customer can only cancel the appointment if the edit time period is not over - * yet. Provide the $_POST['cancel_reason'] parameter to describe the cancellation reason. + * yet. * - * @param string $appointment_hash This is used to distinguish the appointment record. + * @param string $appointment_hash This appointment hash identifier. */ public function cancel($appointment_hash) { try { - $this->load->model('appointments_model'); - $this->load->model('providers_model'); - $this->load->model('customers_model'); - $this->load->model('services_model'); - $this->load->model('settings_model'); - // Check whether the appointment hash exists in the database. - $records = $this->appointments_model->get_batch(['hash' => $appointment_hash]); - if (count($records) == 0) + $appointments = $this->appointments_model->get_batch(['hash' => $appointment_hash]); + + if (empty($appointments)) { throw new Exception('No record matches the provided hash.'); } - $appointment = $records[0]; + $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']); - $company_settings = [ + $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'), @@ -215,21 +231,22 @@ class Appointments extends CI_Controller { 'time_format' => $this->settings_model->get_setting('time_format') ]; - // :: DELETE APPOINTMENT RECORD FROM THE DATABASE. + // 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.'); } - // :: SYNC APPOINTMENT REMOVAL WITH GOOGLE CALENDAR + // Remove the appointment from Google Calendar if needed. if ($appointment['id_google_calendar'] != NULL) { try { - $google_sync = filter_var($this->providers_model - ->get_setting('google_sync', $appointment['id_users_provider']), FILTER_VALIDATE_BOOLEAN); + $google_sync = filter_var( + $this->providers_model->get_setting('google_sync', $appointment['id_users_provider']), + FILTER_VALIDATE_BOOLEAN); - if ($google_sync == TRUE) + if ($google_sync === TRUE) { $google_token = json_decode($this->providers_model ->get_setting('google_token', $provider['id'])); @@ -238,53 +255,54 @@ class Appointments extends CI_Controller { $this->google_sync->delete_appointment($provider, $appointment['id_google_calendar']); } } - catch (Exception $exc) + catch (Exception $exception) { - $exceptions[] = $exc; + $exceptions[] = $exception; } } - // :: SEND NOTIFICATION EMAILS TO CUSTOMER AND PROVIDER + // Send email notification to customer and provider. try { - $this->config->load('email'); - $email = new \EA\Engine\Notifications\Email($this, $this->config->config); + $email = new EmailClient($this, $this->config->config); $send_provider = filter_var($this->providers_model - ->get_setting('notifications', $provider['id']), FILTER_VALIDATE_BOOLEAN); + ->get_setting('notifications', $provider['id']), + FILTER_VALIDATE_BOOLEAN); if ($send_provider === TRUE) { $email->sendDeleteAppointment($appointment, $provider, - $service, $customer, $company_settings, new Email($provider['email']), + $service, $customer, $settings, new Email($provider['email']), new Text($this->input->post('cancel_reason'))); } - $send_customer = filter_var($this->settings_model->get_setting('customer_notifications'), + $send_customer = filter_var( + $this->settings_model->get_setting('customer_notifications'), FILTER_VALIDATE_BOOLEAN); if ($send_customer === TRUE) { $email->sendDeleteAppointment($appointment, $provider, - $service, $customer, $company_settings, new Email($customer['email']), + $service, $customer, $settings, new Email($customer['email']), new Text($this->input->post('cancel_reason'))); } } - catch (Exception $exc) + catch (Exception $exception) { - $exceptions[] = $exc; + $exceptions[] = $exception; } } - catch (Exception $exc) + catch (Exception $exception) { // Display the error message to the customer. - $exceptions[] = $exc; + $exceptions[] = $exception; } $view = [ - 'message_title' => $this->lang->line('appointment_cancelled_title'), - 'message_text' => $this->lang->line('appointment_cancelled'), + 'message_title' => lang('appointment_cancelled_title'), + 'message_text' => lang('appointment_cancelled'), 'message_icon' => base_url('assets/img/success.png') ]; @@ -299,21 +317,21 @@ class Appointments extends CI_Controller { /** * GET an specific appointment book and redirect to the success screen. * - * @param int $appointment_id Contains the ID of the appointment to retrieve. + * @param string $appointment_hash The appointment hash identifier. + * + * @throws Exception */ - public function book_success($appointment_id) + public function book_success($appointment_hash) { - // If the appointment id doesn't exist or zero redirect to index. - if ( ! $appointment_id) + $appointments = $this->appointments_model->get_batch(['hash' => $appointment_hash]); + + if (empty($appointments)) { - redirect('appointments'); + redirect('appointments'); // The appointment does not exist. + return; } - $this->load->model('appointments_model'); - $this->load->model('providers_model'); - $this->load->model('services_model'); - $this->load->model('settings_model'); - //retrieve the data needed in the view - $appointment = $this->appointments_model->get_row($appointment_id); + + $appointment = $appointments[0]; unset($appointment['notes']); $provider = $this->providers_model->get_row($appointment['id_users_provider']); @@ -322,22 +340,22 @@ class Appointments extends CI_Controller { $service = $this->services_model->get_row($appointment['id_services']); $company_name = $this->settings_model->get_setting('company_name'); - //get the exceptions + + // Get any pending exceptions. $exceptions = $this->session->flashdata('book_success'); - unset($provider['settings']); - - // :: LOAD THE BOOK SUCCESS VIEW $view = [ 'appointment_data' => $appointment, 'provider_data' => $provider, 'service_data' => $service, 'company_name' => $company_name, ]; + if ($exceptions) { $view['exceptions'] = $exceptions; } + $this->load->view('appointments/book_success', $view); } @@ -347,81 +365,69 @@ class Appointments extends CI_Controller { * This method answers to an AJAX request. It calculates the available hours for the given service, provider and * date. * - * Required POST parameters: - * - * - int $_POST['service_id'] Selected service record ID. - * - int|string $_POST['provider_id'] Selected provider record id, can also be 'any-provider'. - * - string $_POST['selected_date'] Selected date for availabilities. - * - int $_POST['service_duration'] Selected service duration in minutes. - * - string $_POST['manage_mode'] Contains either 'true' or 'false' and determines the if current user - * is managing an already booked appointment or not. - * * Outputs a JSON string with the availabilities. - * - * @deprecated Since v1.3.0, this method will be replaced with a future release. */ public function ajax_get_available_hours() { - $this->load->model('providers_model'); - $this->load->model('appointments_model'); - $this->load->model('settings_model'); - $this->load->model('services_model'); - try { + $provider_id = $this->input->post('provider_id'); + $service_id = $this->input->post('service_id'); + $selected_date = $this->input->post('selected_date'); + // Do not continue if there was no provider selected (more likely there is no provider in the system). - if (empty($this->input->post('provider_id'))) + if (empty($provider_id)) { $this->output ->set_content_type('application/json') ->set_output(json_encode([])); + return; } - // 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_appointments = ($this->input->post('manage_mode') === 'true') - ? [$this->input->post('appointment_id')] - : []; + // 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_appointments = []; - // 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. - if ($this->input->post('provider_id') === ANY_PROVIDER) + if ($this->input->post('manage_mode') === 'true') { - $_POST['provider_id'] = $this->_search_any_provider($this->input->post('service_id'), - $this->input->post('selected_date')); - if ($this->input->post('provider_id') === NULL) + $exclude_appointments[] = $this->input->post('appointment_id'); + } + + // 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. + if ($provider_id === ANY_PROVIDER) + { + $provider_id = $this->search_any_provider($service_id, $selected_date); + + if ($provider_id === NULL) { $this->output ->set_content_type('application/json') ->set_output(json_encode([])); + return; } } - $service = $this->services_model->get_row($this->input->post('service_id')); - $provider = $this->providers_model->get_row($_POST['provider_id']); + $service = $this->services_model->get_row($service_id); + $provider = $this->providers_model->get_row($provider_id); - $empty_periods = $this->_get_provider_available_time_periods($this->input->post('provider_id'), - $this->input->post('service_id'), - $this->input->post('selected_date'), $exclude_appointments); + $empty_periods = $this->get_provider_available_time_periods($provider_id, + $selected_date, $exclude_appointments); - $available_hours = $this->_calculate_available_hours($empty_periods, $this->input->post('selected_date'), - $this->input->post('service_duration'), - filter_var($this->input->post('manage_mode'), FILTER_VALIDATE_BOOLEAN), - $service['availabilities_type']); + $available_hours = $this->calculate_available_hours($empty_periods, $selected_date, + $service['duration'], $service['availabilities_type']); if ($service['attendants_number'] > 1) { - $available_hours = $this->_get_multiple_attendants_hours($this->input->post('selected_date'), $service, + $available_hours = $this->get_multiple_attendants_hours($selected_date, $service, $provider); } - // If the selected date is today, remove past hours. It is important include the timeout before - // booking that is set in the back-office the system. Normally we might want the customer to book - // an appointment that is at least half or one hour from now. The setting is stored in minutes. - $selected_date = $this->input->post('selected_date'); - + // If the selected date is today, remove past hours. It is important include the timeout before booking + // that is set in the back-office the system. Normally we might want the customer to book an appointment + // that is at least half or one hour from now. The setting is stored in minutes. $provider_timezone = new DateTimeZone($provider['timezone']); $book_advance_timeout = $this->settings_model->get_setting('book_advance_timeout'); @@ -442,361 +448,73 @@ class Appointments extends CI_Controller { sort($available_hours, SORT_STRING); $available_hours = array_values($available_hours); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($available_hours)); + $response = $available_hours; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'exceptions' => [exceptionToJavaScript($exc)] - ])); - } - } + $this->output->set_status_header(500); - /** - * [AJAX] 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'); // alias - $post_data['manage_mode'] = filter_var($post_data['manage_mode'], FILTER_VALIDATE_BOOLEAN); - - $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'); - - // Validate the CAPTCHA string. - if ($this->settings_model->get_setting('require_captcha') === '1' - && $this->session->userdata('captcha_phrase') !== $this->input->post('captcha')) - { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'captcha_verification' => FALSE - ])); - return; - } - - // Check appointment availability. - if ( ! $this->_check_datetime_availability()) - { - throw new Exception($this->lang->line('requested_hour_is_unavailable')); - } - - $appointment = $_POST['post_data']['appointment']; - $customer = $_POST['post_data']['customer']; - - if ($this->customers_model->exists($customer)) - { - $customer['id'] = $this->customers_model->find_record_id($customer); - } - - $provider = $this->providers_model->get_row($appointment['id_users_provider']); - $service = $this->services_model->get_row($appointment['id_services']); - - if (empty($appointment['location']) && !empty($service['location'])) { - $appointment['location'] = $service['location']; - } - - $customer_id = $this->customers_model->add($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']); - - $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'), - 'date_format' => $this->settings_model->get_setting('date_format'), - 'time_format' => $this->settings_model->get_setting('time_format') + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] ]; - - // :: SYNCHRONIZE APPOINTMENT WITH PROVIDER'S GOOGLE CALENDAR - // The provider must have previously granted access to his google calendar account - // in order to sync the appointment. - try - { - $google_sync = filter_var($this->providers_model->get_setting('google_sync', - $appointment['id_users_provider']), FILTER_VALIDATE_BOOLEAN); - - if ($google_sync == TRUE) - { - $google_token = json_decode($this->providers_model - ->get_setting('google_token', $appointment['id_users_provider'])); - - $this->load->library('google_sync'); - $this->google_sync->refresh_token($google_token->refresh_token); - - if ($post_data['manage_mode'] === FALSE) - { - // Add appointment to Google Calendar. - $google_event = $this->google_sync->add_appointment($appointment, $provider, - $service, $customer, $company_settings); - $appointment['id_google_calendar'] = $google_event->id; - $this->appointments_model->add($appointment); - } - else - { - // Update appointment to Google Calendar. - $appointment['id_google_calendar'] = $this->appointments_model - ->get_value('id_google_calendar', $appointment['id']); - - $this->google_sync->update_appointment($appointment, $provider, - $service, $customer, $company_settings); - } - } - } - catch (Exception $exc) - { - log_message('error', $exc->getMessage()); - log_message('error', $exc->getTraceAsString()); - } - - // :: SEND NOTIFICATION EMAILS TO BOTH CUSTOMER AND PROVIDER - try - { - $this->config->load('email'); - $email = new \EA\Engine\Notifications\Email($this, $this->config->config); - - if ($post_data['manage_mode'] == FALSE) - { - $customer_title = new Text($this->lang->line('appointment_booked')); - $customer_message = new Text($this->lang->line('thank_you_for_appointment')); - $provider_title = new Text($this->lang->line('appointment_added_to_your_plan')); - $provider_message = new Text($this->lang->line('appointment_link_description')); - - } - else - { - $customer_title = new Text($this->lang->line('appointment_changes_saved')); - $customer_message = new Text(''); - $provider_title = new Text($this->lang->line('appointment_details_changed')); - $provider_message = new Text(''); - } - - $customer_link = new Url(site_url('appointments/index/' . $appointment['hash'])); - $provider_link = new Url(site_url('backend/index/' . $appointment['hash'])); - - $send_customer = filter_var($this->settings_model->get_setting('customer_notifications'), - FILTER_VALIDATE_BOOLEAN); - - $this->load->library('ics_file'); - $ics_stream = $this->ics_file->get_stream($appointment, $service, $provider, $customer); - - if ($send_customer === TRUE) - { - $email->sendAppointmentDetails($appointment, $provider, - $service, $customer, $company_settings, $customer_title, - $customer_message, $customer_link, new Email($customer['email']), new Text($ics_stream)); - } - - $send_provider = filter_var($this->providers_model->get_setting('notifications', $provider['id']), - FILTER_VALIDATE_BOOLEAN); - - if ($send_provider === TRUE) - { - $email->sendAppointmentDetails($appointment, $provider, - $service, $customer, $company_settings, $provider_title, - $provider_message, $provider_link, new Email($provider['email']), new Text($ics_stream)); - } - } - catch (Exception $exc) - { - log_message('error', $exc->getMessage()); - log_message('error', $exc->getTraceAsString()); - } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'appointment_id' => $appointment['id'] - ])); - } - catch (Exception $exc) - { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'exceptions' => [exceptionToJavaScript($exc)] - ])); } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Get Unavailable Dates + * Search for any provider that can handle the requested service. * - * Get an array with the available dates of a specific provider, service and month of the year. Provide the - * "provider_id", "service_id" and "selected_date" as GET parameters to the request. The "selected_date" parameter - * must have the Y-m-d format. + * This method will return the database ID of the provider with the most available periods. * - * Outputs a JSON string with the unavailable dates. that are unavailable. + * @param int $service_id The requested service ID. + * @param string $selected_date The date to be searched. * - * @deprecated Since v1.3.0, this method will be replaced with a future release. + * @return int Returns the ID of the provider that can provide the service at the selected date. + * + * @throws Exception */ - public function ajax_get_unavailable_dates() + protected function search_any_provider($service_id, $selected_date) { - try + $available_providers = $this->providers_model->get_available_providers(); + + $service = $this->services_model->get_row($service_id); + + $provider_id = NULL; + + $max_hours_count = 0; + + foreach ($available_providers as $provider) { - $provider_id = $this->input->get('provider_id'); - $service_id = $this->input->get('service_id'); - $selected_date_string = $this->input->get('selected_date'); - $selected_date = new DateTime($selected_date_string); - $number_of_days_in_month = (int)$selected_date->format('t'); - $unavailable_dates = []; - $manage_mode = filter_var($this->input->get('manage_mode'), FILTER_VALIDATE_BOOLEAN); - - $exclude_appointments = ($_REQUEST['manage_mode'] === 'true') - ? [$_REQUEST['appointment_id']] - : []; - - $provider_list = ($provider_id === ANY_PROVIDER) ? $this->_search_providers_by_service($service_id) : [$provider_id] ; - - $this->load->model('providers_model'); - - // Get the service record. - $this->load->model('services_model'); - $service = $this->services_model->get_row($service_id); - - for ($i = 1; $i <= $number_of_days_in_month; $i++) + foreach ($provider['services'] as $provider_service_id) { - $current_date = new DateTime($selected_date->format('Y-m') . '-' . $i); - - if ($current_date < new DateTime(date('Y-m-d 00:00:00'))) + if ($provider_service_id == $service_id) { - // Past dates become immediately unavailable. - $unavailable_dates[] = $current_date->format('Y-m-d'); - continue; - } + // Check if the provider is available for the requested date. + $empty_periods = $this->get_provider_available_time_periods($provider['id'], $selected_date); - // Finding at least one slot of availablity - foreach ($provider_list as $curr_provider_id) - { - // Get the provider record. - $curr_provider = $this->providers_model->get_row($curr_provider_id); - - $empty_periods = $this->_get_provider_available_time_periods($curr_provider_id, - $service_id, - $current_date->format('Y-m-d'), $exclude_appointments); - - $available_hours = $this->_calculate_available_hours($empty_periods, $current_date->format('Y-m-d'), - $service['duration'], $manage_mode, $service['availabilities_type']); - if (! empty($available_hours)) break; + $available_hours = $this->calculate_available_hours($empty_periods, $selected_date, + $service['duration'], $service['availabilities_type']); if ($service['attendants_number'] > 1) { - $available_hours = $this->_get_multiple_attendants_hours($current_date->format('Y-m-d'), $service, - $curr_provider); - if (! empty($available_hours)) break; + $available_hours = $this->get_multiple_attendants_hours($selected_date, $service, + $provider); + } + + if (count($available_hours) > $max_hours_count) + { + $provider_id = $provider['id']; + $max_hours_count = count($available_hours); } } - - // No availability amongst all the provider - if (empty($available_hours)) - { - $unavailable_dates[] = $current_date->format('Y-m-d'); - } - } - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($unavailable_dates)); - } - catch (Exception $exc) - { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'exceptions' => [exceptionToJavaScript($exc)] - ])); - } - } - - /** - * 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. - * - * @return bool Returns whether the selected datetime is still available. - */ - protected function _check_datetime_availability() - { - $this->load->model('services_model'); - $this->load->model('appointments_model'); - - $appointment = $_POST['post_data']['appointment']; - - $service_duration = $this->services_model->get_value('duration', $appointment['id_services']); - - $exclude_appointments = (isset($appointment['id'])) ? [$appointment['id']] : []; - - $attendants_number = $this->services_model->get_value('attendants_number', $appointment['id_services']); - - if ($attendants_number > 1) - { - // Exclude all the appointments that will are currently registered. - $exclude = $this->appointments_model->get_batch([ - 'id_services' => $appointment['id_services'], - 'start_datetime' => $appointment['start_datetime'] - ]); - - if ( ! empty($exclude) && count($exclude) < $attendants_number) - { - foreach ($exclude as $entry) - { - $exclude_appointments[] = $entry['id']; - } } } - if ($appointment['id_users_provider'] === ANY_PROVIDER) - { - $appointment['id_users_provider'] = $this->_search_any_provider($appointment['id_services'], - date('Y-m-d', strtotime($appointment['start_datetime']))); - $_POST['post_data']['appointment']['id_users_provider'] = $appointment['id_users_provider']; - return TRUE; // The selected provider is always available. - } - - $available_periods = $this->_get_provider_available_time_periods( - $appointment['id_users_provider'], $appointment['id_services'], - date('Y-m-d', strtotime($appointment['start_datetime'])), - $exclude_appointments); - - $is_still_available = FALSE; - - foreach ($available_periods as $period) - { - $appt_start = new DateTime($appointment['start_datetime']); - $appt_start = $appt_start->format('H:i'); - - $appt_end = new DateTime($appointment['start_datetime']); - $appt_end->add(new DateInterval('PT' . $service_duration . 'M')); - $appt_end = $appt_end->format('H:i'); - - $period_start = date('H:i', strtotime($period['start'])); - $period_end = date('H:i', strtotime($period['end'])); - - if ($period_start <= $appt_start && $period_end >= $appt_end) - { - $is_still_available = TRUE; - break; - } - } - - return $is_still_available; + return $provider_id; } /** @@ -807,23 +525,20 @@ class Appointments extends CI_Controller { * values that have the start and the end time of an available time period. * * @param int $provider_id Provider record ID. - * @param int $service_id Service record ID. * @param string $selected_date Date to be checked (MySQL formatted string). * @param array $excluded_appointment_ids Array containing the IDs of the appointments that will not be taken into * consideration when the available time periods are calculated. * * @return array Returns an array with the available time periods of the provider. + * + * @throws Exception */ - protected function _get_provider_available_time_periods( + protected function get_provider_available_time_periods( $provider_id, - $service_id, $selected_date, $excluded_appointment_ids = [] - ) { - $this->load->model('appointments_model'); - $this->load->model('providers_model'); - $this->load->model('services_model'); - + ) + { // Get the service, provider's working plan and provider appointments. $working_plan = json_decode($this->providers_model->get_setting('working_plan', $provider_id), TRUE); @@ -852,13 +567,14 @@ class Appointments extends CI_Controller { $selected_date_working_plan = $working_plan[strtolower(date('l', strtotime($selected_date)))]; // Search if the $selected_date is an extra date added outside the normal working plan - if ($selected_date_working_plan == null) { - if (isset($extra_working_plan[strtolower(date('Y-m-d', strtotime($selected_date)))])){ + if ($selected_date_working_plan == NULL) + { + if (isset($extra_working_plan[strtolower(date('Y-m-d', strtotime($selected_date)))])) + { $selected_date_working_plan = $extra_working_plan[strtolower(date('Y-m-d', strtotime($selected_date)))]; } } - $periods = []; if (isset($selected_date_working_plan['breaks'])) @@ -940,7 +656,8 @@ class Appointments extends CI_Controller { $appointment_start = new DateTime($provider_appointment['start_datetime']); $appointment_end = new DateTime($provider_appointment['end_datetime']); - if ($appointment_start >= $appointment_end) { + if ($appointment_start >= $appointment_end) + { continue; } @@ -950,6 +667,7 @@ class Appointments extends CI_Controller { if ($appointment_start <= $period_start && $appointment_end <= $period_end && $appointment_end <= $period_start) { // The appointment does not belong in this time period, so we will not change anything. + continue; } else { @@ -994,6 +712,7 @@ class Appointments extends CI_Controller { if ($appointment_start >= $period_start && $appointment_end >= $period_end && $appointment_start >= $period_end) { // The appointment does not belong in the period so do not change anything. + continue; } else { @@ -1013,86 +732,6 @@ class Appointments extends CI_Controller { return array_values($periods); } - /** - * Search for any provider that can handle the requested service. - * - * 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 $selected_date The date to be searched. - * - * @return int Returns the ID of the provider that can provide the service at the selected date. - */ - protected function _search_any_provider($service_id, $selected_date) - { - $this->load->model('providers_model'); - $this->load->model('services_model'); - $available_providers = $this->providers_model->get_available_providers(); - $service = $this->services_model->get_row($service_id); - $provider_id = NULL; - $max_hours_count = 0; - - foreach ($available_providers as $provider) - { - foreach ($provider['services'] as $provider_service_id) - { - if ($provider_service_id == $service_id) - { - // Check if the provider is available for the requested date. - $empty_periods = $this->_get_provider_available_time_periods($provider['id'], $service_id, - $selected_date); - - $available_hours = $this->_calculate_available_hours($empty_periods, $selected_date, - $service['duration'], FALSE, $service['availabilities_type']); - - if ($service['attendants_number'] > 1) - { - $available_hours = $this->_get_multiple_attendants_hours($selected_date, $service, - $provider); - } - - if (count($available_hours) > $max_hours_count) - { - $provider_id = $provider['id']; - $max_hours_count = count($available_hours); - } - } - } - } - - return $provider_id; - } - - /** - * Search for any provider that can handle the requested service. - * - * This method will return the database ID of the providers affected to the requested service. - * - * @param numeric $service_id The requested service ID. - * - * @return array Returns the ID of the provider that can provide the requested service. - */ - protected function _search_providers_by_service($service_id) - { - $this->load->model('providers_model'); - $available_providers = $this->providers_model->get_available_providers(); - $provider_list = array(); - - foreach ($available_providers as $provider) - { - foreach ($provider['services'] as $provider_service_id) - { - if ($provider_service_id === $service_id) - { - // Check if the provider is affected to the selected service. - $provider_list[] = $provider['id']; - } - } - } - - return $provider_list; - } - /** * Calculate the available appointment hours. * @@ -1100,24 +739,22 @@ class Appointments extends CI_Controller { * are broken down to 15 min and if the service fit in each quarter then a new * available hour is added to the "$available_hours" array. * - * @param array $empty_periods Contains the empty periods as generated by the "_get_provider_available_time_periods" + * @param array $empty_periods Contains the empty periods as generated by the "get_provider_available_time_periods" * method. * @param string $selected_date The selected date to be search (format ) * @param int $service_duration The service duration is required for the hour calculation. - * @param bool $manage_mode (optional) Whether we are currently on manage mode (editing an existing appointment). * @param string $availabilities_type Optional ('flexible'), the service availabilities type. * * @return array Returns an array with the available hours for the appointment. + * @throws Exception */ - protected function _calculate_available_hours( + protected function calculate_available_hours( array $empty_periods, $selected_date, $service_duration, - $manage_mode = FALSE, $availabilities_type = 'flexible' - ) { - $this->load->model('settings_model'); - + ) + { $available_hours = []; foreach ($empty_periods as $period) @@ -1150,17 +787,15 @@ class Appointments extends CI_Controller { * @param array $provider Selected provider data. * * @return array Returns the available hours array. + * @throws Exception */ - protected function _get_multiple_attendants_hours( + protected function get_multiple_attendants_hours( $selected_date, $service, $provider - ) { - $this->load->model('appointments_model'); - $this->load->model('services_model'); - $this->load->model('providers_model'); - - $unavailabilities = $this->appointments_model->get_batch([ + ) + { + $unavailability_events = $this->appointments_model->get_batch([ 'is_unavailable' => TRUE, 'DATE(start_datetime)' => $selected_date, 'id_users_provider' => $provider['id'] @@ -1178,7 +813,7 @@ class Appointments extends CI_Controller { ]; $periods = $this->remove_breaks($selected_date, $periods, $working_hours['breaks']); - $periods = $this->remove_unavailabilities($periods, $unavailabilities); + $periods = $this->remove_unavailability_events($periods, $unavailability_events); $hours = []; @@ -1219,6 +854,7 @@ class Appointments extends CI_Controller { * @param array $breaks Breaks array for the current date. * * @return array Returns the available time periods without the breaks. + * @throws Exception */ public function remove_breaks($selected_date, $periods, $breaks) { @@ -1275,19 +911,21 @@ class Appointments extends CI_Controller { } /** - * Remove the unavailabilities from the available time periods of the selected date. + * Remove the unavailability entries from the available time periods of the selected date. * * @param array $periods Available time periods. - * @param array $unavailabilities Unavailabilities of the current date. + * @param array $unavailability_events Unavailability events of the current date. * - * @return array Returns the available time periods without the unavailabilities. + * @return array Returns the available time periods without the unavailability events. + * + * @throws Exception */ - public function remove_unavailabilities($periods, $unavailabilities) + public function remove_unavailability_events($periods, $unavailability_events) { - foreach ($unavailabilities as $unavailability) + foreach ($unavailability_events as $unavailability_event) { - $unavailability_start = new DateTime($unavailability['start_datetime']); - $unavailability_end = new DateTime($unavailability['end_datetime']); + $unavailability_start = new DateTime($unavailability_event['start_datetime']); + $unavailability_end = new DateTime($unavailability_event['end_datetime']); foreach ($periods as &$period) { @@ -1321,7 +959,7 @@ class Appointments extends CI_Controller { if ($unavailability_start <= $period_start && $unavailability_end >= $period_end) { - // Unavaibility contains period + // Unavailability contains period $period['start'] = $unavailability_end; continue; } @@ -1330,4 +968,409 @@ class Appointments extends CI_Controller { return $periods; } + + /** + * [AJAX] Register the appointment to the database. + * + * Outputs a JSON string with the appointment ID. + */ + public function ajax_register_appointment() + { + try + { + $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'); + + $post_data = $this->input->post('post_data'); + $captcha = $this->input->post('captcha'); + $manage_mode = filter_var($post_data['manage_mode'], FILTER_VALIDATE_BOOLEAN); + $appointment = $post_data['appointment']; + $customer = $post_data['customer']; + + $provider = $this->providers_model->get_row($appointment['id_users_provider']); + $service = $this->services_model->get_row($appointment['id_services']); + + $require_captcha = $this->settings_model->get_setting('require_captcha'); + $captcha_phrase = $this->session->userdata('captcha_phrase'); + + // Validate the CAPTCHA string. + if ($require_captcha === '1' && $captcha_phrase !== $captcha) + { + $this->output + ->set_content_type('application/json') + ->set_output(json_encode([ + 'captcha_verification' => FALSE + ])); + + return; + } + + // Check appointment availability before registering it to the database. + if ( ! $this->check_datetime_availability()) + { + throw new Exception(lang('requested_hour_is_unavailable')); + } + + if ($this->customers_model->exists($customer)) + { + $customer['id'] = $this->customers_model->find_record_id($customer); + } + + if (empty($appointment['location']) && ! empty($service['location'])) + { + $appointment['location'] = $service['location']; + } + + $customer_id = $this->customers_model->add($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']); + + $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') + ]; + + // Synchronize the appointment with the provider's Google Calendar. + try + { + $google_sync = filter_var( + $this->providers_model->get_setting('google_sync', $appointment['id_users_provider']), + FILTER_VALIDATE_BOOLEAN); + + if ($google_sync === TRUE) + { + $google_token = json_decode( + $this->providers_model->get_setting('google_token', $appointment['id_users_provider'])); + + $this->load->library('google_sync'); + + $this->google_sync->refresh_token($google_token->refresh_token); + + if ($manage_mode === FALSE) + { + // Add appointment to Google Calendar. + $google_event = $this->google_sync->add_appointment($appointment, $provider, + $service, $customer, $settings); + $appointment['id_google_calendar'] = $google_event->id; + $this->appointments_model->add($appointment); + } + else + { + // Update appointment to Google Calendar. + $appointment['id_google_calendar'] = $this->appointments_model + ->get_value('id_google_calendar', $appointment['id']); + + $this->google_sync->update_appointment($appointment, $provider, + $service, $customer, $settings); + } + } + } + catch (Exception $exception) + { + log_message('error', $exception->getMessage()); + log_message('error', $exception->getTraceAsString()); + } + + // Send email notifications to customer and provider. + try + { + $this->config->load('email'); + + $email = new EmailClient($this, $this->config->config); + + if ($manage_mode === FALSE) + { + $customer_title = new Text(lang('appointment_booked')); + $customer_message = new Text(lang('thank_you_for_appointment')); + $provider_title = new Text(lang('appointment_added_to_your_plan')); + $provider_message = new Text(lang('appointment_link_description')); + + } + else + { + $customer_title = new Text(lang('appointment_changes_saved')); + $customer_message = new Text(''); + $provider_title = new Text(lang('appointment_details_changed')); + $provider_message = new Text(''); + } + + $customer_link = new Url(site_url('appointments/index/' . $appointment['hash'])); + $provider_link = new Url(site_url('backend/index/' . $appointment['hash'])); + + $send_customer = filter_var( + $this->settings_model->get_setting('customer_notifications'), + FILTER_VALIDATE_BOOLEAN); + + $this->load->library('ics_file'); + + $ics_stream = $this->ics_file->get_stream($appointment, $service, $provider, $customer); + + if ($send_customer === TRUE) + { + $email->sendAppointmentDetails($appointment, $provider, + $service, $customer, $settings, $customer_title, + $customer_message, $customer_link, new Email($customer['email']), new Text($ics_stream)); + } + + $send_provider = filter_var( + $this->providers_model->get_setting('notifications', $provider['id']), + FILTER_VALIDATE_BOOLEAN); + + if ($send_provider === TRUE) + { + $email->sendAppointmentDetails($appointment, $provider, + $service, $customer, $settings, $provider_title, + $provider_message, $provider_link, new Email($provider['email']), new Text($ics_stream)); + } + } + catch (Exception $exception) + { + log_message('error', $exception->getMessage()); + log_message('error', $exception->getTraceAsString()); + } + + $response = [ + 'appointment_id' => $appointment['id'], + 'appointment_hash' => $appointment['hash'] + ]; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * 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. + * + * @return int Returns the ID of the provider that is available for the appointment. + * + * @throws Exception + */ + protected function check_datetime_availability() + { + $this->load->model('services_model'); + $this->load->model('appointments_model'); + + $post_data = $this->input->post('post_data'); + + $appointment = $post_data['appointment']; + + $service_duration = $this->services_model->get_value('duration', $appointment['id_services']); + + $exclude_appointments = []; + + if (isset($appointment['id'])) + { + $exclude_appointments[] = $appointment['id']; + } + + $attendants_number = $this->services_model->get_value('attendants_number', $appointment['id_services']); + + if ($attendants_number > 1) + { + // Exclude all the appointments that are currently registered. + $existing_appointments = $this->appointments_model->get_batch([ + 'id_services' => $appointment['id_services'], + 'start_datetime' => $appointment['start_datetime'] + ]); + + if ( ! empty($existing_appointments) && count($existing_appointments) < $attendants_number) + { + foreach ($existing_appointments as $existing_appointment) + { + $exclude_appointments[] = $existing_appointment['id']; + } + } + } + + if ($appointment['id_users_provider'] === ANY_PROVIDER) + { + $appointment['id_users_provider'] = $this->search_any_provider($appointment['id_services'], + date('Y-m-d', strtotime($appointment['start_datetime']))); + + return $appointment['id_users_provider']; + } + + $available_periods = $this->get_provider_available_time_periods( + $appointment['id_users_provider'], + date('Y-m-d', strtotime($appointment['start_datetime'])), + $exclude_appointments); + + $is_still_available = FALSE; + + foreach ($available_periods as $period) + { + $appt_start = new DateTime($appointment['start_datetime']); + $appt_start = $appt_start->format('H:i'); + + $appt_end = new DateTime($appointment['start_datetime']); + $appt_end->add(new DateInterval('PT' . $service_duration . 'M')); + $appt_end = $appt_end->format('H:i'); + + $period_start = date('H:i', strtotime($period['start'])); + $period_end = date('H:i', strtotime($period['end'])); + + if ($period_start <= $appt_start && $period_end >= $appt_end) + { + $is_still_available = TRUE; + break; + } + } + + return $is_still_available ? $appointment['id_users_provider'] : NULL; + } + + /** + * [AJAX] Get Unavailable Dates + * + * Get an array with the available dates of a specific provider, service and month of the year. Provide the + * "provider_id", "service_id" and "selected_date" as GET parameters to the request. The "selected_date" parameter + * must have the Y-m-d format. + * + * Outputs a JSON string with the unavailable dates. that are unavailable. + */ + public function ajax_get_unavailable_dates() + { + try + { + $this->load->model('providers_model'); + $this->load->model('services_model'); + + $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'); + $selected_date = new DateTime($selected_date_string); + $number_of_days_in_month = (int)$selected_date->format('t'); + $unavailable_dates = []; + + $exclude_appointments = []; + + if ($manage_mode === 'true') + { + $exclude_appointments[] = $appointment_id; + } + + $provider_list = $provider_id === ANY_PROVIDER + ? $this->search_providers_by_service($service_id) + : [$provider_id]; + + // Get the service record. + $service = $this->services_model->get_row($service_id); + + for ($i = 1; $i <= $number_of_days_in_month; $i++) + { + $current_date = new DateTime($selected_date->format('Y-m') . '-' . $i); + + if ($current_date < new DateTime(date('Y-m-d 00:00:00'))) + { + // Past dates become immediately unavailable. + $unavailable_dates[] = $current_date->format('Y-m-d'); + continue; + } + + // Finding at least one slot of availability. + foreach ($provider_list as $current_provider_id) + { + // Get the provider record. + $curr_provider = $this->providers_model->get_row($current_provider_id); + + $empty_periods = $this->get_provider_available_time_periods($current_provider_id, + $current_date->format('Y-m-d'), $exclude_appointments); + + $available_hours = $this->calculate_available_hours($empty_periods, $current_date->format('Y-m-d'), + $service['duration'], $service['availabilities_type']); + + if ( ! empty($available_hours)) + { + break; + } + + if ($service['attendants_number'] > 1) + { + $available_hours = $this->get_multiple_attendants_hours($current_date->format('Y-m-d'), $service, + $curr_provider); + if ( ! empty($available_hours)) break; + } + } + + // No availability amongst all the provider. + if (empty($available_hours)) + { + $unavailable_dates[] = $current_date->format('Y-m-d'); + } + } + + $response = $unavailable_dates; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Search for any provider that can handle the requested service. + * + * This method will return the database ID of the providers affected to the requested service. + * + * @param int $service_id The requested service ID. + * + * @return array Returns the ID of the provider that can provide the requested service. + */ + protected function search_providers_by_service($service_id) + { + $this->load->model('providers_model'); + $available_providers = $this->providers_model->get_available_providers(); + $provider_list = []; + + foreach ($available_providers as $provider) + { + foreach ($provider['services'] as $provider_service_id) + { + if ($provider_service_id === $service_id) + { + // Check if the provider is affected to the selected service. + $provider_list[] = $provider['id']; + } + } + } + + return $provider_list; + } } diff --git a/application/controllers/Backend.php b/application/controllers/Backend.php index ae9e705f..839c03ad 100755 --- a/application/controllers/Backend.php +++ b/application/controllers/Backend.php @@ -1,4 +1,4 @@ -load->library('session'); - // Set user's selected language. if ($this->session->userdata('language')) { + // Set user's selected language. $this->config->set_item('language', $this->session->userdata('language')); $this->lang->load('translations', $this->session->userdata('language')); } else { - $this->lang->load('translations', $this->config->item('language')); // default + // Set the default language. + $this->lang->load('translations', $this->config->item('language')); } } @@ -45,12 +68,14 @@ class Backend extends CI_Controller { * 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 = '') { $this->session->set_userdata('dest_url', site_url('backend')); - if ( ! $this->_has_privileges(PRIV_APPOINTMENTS)) + if ( ! $this->has_privileges(PRIV_APPOINTMENTS)) { return; } @@ -76,7 +101,7 @@ class Backend extends CI_Controller { $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(); - $user = $this->user_model->get_settings($this->session->userdata('user_id')); + $user = $this->user_model->get_user($this->session->userdata('user_id')); $view['calendar_view'] = $user['settings']['calendar_view']; $view['timezones'] = $this->timezones_model->to_array(); $this->set_user_data($view); @@ -109,6 +134,72 @@ class Backend extends CI_Controller { $this->load->view('backend/footer', $view); } + /** + * Check whether current user is logged in and has the required privileges to view a page. + * + * 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). + * + * @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. + */ + protected function has_privileges($page, $redirect = TRUE) + { + // Check if user is logged in. + $user_id = $this->session->userdata('user_id'); + + if ($user_id == FALSE) + { + // User not logged in, display the login view. + if ($redirect) + { + header('Location: ' . site_url('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_privileges = $this->db->get_where('ea_roles', ['slug' => $role_slug])->row_array(); + + if ($role_privileges[$page] < PRIV_VIEW) + { + // User does not have the permission to view the page. + if ($redirect) + { + header('Location: ' . site_url('user/no_privileges')); + } + return FALSE; + } + + return TRUE; + } + + /** + * Set the user data in order to be available at the view and js code. + * + * @param array $view Contains the view data. + */ + protected function set_user_data(&$view) + { + $this->load->model('roles_model'); + + // Get privileges + $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')); + } + /** * Display the backend customers page. * @@ -118,7 +209,7 @@ class Backend extends CI_Controller { { $this->session->set_userdata('dest_url', site_url('backend/customers')); - if ( ! $this->_has_privileges(PRIV_CUSTOMERS)) + if ( ! $this->has_privileges(PRIV_CUSTOMERS)) { return; } @@ -173,7 +264,7 @@ class Backend extends CI_Controller { { $this->session->set_userdata('dest_url', site_url('backend/services')); - if ( ! $this->_has_privileges(PRIV_SERVICES)) + if ( ! $this->has_privileges(PRIV_SERVICES)) { return; } @@ -211,7 +302,7 @@ class Backend extends CI_Controller { { $this->session->set_userdata('dest_url', site_url('backend/users')); - if ( ! $this->_has_privileges(PRIV_USERS)) + if ( ! $this->has_privileges(PRIV_USERS)) { return; } @@ -255,8 +346,8 @@ class Backend extends CI_Controller { 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)) + if ( ! $this->has_privileges(PRIV_SYSTEM_SETTINGS, FALSE) + && ! $this->has_privileges(PRIV_USER_SETTINGS)) { return; } @@ -277,7 +368,7 @@ class Backend extends CI_Controller { $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_settings($user_id); + $view['user_settings'] = $this->user_model->get_user($user_id); $view['timezones'] = $this->timezones_model->to_array(); $this->set_user_data($view); @@ -286,52 +377,6 @@ class Backend extends CI_Controller { $this->load->view('backend/footer', $view); } - /** - * Check whether current user is logged in and has the required privileges to view a page. - * - * 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. - * - * @see Constant definition in application/config/constants.php. - * - * @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). - * - * @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. - */ - protected function _has_privileges($page, $redirect = TRUE) - { - // Check if user is logged in. - $user_id = $this->session->userdata('user_id'); - if ($user_id == FALSE) - { // User not logged in, display the login view. - if ($redirect) - { - header('Location: ' . site_url('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_priv = $this->db->get_where('ea_roles', ['slug' => $role_slug])->row_array(); - if ($role_priv[$page] < PRIV_VIEW) - { // User does not have the permission to view the page. - if ($redirect) - { - header('Location: ' . site_url('user/no_privileges')); - } - return FALSE; - } - - return TRUE; - } - /** * This method will update the installation to the latest available version in the server. * @@ -345,7 +390,7 @@ class Backend extends CI_Controller { { try { - if ( ! $this->_has_privileges(PRIV_SYSTEM_SETTINGS, TRUE)) + if ( ! $this->has_privileges(PRIV_SYSTEM_SETTINGS, TRUE)) { throw new Exception('You do not have the required privileges for this task!'); } @@ -359,28 +404,11 @@ class Backend extends CI_Controller { $view = ['success' => TRUE]; } - catch (Exception $exc) + catch (Exception $exception) { - $view = ['success' => FALSE, 'exception' => $exc->getMessage()]; + $view = ['success' => FALSE, 'exception' => $exception->getMessage()]; } $this->load->view('general/update', $view); } - - /** - * Set the user data in order to be available at the view and js code. - * - * @param array $view Contains the view data. - */ - protected function set_user_data(&$view) - { - $this->load->model('roles_model'); - - // Get privileges - $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')); - } } diff --git a/application/controllers/Backend_api.php b/application/controllers/Backend_api.php index 0aede844..0345c6ac 100755 --- a/application/controllers/Backend_api.php +++ b/application/controllers/Backend_api.php @@ -1,4 +1,4 @@ -security->csrf_show_error(); - } - $this->load->library('session'); $this->load->model('roles_model'); @@ -146,26 +163,26 @@ class Backend_api extends CI_Controller { $this->output->set_output(json_encode($response)); } - catch (Exception $exc) + catch (Exception $exception) { - $this->output->set_output(json_encode([ - 'exceptions' => [exceptionToJavaScript($exc)] - ])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Get the registered appointments for the given date period and record. + * 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). - * - * Required POST Parameters: - * - * - int $_POST['record_id'] Selected record id. - * - string $_POST['filter_type'] Could be either FILTER_TYPE_PROVIDER or FILTER_TYPE_SERVICE. - * - string $_POST['start_date'] The user selected start date. - * - string $_POST['end_date'] The user selected end date. */ public function ajax_get_calendar_appointments() { @@ -199,9 +216,9 @@ class Backend_api extends CI_Controller { } // Get appointments - $record_id = $this->db->escape($_POST['record_id']); - $start_date = $this->db->escape($_POST['start_date']); - $end_date = $this->db->escape(date('Y-m-d', strtotime($_POST['end_date'] . ' +1 day'))); + $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'))); $where_clause = $where_id . ' = ' . $record_id . ' AND ((start_datetime > ' . $start_date . ' AND start_datetime < ' . $end_date . ') @@ -236,21 +253,23 @@ class Backend_api extends CI_Controller { ->set_content_type('application/json') ->set_output(json_encode($response)); } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Save appointment changes that are made from the backend calendar page. - * - * Required POST Parameters: - * - * - array $_POST['appointment_data'] (OPTIONAL) Array with the appointment data. - * - array $_POST['customer_data'] (OPTIONAL) Array with the customer data. + * Save appointment changes that are made from the backend calendar page. */ public function ajax_save_appointment() { @@ -263,15 +282,15 @@ class Backend_api extends CI_Controller { $this->load->model('settings_model'); $this->load->model('timezones_model'); - // :: SAVE CUSTOMER CHANGES TO DATABASE + // Save customer changes to the database. if ($this->input->post('customer_data')) { $customer = json_decode($this->input->post('customer_data'), TRUE); - $REQUIRED_PRIV = ( ! isset($customer['id'])) + $required_privilegesileges = ( ! isset($customer['id'])) ? $this->privileges[PRIV_CUSTOMERS]['add'] : $this->privileges[PRIV_CUSTOMERS]['edit']; - if ($REQUIRED_PRIV == FALSE) + if ($required_privilegesileges == FALSE) { throw new Exception('You do not have the required privileges for this task.'); } @@ -279,15 +298,15 @@ class Backend_api extends CI_Controller { $customer['id'] = $this->customers_model->add($customer); } - // :: SAVE APPOINTMENT CHANGES TO DATABASE + // Save appointment changes to the database. if ($this->input->post('appointment_data')) { $appointment = json_decode($this->input->post('appointment_data'), TRUE); - $REQUIRED_PRIV = ( ! isset($appointment['id'])) + $required_privilegesileges = ( ! isset($appointment['id'])) ? $this->privileges[PRIV_APPOINTMENTS]['add'] : $this->privileges[PRIV_APPOINTMENTS]['edit']; - if ($REQUIRED_PRIV == FALSE) + if ($required_privilegesileges == FALSE) { throw new Exception('You do not have the required privileges for this task.'); } @@ -326,7 +345,7 @@ class Backend_api extends CI_Controller { 'time_format' => $this->settings_model->get_setting('time_format') ]; - // :: SYNC APPOINTMENT CHANGES WITH GOOGLE CALENDAR + // Sync appointment changes with Google Calendar. try { $google_sync = $this->providers_model->get_setting('google_sync', @@ -354,32 +373,35 @@ class Backend_api extends CI_Controller { } } } - catch (Exception $exc) + catch (Exception $exception) { - $warnings[] = exceptionToJavaScript($exc); + $warnings[] = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } - // :: SEND EMAIL NOTIFICATIONS TO PROVIDER AND CUSTOMER + // Send email notifications to provider and customer. try { $this->config->load('email'); - $email = new \EA\Engine\Notifications\Email($this, $this->config->config); + $email = new EmailClient($this, $this->config->config); $send_provider = $this->providers_model ->get_setting('notifications', $provider['id']); if ( ! $manage_mode) { - $customer_title = new Text($this->lang->line('appointment_booked')); - $customer_message = new Text($this->lang->line('thank_you_for_appointment')); - $provider_title = new Text($this->lang->line('appointment_added_to_your_plan')); - $provider_message = new Text($this->lang->line('appointment_link_description')); + $customer_title = new Text(lang('appointment_booked')); + $customer_message = new Text(lang('thank_you_for_appointment')); + $provider_title = new Text(lang('appointment_added_to_your_plan')); + $provider_message = new Text(lang('appointment_link_description')); } else { - $customer_title = new Text($this->lang->line('appointment_details_changed')); + $customer_title = new Text(lang('appointment_details_changed')); $customer_message = new Text(''); - $provider_title = new Text($this->lang->line('appointment_changes_saved')); + $provider_title = new Text(lang('appointment_changes_saved')); $provider_message = new Text(''); } @@ -406,42 +428,44 @@ class Backend_api extends CI_Controller { } } - catch (Exception $exc) + catch (Exception $exception) { - $warnings[] = exceptionToJavaScript($exc); + $warnings[] = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } - if ( ! isset($warnings)) + if (empty($warnings)) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); + $response = AJAX_SUCCESS; } else { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['warnings' => $warnings])); + $response = ['warnings' => $warnings]; } } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Delete appointment from the database. + * Delete appointment from the database. * * This method deletes an existing appointment from the database. Once this action is finished it cannot be undone. * Notification emails are send to both provider and customer and the delete action is executed to the Google * Calendar account of the provider, if the "google_sync" setting is enabled. - * - * Required POST Parameters: - * - * - int $_POST['appointment_id'] The appointment id to be deleted. */ public function ajax_delete_appointment() { @@ -457,7 +481,7 @@ class Backend_api extends CI_Controller { throw new Exception('No appointment id provided.'); } - // :: STORE APPOINTMENT DATA FOR LATER USE IN THIS METHOD + // Store appointment data for later use in this method. $this->load->model('appointments_model'); $this->load->model('providers_model'); $this->load->model('customers_model'); @@ -477,10 +501,10 @@ class Backend_api extends CI_Controller { 'time_format' => $this->settings_model->get_setting('time_format') ]; - // :: DELETE APPOINTMENT RECORD FROM DATABASE + // Delete appointment record from the database. $this->appointments_model->delete($this->input->post('appointment_id')); - // :: SYNC DELETE WITH GOOGLE CALENDAR + // Sync removal with Google Calendar. if ($appointment['id_google_calendar'] != NULL) { try @@ -496,17 +520,21 @@ class Backend_api extends CI_Controller { $this->google_sync->delete_appointment($provider, $appointment['id_google_calendar']); } } - catch (Exception $exc) + catch (Exception $exception) { - $warnings[] = exceptionToJavaScript($exc); + $warnings[] = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } } - // :: SEND NOTIFICATION EMAILS TO PROVIDER AND CUSTOMER + // Send notification emails to provider and customer. try { $this->config->load('email'); - $email = new \EA\Engine\Notifications\Email($this, $this->config->config); + + $email = new EmailClient($this, $this->config->config); $send_provider = $this->providers_model ->get_setting('notifications', $provider['id']); @@ -527,42 +555,43 @@ class Backend_api extends CI_Controller { new Text($this->input->post('delete_reason'))); } } - catch (Exception $exc) + catch (Exception $exception) { - $warnings[] = exceptionToJavaScript($exc); + $warnings[] = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } - // :: SEND RESPONSE TO CLIENT BROWSER - if ( ! isset($warnings)) + if (empty($warnings)) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); + $response = AJAX_SUCCESS; } else { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['warnings' => $warnings])); + $response = ['warnings' => $warnings]; } } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Disable a providers sync setting. + * 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. - * - * Required POST Parameters: - * - * - string $_POST['provider_id'] The selected provider record id. */ public function ajax_disable_provider_sync() { @@ -585,24 +614,25 @@ class Backend_api extends CI_Controller { $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->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); + $response = AJAX_SUCCESS; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Filter the customer records with the given key string. - * - * Required POST Parameters: - * - * - string $_POST['key'] The filter key string. + * Filter the customer records with the given key string. * * Outputs the search results. */ @@ -658,24 +688,25 @@ class Backend_api extends CI_Controller { $customer['appointments'] = $appointments; } - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($customers)); + $response = $customers; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Insert of update unavailable time period to database. - * - * Required POST Parameters: - * - * - array $_POST['unavailable'] JSON encoded array that contains the unavailable period data. + * Insert of update unavailable time period to database. */ public function ajax_save_unavailable() { @@ -684,10 +715,10 @@ class Backend_api extends CI_Controller { // Check privileges $unavailable = json_decode($this->input->post('unavailable'), TRUE); - $REQUIRED_PRIV = ( ! isset($unavailable['id'])) + $required_privileges = ( ! isset($unavailable['id'])) ? $this->privileges[PRIV_APPOINTMENTS]['add'] : $this->privileges[PRIV_APPOINTMENTS]['edit']; - if ($REQUIRED_PRIV == FALSE) + if ($required_privileges == FALSE) { throw new Exception('You do not have the required privileges for this task.'); } @@ -723,13 +754,13 @@ class Backend_api extends CI_Controller { } else { - $google_event = $this->google_sync->update_unavailable($provider, $unavailable); + $this->google_sync->update_unavailable($provider, $unavailable); } } } - catch (Exception $exc) + catch (Exception $exception) { - $warnings[] = $exc; + $warnings[] = $exception; } if (isset($warnings)) @@ -746,20 +777,23 @@ class Backend_api extends CI_Controller { } } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Delete an unavailable time period from database. - * - * Required POST Parameters: - * - * - int $_POST['unavailable_id'] Record id to be deleted. + * Delete an unavailable time period from database. */ public function ajax_delete_unavailable() { @@ -791,39 +825,37 @@ class Backend_api extends CI_Controller { $this->google_sync->delete_unavailable($provider, $unavailable['id_google_calendar']); } } - catch (Exception $exc) + catch (Exception $exception) { - $warnings[] = $exc; + $warnings[] = $exception; } - if (isset($warnings)) + if (empty($warnings)) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['warnings' => $warnings])); + $response = AJAX_SUCCESS; } else { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); + $response = ['warnings' => $warnings]; } - } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Insert of update extra working plan time period to database. - * - * Required POST Parameters: - * - * - array $_POST['extra_period'] JSON encoded array that contains the unavailable period data. + * Insert of update extra working plan time period to database. */ public function ajax_save_extra_period() { @@ -832,10 +864,10 @@ class Backend_api extends CI_Controller { // Check privileges $extra_period = json_decode($this->input->post('extra_period'), TRUE); - $REQUIRED_PRIV = ( ! isset($extra_period['id'])) + $required_privileges = ( ! isset($extra_period['id'])) ? $this->privileges[PRIV_APPOINTMENTS]['add'] : $this->privileges[PRIV_APPOINTMENTS]['edit']; - if ($REQUIRED_PRIV == FALSE) + if ($required_privileges == FALSE) { throw new Exception('You do not have the required privileges for this task.'); } @@ -844,34 +876,32 @@ class Backend_api extends CI_Controller { $success = $this->providers_model->set_extra_working_day($extra_period, $extra_period['id_users_provider']); - if ( ! $success) + if ($success) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['warnings' => 'Error on saving extra period.'])); + $response = AJAX_SUCCESS; } else { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); + $response = ['warnings' => 'Error on saving extra period.']; } } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Delete an extra working plan time period to database. - * - * Required POST Parameters: - * - * - String $_POST['extra_period'] Date to be deleted. - * - int $_POST['provider_id'] Record id to be deleted. + * Delete an extra working plan time period to database. */ public function ajax_delete_extra_period() { @@ -891,34 +921,32 @@ class Backend_api extends CI_Controller { // Delete unavailable $success = $this->providers_model->delete_extra_working_day($extra_period, $provider_id); - if ( ! $success) + if ($success) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['warnings' => 'Error on deleting extra working day'])); + $response = AJAX_SUCCESS; } else { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); + $response = ['warnings' => 'Error on deleting extra period.']; } + } + catch (Exception $exception) + { + $this->output->set_status_header(500); - } // - catch (Exception $exc) // - { // - $this->output // - ->set_content_type('application/json') // - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); // - }// - } // + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } /** - * [AJAX] Save (insert or update) a customer record. - * - * Require POST Parameters: - * - * - array $_POST['customer'] JSON encoded array that contains the customer's data. + * Save (insert or update) a customer record. */ public function ajax_save_customer() { @@ -927,36 +955,38 @@ class Backend_api extends CI_Controller { $this->load->model('customers_model'); $customer = json_decode($this->input->post('customer'), TRUE); - $REQUIRED_PRIV = ( ! isset($customer['id'])) + $required_privilegesileges = ( ! isset($customer['id'])) ? $this->privileges[PRIV_CUSTOMERS]['add'] : $this->privileges[PRIV_CUSTOMERS]['edit']; - if ($REQUIRED_PRIV == FALSE) + if ($required_privilegesileges == FALSE) { throw new Exception('You do not have the required privileges for this task.'); } $customer_id = $this->customers_model->add($customer); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'status' => AJAX_SUCCESS, - 'id' => $customer_id - ])); + + $response = [ + 'status' => AJAX_SUCCESS, + 'id' => $customer_id + ]; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Delete customer from database. - * - * Required POST Parameters: - * - * - int $_POST['customer_id'] Customer record id to be deleted. + * Delete customer from database. */ public function ajax_delete_customer() { @@ -968,25 +998,28 @@ class Backend_api extends CI_Controller { } $this->load->model('customers_model'); + $this->customers_model->delete($this->input->post('customer_id')); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); + + $response = AJAX_SUCCESS; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Save (insert or update) service record. - * - * Required POST Parameters: - * - * - array $_POST['service'] Contains the service data (json encoded). + * Save (insert or update) service record. */ public function ajax_save_service() { @@ -995,36 +1028,37 @@ class Backend_api extends CI_Controller { $this->load->model('services_model'); $service = json_decode($this->input->post('service'), TRUE); - $REQUIRED_PRIV = ( ! isset($service['id'])) + $required_privilegesileges = ( ! isset($service['id'])) ? $this->privileges[PRIV_SERVICES]['add'] : $this->privileges[PRIV_SERVICES]['edit']; - if ($REQUIRED_PRIV == FALSE) + if ($required_privilegesileges == FALSE) { throw new Exception('You do not have the required privileges for this task.'); } $service_id = $this->services_model->add($service); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'status' => AJAX_SUCCESS, - 'id' => $service_id - ])); + $response = [ + 'status' => AJAX_SUCCESS, + 'id' => $service_id + ]; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Delete service record from database. - * - * Required POST Parameters: - * - * - int $_POST['service_id'] Record id to be deleted. + * Delete service record from database. */ public function ajax_delete_service() { @@ -1036,28 +1070,28 @@ class Backend_api extends CI_Controller { } $this->load->model('services_model'); + $result = $this->services_model->delete($this->input->post('service_id')); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($result ? AJAX_SUCCESS : AJAX_FAILURE)); + $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Filter service records by given key string. - * - * Required POST Parameters: - * - * - string $_POST['key'] Key string used to filter the records. - * - * Outputs a JSON encoded array back to client. + * Filter service records by given key string. */ public function ajax_filter_services() { @@ -1069,31 +1103,33 @@ class Backend_api extends CI_Controller { } $this->load->model('services_model'); + $key = $this->db->escape_str($this->input->post('key')); + $where = '(name LIKE "%' . $key . '%" OR duration LIKE "%' . $key . '%" OR ' . 'price LIKE "%' . $key . '%" OR currency LIKE "%' . $key . '%" OR ' . 'description LIKE "%' . $key . '%")'; - $services = $this->services_model->get_batch($where); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($services)); + + $response = $this->services_model->get_batch($where); } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Save (insert or update) category record. - * - * Required POST Parameters: - * - * - array $_POST['category'] Json encoded array with the category data. If an ID value is provided then the - * category is going to be updated instead of inserted. + * Save (insert or update) category record. */ public function ajax_save_service_category() { @@ -1102,35 +1138,38 @@ class Backend_api extends CI_Controller { $this->load->model('services_model'); $category = json_decode($this->input->post('category'), TRUE); - $REQUIRED_PRIV = ( ! isset($category['id'])) + $required_privilegesileges = ( ! isset($category['id'])) ? $this->privileges[PRIV_SERVICES]['add'] : $this->privileges[PRIV_SERVICES]['edit']; - if ($REQUIRED_PRIV == FALSE) + if ($required_privilegesileges == FALSE) { throw new Exception('You do not have the required privileges for this task.'); } $category_id = $this->services_model->add_category($category); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'status' => AJAX_SUCCESS, - 'id' => $category_id - ])); + $response = [ + 'status' => AJAX_SUCCESS, + 'id' => $category_id + ]; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Delete category record from database. - * - * - int $_POST['category_id'] Record id to be deleted. + * Delete category record from database. */ public function ajax_delete_service_category() { @@ -1142,28 +1181,28 @@ class Backend_api extends CI_Controller { } $this->load->model('services_model'); + $result = $this->services_model->delete_category($this->input->post('category_id')); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($result ? AJAX_SUCCESS : AJAX_FAILURE)); + $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Filter services categories with key string. - * - * Required POST Parameters: - * - * - string $_POST['key'] The key string used to filter the records. - * - * Outputs a JSON encoded array back to client with the category records. + * Filter services categories with key string. */ public function ajax_filter_service_categories() { @@ -1175,29 +1214,30 @@ class Backend_api extends CI_Controller { } $this->load->model('services_model'); + $key = $this->db->escape_str($this->input->post('key')); + $where = '(name LIKE "%' . $key . '%" OR description LIKE "%' . $key . '%")'; - $categories = $this->services_model->get_all_categories($where); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($categories)); + + $response = $this->services_model->get_all_categories($where); } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Filter admin records with string key. - * - * Required POST Parameters: - * - * - string $_POST['key'] The key string used to filter the records. - * - * Outputs a JSON encoded array back to client with the admin records. + * Filter admin records with string key. */ public function ajax_filter_admins() { @@ -1209,35 +1249,35 @@ class Backend_api extends CI_Controller { } $this->load->model('admins_model'); + $key = $this->db->escape_str($this->input->post('key')); + $where = '(first_name LIKE "%' . $key . '%" OR last_name LIKE "%' . $key . '%" ' . 'OR email LIKE "%' . $key . '%" OR mobile_number LIKE "%' . $key . '%" ' . 'OR phone_number LIKE "%' . $key . '%" OR address LIKE "%' . $key . '%" ' . 'OR city LIKE "%' . $key . '%" OR state LIKE "%' . $key . '%" ' . 'OR zip_code LIKE "%' . $key . '%" OR notes LIKE "%' . $key . '%")'; - $admins = $this->admins_model->get_batch($where); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($admins)); + + $response = $this->admins_model->get_batch($where); } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Save (insert or update) admin record into database. - * - * Required POST Parameters: - * - * - array $_POST['admin'] A json encoded array that contains the admin data. If an 'id' - * value is provided then the record is going to be updated. - * - * Outputs an array with the operation status and the record id that was saved into the database. + * Save (insert or update) admin record into database. */ public function ajax_save_admin() { @@ -1246,10 +1286,10 @@ class Backend_api extends CI_Controller { $this->load->model('admins_model'); $admin = json_decode($this->input->post('admin'), TRUE); - $REQUIRED_PRIV = ( ! isset($admin['id'])) + $required_privileges = ( ! isset($admin['id'])) ? $this->privileges[PRIV_USERS]['add'] : $this->privileges[PRIV_USERS]['edit']; - if ($REQUIRED_PRIV == FALSE) + if ($required_privileges == FALSE) { throw new Exception('You do not have the required privileges for this task.'); } @@ -1260,27 +1300,24 @@ class Backend_api extends CI_Controller { 'status' => AJAX_SUCCESS, 'id' => $admin_id ]; - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($response)); } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Delete an admin record from the database. - * - * Required POST Parameters: - * - * - int $_POST['admin_id'] The id of the record to be deleted. - * - * Outputs the operation result constant (AJAX_SUCCESS or AJAX_FAILURE). + * Delete an admin record from the database. */ public function ajax_delete_admin() { @@ -1292,27 +1329,28 @@ class Backend_api extends CI_Controller { } $this->load->model('admins_model'); + $result = $this->admins_model->delete($this->input->post('admin_id')); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($result ? AJAX_SUCCESS : AJAX_FAILURE)); + + $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Filter provider records with string key. - * - * Required POST Parameters: - * - * - string $_POST['key'] The key string used to filter the records. - * - * Outputs a JSON encoded array back to client with the provider records. + * Filter provider records with string key. */ public function ajax_filter_providers() { @@ -1324,35 +1362,35 @@ class Backend_api extends CI_Controller { } $this->load->model('providers_model'); + $key = $this->db->escape_str($this->input->post('key')); + $where = '(first_name LIKE "%' . $key . '%" OR last_name LIKE "%' . $key . '%" ' . 'OR email LIKE "%' . $key . '%" OR mobile_number LIKE "%' . $key . '%" ' . 'OR phone_number LIKE "%' . $key . '%" OR address LIKE "%' . $key . '%" ' . 'OR city LIKE "%' . $key . '%" OR state LIKE "%' . $key . '%" ' . 'OR zip_code LIKE "%' . $key . '%" OR notes LIKE "%' . $key . '%")'; - $providers = $this->providers_model->get_batch($where); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($providers)); + + $response = $this->providers_model->get_batch($where); } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Save (insert or update) a provider record into database. - * - * Required POST Parameters: - * - * - array $_POST['provider'] A json encoded array that contains the provider data. If an 'id' - * value is provided then the record is going to be updated. - * - * Outputs the success constant 'AJAX_SUCCESS' so javascript knows that everything completed successfully. + * Save (insert or update) a provider record into database. */ public function ajax_save_provider() { @@ -1361,10 +1399,10 @@ class Backend_api extends CI_Controller { $this->load->model('providers_model'); $provider = json_decode($this->input->post('provider'), TRUE); - $REQUIRED_PRIV = ( ! isset($provider['id'])) + $required_privileges = ( ! isset($provider['id'])) ? $this->privileges[PRIV_USERS]['add'] : $this->privileges[PRIV_USERS]['edit']; - if ($REQUIRED_PRIV == FALSE) + if ($required_privileges == FALSE) { throw new Exception('You do not have the required privileges for this task.'); } @@ -1378,30 +1416,28 @@ class Backend_api extends CI_Controller { $provider_id = $this->providers_model->add($provider); - - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'status' => AJAX_SUCCESS, - 'id' => $provider_id - ])); + $response = [ + 'status' => AJAX_SUCCESS, + 'id' => $provider_id + ]; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Delete a provider record from the database. - * - * Required POST Parameters: - * - * - int $_POST['provider_id'] The id of the record to be deleted. - * - * Outputs the operation result constant (AJAX_SUCCESS or AJAX_FAILURE). + * Delete a provider record from the database. */ public function ajax_delete_provider() { @@ -1413,27 +1449,28 @@ class Backend_api extends CI_Controller { } $this->load->model('providers_model'); + $result = $this->providers_model->delete($this->input->post('provider_id')); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($result ? AJAX_SUCCESS : AJAX_FAILURE)); + + $response =$result ? AJAX_SUCCESS : AJAX_FAILURE; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Filter secretary records with string key. - * - * Required POST Parameters: - * - * - string $_POST['key'] The key string used to filter the records. - * - * Outputs a JSON encoded array back to client with the secretary records. + * Filter secretary records with string key. */ public function ajax_filter_secretaries() { @@ -1445,35 +1482,35 @@ class Backend_api extends CI_Controller { } $this->load->model('secretaries_model'); + $key = $this->db->escape_str($this->input->post('key')); + $where = '(first_name LIKE "%' . $key . '%" OR last_name LIKE "%' . $key . '%" ' . 'OR email LIKE "%' . $key . '%" OR mobile_number LIKE "%' . $key . '%" ' . 'OR phone_number LIKE "%' . $key . '%" OR address LIKE "%' . $key . '%" ' . 'OR city LIKE "%' . $key . '%" OR state LIKE "%' . $key . '%" ' . 'OR zip_code LIKE "%' . $key . '%" OR notes LIKE "%' . $key . '%")'; - $secretaries = $this->secretaries_model->get_batch($where); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($secretaries)); + + $response = $this->secretaries_model->get_batch($where); } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Save (insert or update) a secretary record into database. - * - * Required POST Parameters: - * - * - array $_POST['secretary'] A json encoded array that contains the secretary data. - * If an 'id' value is provided then the record is going to be updated. - * - * Outputs the success constant 'AJAX_SUCCESS' so JavaScript knows that everything completed successfully. + * Save (insert or update) a secretary record into database. */ public function ajax_save_secretary() { @@ -1482,39 +1519,38 @@ class Backend_api extends CI_Controller { $this->load->model('secretaries_model'); $secretary = json_decode($this->input->post('secretary'), TRUE); - $REQUIRED_PRIV = ( ! isset($secretary['id'])) + $required_privileges = ( ! isset($secretary['id'])) ? $this->privileges[PRIV_USERS]['add'] : $this->privileges[PRIV_USERS]['edit']; - if ($REQUIRED_PRIV == FALSE) + if ($required_privileges == FALSE) { throw new Exception('You do not have the required privileges for this task.'); } $secretary_id = $this->secretaries_model->add($secretary); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'status' => AJAX_SUCCESS, - 'id' => $secretary_id - ])); + $response =[ + 'status' => AJAX_SUCCESS, + 'id' => $secretary_id + ]; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Delete a secretary record from the database. - * - * Required POST Parameters: - * - * - int $_POST['secretary_id'] The id of the record to be deleted. - * - * Outputs the operation result constant (AJAX_SUCCESS or AJAX_FAILURE). + * Delete a secretary record from the database. */ public function ajax_delete_secretary() { @@ -1526,30 +1562,28 @@ class Backend_api extends CI_Controller { } $this->load->model('secretaries_model'); + $result = $this->secretaries_model->delete($this->input->post('secretary_id')); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($result ? AJAX_SUCCESS : AJAX_FAILURE)); + $response =$result ? AJAX_SUCCESS : AJAX_FAILURE; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Save a setting or multiple settings in the database. - * - * This method is used to store settings in the database. It can be either system or user settings, one or many. - * Use the $_POST variables accordingly. - * - * Required POST Parameters: - * - * - array $_POST['settings'] Contains an array with settings. - * - bool $_POST['type'] Determines the settings type, can be either SETTINGS_SYSTEM or SETTINGS_USER. + * Save a setting or multiple settings in the database. */ public function ajax_save_settings() { @@ -1561,8 +1595,11 @@ class Backend_api extends CI_Controller { { throw new Exception('You do not have the required privileges for this task.'); } + $this->load->model('settings_model'); + $settings = json_decode($this->input->post('settings'), TRUE); + $this->settings_model->save_settings($settings); } else @@ -1573,60 +1610,66 @@ class Backend_api extends CI_Controller { { throw new Exception('You do not have the required privileges for this task.'); } + $this->load->model('user_model'); - $this->user_model->save_settings(json_decode($this->input->post('settings'), TRUE)); + + $this->user_model->save_user(json_decode($this->input->post('settings'), TRUE)); } } - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); + $response = AJAX_SUCCESS; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] This method checks whether the username already exists in the database. - * - * Required POST Parameters: - * - * - string $_POST['username'] Record's username to validate. - * - bool $_POST['record_exists'] Whether the record already exists in database. + * This method checks whether the username already exists in the database. */ public function ajax_validate_username() { try { - // We will only use the function in the admins_model because it is sufficient - // for the rest user types for now (providers, secretaries). + // We will only use the function in the admins_model because it is sufficient for the rest user types for + // now (providers, secretaries). + $this->load->model('admins_model'); + $is_valid = $this->admins_model->validate_username($this->input->post('username'), $this->input->post('user_id')); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($is_valid)); + + $response = $is_valid; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** - * [AJAX] Change system language for current user. + * Change system language for current user. * * The language setting is stored in session data and retrieved every time the user visits any of the system pages. - * - * Required POST Parameters: - * - * - string $_POST['language'] Selected language name. */ public function ajax_change_language() { @@ -1634,6 +1677,7 @@ class Backend_api extends CI_Controller { { // Check if language exists in the available languages. $found = FALSE; + foreach ($this->config->item('available_languages') as $lang) { if ($lang == $this->input->post('language')) @@ -1651,17 +1695,21 @@ class Backend_api extends CI_Controller { $this->session->set_userdata('language', $this->input->post('language')); $this->config->set_item('language', $this->input->post('language')); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); - + $response = AJAX_SUCCESS; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** @@ -1669,10 +1717,6 @@ class Backend_api extends CI_Controller { * * 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. - * - * Required POST Parameters: - * - * - string $_POST['provider_id'] Provider record id. */ public function ajax_get_google_calendars() { @@ -1688,40 +1732,41 @@ class Backend_api extends CI_Controller { // Check if selected provider has sync enabled. $google_sync = $this->providers_model->get_setting('google_sync', $this->input->post('provider_id')); + 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); + $calendars = $this->google_sync->get_google_calendars(); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($calendars)); + + $response = $calendars; } else { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_FAILURE)); + $response =AJAX_FAILURE; } } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** * Select a specific google calendar for a provider. * * All the appointments will be synced with this particular calendar. - * - * Required POST Parameters: - * - * - int $_POST['provider_id'] Provider record id. - * - string $_POST['calendar_id'] Google calendar's id. */ public function ajax_select_google_calendar() { @@ -1734,19 +1779,25 @@ class Backend_api extends CI_Controller { } $this->load->model('providers_model'); + $result = $this->providers_model->set_setting('google_calendar', $this->input->post('calendar_id'), $this->input->post('provider_id')); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($result ? AJAX_SUCCESS : AJAX_FAILURE)); + $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** @@ -1772,14 +1823,20 @@ class Backend_api extends CI_Controller { $this->providers_model->set_setting('working_plan', $working_plan, $provider['id']); } - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); - } catch (Exception $exc) - { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $response =AJAX_SUCCESS; } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $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 8c4d5db8..634f6d95 100644 --- a/application/controllers/Captcha.php +++ b/application/controllers/Captcha.php @@ -1,4 +1,4 @@ -input->post('consent'); - $this->load->model('consents_model'); + $consent = $this->input->post('consent'); + $consent['ip'] = $this->input->ip_address(); $consent['id'] = $this->consents_model->add($consent); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'success' => TRUE, - 'id' => $consent['id'] - ])); + $response = [ + 'success' => TRUE, + 'id' => $consent['id'] + ]; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'exceptions' => [exceptionToJavaScript($exc)] - ])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } } diff --git a/application/controllers/Errors.php b/application/controllers/Errors.php index d0f4d583..a831a993 100644 --- a/application/controllers/Errors.php +++ b/application/controllers/Errors.php @@ -1,4 +1,4 @@ -load->library('session'); - // Set user's selected language. if ($this->session->userdata('language')) { + // Set user's selected language. $this->config->set_item('language', $this->session->userdata('language')); $this->lang->load('translations', $this->session->userdata('language')); } else { - $this->lang->load('translations', $this->config->item('language')); // default + // Set the default language. + $this->lang->load('translations', $this->config->item('language')); } } @@ -43,7 +66,7 @@ class Errors extends CI_Controller { */ public function index() { - $this->e404(); + $this->error404(); } /** @@ -53,7 +76,9 @@ class Errors extends CI_Controller { { $this->load->helper('google_analytics'); $this->load->model('settings_model'); + $view['company_name'] = $this->settings_model->get_setting('company_name'); + $this->load->view('general/error404', $view); } } diff --git a/application/controllers/Google.php b/application/controllers/Google.php index df19e76a..7f589f40 100644 --- a/application/controllers/Google.php +++ b/application/controllers/Google.php @@ -1,4 +1,4 @@ -session->set_userdata('oauth_provider_id', $provider_id); // Redirect browser to google user content page. - $this->load->library('Google_sync'); + $this->load->library('google_sync'); header('Location: ' . $this->google_sync->get_auth_url()); } @@ -55,7 +77,7 @@ class Google extends CI_Controller { * * IMPORTANT: Because it is necessary to authorize the application using the web server flow (see official * documentation of OAuth), every Easy!Appointments installation should use its own calendar api key. So in every - * api console account, the "http://path-to-e!a/google/oauth_callback" should be included in an allowed redirect URL. + * api console account, the "http://path-to-Easy!Appointments/google/oauth_callback" should be included in an allowed redirect URL. */ public function oauth_callback() { @@ -65,12 +87,14 @@ class Google extends CI_Controller { $token = $this->google_sync->authenticate($this->input->get('code')); // Store the token into the database for future reference. - if (isset($_SESSION['oauth_provider_id'])) + $oauth_provider_id = $this->session->userdata('oauth_provider_id'); + + if ($oauth_provider_id) { $this->load->model('providers_model'); - $this->providers_model->set_setting('google_sync', TRUE, $_SESSION['oauth_provider_id']); - $this->providers_model->set_setting('google_token', $token, $_SESSION['oauth_provider_id']); - $this->providers_model->set_setting('google_calendar', 'primary', $_SESSION['oauth_provider_id']); + $this->providers_model->set_setting('google_sync', TRUE, $oauth_provider_id); + $this->providers_model->set_setting('google_token', $token, $oauth_provider_id); + $this->providers_model->set_setting('google_calendar', 'primary', $oauth_provider_id); } else { @@ -149,7 +173,7 @@ class Google extends CI_Controller { 'company_email' => $this->settings_model->get_setting('company_email') ]; - $provider_timezone = new \DateTimeZone($provider['timezone']); + $provider_timezone = new DateTimeZone($provider['timezone']); // Sync each appointment with Google Calendar by following the project's sync protocol (see documentation). foreach ($appointments as $appointment) @@ -165,13 +189,13 @@ class Google extends CI_Controller { $customer = NULL; } - // If current appointment not synced yet, add to gcal. + // If current appointment not synced yet, add to Google Calendar. if ($appointment['id_google_calendar'] == NULL) { $google_event = $this->google_sync->add_appointment($appointment, $provider, $service, $customer, $company_settings); $appointment['id_google_calendar'] = $google_event->id; - $this->appointments_model->add($appointment); // Save gcal id + $this->appointments_model->add($appointment); // Save the Google Calendar ID. } else { @@ -185,13 +209,14 @@ class Google extends CI_Controller { throw new Exception('Event is cancelled, remove the record from Easy!Appointments.'); } - // If gcal event is different from e!a appointment then update e!a record. + // 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']); - $event_start = new \DateTime($google_event->getStart()->getDateTime()); + $event_start = new DateTime($google_event->getStart()->getDateTime()); $event_start->setTimezone($provider_timezone); - $event_end = new \DateTime($google_event->getEnd()->getDateTime()); + $event_end = new DateTime($google_event->getEnd()->getDateTime()); $event_end->setTimezone($provider_timezone); @@ -210,49 +235,52 @@ class Google extends CI_Controller { } } - catch (Exception $exc) + catch (Exception $exception) { - // Appointment not found on gcal, delete from e!a. + // Appointment not found on Google Calendar, delete from Easy!Appoinmtents. $this->appointments_model->delete($appointment['id']); $appointment['id_google_calendar'] = NULL; } } } - // :: ADD GCAL EVENTS THAT ARE NOT PRESENT ON E!A + // Add Google Calendar events that do not exist in Easy!Appointments. $google_calendar = $provider['settings']['google_calendar']; - $events = $this->google_sync->get_sync_events($google_calendar, $start, $end); + $google_events = $this->google_sync->get_sync_events($google_calendar, $start, $end); - foreach ($events->getItems() as $event) + foreach ($google_events->getItems() as $google_event) { - if ($event->getStatus() === 'cancelled') { + if ($google_event->getStatus() === 'cancelled') + { continue; } - if ($event->getStart() === null || $event->getEnd() === null) { + if ($google_event->getStart() === NULL || $google_event->getEnd() === NULL) + { continue; } - $results = $this->appointments_model->get_batch(['id_google_calendar' => $event->getId()]); + $results = $this->appointments_model->get_batch(['id_google_calendar' => $google_event->getId()]); - if (!empty($results)) { + if ( ! empty($results)) + { continue; } - $event_start = new \DateTime($event->getStart()->getDateTime()); + $event_start = new DateTime($google_event->getStart()->getDateTime()); $event_start->setTimezone($provider_timezone); - $event_end = new \DateTime($event->getEnd()->getDateTime()); + $event_end = new DateTime($google_event->getEnd()->getDateTime()); $event_end->setTimezone($provider_timezone); - // Record doesn't exist in E!A, so add the event now. + // 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'), 'end_datetime' => $event_end->format('Y-m-d H:i:s'), 'is_unavailable' => TRUE, - 'location' => $event->getLocation(), - 'notes' => $event->getSummary() . ' ' . $event->getDescription(), + 'location' => $google_event->getLocation(), + 'notes' => $google_event->getSummary() . ' ' . $google_event->getDescription(), 'id_users_provider' => $provider_id, - 'id_google_calendar' => $event->getId(), + 'id_google_calendar' => $google_event->getId(), 'id_users_customer' => NULL, 'id_services' => NULL, ]; @@ -260,15 +288,20 @@ class Google extends CI_Controller { $this->appointments_model->add($appointment); } - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); + $response = AJAX_SUCCESS; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } } diff --git a/application/controllers/Installation.php b/application/controllers/Installation.php index 20ec62e1..b6f79c69 100644 --- a/application/controllers/Installation.php +++ b/application/controllers/Installation.php @@ -1,4 +1,4 @@ -load->helper('installation'); $this->load->library('session'); - // Set user's selected language. if ($this->session->userdata('language')) { + // Set user's selected language. $this->config->set_item('language', $this->session->userdata('language')); $this->lang->load('translations', $this->session->userdata('language')); } else { - $this->lang->load('translations', $this->config->item('language')); // default + // Set the default language. + $this->lang->load('translations', $this->config->item('language')); } } @@ -58,11 +82,6 @@ class Installation extends CI_Controller { /** * [AJAX] Installs Easy!Appointments on the server. - * - * Required POST Parameters - * - * - array $_POST['admin'] Contains the initial admin user data. The App needs at least one admin user to work. - * - array $_POST['company'] Contains the basic company data. */ public function ajax_install() { @@ -73,7 +92,17 @@ class Installation extends CI_Controller { return; } - // Create E!A database structure. + $this->load->model('admins_model'); + $this->load->model('settings_model'); + $this->load->model('services_model'); + $this->load->model('providers_model'); + $this->load->library('session'); + + $admin = $this->input->post('admin'); + $company = $this->input->post('company'); + + + // Create the Easy!Appointments database structure. $file_contents = file_get_contents(__DIR__ . '/../../assets/sql/structure.sql'); $sql_queries = explode(';', $file_contents); array_pop($sql_queries); @@ -82,7 +111,7 @@ class Installation extends CI_Controller { $this->db->query($query); } - // Insert default E!A entries into the database. + // Insert default Easy!Appointments entries into the database. $file_contents = file_get_contents(__DIR__ . '/../../assets/sql/data.sql'); $sql_queries = explode(';', $file_contents); array_pop($sql_queries); @@ -92,47 +121,43 @@ class Installation extends CI_Controller { } // Insert admin - $this->load->model('admins_model'); - $admin = $this->input->post('admin'); $admin['settings']['username'] = $admin['username']; $admin['settings']['password'] = $admin['password']; $admin['settings']['calendar_view'] = CALENDAR_VIEW_DEFAULT; unset($admin['username'], $admin['password']); $admin['id'] = $this->admins_model->add($admin); - $this->load->library('session'); $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('username', $admin['settings']['username']); // Save company settings - $this->load->model('settings_model'); - $company = $this->input->post('company'); $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']); // Create sample records. - $this->load->model('services_model'); - $this->load->model('providers_model'); - $sample_service = get_sample_service(); $sample_service['id'] = $this->services_model->add($sample_service); $sample_provider = get_sample_provider(); $sample_provider['services'][] = $sample_service['id']; $this->providers_model->add($sample_provider); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); - + $response = AJAX_SUCCESS; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $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 7a30b5d8..8d54b72d 100644 --- a/application/controllers/Privacy.php +++ b/application/controllers/Privacy.php @@ -1,4 +1,4 @@ -load->model('customers_model'); $this->customers_model->delete($customer_id); - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'success' => TRUE - ])); + $response = [ + 'success' => TRUE + ]; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode([ - 'exceptions' => [exceptionToJavaScript($exc)] - ])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $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 b56c151b..e2d07c88 100644 --- a/application/controllers/User.php +++ b/application/controllers/User.php @@ -1,4 +1,4 @@ -load->library('session'); - // Set user's selected language. if ($this->session->userdata('language')) { + // Set user's selected language. $this->config->set_item('language', $this->session->userdata('language')); $this->lang->load('translations', $this->session->userdata('language')); } else { + // Set the default language. $this->lang->load('translations', $this->config->item('language')); // default } } @@ -52,6 +77,8 @@ class User extends CI_Controller { /** * Display the login page. + * + * @throws Exception */ public function login() { @@ -66,6 +93,7 @@ class User extends CI_Controller { } $view['company_name'] = $this->settings_model->get_setting('company_name'); + $this->load->view('user/login', $view); } @@ -89,6 +117,7 @@ class User extends CI_Controller { /** * Display the "forgot password" page. + * @throws Exception */ public function forgot_password() { @@ -100,6 +129,7 @@ class User extends CI_Controller { /** * Display the "not authorized" page. + * @throws Exception */ public function no_privileges() { @@ -128,29 +158,33 @@ class User extends CI_Controller { } $this->load->model('user_model'); + $user_data = $this->user_model->check_login($this->input->post('username'), $this->input->post('password')); if ($user_data) { $this->session->set_userdata($user_data); // Save data on user's session. - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_SUCCESS)); + + $response = AJAX_SUCCESS; } else { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(AJAX_FAILURE)); + $response = AJAX_FAILURE; } - } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } /** @@ -175,13 +209,17 @@ class User extends CI_Controller { $this->load->model('user_model'); $this->load->model('settings_model'); - $new_password = $this->user_model->regenerate_password($this->input->post('username'), - $this->input->post('email')); + $new_password = $this->user_model->regenerate_password( + $this->input->post('username'), + $this->input->post('email') + ); if ($new_password != FALSE) { $this->config->load('email'); - $email = new \EA\Engine\Notifications\Email($this, $this->config->config); + + $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'), @@ -192,15 +230,20 @@ class User extends CI_Controller { $company_settings); } - $this->output - ->set_content_type('application/json') - ->set_output(json_encode($new_password != FALSE ? AJAX_SUCCESS : AJAX_FAILURE)); + $response = $new_password != FALSE ? AJAX_SUCCESS : AJAX_FAILURE; } - catch (Exception $exc) + catch (Exception $exception) { - $this->output - ->set_content_type('application/json') - ->set_output(json_encode(['exceptions' => [exceptionToJavaScript($exc)]])); + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); } } diff --git a/application/controllers/api/v1/API_V1_Controller.php b/application/controllers/api/v1/API_V1_Controller.php index c92a47ea..103c0f81 100644 --- a/application/controllers/api/v1/API_V1_Controller.php +++ b/application/controllers/api/v1/API_V1_Controller.php @@ -1,4 +1,4 @@ -settings_model->get_setting('api_token'); - $authorization = new \EA\Engine\Api\V1\Authorization($this); + $authorization = new Authorization($this); if ( ! empty($api_token) && $api_token === $this->_getBearerToken()) { @@ -59,7 +60,8 @@ class API_V1_Controller extends CI_Controller { $username = new NonEmptyText($_SERVER['PHP_AUTH_USER']); $password = new NonEmptyText($_SERVER['PHP_AUTH_PW']); $authorization->basic($username, $password); - } catch (\Exception $exception) + } + catch (Exception $exception) { exit($this->_handleException($exception)); } @@ -96,13 +98,15 @@ class API_V1_Controller extends CI_Controller { if (isset($_SERVER['Authorization'])) { $headers = trim($_SERVER['Authorization']); - } else + } + else { if (isset($_SERVER['HTTP_AUTHORIZATION'])) { //Nginx or fast CGI $headers = trim($_SERVER['HTTP_AUTHORIZATION']); - } elseif (function_exists('apache_request_headers')) + } + elseif (function_exists('apache_request_headers')) { $requestHeaders = apache_request_headers(); // Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization) @@ -132,9 +136,9 @@ class API_V1_Controller extends CI_Controller { * * Call this method from catch blocks of child controller callbacks. * - * @param \Exception $exception Thrown exception to be outputted. + * @param Exception $exception Thrown exception to be outputted. */ - protected function _handleException(\Exception $exception) + protected function _handleException(Exception $exception) { $error = [ 'code' => $exception->getCode() ?: 500, diff --git a/application/controllers/api/v1/Admins.php b/application/controllers/api/v1/Admins.php index 90dc8c18..d33985b9 100644 --- a/application/controllers/api/v1/Admins.php +++ b/application/controllers/api/v1/Admins.php @@ -1,4 +1,4 @@ -output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -82,7 +104,7 @@ class Admins extends API_V1_Controller { { try { - // Insert the admin to the database. + // Insert the admin to the database. $request = new Request(); $admin = $request->getBody(); $this->parser->decode($admin); @@ -100,7 +122,7 @@ class Admins extends API_V1_Controller { $status = new NonEmptyText('201 Created'); $response->encode($this->parser)->singleEntry(TRUE)->output($status); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -115,7 +137,7 @@ class Admins extends API_V1_Controller { { try { - // Update the admin record. + // Update the admin record. $batch = $this->admins_model->get_batch('id = ' . $id); if ($id !== NULL && count($batch) === 0) @@ -135,7 +157,7 @@ class Admins extends API_V1_Controller { $response = new Response($batch); $response->encode($this->parser)->singleEntry($id)->output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -159,7 +181,7 @@ class Admins extends API_V1_Controller { $response->output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } diff --git a/application/controllers/api/v1/Appointments.php b/application/controllers/api/v1/Appointments.php index 81664a5c..c2f0fa54 100644 --- a/application/controllers/api/v1/Appointments.php +++ b/application/controllers/api/v1/Appointments.php @@ -1,4 +1,4 @@ -output(); } - catch (\Exception $exception) + catch (Exception $exception) { exit($this->_handleException($exception)); } @@ -108,7 +130,7 @@ class Appointments extends API_V1_Controller { $status = new NonEmptyText('201 Created'); $response->encode($this->parser)->singleEntry(TRUE)->output($status); } - catch (\Exception $exception) + catch (Exception $exception) { exit($this->_handleException($exception)); } @@ -143,7 +165,7 @@ class Appointments extends API_V1_Controller { $response = new Response($batch); $response->encode($this->parser)->singleEntry($id)->output(); } - catch (\Exception $exception) + catch (Exception $exception) { exit($this->_handleException($exception)); } @@ -167,7 +189,7 @@ class Appointments extends API_V1_Controller { $response->output(); } - catch (\Exception $exception) + catch (Exception $exception) { exit($this->_handleException($exception)); } diff --git a/application/controllers/api/v1/Availabilities.php b/application/controllers/api/v1/Availabilities.php index e50770b1..66e0e1c8 100644 --- a/application/controllers/api/v1/Availabilities.php +++ b/application/controllers/api/v1/Availabilities.php @@ -1,4 +1,4 @@ -set_content_type('application/json') ->set_output(json_encode($availableHours)); } - catch (\Exception $exception) + catch (Exception $exception) { exit($this->_handleException($exception)); } @@ -122,7 +144,8 @@ class Availabilities extends API_V1_Controller { $provider_id, $selected_date, $exclude_appointments = [] - ) { + ) + { $this->load->model('appointments_model'); $this->load->model('providers_model'); @@ -318,7 +341,8 @@ class Availabilities extends API_V1_Controller { $service_duration, $manage_mode = FALSE, $availabilities_type = 'flexible' - ) { + ) + { $this->load->model('settings_model'); $available_hours = []; @@ -358,7 +382,8 @@ class Availabilities extends API_V1_Controller { $selected_date, $service, $provider - ) { + ) + { $this->load->model('appointments_model'); $this->load->model('services_model'); $this->load->model('providers_model'); diff --git a/application/controllers/api/v1/Categories.php b/application/controllers/api/v1/Categories.php index b7d9d3b9..d3899a0e 100644 --- a/application/controllers/api/v1/Categories.php +++ b/application/controllers/api/v1/Categories.php @@ -1,4 +1,4 @@ -output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -82,7 +104,7 @@ class Categories extends API_V1_Controller { { try { - // Insert the category to the database. + // Insert the category to the database. $request = new Request(); $category = $request->getBody(); $this->parser->decode($category); @@ -100,7 +122,7 @@ class Categories extends API_V1_Controller { $status = new NonEmptyText('201 Created'); $response->encode($this->parser)->singleEntry(TRUE)->output($status); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -115,7 +137,7 @@ class Categories extends API_V1_Controller { { try { - // Update the category record. + // Update the category record. $batch = $this->services_model->get_all_categories('id = ' . $id); if ($id !== NULL && count($batch) === 0) @@ -135,7 +157,7 @@ class Categories extends API_V1_Controller { $response = new Response($batch); $response->encode($this->parser)->singleEntry($id)->output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -159,7 +181,7 @@ class Categories extends API_V1_Controller { $response->output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } diff --git a/application/controllers/api/v1/Customers.php b/application/controllers/api/v1/Customers.php index 7593b5ab..6e5f26d8 100644 --- a/application/controllers/api/v1/Customers.php +++ b/application/controllers/api/v1/Customers.php @@ -1,4 +1,4 @@ -output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -82,7 +104,7 @@ class Customers extends API_V1_Controller { { try { - // Insert the customer to the database. + // Insert the customer to the database. $request = new Request(); $customer = $request->getBody(); $this->parser->decode($customer); @@ -100,7 +122,7 @@ class Customers extends API_V1_Controller { $status = new NonEmptyText('201 Created'); $response->encode($this->parser)->singleEntry(TRUE)->output($status); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -115,7 +137,7 @@ class Customers extends API_V1_Controller { { try { - // Update the customer record. + // Update the customer record. $batch = $this->customers_model->get_batch('id = ' . $id); if ($id !== NULL && count($batch) === 0) @@ -135,7 +157,7 @@ class Customers extends API_V1_Controller { $response = new Response($batch); $response->encode($this->parser)->singleEntry($id)->output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -159,7 +181,7 @@ class Customers extends API_V1_Controller { $response->output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } diff --git a/application/controllers/api/v1/Providers.php b/application/controllers/api/v1/Providers.php index f2fb79e9..e641472a 100644 --- a/application/controllers/api/v1/Providers.php +++ b/application/controllers/api/v1/Providers.php @@ -1,4 +1,4 @@ -output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -100,7 +122,7 @@ class Providers extends API_V1_Controller { $status = new NonEmptyText('201 Created'); $response->encode($this->parser)->singleEntry(TRUE)->output($status); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -135,7 +157,7 @@ class Providers extends API_V1_Controller { $response = new Response($batch); $response->encode($this->parser)->singleEntry($id)->output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -159,7 +181,7 @@ class Providers extends API_V1_Controller { $response->output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } diff --git a/application/controllers/api/v1/Secretaries.php b/application/controllers/api/v1/Secretaries.php index ee6d31e3..ff5bfb80 100644 --- a/application/controllers/api/v1/Secretaries.php +++ b/application/controllers/api/v1/Secretaries.php @@ -1,4 +1,4 @@ -output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -82,7 +104,7 @@ class Secretaries extends API_V1_Controller { { try { - // Insert the secretary to the database. + // Insert the secretary to the database. $request = new Request(); $secretary = $request->getBody(); $this->parser->decode($secretary); @@ -100,7 +122,7 @@ class Secretaries extends API_V1_Controller { $status = new NonEmptyText('201 Created'); $response->encode($this->parser)->singleEntry(TRUE)->output($status); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -115,7 +137,7 @@ class Secretaries extends API_V1_Controller { { try { - // Update the secretary record. + // Update the secretary record. $batch = $this->secretaries_model->get_batch('id = ' . $id); if ($id !== NULL && count($batch) === 0) @@ -135,7 +157,7 @@ class Secretaries extends API_V1_Controller { $response = new Response($batch); $response->encode($this->parser)->singleEntry($id)->output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -159,7 +181,7 @@ class Secretaries extends API_V1_Controller { $response->output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } diff --git a/application/controllers/api/v1/Services.php b/application/controllers/api/v1/Services.php index 868237a4..2330519a 100644 --- a/application/controllers/api/v1/Services.php +++ b/application/controllers/api/v1/Services.php @@ -1,4 +1,4 @@ -output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -82,7 +104,7 @@ class Services extends API_V1_Controller { { try { - // Insert the service to the database. + // Insert the service to the database. $request = new Request(); $service = $request->getBody(); $this->parser->decode($service); @@ -100,7 +122,7 @@ class Services extends API_V1_Controller { $status = new NonEmptyText('201 Created'); $response->encode($this->parser)->singleEntry(TRUE)->output($status); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -115,7 +137,7 @@ class Services extends API_V1_Controller { { try { - // Update the service record. + // Update the service record. $batch = $this->services_model->get_batch('id = ' . $id); if ($id !== NULL && count($batch) === 0) @@ -135,7 +157,7 @@ class Services extends API_V1_Controller { $response = new Response($batch); $response->encode($this->parser)->singleEntry($id)->output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } @@ -159,7 +181,7 @@ class Services extends API_V1_Controller { $response->output(); } - catch (\Exception $exception) + catch (Exception $exception) { $this->_handleException($exception); } diff --git a/application/controllers/api/v1/Settings.php b/application/controllers/api/v1/Settings.php index a3dfb063..3acfb500 100644 --- a/application/controllers/api/v1/Settings.php +++ b/application/controllers/api/v1/Settings.php @@ -1,4 +1,4 @@ -output(); } - catch (\Exception $exception) + catch (Exception $exception) { exit($this->_handleException($exception)); } @@ -115,7 +137,7 @@ class Settings extends API_V1_Controller { ]); $response->encode($this->parser)->singleEntry($name)->output(); } - catch (\Exception $exception) + catch (Exception $exception) { exit($this->_handleException($exception)); } @@ -139,7 +161,7 @@ class Settings extends API_V1_Controller { $response->output(); } - catch (\Exception $exception) + catch (Exception $exception) { exit($this->_handleException($exception)); } diff --git a/application/controllers/api/v1/Unavailabilities.php b/application/controllers/api/v1/Unavailabilities.php index e1f2bcf4..9b34a37f 100644 --- a/application/controllers/api/v1/Unavailabilities.php +++ b/application/controllers/api/v1/Unavailabilities.php @@ -1,4 +1,4 @@ -output(); } - catch (\Exception $exception) + catch (Exception $exception) { exit($this->_handleException($exception)); } @@ -82,7 +104,7 @@ class Unavailabilities extends API_V1_Controller { { try { - // Insert the appointment to the database. + // Insert the appointment to the database. $request = new Request(); $unavailability = $request->getBody(); $this->parser->decode($unavailability); @@ -100,7 +122,7 @@ class Unavailabilities extends API_V1_Controller { $status = new NonEmptyText('201 Created'); $response->encode($this->parser)->singleEntry(TRUE)->output($status); } - catch (\Exception $exception) + catch (Exception $exception) { exit($this->_handleException($exception)); } @@ -115,7 +137,7 @@ class Unavailabilities extends API_V1_Controller { { try { - // Update the appointment record. + // Update the appointment record. $batch = $this->appointments_model->get_batch('id = ' . $id); if ($id !== NULL && count($batch) === 0) @@ -135,7 +157,7 @@ class Unavailabilities extends API_V1_Controller { $response = new Response($batch); $response->encode($this->parser)->singleEntry($id)->output(); } - catch (\Exception $exception) + catch (Exception $exception) { exit($this->_handleException($exception)); } @@ -159,7 +181,7 @@ class Unavailabilities extends API_V1_Controller { $response->output(); } - catch (\Exception $exception) + catch (Exception $exception) { exit($this->_handleException($exception)); } diff --git a/application/helpers/asset_helper.php b/application/helpers/asset_helper.php index de514082..b16af5dd 100644 --- a/application/helpers/asset_helper.php +++ b/application/helpers/asset_helper.php @@ -1,4 +1,4 @@ -config->item('cache_busting_token') : ''; + $debug = $framework->config->item('debug'); - if (strpos(basename($uri), '.js') !== FALSE && strpos(basename($uri), '.min.js') === FALSE && ! Config::DEBUG_MODE) + $cache_busting_token = ! $debug ? '?' . $framework->config->item('cache_busting_token') : ''; + + if (strpos(basename($uri), '.js') !== FALSE && strpos(basename($uri), '.min.js') === FALSE && ! $debug) { $uri = str_replace('.js', '.min.js', $uri); } - if (strpos(basename($uri), '.css') !== FALSE && strpos(basename($uri), '.min.css') === FALSE && ! Config::DEBUG_MODE) + if (strpos(basename($uri), '.css') !== FALSE && strpos(basename($uri), '.min.css') === FALSE && ! $debug) { $uri = str_replace('.css', '.min.css', $uri); } diff --git a/application/helpers/config_helper.php b/application/helpers/config_helper.php index 899afbcc..3776e0de 100644 --- a/application/helpers/config_helper.php +++ b/application/helpers/config_helper.php @@ -1,4 +1,4 @@ - @@ -55,35 +31,14 @@ function exceptionToHtml($exc)
' . - $exc->getMessage() . ' + $exception->getMessage() . '
-
' . $exc->getTraceAsString() . '
+
' . $exception->getTraceAsString() . '
'; } - -/** - * Get a javascript object of a given exception. - * - * This method is pretty useful whenever we need to pass an exception object - * to javascript during ajax calls. - * - * @param Exception $exception The given exception object. - * @return string Returns the json encoded object of the exception. - */ -function exceptionToJavaScript($exception) -{ - return json_encode([ - 'code' => $exception->getCode(), - 'file' => $exception->getFile(), - 'line' => $exception->getLine(), - 'message' => $exception->getMessage(), - 'previous' => $exception->getPrevious(), - 'trace' => $exception->getTraceAsString() - ]); -} diff --git a/application/helpers/data_validation_helper.php b/application/helpers/data_validation_helper.php index ac71b416..1d73e3e6 100644 --- a/application/helpers/data_validation_helper.php +++ b/application/helpers/data_validation_helper.php @@ -1,4 +1,4 @@ -load->model('settings_model'); + $framework->load->model('settings_model'); - $google_analytics_code = $ci->settings_model->get_setting('google_analytics_code'); + $google_analytics_code = $framework->settings_model->get_setting('google_analytics_code'); if ($google_analytics_code !== '') { diff --git a/application/helpers/installation_helper.php b/application/helpers/installation_helper.php index 27b58955..3ed27bca 100644 --- a/application/helpers/installation_helper.php +++ b/application/helpers/installation_helper.php @@ -1,4 +1,4 @@ -db->table_exists('ea_users'); + $framework =& get_instance(); + + return $framework->db->table_exists('ea_users'); } /** diff --git a/application/helpers/render_helper.php b/application/helpers/render_helper.php index bddbd394..c59f6d54 100644 --- a/application/helpers/render_helper.php +++ b/application/helpers/render_helper.php @@ -1,4 +1,4 @@ -CI =& get_instance(); + $this->framework =& get_instance(); - $this->CI->load->library('session'); + $this->framework->load->library('session'); // Initialize google client and calendar service. $this->client = new Google_Client(); $this->client->setUseObjects(TRUE); - $this->client->setApplicationName(Config::GOOGLE_PRODUCT_NAME); - $this->client->setClientId(Config::GOOGLE_CLIENT_ID); - $this->client->setClientSecret(Config::GOOGLE_CLIENT_SECRET); - $this->client->setDeveloperKey(Config::GOOGLE_API_KEY); + $this->client->setApplicationName($this->framework->config->item('google_application_name')); + $this->client->setClientId($this->framework->config->item('google_client_id')); + $this->client->setClientSecret($this->framework->config->item('google_client_secret')); + $this->client->setDeveloperKey($this->framework->config->item('google_api_key')); $this->client->setRedirectUri(site_url('google/oauth_callback')); $this->service = new Google_CalendarService($this->client); @@ -121,29 +121,26 @@ class Google_Sync { /** * Add an appointment record to its providers Google Calendar account. * - * This method checks whether the appointment's provider has enabled the Google - * Sync utility of Easy!Appointments and the stored access token is still valid. - * If yes, the selected appointment record is going to be added to the Google - * Calendar account. + * This method checks whether the appointment's provider has enabled the Google Sync utility of Easy!Appointments + * and the stored access token is still valid. If yes, the selected appointment record is going to be added to the + * Google Calendar account. * * @param array $appointment Contains the appointment record data. * @param array $provider Contains the provider record data. * @param array $service Contains the service record data. * @param array $customer Contains the customer recod data. - * @parma array $company_settings Contains some company settings that are used - * by this method. By the time the following values must be in the array: - * 'company_name'. + * @param array $settings Contains some company settings that are used by this method. * * @return Google_Event Returns the Google_Event class object. */ - public function add_appointment($appointment, $provider, $service, $customer, $company_settings) + public function add_appointment($appointment, $provider, $service, $customer, $settings) { - $this->CI->load->helper('general'); + $this->framework->load->helper('general'); $event = new Google_Event(); $event->setSummary(($service != NULL) ? $service['name'] : 'Unavailable'); $event->setDescription($appointment['notes']); - $event->setLocation(isset($appointment['location']) ? $appointment['location'] : $company_settings['company_name']); + $event->setLocation(isset($appointment['location']) ? $appointment['location'] : $settings['company_name']); $start = new Google_EventDateTime(); $start->setDateTime(date3339(strtotime($appointment['start_datetime']))); @@ -186,22 +183,20 @@ class Google_Sync { * @param array $provider Contains the provider record data. * @param array $service Contains the service record data. * @param array $customer Contains the customer recod data. - * @parma array $company_settings Contains some company settings that are used - * by this method. By the time the following values must be in the array: - * 'company_name'. + * @parma array $company_settings Contains some company settings that are used by this method. * * @return Google_Event Returns the Google_Event class object. */ - public function update_appointment($appointment, $provider, $service, $customer, $company_settings) + public function update_appointment($appointment, $provider, $service, $customer, $settings) { - $this->CI->load->helper('general'); + $this->framework->load->helper('general'); $event = $this->service->events->get($provider['settings']['google_calendar'], $appointment['id_google_calendar']); $event->setSummary($service['name']); $event->setDescription($appointment['notes']); - $event->setLocation(isset($appointment['location']) ? $appointment['location'] : $company_settings['company_name']); + $event->setLocation(isset($appointment['location']) ? $appointment['location'] : $settings['company_name']); $start = new Google_EventDateTime(); $start->setDateTime(date3339(strtotime($appointment['start_datetime']))); @@ -263,7 +258,7 @@ class Google_Sync { */ public function add_unavailable($provider, $unavailable) { - $this->CI->load->helper('general'); + $this->framework->load->helper('general'); $event = new Google_Event(); $event->setSummary('Unavailable'); @@ -294,7 +289,7 @@ class Google_Sync { */ public function update_unavailable($provider, $unavailable) { - $this->CI->load->helper('general'); + $this->framework->load->helper('general'); $event = $this->service->events->get($provider['settings']['google_calendar'], $unavailable['id_google_calendar']); @@ -349,20 +344,20 @@ class Google_Sync { * Get all the events between the sync period. * * @param string $google_calendar The name of the google calendar to be used. - * @param date $start The start date of sync period. - * @param date $end The end date of sync period. + * @param string $start The start date of sync period. + * @param string $end The end date of sync period. * * @return object Returns an array with Google_Event objects that belong on the given * sync period (start, end). */ public function get_sync_events($google_calendar, $start, $end) { - $this->CI->load->helper('general'); + $this->framework->load->helper('general'); $params = [ 'timeMin' => date3339($start), 'timeMax' => date3339($end), - 'singleEvents' => true, + 'singleEvents' => TRUE, ]; return $this->service->events->listEvents($google_calendar, $params); diff --git a/application/libraries/Ics_file.php b/application/libraries/Ics_file.php index 56ff6dff..f5d4094d 100644 --- a/application/libraries/Ics_file.php +++ b/application/libraries/Ics_file.php @@ -1,4 +1,4 @@ -db->field_exists('google_calendar', 'ea_user_settings')) @@ -28,6 +36,9 @@ class Migration_Specific_calendar_sync extends CI_Migration { } } + /** + * Downgrade method. + */ public function down() { if ($this->db->field_exists('google_calendar', 'ea_user_settings')) diff --git a/application/migrations/002_add_google_analytics_setting.php b/application/migrations/002_add_google_analytics_setting.php index 442763ad..191c2be4 100644 --- a/application/migrations/002_add_google_analytics_setting.php +++ b/application/migrations/002_add_google_analytics_setting.php @@ -1,4 +1,4 @@ -load->model('settings_model'); + } + + /** + * Upgrade method. + * + * @throws Exception + */ public function up() { - $this->load->model('settings_model'); - try { $this->settings_model->get_setting('google_analytics_code'); @@ -26,10 +49,13 @@ class Migration_Add_google_analytics_setting extends CI_Migration { } } + /** + * Downgrade method. + * + * @throws Exception + */ public function down() { - $this->load->model('settings_model'); - $this->settings_model->remove_setting('google_analytics_code'); } } diff --git a/application/migrations/003_add_customer_notifications_setting.php b/application/migrations/003_add_customer_notifications_setting.php index 6c860c1f..0056d566 100644 --- a/application/migrations/003_add_customer_notifications_setting.php +++ b/application/migrations/003_add_customer_notifications_setting.php @@ -1,4 +1,4 @@ -load->model('settings_model'); + } + + /** + * Upgrade method. + * + * @throws Exception + */ public function up() { - $this->load->model('settings_model'); - try { $this->settings_model->get_setting('customer_notifications'); @@ -26,10 +48,13 @@ class Migration_Add_customer_notifications_setting extends CI_Migration { } } + /** + * Downgrade method. + * + * @throws Exception + */ public function down() { - $this->load->model('settings_model'); - $this->settings_model->remove_setting('customer_notifications'); } } diff --git a/application/migrations/004_add_date_format_setting.php b/application/migrations/004_add_date_format_setting.php index 85a38d90..5e382047 100644 --- a/application/migrations/004_add_date_format_setting.php +++ b/application/migrations/004_add_date_format_setting.php @@ -1,4 +1,4 @@ -load->model('settings_model'); + } + + + /** + * Upgrade method. + * + * @throws Exception + */ public function up() { - $this->load->model('settings_model'); - try { $this->settings_model->get_setting('date_format'); @@ -26,10 +50,13 @@ class Migration_Add_date_format_setting extends CI_Migration { } } + /** + * Downgrade method. + * + * @throws Exception + */ public function down() { - $this->load->model('settings_model'); - $this->settings_model->remove_setting('date_format'); } } diff --git a/application/migrations/005_add_require_captcha_setting.php b/application/migrations/005_add_require_captcha_setting.php index 438d60c2..e544d2d6 100644 --- a/application/migrations/005_add_require_captcha_setting.php +++ b/application/migrations/005_add_require_captcha_setting.php @@ -1,4 +1,4 @@ -load->model('settings_model'); + } + + /** + * Upgrade method. + * + * @throws Exception + */ public function up() { - $this->load->model('settings_model'); - try { $this->settings_model->get_setting('require_captcha'); @@ -26,10 +49,13 @@ class Migration_Add_require_captcha_setting extends CI_Migration { } } + /** + * Downgrade method. + * + * @throws Exception + */ public function down() { - $this->load->model('settings_model'); - $this->settings_model->remove_setting('require_captcha'); } } diff --git a/application/migrations/006_add_calendar_view_setting.php b/application/migrations/006_add_calendar_view_setting.php index fedbce06..32fd181a 100644 --- a/application/migrations/006_add_calendar_view_setting.php +++ b/application/migrations/006_add_calendar_view_setting.php @@ -1,4 +1,4 @@ -db->field_exists('calendar_view', 'ea_user_settings')) @@ -30,6 +41,9 @@ class Migration_Add_calendar_view_setting extends CI_Migration { } } + /** + * Downgrade method. + */ public function down() { if ($this->db->field_exists('calendar_view', 'ea_user_settings')) diff --git a/application/migrations/007_add_service_availabilities_type.php b/application/migrations/007_add_service_availabilities_type.php index 34230c34..13acd9ba 100644 --- a/application/migrations/007_add_service_availabilities_type.php +++ b/application/migrations/007_add_service_availabilities_type.php @@ -1,4 +1,4 @@ -db->field_exists('availabilities_type', 'ea_services')) @@ -31,6 +42,9 @@ class Migration_Add_service_availabilities_type extends CI_Migration { } } + /** + * Downgrade method. + */ public function down() { if ($this->db->field_exists('availabilities_type', 'ea_services')) diff --git a/application/migrations/008_add_service_attendants_number.php b/application/migrations/008_add_service_attendants_number.php index c4740ebe..bd8460df 100644 --- a/application/migrations/008_add_service_attendants_number.php +++ b/application/migrations/008_add_service_attendants_number.php @@ -1,4 +1,4 @@ -db->field_exists('attendants_number', 'ea_services')) @@ -31,6 +42,9 @@ class Migration_Add_service_attendants_number extends CI_Migration { } } + /** + * Downgrade method. + */ public function down() { if ($this->db->field_exists('attendants_number', 'ea_services')) diff --git a/application/migrations/009_change_column_types.php b/application/migrations/009_change_column_types.php index 86910380..12140534 100644 --- a/application/migrations/009_change_column_types.php +++ b/application/migrations/009_change_column_types.php @@ -1,4 +1,4 @@ -db->query('ALTER TABLE ea_secretaries_providers CONVERT TO CHARACTER SET utf8'); } + /** + * Downgrade method. + */ public function down() { // Drop table constraints. diff --git a/application/migrations/010_add_time_format_setting.php b/application/migrations/010_add_time_format_setting.php index 884c8737..89dbc057 100644 --- a/application/migrations/010_add_time_format_setting.php +++ b/application/migrations/010_add_time_format_setting.php @@ -1,4 +1,4 @@ -load->model('settings_model'); + } + + /** + * Upgrade method. + */ public function up() { - $this->load->model('settings_model'); - try { $this->settings_model->get_setting('time_format'); @@ -26,10 +47,11 @@ class Migration_Add_time_format_setting extends CI_Migration { } } + /** + * Downgrade method. + */ public function down() { - $this->load->model('settings_model'); - $this->settings_model->remove_setting('time_format'); } } diff --git a/application/migrations/011_remove_prefix_from_fkey_constraints.php b/application/migrations/011_remove_prefix_from_fkey_constraints.php index f88d927c..98f533a1 100644 --- a/application/migrations/011_remove_prefix_from_fkey_constraints.php +++ b/application/migrations/011_remove_prefix_from_fkey_constraints.php @@ -1,4 +1,4 @@ -db->insert('ea_settings', ['name' => 'display_cookie_notice', 'value' => '0']); @@ -40,6 +51,9 @@ class Migration_Legal_contents extends CI_Migration { '); } + /** + * Downgrade method. + */ public function down() { $this->db->delete('ea_settings', ['name' => 'display_cookie_notice']); diff --git a/application/migrations/013_add_weekday_start_setting.php b/application/migrations/013_add_weekday_start_setting.php index 4aa45220..0e3889cd 100644 --- a/application/migrations/013_add_weekday_start_setting.php +++ b/application/migrations/013_add_weekday_start_setting.php @@ -1,4 +1,4 @@ -load->model('settings_model'); + } + + /** + * Upgrade method. + */ public function up() { - $this->load->model('settings_model'); - try { $this->settings_model->get_setting('first_weekday'); @@ -26,10 +47,11 @@ class Migration_Add_weekday_start_setting extends CI_Migration { } } + /** + * Downgrade method. + */ public function down() { - $this->load->model('settings_model'); - $this->settings_model->remove_setting('first_weekday'); } } diff --git a/application/migrations/014_add_appointment_location_column.php b/application/migrations/014_add_appointment_location_column.php index 3bc11f4c..12a8f206 100644 --- a/application/migrations/014_add_appointment_location_column.php +++ b/application/migrations/014_add_appointment_location_column.php @@ -1,4 +1,4 @@ -db->query(' @@ -25,6 +36,9 @@ class Migration_add_appointment_location_column extends CI_Migration { '); } + /** + * Downgrade method. + */ public function down() { $this->db->query(' diff --git a/application/migrations/015_add_user_extra_working_plan.php b/application/migrations/015_add_user_extra_working_plan.php index 6094e502..e83ec271 100644 --- a/application/migrations/015_add_user_extra_working_plan.php +++ b/application/migrations/015_add_user_extra_working_plan.php @@ -1,4 +1,4 @@ -db->field_exists('extra_working_plan', 'ea_user_settings')) { + if ( ! $this->db->field_exists('extra_working_plan', 'ea_user_settings')) + { $fields = [ 'extra_working_plan' => [ 'type' => 'TEXT', @@ -28,9 +40,13 @@ class Migration_Add_user_extra_working_plan extends CI_Migration { } } + /** + * Downgrade method. + */ public function down() { - if (!$this->db->field_exists('extra_working_plan', 'ea_user_settings')) { + if ( ! $this->db->field_exists('extra_working_plan', 'ea_user_settings')) + { $this->dbforge->drop_column('ea_user_settings', 'extra_working_plan'); } } diff --git a/application/migrations/016_add_require_phone_number_setting.php b/application/migrations/016_add_require_phone_number_setting.php index cc369a91..43a85eab 100644 --- a/application/migrations/016_add_require_phone_number_setting.php +++ b/application/migrations/016_add_require_phone_number_setting.php @@ -1,4 +1,4 @@ -load->model('settings_model'); + } + + /** + * Upgrade method. + */ public function up() { - $this->load->model('settings_model'); - try { $this->settings_model->get_setting('require_phone_number'); @@ -26,10 +47,11 @@ class Migration_Add_require_phone_number_setting extends CI_Migration { } } + /** + * Downgrade method. + */ public function down() { - $this->load->model('settings_model'); - $this->settings_model->remove_setting('require_phone_number'); } } diff --git a/application/migrations/017_add_api_token_setting.php b/application/migrations/017_add_api_token_setting.php index e0feda47..a31b65da 100644 --- a/application/migrations/017_add_api_token_setting.php +++ b/application/migrations/017_add_api_token_setting.php @@ -1,4 +1,4 @@ -load->model('settings_model'); + } + + /** + * Upgrade method. + * + * @throws Exception + */ public function up() { - $this->load->model('settings_model'); - try { $this->settings_model->get_setting('api_token'); @@ -26,10 +49,13 @@ class Migration_Add_api_token_setting extends CI_Migration { } } + /** + * Downgrade method. + * + * @throws Exception + */ public function down() { - $this->load->model('settings_model'); - $this->settings_model->remove_setting('api_token'); } } diff --git a/application/migrations/018_add_timezone_columns.php b/application/migrations/018_add_timezone_columns.php index 184aeb12..5a78e6ec 100644 --- a/application/migrations/018_add_timezone_columns.php +++ b/application/migrations/018_add_timezone_columns.php @@ -1,4 +1,4 @@ -db->query(' @@ -20,6 +31,9 @@ class Migration_Add_timezone_columns extends CI_Migration { '); } + /** + * Downgrade method. + */ public function down() { $this->db->query(' diff --git a/application/migrations/019_add_display_any_provider_setting.php b/application/migrations/019_add_display_any_provider_setting.php index 114a8407..dc2743a6 100644 --- a/application/migrations/019_add_display_any_provider_setting.php +++ b/application/migrations/019_add_display_any_provider_setting.php @@ -1,4 +1,4 @@ -db->insert('ea_settings', [ @@ -20,6 +31,9 @@ class Migration_Add_display_any_provider_setting extends CI_Migration { ]); } + /** + * Downgrade method. + */ public function down() { $this->db->delete('ea_settings', [ diff --git a/application/models/Admins_model.php b/application/models/Admins_model.php index 412bfba6..f84365f7 100644 --- a/application/models/Admins_model.php +++ b/application/models/Admins_model.php @@ -1,4 +1,4 @@ ->> array that contains user settings (username, password etc) * + * @property CI_DB_query_builder db + * @property CI_Loader load + * * @package Models */ class Admins_Model extends CI_Model { @@ -63,145 +66,6 @@ class Admins_Model extends CI_Model { return (int)$admin['id']; } - /** - * Check whether a particular admin record exists in the database. - * - * @param array $admin Contains the admin data. The 'email' value is required to be present at the moment. - * - * @return bool Returns whether the record exists or not. - * - * @throws Exception When the 'email' value is not present on the $admin argument. - */ - public function exists($admin) - { - if ( ! isset($admin['email'])) - { - throw new Exception('Admin email is not provided: ' . print_r($admin, TRUE)); - } - - // This method shouldn't depend on another method of this class. - $num_rows = $this->db - ->select('*') - ->from('ea_users') - ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') - ->where('ea_users.email', $admin['email']) - ->where('ea_roles.slug', DB_SLUG_ADMIN) - ->get()->num_rows(); - - return ($num_rows > 0) ? TRUE : FALSE; - } - - /** - * Insert a new admin record into the database. - * - * @param array $admin Contains the admin data. - * - * @return int Returns the new record id. - * - * @throws Exception When the insert operation fails. - */ - protected function _insert($admin) - { - $this->load->helper('general'); - - $admin['id_roles'] = $this->get_admin_role_id(); - $settings = $admin['settings']; - unset($admin['settings']); - - $this->db->trans_begin(); - - if ( ! $this->db->insert('ea_users', $admin)) - { - throw new Exception('Could not insert admin into the database.'); - } - - $admin['id'] = (int)$this->db->insert_id(); - $settings['id_users'] = $admin['id']; - $settings['salt'] = generate_salt(); - $settings['password'] = hash_password($settings['salt'], $settings['password']); - - // Insert admin settings. - if ( ! $this->db->insert('ea_user_settings', $settings)) - { - $this->db->trans_rollback(); - throw new Exception('Could not insert admin settings into the database.'); - } - - $this->db->trans_complete(); - - return $admin['id']; - } - - /** - * Update an existing admin record in the database. - * - * @param array $admin Contains the admin record data. - * - * @return int Returns the record id. - * - * @throws Exception When the update operation fails. - */ - protected function _update($admin) - { - $this->load->helper('general'); - - $settings = $admin['settings']; - unset($admin['settings']); - $settings['id_users'] = $admin['id']; - - if (isset($settings['password'])) - { - $salt = $this->db->get_where('ea_user_settings', ['id_users' => $admin['id']])->row()->salt; - $settings['password'] = hash_password($salt, $settings['password']); - } - - $this->db->where('id', $admin['id']); - if ( ! $this->db->update('ea_users', $admin)) - { - throw new Exception('Could not update admin record.'); - } - - $this->db->where('id_users', $settings['id_users']); - if ( ! $this->db->update('ea_user_settings', $settings)) - { - throw new Exception('Could not update admin settings.'); - } - - return (int)$admin['id']; - } - - /** - * Find the database record id of an admin user. - * - * @param array $admin Contains the admin data. The 'email' value is required in order to find the record id. - * - * @return int Returns the record id - * - * @throws Exception When the 'email' value is not present on the $admin array. - */ - public function find_record_id($admin) - { - if ( ! isset($admin['email'])) - { - throw new Exception('Admin email was not provided: ' . print_r($admin, TRUE)); - } - - $result = $this->db - ->select('ea_users.id') - ->from('ea_users') - ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') - ->where('ea_users.email', $admin['email']) - ->where('ea_roles.slug', DB_SLUG_ADMIN) - ->get(); - - if ($result->num_rows() == 0) - { - throw new Exception('Could not find admin record id.'); - } - - return (int)$result->row()->id; - } - /** * Validate admin user data before add() operation is executed. * @@ -291,6 +155,170 @@ class Admins_Model extends CI_Model { return TRUE; // Operation completed successfully. } + /** + * Validate Records Username + * + * @param string $username The provider records username. + * @param int $user_id The user record id. + * + * @return bool Returns the validation result. + */ + public function validate_username($username, $user_id) + { + $num_rows = $this->db->get_where('ea_user_settings', + ['username' => $username, 'id_users <> ' => $user_id])->num_rows(); + return ($num_rows > 0) ? FALSE : TRUE; + } + + /** + * Check whether a particular admin record exists in the database. + * + * @param array $admin Contains the admin data. The 'email' value is required to be present at the moment. + * + * @return bool Returns whether the record exists or not. + * + * @throws Exception When the 'email' value is not present on the $admin argument. + */ + public function exists($admin) + { + if ( ! isset($admin['email'])) + { + throw new Exception('Admin email is not provided: ' . print_r($admin, TRUE)); + } + + // This method shouldn't depend on another method of this class. + $num_rows = $this->db + ->select('*') + ->from('ea_users') + ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') + ->where('ea_users.email', $admin['email']) + ->where('ea_roles.slug', DB_SLUG_ADMIN) + ->get()->num_rows(); + + return $num_rows > 0; + } + + /** + * Find the database record id of an admin user. + * + * @param array $admin Contains the admin data. The 'email' value is required in order to find the record id. + * + * @return int Returns the record id + * + * @throws Exception When the 'email' value is not present on the $admin array. + */ + public function find_record_id($admin) + { + if ( ! isset($admin['email'])) + { + throw new Exception('Admin email was not provided: ' . print_r($admin, TRUE)); + } + + $result = $this->db + ->select('ea_users.id') + ->from('ea_users') + ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') + ->where('ea_users.email', $admin['email']) + ->where('ea_roles.slug', DB_SLUG_ADMIN) + ->get(); + + if ($result->num_rows() == 0) + { + throw new Exception('Could not find admin record id.'); + } + + return (int)$result->row()->id; + } + + /** + * Insert a new admin record into the database. + * + * @param array $admin Contains the admin data. + * + * @return int Returns the new record id. + * + * @throws Exception When the insert operation fails. + */ + protected function _insert($admin) + { + $this->load->helper('general'); + + $admin['id_roles'] = $this->get_admin_role_id(); + $settings = $admin['settings']; + unset($admin['settings']); + + $this->db->trans_begin(); + + if ( ! $this->db->insert('ea_users', $admin)) + { + throw new Exception('Could not insert admin into the database.'); + } + + $admin['id'] = (int)$this->db->insert_id(); + $settings['id_users'] = $admin['id']; + $settings['salt'] = generate_salt(); + $settings['password'] = hash_password($settings['salt'], $settings['password']); + + // Insert admin settings. + if ( ! $this->db->insert('ea_user_settings', $settings)) + { + $this->db->trans_rollback(); + throw new Exception('Could not insert admin settings into the database.'); + } + + $this->db->trans_complete(); + + return $admin['id']; + } + + /** + * Get the admin users role id. + * + * @return int Returns the role record id. + */ + public function get_admin_role_id() + { + return (int)$this->db->get_where('ea_roles', ['slug' => DB_SLUG_ADMIN])->row()->id; + } + + /** + * Update an existing admin record in the database. + * + * @param array $admin Contains the admin record data. + * + * @return int Returns the record id. + * + * @throws Exception When the update operation fails. + */ + protected function _update($admin) + { + $this->load->helper('general'); + + $settings = $admin['settings']; + unset($admin['settings']); + $settings['id_users'] = $admin['id']; + + if (isset($settings['password'])) + { + $salt = $this->db->get_where('ea_user_settings', ['id_users' => $admin['id']])->row()->salt; + $settings['password'] = hash_password($salt, $settings['password']); + } + + $this->db->where('id', $admin['id']); + if ( ! $this->db->update('ea_users', $admin)) + { + throw new Exception('Could not update admin record.'); + } + + $this->db->where('id_users', $settings['id_users']); + if ( ! $this->db->update('ea_user_settings', $settings)) + { + throw new Exception('Could not update admin settings.'); + } + + return (int)$admin['id']; + } + /** * Delete an existing admin record from the database. * @@ -439,29 +467,4 @@ class Admins_Model extends CI_Model { return $batch; } - - /** - * Get the admin users role id. - * - * @return int Returns the role record id. - */ - public function get_admin_role_id() - { - return (int)$this->db->get_where('ea_roles', ['slug' => DB_SLUG_ADMIN])->row()->id; - } - - /** - * Validate Records Username - * - * @param string $username The provider records username. - * @param int $user_id The user record id. - * - * @return bool Returns the validation result. - */ - public function validate_username($username, $user_id) - { - $num_rows = $this->db->get_where('ea_user_settings', - ['username' => $username, 'id_users <> ' => $user_id])->num_rows(); - return ($num_rows > 0) ? FALSE : TRUE; - } } diff --git a/application/models/Appointments_model.php b/application/models/Appointments_model.php index 9e883f9d..75758a49 100644 --- a/application/models/Appointments_model.php +++ b/application/models/Appointments_model.php @@ -1,4 +1,4 @@ -db->get_where('ea_appointments', [ - 'start_datetime' => $appointment['start_datetime'], - 'end_datetime' => $appointment['end_datetime'], - 'id_users_provider' => $appointment['id_users_provider'], - 'id_users_customer' => $appointment['id_users_customer'], - 'id_services' => $appointment['id_services'], - ]) - ->num_rows(); - - return ($num_rows > 0) ? TRUE : FALSE; - } - - /** - * Insert a new appointment record to the database. - * - * @param array $appointment Associative array with the appointment's data. Each key has the same name with the - * database fields. - * - * @return int Returns the id of the new record. - * - * @throws Exception If appointment record could not be inserted. - */ - protected function _insert($appointment) - { - $appointment['book_datetime'] = date('Y-m-d H:i:s'); - $appointment['hash'] = $this->generate_hash(); - - if ( ! $this->db->insert('ea_appointments', $appointment)) - { - throw new Exception('Could not insert appointment record.'); - } - - return (int)$this->db->insert_id(); - } - - /** - * Update an existing appointment record in the database. - * - * The appointment data argument should already include the record ID in order to process the update operation. - * - * @param array $appointment Associative array with the appointment's data. Each key has the same name with the - * database fields. - * - * @throws Exception If appointment record could not be updated. - */ - protected function _update($appointment) - { - $this->db->where('id', $appointment['id']); - if ( ! $this->db->update('ea_appointments', $appointment)) - { - throw new Exception('Could not update appointment record.'); - } - } - - /** - * Find the database id of an appointment record. - * - * The appointment data should include the following fields in order to get the unique id from the database: - * "start_datetime", "end_datetime", "id_users_provider", "id_users_customer", "id_services". - * - * IMPORTANT: The record must already exists in the database, otherwise an exception is raised. - * - * @param array $appointment Array with the appointment data. The keys of the array should have the same names as - * the db fields. - * - * @return int Returns the db id of the record that matches the appointment data. - * - * @throws Exception If appointment could not be found. - */ - public function find_record_id($appointment) - { - $this->db->where([ - 'start_datetime' => $appointment['start_datetime'], - 'end_datetime' => $appointment['end_datetime'], - 'id_users_provider' => $appointment['id_users_provider'], - 'id_users_customer' => $appointment['id_users_customer'], - 'id_services' => $appointment['id_services'] - ]); - - $result = $this->db->get('ea_appointments'); - - if ($result->num_rows() == 0) - { - throw new Exception('Could not find appointment record id.'); - } - - return $result->row()->id; - } - /** * Validate appointment data before the insert or update operations are executed. * @@ -237,6 +126,135 @@ class Appointments_Model extends CI_Model { return TRUE; } + /** + * Insert a new appointment record to the database. + * + * @param array $appointment Associative array with the appointment's data. Each key has the same name with the + * database fields. + * + * @return int Returns the id of the new record. + * + * @throws Exception If appointment record could not be inserted. + */ + protected function _insert($appointment) + { + $appointment['book_datetime'] = date('Y-m-d H:i:s'); + $appointment['hash'] = $this->generate_hash(); + + if ( ! $this->db->insert('ea_appointments', $appointment)) + { + throw new Exception('Could not insert appointment record.'); + } + + return (int)$this->db->insert_id(); + } + + /** + * Generate a unique hash for the given appointment data. + * + * This method uses the current date-time to generate a unique hash string that is later used to identify this + * appointment. Hash is needed when the email is send to the user with an edit link. + * + * @return string Returns the unique appointment hash. + */ + public function generate_hash() + { + $current_date = new DateTime(); + return md5($current_date->getTimestamp()); + } + + /** + * Update an existing appointment record in the database. + * + * The appointment data argument should already include the record ID in order to process the update operation. + * + * @param array $appointment Associative array with the appointment's data. Each key has the same name with the + * database fields. + * + * @throws Exception If appointment record could not be updated. + */ + protected function _update($appointment) + { + $this->db->where('id', $appointment['id']); + if ( ! $this->db->update('ea_appointments', $appointment)) + { + throw new Exception('Could not update appointment record.'); + } + } + + /** + * Check if a particular appointment record already exists. + * + * This method checks whether the given appointment already exists in the database. It doesn't search with the id, + * but by using the following fields: "start_datetime", "end_datetime", "id_users_provider", "id_users_customer", + * "id_services". + * + * @param array $appointment Associative array with the appointment's data. Each key has the same name with the + * database fields. + * + * @return bool Returns whether the record exists or not. + * + * @throws Exception If appointment fields are missing. + */ + public function exists($appointment) + { + if ( ! isset($appointment['start_datetime']) + || ! isset($appointment['end_datetime']) + || ! isset($appointment['id_users_provider']) + || ! isset($appointment['id_users_customer']) + || ! isset($appointment['id_services'])) + { + throw new Exception('Not all appointment field values are provided: ' + . print_r($appointment, TRUE)); + } + + $num_rows = $this->db->get_where('ea_appointments', [ + 'start_datetime' => $appointment['start_datetime'], + 'end_datetime' => $appointment['end_datetime'], + 'id_users_provider' => $appointment['id_users_provider'], + 'id_users_customer' => $appointment['id_users_customer'], + 'id_services' => $appointment['id_services'], + ]) + ->num_rows(); + + return ($num_rows > 0) ? TRUE : FALSE; + } + + /** + * Find the database id of an appointment record. + * + * The appointment data should include the following fields in order to get the unique id from the database: + * "start_datetime", "end_datetime", "id_users_provider", "id_users_customer", "id_services". + * + * IMPORTANT: The record must already exists in the database, otherwise an exception is raised. + * + * @param array $appointment Array with the appointment data. The keys of the array should have the same names as + * the db fields. + * + * @return int Returns the db id of the record that matches the appointment data. + * + * @throws Exception If appointment could not be found. + */ + public function find_record_id($appointment) + { + $this->db->where([ + 'start_datetime' => $appointment['start_datetime'], + 'end_datetime' => $appointment['end_datetime'], + 'id_users_provider' => $appointment['id_users_provider'], + 'id_users_customer' => $appointment['id_users_customer'], + 'id_services' => $appointment['id_services'] + ]); + + $result = $this->db->get('ea_appointments'); + + if ($result->num_rows() == 0) + { + throw new Exception('Could not find appointment record id.'); + } + + return $result->row()->id; + } + /** * Delete an existing appointment record from the database. * @@ -383,17 +401,21 @@ class Appointments_Model extends CI_Model { } /** - * Generate a unique hash for the given appointment data. + * Get the aggregates of an appointment. * - * This method uses the current date-time to generate a unique hash string that is later used to identify this - * appointment. Hash is needed when the email is send to the user with an edit link. + * @param array $appointment Appointment data. * - * @return string Returns the unique appointment hash. + * @return array Returns the appointment with the aggregates. */ - public function generate_hash() + private function get_aggregates(array $appointment) { - $current_date = new DateTime(); - return md5($current_date->getTimestamp()); + $appointment['service'] = $this->db->get_where('ea_services', + ['id' => $appointment['id_services']])->row_array(); + $appointment['provider'] = $this->db->get_where('ea_users', + ['id' => $appointment['id_users_provider']])->row_array(); + $appointment['customer'] = $this->db->get_where('ea_users', + ['id' => $appointment['id_users_customer']])->row_array(); + return $appointment; } /** @@ -535,22 +557,4 @@ class Appointments_Model extends CI_Model { ->row() ->attendants_number; } - - /** - * Get the aggregates of an appointment. - * - * @param array $appointment Appointment data. - * - * @return array Returns the appointment with the aggregates. - */ - private function get_aggregates(array $appointment) - { - $appointment['service'] = $this->db->get_where('ea_services', - ['id' => $appointment['id_services']])->row_array(); - $appointment['provider'] = $this->db->get_where('ea_users', - ['id' => $appointment['id_users_provider']])->row_array(); - $appointment['customer'] = $this->db->get_where('ea_users', - ['id' => $appointment['id_users_customer']])->row_array(); - return $appointment; - } } diff --git a/application/models/Consents_model.php b/application/models/Consents_model.php index 87511d45..7ac5ae1c 100644 --- a/application/models/Consents_model.php +++ b/application/models/Consents_model.php @@ -1,4 +1,4 @@ -load->helper('data_validation'); + + // If a customer id is provided, check whether the record + // exist in the database. + if (isset($customer['id'])) + { + $num_rows = $this->db->get_where('ea_users', + ['id' => $customer['id']])->num_rows(); + if ($num_rows == 0) + { + throw new Exception('Provided customer id does not ' + . 'exist in the database.'); + } + } + + $query = $this->db->get_where('ea_settings', ['name' => 'require_phone_number']); + $phone_number_required = $query->num_rows() > 0 ? $query->row() === '1' : FALSE; + + // Validate required fields + if (empty($customer['first_name']) + || empty($customer['last_name']) + || empty($customer['email']) + || (empty($customer['phone_number']) && $phone_number_required)) + { + throw new Exception('Not all required fields are provided: ' + . print_r($customer, TRUE)); + } + + // Validate email address + if ( ! filter_var($customer['email'], FILTER_VALIDATE_EMAIL)) + { + throw new Exception('Invalid email address provided: ' + . $customer['email']); + } + + // When inserting a record the email address must be unique. + $customer_id = (isset($customer['id'])) ? $customer['id'] : ''; + + $num_rows = $this->db + ->select('*') + ->from('ea_users') + ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') + ->where('ea_roles.slug', DB_SLUG_CUSTOMER) + ->where('ea_users.email', $customer['email']) + ->where('ea_users.id <>', $customer_id) + ->get() + ->num_rows(); + + if ($num_rows > 0) + { + throw new Exception('Given email address belongs to another customer record. ' + . 'Please use a different email.'); + } + + return TRUE; + } + /** * Check if a particular customer record already exists. * @@ -85,6 +156,45 @@ class Customers_Model extends CI_Model { return ($num_rows > 0) ? TRUE : FALSE; } + /** + * Find the database id of a customer record. + * + * The customer data should include the following fields in order to get the unique id from the database: "email" + * + * IMPORTANT: The record must already exists in the database, otherwise an exception is raised. + * + * @param array $customer Array with the customer data. The keys of the array should have the same names as the + * database fields. + * + * @return int Returns the ID. + * + * @throws Exception If customer record does not exist. + */ + public function find_record_id($customer) + { + if (empty($customer['email'])) + { + throw new Exception('Customer\'s email was not provided: ' + . print_r($customer, TRUE)); + } + + // Get customer's role id + $result = $this->db + ->select('ea_users.id') + ->from('ea_users') + ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') + ->where('ea_users.email', $customer['email']) + ->where('ea_roles.slug', DB_SLUG_CUSTOMER) + ->get(); + + if ($result->num_rows() == 0) + { + throw new Exception('Could not find customer record id.'); + } + + return $result->row()->id; + } + /** * Insert a new customer record to the database. * @@ -139,113 +249,6 @@ class Customers_Model extends CI_Model { return (int)$customer['id']; } - /** - * Find the database id of a customer record. - * - * The customer data should include the following fields in order to get the unique id from the database: "email" - * - * IMPORTANT: The record must already exists in the database, otherwise an exception is raised. - * - * @param array $customer Array with the customer data. The keys of the array should have the same names as the - * database fields. - * - * @return int Returns the ID. - * - * @throws Exception If customer record does not exist. - */ - public function find_record_id($customer) - { - if (empty($customer['email'])) - { - throw new Exception('Customer\'s email was not provided: ' - . print_r($customer, TRUE)); - } - - // Get customer's role id - $result = $this->db - ->select('ea_users.id') - ->from('ea_users') - ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') - ->where('ea_users.email', $customer['email']) - ->where('ea_roles.slug', DB_SLUG_CUSTOMER) - ->get(); - - if ($result->num_rows() == 0) - { - throw new Exception('Could not find customer record id.'); - } - - return $result->row()->id; - } - - /** - * Validate customer data before the insert or update operation is executed. - * - * @param array $customer Contains the customer data. - * - * @return bool Returns the validation result. - * - * @throws Exception If customer validation fails. - */ - public function validate($customer) - { - $this->load->helper('data_validation'); - - // If a customer id is provided, check whether the record - // exist in the database. - if (isset($customer['id'])) - { - $num_rows = $this->db->get_where('ea_users', - ['id' => $customer['id']])->num_rows(); - if ($num_rows == 0) - { - throw new Exception('Provided customer id does not ' - . 'exist in the database.'); - } - } - - $query = $this->db->get_where('ea_settings', ['name' => 'require_phone_number']); - $phone_number_required = $query->num_rows() > 0 ? $query->row() === '1' : false; - - // Validate required fields - if ( empty($customer['first_name']) - || empty($customer['last_name']) - || empty($customer['email']) - || (empty($customer['phone_number']) && $phone_number_required)) - { - throw new Exception('Not all required fields are provided: ' - . print_r($customer, TRUE)); - } - - // Validate email address - if ( ! filter_var($customer['email'], FILTER_VALIDATE_EMAIL)) - { - throw new Exception('Invalid email address provided: ' - . $customer['email']); - } - - // When inserting a record the email address must be unique. - $customer_id = (isset($customer['id'])) ? $customer['id'] : ''; - - $num_rows = $this->db - ->select('*') - ->from('ea_users') - ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') - ->where('ea_roles.slug', DB_SLUG_CUSTOMER) - ->where('ea_users.email', $customer['email']) - ->where('ea_users.id <>', $customer_id) - ->get() - ->num_rows(); - - if ($num_rows > 0) - { - throw new Exception('Given email address belongs to another customer record. ' - . 'Please use a different email.'); - } - - return TRUE; - } - /** * Delete an existing customer record from the database. * diff --git a/application/models/Providers_model.php b/application/models/Providers_model.php index bfac563e..a4e0219d 100755 --- a/application/models/Providers_model.php +++ b/application/models/Providers_model.php @@ -1,4 +1,4 @@ -db - ->select('*') - ->from('ea_users') - ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') - ->where('ea_users.email', $provider['email']) - ->where('ea_roles.slug', DB_SLUG_PROVIDER) - ->get()->num_rows(); - - return ($num_rows > 0) ? TRUE : FALSE; - } - - /** - * Insert a new provider record into the database. - * - * @param array $provider Contains the provider data (must be already validated). - * - * @return int Returns the new record id. - * - * @throws Exception When the insert operation fails. - */ - protected function _insert($provider) - { - $this->load->helper('general'); - - // Get provider role id. - $provider['id_roles'] = $this->get_providers_role_id(); - - // Store provider settings and services (must not be present on the $provider array). - $services = $provider['services']; - unset($provider['services']); - $settings = $provider['settings']; - unset($provider['settings']); - - // Insert provider record and save settings. - if ( ! $this->db->insert('ea_users', $provider)) - { - throw new Exception('Could not insert provider into the database'); - } - - $settings['salt'] = generate_salt(); - $settings['password'] = hash_password($settings['salt'], $settings['password']); - - $provider['id'] = $this->db->insert_id(); - $this->save_settings($settings, $provider['id']); - $this->save_services($services, $provider['id']); - - // Return the new record id. - return (int)$provider['id']; - } - - /** - * Update an existing provider record in the database. - * - * @param array $provider Contains the provider data. - * - * @return int Returns the record id. - * - * @throws Exception When the update operation fails. - */ - protected function _update($provider) - { - $this->load->helper('general'); - - // Store service and settings (must not be present on the $provider array). - $services = $provider['services']; - unset($provider['services']); - $settings = $provider['settings']; - unset($provider['settings']); - - if (isset($settings['password'])) - { - $salt = $this->db->get_where('ea_user_settings', ['id_users' => $provider['id']])->row()->salt; - $settings['password'] = hash_password($salt, $settings['password']); - } - - // Update provider record. - $this->db->where('id', $provider['id']); - if ( ! $this->db->update('ea_users', $provider)) - { - throw new Exception('Could not update provider record.'); - } - - $this->save_services($services, $provider['id']); - $this->save_settings($settings, $provider['id']); - - // Return record id. - return (int)$provider['id']; - } - - /** - * Find the database record id of a provider. - * - * @param array $provider Contains the provider data. The 'email' value is required in order to find the record id. - * - * @return int Returns the record id. - * - * @throws Exception When the provider's email value is not provided. - */ - public function find_record_id($provider) - { - if ( ! isset($provider['email'])) - { - throw new Exception('Provider email was not provided:' . print_r($provider, TRUE)); - } - - $result = $this->db - ->select('ea_users.id') - ->from('ea_users') - ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') - ->where('ea_users.email', $provider['email']) - ->where('ea_roles.slug', DB_SLUG_PROVIDER) - ->get(); - - if ($result->num_rows() == 0) - { - throw new Exception('Could not find provider record id.'); - } - - return (int)$result->row()->id; - } - /** * Validate provider data before the insert or update operation is executed. * @@ -328,6 +193,260 @@ class Providers_Model extends CI_Model { return TRUE; } + /** + * Validate Records Username + * + * @param string $username The provider records username. + * @param int $user_id The user record id. + * + * @return bool Returns the validation result. + */ + public function validate_username($username, $user_id) + { + $num_rows = $this->db->get_where('ea_user_settings', + ['username' => $username, 'id_users <> ' => $user_id])->num_rows(); + return ($num_rows > 0) ? FALSE : TRUE; + } + + /** + * Check whether a particular provider record already exists in the database. + * + * @param array $provider Contains the provider data. The 'email' value is required in order to check for a provider. + * + * @return bool Returns whether the provider record exists or not. + * + * @throws Exception When the 'email' value is not provided. + */ + public function exists($provider) + { + if ( ! isset($provider['email'])) + { + throw new Exception('Provider email is not provided:' . print_r($provider, TRUE)); + } + + // This method shouldn't depend on another method of this class. + $num_rows = $this->db + ->select('*') + ->from('ea_users') + ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') + ->where('ea_users.email', $provider['email']) + ->where('ea_roles.slug', DB_SLUG_PROVIDER) + ->get()->num_rows(); + + return ($num_rows > 0) ? TRUE : FALSE; + } + + /** + * Find the database record id of a provider. + * + * @param array $provider Contains the provider data. The 'email' value is required in order to find the record id. + * + * @return int Returns the record id. + * + * @throws Exception When the provider's email value is not provided. + */ + public function find_record_id($provider) + { + if ( ! isset($provider['email'])) + { + throw new Exception('Provider email was not provided:' . print_r($provider, TRUE)); + } + + $result = $this->db + ->select('ea_users.id') + ->from('ea_users') + ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') + ->where('ea_users.email', $provider['email']) + ->where('ea_roles.slug', DB_SLUG_PROVIDER) + ->get(); + + if ($result->num_rows() == 0) + { + throw new Exception('Could not find provider record id.'); + } + + return (int)$result->row()->id; + } + + /** + * Insert a new provider record into the database. + * + * @param array $provider Contains the provider data (must be already validated). + * + * @return int Returns the new record id. + * + * @throws Exception When the insert operation fails. + */ + protected function _insert($provider) + { + $this->load->helper('general'); + + // Get provider role id. + $provider['id_roles'] = $this->get_providers_role_id(); + + // Store provider settings and services (must not be present on the $provider array). + $services = $provider['services']; + unset($provider['services']); + $settings = $provider['settings']; + unset($provider['settings']); + + // Insert provider record and save settings. + if ( ! $this->db->insert('ea_users', $provider)) + { + throw new Exception('Could not insert provider into the database'); + } + + $settings['salt'] = generate_salt(); + $settings['password'] = hash_password($settings['salt'], $settings['password']); + + $provider['id'] = $this->db->insert_id(); + $this->save_settings($settings, $provider['id']); + $this->save_services($services, $provider['id']); + + // Return the new record id. + return (int)$provider['id']; + } + + /** + * Get the providers role id from the database. + * + * @return int Returns the role id for the provider records. + */ + public function get_providers_role_id() + { + return $this->db->get_where('ea_roles', ['slug' => DB_SLUG_PROVIDER])->row()->id; + } + + /** + * Save the provider settings (used from insert or update operation). + * + * @param array $settings Contains the setting values. + * @param int $provider_id Record id of the provider. + * + * @throws Exception If $provider_id argument is invalid. + * @throws Exception If $settings argument is invalid. + */ + protected function save_settings($settings, $provider_id) + { + if ( ! is_numeric($provider_id)) + { + throw new Exception('Invalid $provider_id argument given:' . $provider_id); + } + + if (count($settings) == 0 || ! is_array($settings)) + { + throw new Exception('Invalid $settings argument given:' . print_r($settings, TRUE)); + } + + // Check if the setting record exists in db. + if ($this->db->get_where('ea_user_settings', ['id_users' => $provider_id]) + ->num_rows() == 0) + { + $this->db->insert('ea_user_settings', ['id_users' => $provider_id]); + } + + foreach ($settings as $name => $value) + { + // Sort in descending order the extra working plan days + if ($name == 'extra_working_plan') + { + $value = json_decode($value, TRUE); + // Sort the array and put in reverse order + krsort($value); + $value = json_encode($value); + } + $this->set_setting($name, $value, $provider_id); + } + } + + /** + * Set a provider's setting value in the database. + * + * The provider and settings record must already exist. + * + * @param string $setting_name The setting's name. + * @param string $value The setting's value. + * @param int $provider_id The selected provider id. + */ + public function set_setting($setting_name, $value, $provider_id) + { + $this->db->where(['id_users' => $provider_id]); + return $this->db->update('ea_user_settings', [$setting_name => $value]); + } + + /** + * Save the provider services in the database (use on both insert and update operation). + * + * @param array $services Contains the service ids that the selected provider can provide. + * @param int $provider_id The selected provider record id. + * + * @throws Exception When the $services argument type is not array. + * @throws Exception When the $provider_id argument type is not int. + */ + protected function save_services($services, $provider_id) + { + // Validate method arguments. + if ( ! is_array($services)) + { + throw new Exception('Invalid argument type $services: ' . $services); + } + + if ( ! is_numeric($provider_id)) + { + throw new Exception('Invalid argument type $provider_id: ' . $provider_id); + } + + // Save provider services in the database (delete old records and add new). + $this->db->delete('ea_services_providers', ['id_users' => $provider_id]); + foreach ($services as $service_id) + { + $service_provider = [ + 'id_users' => $provider_id, + 'id_services' => $service_id + ]; + $this->db->insert('ea_services_providers', $service_provider); + } + } + + /** + * Update an existing provider record in the database. + * + * @param array $provider Contains the provider data. + * + * @return int Returns the record id. + * + * @throws Exception When the update operation fails. + */ + protected function _update($provider) + { + $this->load->helper('general'); + + // Store service and settings (must not be present on the $provider array). + $services = $provider['services']; + unset($provider['services']); + $settings = $provider['settings']; + unset($provider['settings']); + + if (isset($settings['password'])) + { + $salt = $this->db->get_where('ea_user_settings', ['id_users' => $provider['id']])->row()->salt; + $settings['password'] = hash_password($salt, $settings['password']); + } + + // Update provider record. + $this->db->where('id', $provider['id']); + if ( ! $this->db->update('ea_users', $provider)) + { + throw new Exception('Could not update provider record.'); + } + + $this->save_services($services, $provider['id']); + $this->save_settings($settings, $provider['id']); + + // Return record id. + return (int)$provider['id']; + } + /** * Delete an existing provider record from the database. * @@ -539,120 +658,6 @@ class Providers_Model extends CI_Model { return $providers; } - /** - * Get the providers role id from the database. - * - * @return int Returns the role id for the provider records. - */ - public function get_providers_role_id() - { - return $this->db->get_where('ea_roles', ['slug' => DB_SLUG_PROVIDER])->row()->id; - } - - /** - * Get a providers setting from the database. - * - * @param string $setting_name The setting name that is going to be returned. - * @param int $provider_id The selected provider id. - * - * @return string Returns the value of the selected user setting. - */ - public function get_setting($setting_name, $provider_id) - { - $provider_settings = $this->db->get_where('ea_user_settings', ['id_users' => $provider_id])->row_array(); - return $provider_settings[$setting_name]; - } - - /** - * Set a provider's setting value in the database. - * - * The provider and settings record must already exist. - * - * @param string $setting_name The setting's name. - * @param string $value The setting's value. - * @param int $provider_id The selected provider id. - */ - public function set_setting($setting_name, $value, $provider_id) - { - $this->db->where(['id_users' => $provider_id]); - return $this->db->update('ea_user_settings', [$setting_name => $value]); - } - - /** - * Save the provider settings (used from insert or update operation). - * - * @param array $settings Contains the setting values. - * @param int $provider_id Record id of the provider. - * - * @throws Exception If $provider_id argument is invalid. - * @throws Exception If $settings argument is invalid. - */ - protected function save_settings($settings, $provider_id) - { - if ( ! is_numeric($provider_id)) - { - throw new Exception('Invalid $provider_id argument given:' . $provider_id); - } - - if (count($settings) == 0 || ! is_array($settings)) - { - throw new Exception('Invalid $settings argument given:' . print_r($settings, TRUE)); - } - - // Check if the setting record exists in db. - if ($this->db->get_where('ea_user_settings', ['id_users' => $provider_id]) - ->num_rows() == 0) - { - $this->db->insert('ea_user_settings', ['id_users' => $provider_id]); - } - - foreach ($settings as $name => $value) - { - // Sort in descending order the extra working plan days - if ($name == 'extra_working_plan') { - $value = json_decode($value, true); - // Sort the array and put in reverse order - krsort($value); - $value = json_encode($value); - } - $this->set_setting($name, $value, $provider_id); - } - } - - /** - * Save the provider services in the database (use on both insert and update operation). - * - * @param array $services Contains the service ids that the selected provider can provide. - * @param int $provider_id The selected provider record id. - * - * @throws Exception When the $services argument type is not array. - * @throws Exception When the $provider_id argument type is not int. - */ - protected function save_services($services, $provider_id) - { - // Validate method arguments. - if ( ! is_array($services)) - { - throw new Exception('Invalid argument type $services: ' . $services); - } - - if ( ! is_numeric($provider_id)) - { - throw new Exception('Invalid argument type $provider_id: ' . $provider_id); - } - - // Save provider services in the database (delete old records and add new). - $this->db->delete('ea_services_providers', ['id_users' => $provider_id]); - foreach ($services as $service_id) - { - $service_provider = [ - 'id_users' => $provider_id, - 'id_services' => $service_id - ]; - $this->db->insert('ea_services_providers', $service_provider); - } - } - /** * Save the provider extra working plan days. * @@ -668,8 +673,8 @@ class Providers_Model extends CI_Model { { // Validate period $dateStart = date('Y-m-d', strtotime($extra_period['start_datetime'])); - $start = date('H:i',strtotime($extra_period['start_datetime'])); - $end = date('H:i',strtotime($extra_period['end_datetime'])); + $start = date('H:i', strtotime($extra_period['start_datetime'])); + $end = date('H:i', strtotime($extra_period['end_datetime'])); if ($start > $end) { throw new Exception('Unavailable period start must be prior to end.'); @@ -687,7 +692,7 @@ class Providers_Model extends CI_Model { } // Add record to database. - $extra_working_plan = json_decode($this->get_setting('extra_working_plan', $provider_id), true); + $extra_working_plan = json_decode($this->get_setting('extra_working_plan', $provider_id), TRUE); $extra_working_plan[$dateStart] = [ 'start' => $start, @@ -700,6 +705,20 @@ class Providers_Model extends CI_Model { return $success; } + /** + * Get a providers setting from the database. + * + * @param string $setting_name The setting name that is going to be returned. + * @param int $provider_id The selected provider id. + * + * @return string Returns the value of the selected user setting. + */ + public function get_setting($setting_name, $provider_id) + { + $provider_settings = $this->db->get_where('ea_user_settings', ['id_users' => $provider_id])->row_array(); + return $provider_settings[$setting_name]; + } + /** * Delete a provider extra working plan day. * @@ -724,7 +743,7 @@ class Providers_Model extends CI_Model { } // Add record to database. - $extra_working_plan = json_decode($this->get_setting('extra_working_plan', $provider_id), true); + $extra_working_plan = json_decode($this->get_setting('extra_working_plan', $provider_id), TRUE); unset($extra_working_plan[$extra_period]); @@ -732,19 +751,4 @@ class Providers_Model extends CI_Model { return $success; } - - /** - * Validate Records Username - * - * @param string $username The provider records username. - * @param int $user_id The user record id. - * - * @return bool Returns the validation result. - */ - public function validate_username($username, $user_id) - { - $num_rows = $this->db->get_where('ea_user_settings', - ['username' => $username, 'id_users <> ' => $user_id])->num_rows(); - return ($num_rows > 0) ? FALSE : TRUE; - } } diff --git a/application/models/Roles_model.php b/application/models/Roles_model.php index 4198df2e..57533b65 100644 --- a/application/models/Roles_model.php +++ b/application/models/Roles_model.php @@ -1,4 +1,4 @@ -> array with provider ids that the secretary handles * 'settings' >> array with the secretary settings * + * @property CI_DB_query_builder db + * @property CI_Loader load + * * @package Models */ class Secretaries_Model extends CI_Model { @@ -56,7 +59,8 @@ class Secretaries_Model extends CI_Model { if ( ! isset($secretary['id'])) { $secretary['id'] = $this->_insert($secretary); - } else + } + else { $secretary['id'] = $this->_update($secretary); } @@ -64,137 +68,6 @@ class Secretaries_Model extends CI_Model { return (int)$secretary['id']; } - /** - * Check whether a particular secretary record exists in the database. - * - * @param array $secretary Contains the secretary data. The 'email' value is required to be present at the moment. - * - * @return bool Returns whether the record exists or not. - * - * @throws Exception When the 'email' value is not present on the $secretary argument. - */ - public function exists($secretary) - { - if ( ! isset($secretary['email'])) - { - throw new Exception('Secretary email is not provided: ' . print_r($secretary, TRUE)); - } - - // This method shouldn't depend on another method of this class. - $num_rows = $this->db - ->select('*') - ->from('ea_users') - ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') - ->where('ea_users.email', $secretary['email']) - ->where('ea_roles.slug', DB_SLUG_SECRETARY) - ->get()->num_rows(); - - return ($num_rows > 0) ? TRUE : FALSE; - } - - /** - * Insert a new secretary record into the database. - * - * @param array $secretary Contains the secretary data. - * - * @return int Returns the new record id. - * - * @throws Exception When the insert operation fails. - */ - protected function _insert($secretary) - { - $this->load->helper('general'); - - $providers = $secretary['providers']; - unset($secretary['providers']); - $settings = $secretary['settings']; - unset($secretary['settings']); - - $secretary['id_roles'] = $this->get_secretary_role_id(); - - if ( ! $this->db->insert('ea_users', $secretary)) - { - throw new Exception('Could not insert secretary into the database.'); - } - - $secretary['id'] = (int)$this->db->insert_id(); - $settings['salt'] = generate_salt(); - $settings['password'] = hash_password($settings['salt'], $settings['password']); - - $this->save_providers($providers, $secretary['id']); - $this->save_settings($settings, $secretary['id']); - - return $secretary['id']; - } - - /** - * Update an existing secretary record in the database. - * - * @param array $secretary Contains the secretary record data. - * - * @return int Returns the record id. - * - * @throws Exception When the update operation fails. - */ - protected function _update($secretary) - { - $this->load->helper('general'); - - $providers = $secretary['providers']; - unset($secretary['providers']); - $settings = $secretary['settings']; - unset($secretary['settings']); - - if (isset($settings['password'])) - { - $salt = $this->db->get_where('ea_user_settings', ['id_users' => $secretary['id']])->row()->salt; - $settings['password'] = hash_password($salt, $settings['password']); - } - - $this->db->where('id', $secretary['id']); - if ( ! $this->db->update('ea_users', $secretary)) - { - throw new Exception('Could not update secretary record.'); - } - - $this->save_providers($providers, $secretary['id']); - $this->save_settings($settings, $secretary['id']); - - return (int)$secretary['id']; - } - - /** - * Find the database record id of a secretary. - * - * @param array $secretary Contains the secretary data. The 'email' value is required in order to find the record id. - * - * @return int Returns the record id - * - * @throws Exception When the 'email' value is not present on the $secretary array. - */ - public function find_record_id($secretary) - { - if ( ! isset($secretary['email'])) - { - throw new Exception('Secretary email was not provided: ' . print_r($secretary, TRUE)); - } - - $result = $this->db - ->select('ea_users.id') - ->from('ea_users') - ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') - ->where('ea_users.email', $secretary['email']) - ->where('ea_roles.slug', DB_SLUG_SECRETARY) - ->get(); - - if ($result->num_rows() == 0) - { - throw new Exception('Could not find secretary record id.'); - } - - return (int)$result->row()->id; - } - /** * Validate secretary user data before add() operation is executed. * @@ -290,6 +163,242 @@ class Secretaries_Model extends CI_Model { return TRUE; } + /** + * Validate Records Username + * + * @param string $username The provider records username. + * @param int $user_id The user record id. + * + * @return bool Returns the validation result. + */ + public function validate_username($username, $user_id) + { + $num_rows = $this->db->get_where('ea_user_settings', + ['username' => $username, 'id_users <> ' => $user_id])->num_rows(); + return ($num_rows > 0) ? FALSE : TRUE; + } + + /** + * Check whether a particular secretary record exists in the database. + * + * @param array $secretary Contains the secretary data. The 'email' value is required to be present at the moment. + * + * @return bool Returns whether the record exists or not. + * + * @throws Exception When the 'email' value is not present on the $secretary argument. + */ + public function exists($secretary) + { + if ( ! isset($secretary['email'])) + { + throw new Exception('Secretary email is not provided: ' . print_r($secretary, TRUE)); + } + + // This method shouldn't depend on another method of this class. + $num_rows = $this->db + ->select('*') + ->from('ea_users') + ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') + ->where('ea_users.email', $secretary['email']) + ->where('ea_roles.slug', DB_SLUG_SECRETARY) + ->get()->num_rows(); + + return ($num_rows > 0) ? TRUE : FALSE; + } + + /** + * Find the database record id of a secretary. + * + * @param array $secretary Contains the secretary data. The 'email' value is required in order to find the record id. + * + * @return int Returns the record id + * + * @throws Exception When the 'email' value is not present on the $secretary array. + */ + public function find_record_id($secretary) + { + if ( ! isset($secretary['email'])) + { + throw new Exception('Secretary email was not provided: ' . print_r($secretary, TRUE)); + } + + $result = $this->db + ->select('ea_users.id') + ->from('ea_users') + ->join('ea_roles', 'ea_roles.id = ea_users.id_roles', 'inner') + ->where('ea_users.email', $secretary['email']) + ->where('ea_roles.slug', DB_SLUG_SECRETARY) + ->get(); + + if ($result->num_rows() == 0) + { + throw new Exception('Could not find secretary record id.'); + } + + return (int)$result->row()->id; + } + + /** + * Insert a new secretary record into the database. + * + * @param array $secretary Contains the secretary data. + * + * @return int Returns the new record id. + * + * @throws Exception When the insert operation fails. + */ + protected function _insert($secretary) + { + $this->load->helper('general'); + + $providers = $secretary['providers']; + unset($secretary['providers']); + $settings = $secretary['settings']; + unset($secretary['settings']); + + $secretary['id_roles'] = $this->get_secretary_role_id(); + + if ( ! $this->db->insert('ea_users', $secretary)) + { + throw new Exception('Could not insert secretary into the database.'); + } + + $secretary['id'] = (int)$this->db->insert_id(); + $settings['salt'] = generate_salt(); + $settings['password'] = hash_password($settings['salt'], $settings['password']); + + $this->save_providers($providers, $secretary['id']); + $this->save_settings($settings, $secretary['id']); + + return $secretary['id']; + } + + /** + * Get the secretary users role id. + * + * @return int Returns the role record id. + */ + public function get_secretary_role_id() + { + return (int)$this->db->get_where('ea_roles', ['slug' => DB_SLUG_SECRETARY])->row()->id; + } + + /** + * Save a secretary handling users. + * + * @param array $providers Contains the provider ids that are handled by the secretary. + * @param int $secretary_id The selected secretary record. + * + * @throws Exception If $providers argument is invalid. + */ + protected function save_providers($providers, $secretary_id) + { + if ( ! is_array($providers)) + { + throw new Exception('Invalid argument given $providers: ' . print_r($providers, TRUE)); + } + + // Delete old connections + $this->db->delete('ea_secretaries_providers', ['id_users_secretary' => $secretary_id]); + + if (count($providers) > 0) + { + foreach ($providers as $provider_id) + { + $this->db->insert('ea_secretaries_providers', [ + 'id_users_secretary' => $secretary_id, + 'id_users_provider' => $provider_id + ]); + } + } + } + + /** + * Save the secretary settings (used from insert or update operation). + * + * @param array $settings Contains the setting values. + * @param int $secretary_id Record id of the secretary. + * + * @throws Exception If $secretary_id argument is invalid. + * @throws Exception If $settings argument is invalid. + */ + protected function save_settings($settings, $secretary_id) + { + if ( ! is_numeric($secretary_id)) + { + throw new Exception('Invalid $secretary_id argument given:' . $secretary_id); + } + + if (count($settings) == 0 || ! is_array($settings)) + { + throw new Exception('Invalid $settings argument given:' . print_r($settings, TRUE)); + } + + // Check if the setting record exists in db. + $num_rows = $this->db->get_where('ea_user_settings', + ['id_users' => $secretary_id])->num_rows(); + if ($num_rows == 0) + { + $this->db->insert('ea_user_settings', ['id_users' => $secretary_id]); + } + + foreach ($settings as $name => $value) + { + $this->set_setting($name, $value, $secretary_id); + } + } + + /** + * Set a provider's setting value in the database. + * + * The provider and settings record must already exist. + * + * @param string $setting_name The setting's name. + * @param string $value The setting's value. + * @param int $secretary_id The selected provider id. + */ + public function set_setting($setting_name, $value, $secretary_id) + { + $this->db->where(['id_users' => $secretary_id]); + return $this->db->update('ea_user_settings', [$setting_name => $value]); + } + + /** + * Update an existing secretary record in the database. + * + * @param array $secretary Contains the secretary record data. + * + * @return int Returns the record id. + * + * @throws Exception When the update operation fails. + */ + protected function _update($secretary) + { + $this->load->helper('general'); + + $providers = $secretary['providers']; + unset($secretary['providers']); + $settings = $secretary['settings']; + unset($secretary['settings']); + + if (isset($settings['password'])) + { + $salt = $this->db->get_where('ea_user_settings', ['id_users' => $secretary['id']])->row()->salt; + $settings['password'] = hash_password($salt, $settings['password']); + } + + $this->db->where('id', $secretary['id']); + if ( ! $this->db->update('ea_users', $secretary)) + { + throw new Exception('Could not update secretary record.'); + } + + $this->save_providers($providers, $secretary['id']); + $this->save_settings($settings, $secretary['id']); + + return (int)$secretary['id']; + } + /** * Delete an existing secretary record from the database. * @@ -445,81 +554,6 @@ class Secretaries_Model extends CI_Model { return $batch; } - /** - * Get the secretary users role id. - * - * @return int Returns the role record id. - */ - public function get_secretary_role_id() - { - return (int)$this->db->get_where('ea_roles', ['slug' => DB_SLUG_SECRETARY])->row()->id; - } - - /** - * Save a secretary handling users. - * - * @param array $providers Contains the provider ids that are handled by the secretary. - * @param int $secretary_id The selected secretary record. - * - * @throws Exception If $providers argument is invalid. - */ - protected function save_providers($providers, $secretary_id) - { - if ( ! is_array($providers)) - { - throw new Exception('Invalid argument given $providers: ' . print_r($providers, TRUE)); - } - - // Delete old connections - $this->db->delete('ea_secretaries_providers', ['id_users_secretary' => $secretary_id]); - - if (count($providers) > 0) - { - foreach ($providers as $provider_id) - { - $this->db->insert('ea_secretaries_providers', [ - 'id_users_secretary' => $secretary_id, - 'id_users_provider' => $provider_id - ]); - } - } - } - - /** - * Save the secretary settings (used from insert or update operation). - * - * @param array $settings Contains the setting values. - * @param int $secretary_id Record id of the secretary. - * - * @throws Exception If $secretary_id argument is invalid. - * @throws Exception If $settings argument is invalid. - */ - protected function save_settings($settings, $secretary_id) - { - if ( ! is_numeric($secretary_id)) - { - throw new Exception('Invalid $secretary_id argument given:' . $secretary_id); - } - - if (count($settings) == 0 || ! is_array($settings)) - { - throw new Exception('Invalid $settings argument given:' . print_r($settings, TRUE)); - } - - // Check if the setting record exists in db. - $num_rows = $this->db->get_where('ea_user_settings', - ['id_users' => $secretary_id])->num_rows(); - if ($num_rows == 0) - { - $this->db->insert('ea_user_settings', ['id_users' => $secretary_id]); - } - - foreach ($settings as $name => $value) - { - $this->set_setting($name, $value, $secretary_id); - } - } - /** * Get a providers setting from the database. * @@ -534,34 +568,4 @@ class Secretaries_Model extends CI_Model { ['id_users' => $secretary_id])->row_array(); return $provider_settings[$setting_name]; } - - /** - * Set a provider's setting value in the database. - * - * The provider and settings record must already exist. - * - * @param string $setting_name The setting's name. - * @param string $value The setting's value. - * @param int $secretary_id The selected provider id. - */ - public function set_setting($setting_name, $value, $secretary_id) - { - $this->db->where(['id_users' => $secretary_id]); - return $this->db->update('ea_user_settings', [$setting_name => $value]); - } - - /** - * Validate Records Username - * - * @param string $username The provider records username. - * @param int $user_id The user record id. - * - * @return bool Returns the validation result. - */ - public function validate_username($username, $user_id) - { - $num_rows = $this->db->get_where('ea_user_settings', - ['username' => $username, 'id_users <> ' => $user_id])->num_rows(); - return ($num_rows > 0) ? FALSE : TRUE; - } } diff --git a/application/models/Services_model.php b/application/models/Services_model.php index 8ee64bde..f8ec7251 100644 --- a/application/models/Services_model.php +++ b/application/models/Services_model.php @@ -1,4 +1,4 @@ -db->insert('ea_services', $service)) - { - throw new Exception('Could not insert service record.'); - } - return (int)$this->db->insert_id(); - } - - /** - * Update service record. - * - * @param array $service Contains the service data. The record id needs to be included in the array. - * - * @throws Exception If service record could not be updated. - */ - protected function _update($service) - { - $this->db->where('id', $service['id']); - if ( ! $this->db->update('ea_services', $service)) - { - throw new Exception('Could not update service record'); - } - } - - /** - * Checks whether an service record already exists in the database. - * - * @param array $service Contains the service data. Name, duration and price values are mandatory in order to - * perform the checks. - * - * @return bool Returns whether the service record exists. - * - * @throws Exception If required fields are missing. - */ - public function exists($service) - { - if ( ! isset($service['name']) - || ! isset($service['duration']) - || ! isset($service['price'])) - { - throw new Exception('Not all service fields are provided in order to check whether ' - . 'a service record already exists: ' . print_r($service, TRUE)); - } - - $num_rows = $this->db->get_where('ea_services', [ - 'name' => $service['name'], - 'duration' => $service['duration'], - 'price' => $service['price'] - ])->num_rows(); - - return ($num_rows > 0) ? TRUE : FALSE; - } - /** * Validate a service record data. * @@ -181,6 +122,69 @@ class Services_Model extends CI_Model { return TRUE; } + /** + * Insert service record into database. + * + * @param array $service Contains the service record data. + * + * @return int Returns the new service record id. + * + * @throws Exception If service record could not be inserted. + */ + protected function _insert($service) + { + if ( ! $this->db->insert('ea_services', $service)) + { + throw new Exception('Could not insert service record.'); + } + return (int)$this->db->insert_id(); + } + + /** + * Update service record. + * + * @param array $service Contains the service data. The record id needs to be included in the array. + * + * @throws Exception If service record could not be updated. + */ + protected function _update($service) + { + $this->db->where('id', $service['id']); + if ( ! $this->db->update('ea_services', $service)) + { + throw new Exception('Could not update service record'); + } + } + + /** + * Checks whether an service record already exists in the database. + * + * @param array $service Contains the service data. Name, duration and price values are mandatory in order to + * perform the checks. + * + * @return bool Returns whether the service record exists. + * + * @throws Exception If required fields are missing. + */ + public function exists($service) + { + if ( ! isset($service['name']) + || ! isset($service['duration']) + || ! isset($service['price'])) + { + throw new Exception('Not all service fields are provided in order to check whether ' + . 'a service record already exists: ' . print_r($service, TRUE)); + } + + $num_rows = $this->db->get_where('ea_services', [ + 'name' => $service['name'], + 'duration' => $service['duration'], + 'price' => $service['price'] + ])->num_rows(); + + return ($num_rows > 0) ? TRUE : FALSE; + } + /** * Get the record id of an existing record. * @@ -304,12 +308,12 @@ class Services_Model extends CI_Model { /** * Get all, or specific records from service's table. * - * @example $this->Model->getBatch('id = ' . $recordId); - * * @param string $whereClause (OPTIONAL) The WHERE clause of * the query to be executed. DO NOT INCLUDE 'WHERE' KEYWORD. * * @return array Returns the rows from the database. + * @example $this->Model->getBatch('id = ' . $recordId); + * */ public function get_batch($where = NULL, $order_by = NULL, $limit = NULL, $offset = NULL) { @@ -376,6 +380,40 @@ class Services_Model extends CI_Model { return (int)$category['id']; } + /** + * Validate a service category record data. This method must be used before adding + * a service category record into database in order to secure the record integrity. + * + * @param array $category Contains the service category data. + * + * @return bool Returns the validation result. + * + * @throws Exception If required fields are missing. + */ + public function validate_category($category) + { + try + { + // Required Fields + if ( ! isset($category['name'])) + { + throw new Exception('Not all required fields where provided '); + } + + if ($category['name'] == '' || $category['name'] == NULL) + { + throw new Exception('Required fields cannot be empty or null ($category: ' + . print_r($category, TRUE) . ')'); + } + + return TRUE; + } + catch (Exception $exception) + { + return FALSE; + } + } + /** * Delete a service category record from the database. * @@ -449,38 +487,4 @@ class Services_Model extends CI_Model { return $this->db->get('ea_service_categories', $limit, $offset)->result_array(); } - - /** - * Validate a service category record data. This method must be used before adding - * a service category record into database in order to secure the record integrity. - * - * @param array $category Contains the service category data. - * - * @return bool Returns the validation result. - * - * @throws Exception If required fields are missing. - */ - public function validate_category($category) - { - try - { - // Required Fields - if ( ! isset($category['name'])) - { - throw new Exception('Not all required fields where provided '); - } - - if ($category['name'] == '' || $category['name'] == NULL) - { - throw new Exception('Required fields cannot be empty or null ($category: ' - . print_r($category, TRUE) . ')'); - } - - return TRUE; - } - catch (Exception $exc) - { - return FALSE; - } - } } diff --git a/application/models/Settings_model.php b/application/models/Settings_model.php index 9d318d10..4cd4ec1b 100644 --- a/application/models/Settings_model.php +++ b/application/models/Settings_model.php @@ -1,4 +1,4 @@ -timezones)); - } - /** * Get all timezones to a grouped array (by continent). * @@ -477,33 +470,6 @@ class Timezones_Model extends CI_Model { return $this->timezones; } - /** - * Convert a date time value to a new timezone. - * - * @param string $value Provide a date time value as a string (format Y-m-d H:i:s). - * @param string $from_timezone From timezone value. - * @param string $to_timezone To timezone value. - * @return string - * @throws Exception - */ - public function convert($value, $from_timezone, $to_timezone) - { - if ( ! $to_timezone) - { - return $value; - } - - $from = new \DateTimeZone($from_timezone); - - $to = new \DateTimeZone($to_timezone); - - $result = new \DateTime($value, $from); - - $result->setTimezone($to); - - return $result->format('Y-m-d H:i:s'); - } - /** * Convert the dates of an event to the timezone of the user. * @@ -558,6 +524,43 @@ class Timezones_Model extends CI_Model { return isset($this->session->timezone) ? $this->session->timezone : $default_timezone; } + /** + * Get the default timezone value of the current system. + * + * @return string + */ + public function get_default_timezone() + { + return 'UTC'; + } + + /** + * Convert a date time value to a new timezone. + * + * @param string $value Provide a date time value as a string (format Y-m-d H:i:s). + * @param string $from_timezone From timezone value. + * @param string $to_timezone To timezone value. + * @return string + * @throws Exception + */ + public function convert($value, $from_timezone, $to_timezone) + { + if ( ! $to_timezone) + { + return $value; + } + + $from = new DateTimeZone($from_timezone); + + $to = new DateTimeZone($to_timezone); + + $result = new DateTime($value, $from); + + $result->setTimezone($to); + + return $result->format('Y-m-d H:i:s'); + } + /** * Get the timezone name for the provided value. * @@ -571,14 +574,13 @@ class Timezones_Model extends CI_Model { return isset($timezones[$value]) ? $timezones[$value] : NULL; } - /** - * Get the default timezone value of the current system. + * Get all timezones to a flat array. * - * @return string + * @return array */ - public function get_default_timezone() + public function to_array() { - return 'UTC'; + return array_merge(...array_values($this->timezones)); } } diff --git a/application/models/User_model.php b/application/models/User_model.php index e106ffac..520ea076 100644 --- a/application/models/User_model.php +++ b/application/models/User_model.php @@ -1,4 +1,4 @@ -db->get_where('ea_users', ['id' => $user_id])->row_array(); $user['settings'] = $this->db->get_where('ea_user_settings', ['id_users' => $user_id])->row_array(); @@ -42,10 +43,8 @@ class User_Model extends CI_Model { * @param array $user Contains the current users data. * * @return bool Returns the operation result. - * - * @todo Refactor this method as it does not do as it states. */ - public function save_settings($user) + public function save_user($user) { $user_settings = $user['settings']; $user_settings['id_users'] = $user['id']; @@ -72,19 +71,6 @@ class User_Model extends CI_Model { return TRUE; } - /** - * Retrieve user's salt from database. - * - * @param string $username This will be used to find the user record. - * - * @return string Returns the salt db value. - */ - public function get_salt($username) - { - $user = $this->db->get_where('ea_user_settings', ['username' => $username])->row_array(); - return ($user) ? $user['salt'] : ''; - } - /** * Performs the check of the given user credentials. * @@ -96,7 +82,7 @@ class User_Model extends CI_Model { public function check_login($username, $password) { $this->load->helper('general'); - $salt = $this->user_model->get_salt($username); + $salt = $this->get_salt($username); $password = hash_password($salt, $password); $user_settings = $this->db->get_where('ea_user_settings', [ @@ -136,6 +122,19 @@ class User_Model extends CI_Model { ]; } + /** + * Retrieve user's salt from database. + * + * @param string $username This will be used to find the user record. + * + * @return string Returns the salt db value. + */ + public function get_salt($username) + { + $user = $this->db->get_where('ea_user_settings', ['username' => $username])->row_array(); + return ($user) ? $user['salt'] : ''; + } + /** * Get the given user's display name (first + last name). * diff --git a/application/views/appointments/book.php b/application/views/appointments/book.php index b777838c..3ac56825 100755 --- a/application/views/appointments/book.php +++ b/application/views/appointments/book.php @@ -1,5 +1,5 @@ - + @@ -343,7 +343,7 @@ Easy!Appointments | - config->item('language')) ?> + | @@ -385,7 +385,7 @@ }; var EALang = lang->language) ?>; - var availableLanguages = config->item('available_languages')) ?>; + var availableLanguages = ; diff --git a/application/views/appointments/book_success.php b/application/views/appointments/book_success.php index 02b830e6..f1ddfa94 100755 --- a/application/views/appointments/book_success.php +++ b/application/views/appointments/book_success.php @@ -1,5 +1,5 @@ - + @@ -37,7 +37,7 @@ '; - if ($this->config->item('google_sync_feature')) { + if (config('google_sync_feature')) { echo '