Updated all the main controllers to work with the updated code.

This commit is contained in:
Alex Tselegidis 2021-10-28 14:01:17 +02:00
parent 61a718cb2f
commit a280496294
11 changed files with 1004 additions and 1221 deletions

View File

@ -12,7 +12,9 @@
* ---------------------------------------------------------------------------- */
/**
* Appointments Controller
* Appointments controller
*
* Handles the appointment related operations.
*
* @package Controllers
*/
@ -24,19 +26,20 @@ class Appointments extends EA_Controller {
{
parent::__construct();
$this->load->helper('installation');
$this->load->helper('google_analytics');
$this->load->model('appointments_model');
$this->load->model('providers_model');
$this->load->model('admins_model');
$this->load->model('secretaries_model');
$this->load->model('service_categories_model');
$this->load->model('services_model');
$this->load->model('customers_model');
$this->load->model('settings_model');
$this->load->library('timezones');
$this->load->library('synchronization');
$this->load->library('notifications');
$this->load->library('availability');
$this->load->driver('cache', ['adapter' => 'file']);
}
@ -44,40 +47,40 @@ class Appointments extends EA_Controller {
* Default callback method of the application.
*
* This method creates the appointment book wizard. If an appointment hash is provided then it means that the
* customer followed the appointment manage link that was send with the book success email.
* customer followed the appointment manage link that was sent with the book success email.
*
* @param string $appointment_hash The appointment hash identifier.
*/
public function index($appointment_hash = '')
public function index(string $appointment_hash = '')
{
try
{
if ( ! is_app_installed())
{
redirect('installation/index');
redirect('installation');
return;
}
$available_services = $this->services_model->get_available_services();
$available_providers = $this->providers_model->get_available_providers();
$company_name = $this->settings_model->get_setting('company_name');
$book_advance_timeout = $this->settings_model->get_setting('book_advance_timeout');
$date_format = $this->settings_model->get_setting('date_format');
$time_format = $this->settings_model->get_setting('time_format');
$first_weekday = $this->settings_model->get_setting('first_weekday');
$require_phone_number = $this->settings_model->get_setting('require_phone_number');
$show_field['phone-number'] = $this->settings_model->get_setting('show_phone_number');
$show_field['address'] = $this->settings_model->get_setting('show_address');
$show_field['city'] = $this->settings_model->get_setting('show_city');
$show_field['zip-code'] = $this->settings_model->get_setting('show_zip_code');
$show_field['notes'] = $this->settings_model->get_setting('show_notes');
$display_cookie_notice = $this->settings_model->get_setting('display_cookie_notice');
$cookie_notice_content = $this->settings_model->get_setting('cookie_notice_content');
$display_terms_and_conditions = $this->settings_model->get_setting('display_terms_and_conditions');
$terms_and_conditions_content = $this->settings_model->get_setting('terms_and_conditions_content');
$display_privacy_policy = $this->settings_model->get_setting('display_privacy_policy');
$privacy_policy_content = $this->settings_model->get_setting('privacy_policy_content');
$display_any_provider = $this->settings_model->get_setting('display_any_provider');
$company_name = setting('company_name');
$book_advance_timeout = setting('book_advance_timeout');
$date_format = setting('date_format');
$time_format = setting('time_format');
$first_weekday = setting('first_weekday');
$require_phone_number = setting('require_phone_number');
$show_field['phone-number'] = setting('show_phone_number');
$show_field['address'] = setting('show_address');
$show_field['city'] = setting('show_city');
$show_field['zip-code'] = setting('show_zip_code');
$show_field['notes'] = setting('show_notes');
$display_cookie_notice = setting('display_cookie_notice');
$cookie_notice_content = setting('cookie_notice_content');
$display_terms_and_conditions = setting('display_terms_and_conditions');
$terms_and_conditions_content = setting('terms_and_conditions_content');
$display_privacy_policy = setting('display_privacy_policy');
$privacy_policy_content = setting('privacy_policy_content');
$display_any_provider = setting('display_any_provider');
$timezones = $this->timezones->to_array();
// Remove the data that are not needed inside the $available_providers array.
@ -100,7 +103,7 @@ class Appointments extends EA_Controller {
// Load the appointments data and enable the manage mode of the page.
$manage_mode = TRUE;
$results = $this->appointments_model->get_batch(['hash' => $appointment_hash]);
$results = $this->appointments_model->get(['hash' => $appointment_hash]);
if (empty($results))
{
@ -118,10 +121,11 @@ class Appointments extends EA_Controller {
// If the requested appointment begin date is lower than book_advance_timeout. Display a message to the
// customer.
$startDate = strtotime($results[0]['start_datetime']);
$start_datetime = strtotime($results[0]['start_datetime']);
$limit = strtotime('+' . $book_advance_timeout . ' minutes', strtotime('now'));
if ($startDate < $limit)
if ($start_datetime < $limit)
{
$hours = floor($book_advance_timeout / 60);
$minutes = ($book_advance_timeout % 60);
@ -133,13 +137,17 @@ class Appointments extends EA_Controller {
]),
'message_icon' => base_url('assets/img/error.png')
];
$this->load->view('appointments/message', $view);
return;
}
$appointment = $results[0];
$provider = $this->providers_model->get_row($appointment['id_users_provider']);
$customer = $this->customers_model->get_row($appointment['id_users_customer']);
$provider = $this->providers_model->find($appointment['id_users_provider']);
$customer = $this->customers_model->find($appointment['id_users_customer']);
$customer_token = md5(uniqid(mt_rand(), TRUE));
@ -182,9 +190,9 @@ class Appointments extends EA_Controller {
'display_any_provider' => $display_any_provider,
];
}
catch (Exception $exception)
catch (Throwable $e)
{
$variables['exceptions'][] = $exception;
$variables['exceptions'][] = $e;
}
$this->load->view('appointments/book', $variables);
@ -199,44 +207,42 @@ class Appointments extends EA_Controller {
*
* @param string $appointment_hash This appointment hash identifier.
*/
public function cancel($appointment_hash)
public function cancel(string $appointment_hash)
{
try
{
// Check whether the appointment hash exists in the database.
$appointments = $this->appointments_model->get_batch(['hash' => $appointment_hash]);
$occurrences = $this->appointments_model->get(['hash' => $appointment_hash]);
if (empty($appointments))
if (empty($occurrences))
{
throw new Exception('No record matches the provided hash.');
}
$appointment = $appointments[0];
$provider = $this->providers_model->get_row($appointment['id_users_provider']);
$customer = $this->customers_model->get_row($appointment['id_users_customer']);
$service = $this->services_model->get_row($appointment['id_services']);
$appointment = $occurrences[0];
$provider = $this->providers_model->find($appointment['id_users_provider']);
$customer = $this->customers_model->find($appointment['id_users_customer']);
$service = $this->services_model->find($appointment['id_services']);
$settings = [
'company_name' => $this->settings_model->get_setting('company_name'),
'company_email' => $this->settings_model->get_setting('company_email'),
'company_link' => $this->settings_model->get_setting('company_link'),
'date_format' => $this->settings_model->get_setting('date_format'),
'time_format' => $this->settings_model->get_setting('time_format')
'company_name' => setting('company_name'),
'company_email' => setting('company_email'),
'company_link' => setting('company_link'),
'date_format' => setting('date_format'),
'time_format' => setting('time_format')
];
// Remove the appointment record from the data.
if ( ! $this->appointments_model->delete($appointment['id']))
{
throw new Exception('Appointment could not be deleted from the database.');
}
$this->appointments_model->delete($appointment['id']);
$this->synchronization->sync_appointment_deleted($appointment, $provider);
$this->notifications->notify_appointment_deleted($appointment, $service, $provider, $customer, $settings);
}
catch (Exception $exception)
catch (Throwable $e)
{
// Display the error message to the customer.
$exceptions[] = $exception;
$exceptions[] = $e;
}
$view = [
@ -254,34 +260,34 @@ class Appointments extends EA_Controller {
}
/**
* GET an specific appointment book and redirect to the success screen.
* Display the appointment registration success page.
*
* @param string $appointment_hash The appointment hash identifier.
*
* @throws Exception
*/
public function book_success($appointment_hash)
public function book_success(string $appointment_hash)
{
$appointments = $this->appointments_model->get_batch(['hash' => $appointment_hash]);
$occurrences = $this->appointments_model->get(['hash' => $appointment_hash]);
if (empty($appointments))
if (empty($occurrences))
{
redirect('appointments'); // The appointment does not exist.
return;
}
$appointment = $appointments[0];
$appointment = $occurrences[0];
unset($appointment['notes']);
$customer = $this->customers_model->get_row($appointment['id_users_customer']);
$customer = $this->customers_model->find($appointment['id_users_customer']);
$provider = $this->providers_model->get_row($appointment['id_users_provider']);
$provider = $this->providers_model->find($appointment['id_users_provider']);
$service = $this->services_model->get_row($appointment['id_services']);
$service = $this->services_model->find($appointment['id_services']);
$company_name = $this->settings_model->get_setting('company_name');
$company_name = setting('company_name');
// Get any pending exceptions.
$exceptions = $this->session->flashdata('book_success');
$view = [
@ -313,20 +319,18 @@ class Appointments extends EA_Controller {
}
/**
* Get the available appointment hours for the given date.
* Get the available appointment hours for the selected date.
*
* This method answers to an AJAX request. It calculates the available hours for the given service, provider and
* date.
*
* Outputs a JSON string with the availabilities.
*/
public function ajax_get_available_hours()
{
try
{
$provider_id = $this->input->post('provider_id');
$service_id = $this->input->post('service_id');
$selected_date = $this->input->post('selected_date');
$provider_id = request('provider_id');
$service_id = request('service_id');
$selected_date = request('selected_date');
// Do not continue if there was no provider selected (more likely there is no provider in the system).
if (empty($provider_id))
@ -340,46 +344,46 @@ class Appointments extends EA_Controller {
// If manage mode is TRUE then the following we should not consider the selected appointment when
// calculating the available time periods of the provider.
$exclude_appointment_id = $this->input->post('manage_mode') === 'true' ? $this->input->post('appointment_id') : NULL;
$exclude_appointment_id = request('manage_mode') === 'true' ? request('appointment_id') : NULL;
// If the user has selected the "any-provider" option then we will need to search for an available provider
// that will provide the requested service.
$service = $this->services_model->get_row($service_id);
$service = $this->services_model->find($service_id);
if ($provider_id === ANY_PROVIDER)
{
$providers = $this->providers_model->get_batch();
$available_hours = [];
foreach($providers as $provider)
$providers = $this->providers_model->get();
$available_hours = [];
foreach ($providers as $provider)
{
if (!in_array($service_id, $provider['services']))
if ( ! in_array($service_id, $provider['services']))
{
continue;
continue;
}
$provider_available_hours = $this->availability->get_available_hours($selected_date, $service, $provider, $exclude_appointment_id);
$provider_available_hours = $this->availability->get_available_hours($selected_date, $service, $provider, $exclude_appointment_id);
$available_hours = array_merge($available_hours, $provider_available_hours);
}
$response = array_unique(array_values($available_hours));
$response = array_unique(array_values($available_hours));
}
else
{
$provider = $this->providers_model->get_row($provider_id);
$provider = $this->providers_model->find($provider_id);
$response = $this->availability->get_available_hours($selected_date, $service, $provider, $exclude_appointment_id);
}
}
catch (Exception $exception)
catch (Throwable $e)
{
$this->output->set_status_header(500);
$response = [
'message' => $exception->getMessage(),
'trace' => config('debug') ? $exception->getTrace() : []
'message' => $e->getMessage(),
'trace' => config('debug') ? $e->getTrace() : []
];
}
@ -393,19 +397,19 @@ class Appointments extends EA_Controller {
*
* This method will return the database ID of the provider with the most available periods.
*
* @param int $service_id The requested service ID.
* @param string $date The date to be searched (Y-m-d).
* @param string $hour The hour to be searched (H:i).
* @param int $service_id Service ID
* @param string $date Selected date (Y-m-d).
* @param string|null $hour Selected hour (H:i).
*
* @return int Returns the ID of the provider that can provide the service at the selected date.
*
* @throws Exception
*/
protected function search_any_provider($service_id, $date, $hour = null)
protected function search_any_provider(int $service_id, string $date, string $hour = NULL): int
{
$available_providers = $this->providers_model->get_available_providers();
$service = $this->services_model->get_row($service_id);
$service = $this->services_model->find($service_id);
$provider_id = NULL;
@ -420,9 +424,10 @@ class Appointments extends EA_Controller {
// Check if the provider is available for the requested date.
$available_hours = $this->availability->get_available_hours($date, $service, $provider);
if (count($available_hours) > $max_hours_count && (empty($hour) || in_array($hour, $available_hours, false)))
if (count($available_hours) > $max_hours_count && (empty($hour) || in_array($hour, $available_hours, FALSE)))
{
$provider_id = $provider['id'];
$max_hours_count = count($available_hours);
}
}
@ -435,24 +440,37 @@ class Appointments extends EA_Controller {
/**
* Register the appointment to the database.
*
* Outputs a JSON string with the appointment ID.
*/
public function ajax_register_appointment()
{
try
{
$post_data = $this->input->post('post_data');
$captcha = $this->input->post('captcha');
$post_data = request('post_data');
$captcha = request('captcha');
$manage_mode = filter_var($post_data['manage_mode'], FILTER_VALIDATE_BOOLEAN);
$appointment = $post_data['appointment'];
$customer = $post_data['customer'];
if (!array_key_exists('address', $customer)){ $customer['address'] = ""; }
if (!array_key_exists('city', $customer)){ $customer['city'] = ""; }
if (!array_key_exists('zip_code', $customer)){ $customer['zip_code'] = ""; }
if (!array_key_exists('notes', $customer)){ $customer['notes'] = ""; }
if (!array_key_exists('phone_number', $customer)){ $customer['address'] = ""; }
if ( ! array_key_exists('address', $customer))
{
$customer['address'] = '';
}
if ( ! array_key_exists('city', $customer))
{
$customer['city'] = '';
}
if ( ! array_key_exists('zip_code', $customer))
{
$customer['zip_code'] = '';
}
if ( ! array_key_exists('notes', $customer))
{
$customer['notes'] = '';
}
if ( ! array_key_exists('phone_number', $customer))
{
$customer['address'] = '';
}
// Check appointment availability before registering it to the database.
$appointment['id_users_provider'] = $this->check_datetime_availability();
@ -462,14 +480,16 @@ class Appointments extends EA_Controller {
throw new Exception(lang('requested_hour_is_unavailable'));
}
$provider = $this->providers_model->get_row($appointment['id_users_provider']);
$service = $this->services_model->get_row($appointment['id_services']);
$provider = $this->providers_model->find($appointment['id_users_provider']);
$require_captcha = $this->settings_model->get_setting('require_captcha');
$captcha_phrase = $this->session->userdata('captcha_phrase');
$service = $this->services_model->find($appointment['id_services']);
$require_captcha = (bool)setting('require_captcha');
$captcha_phrase = session('captcha_phrase');
// Validate the CAPTCHA string.
if ($require_captcha === '1' && $captcha_phrase !== $captcha)
if ($require_captcha && $captcha_phrase !== $captcha)
{
$this->output
->set_content_type('application/json')
@ -491,23 +511,24 @@ class Appointments extends EA_Controller {
}
// Save customer language (the language which is used to render the booking page).
$customer['language'] = config('language');
$customer_id = $this->customers_model->add($customer);
$customer['language'] = session('language') ?? config('language');
$customer_id = $this->customers_model->save($customer);
$appointment['id_users_customer'] = $customer_id;
$appointment['is_unavailable'] = (int)$appointment['is_unavailable']; // needs to be type casted
$appointment['id'] = $this->appointments_model->add($appointment);
$appointment['hash'] = $this->appointments_model->get_value('hash', $appointment['id']);
$appointment['is_unavailable'] = (int)$appointment['is_unavailable'];
$appointment['id'] = $this->appointments_model->save($appointment);
$appointment['hash'] = $this->appointments_model->value($appointment['id'], 'hash');
$settings = [
'company_name' => $this->settings_model->get_setting('company_name'),
'company_link' => $this->settings_model->get_setting('company_link'),
'company_email' => $this->settings_model->get_setting('company_email'),
'date_format' => $this->settings_model->get_setting('date_format'),
'time_format' => $this->settings_model->get_setting('time_format')
'company_name' => setting('company_name'),
'company_link' => setting('company_link'),
'company_email' => setting('company_email'),
'date_format' => setting('date_format'),
'time_format' => setting('time_format')
];
$this->synchronization->sync_appointment_saved($appointment, $service, $provider, $customer, $settings, $manage_mode);
$this->notifications->notify_appointment_saved($appointment, $service, $provider, $customer, $settings, $manage_mode);
$response = [
@ -515,13 +536,13 @@ class Appointments extends EA_Controller {
'appointment_hash' => $appointment['hash']
];
}
catch (Exception $exception)
catch (Throwable $e)
{
$this->output->set_status_header(500);
$response = [
'message' => $exception->getMessage(),
'trace' => config('debug') ? $exception->getTrace() : []
'message' => $e->getMessage(),
'trace' => config('debug') ? $e->getTrace() : []
];
}
@ -533,24 +554,27 @@ class Appointments extends EA_Controller {
/**
* Check whether the provider is still available in the selected appointment date.
*
* It might be times where two or more customers select the same appointment date and time. This shouldn't be
* allowed to happen, so one of the two customers will eventually get the preferred date and the other one will have
* to choose for another date. Use this method just before the customer confirms the appointment details. If the
* selected date was taken in the mean time, the customer must be prompted to select another time for his
* appointment.
* It is possible that two or more customers select the same appointment date and time concurrently. The app won't
* allow this to happen, so one of the two will eventually get the selected date and the other one will have
* to choose for another one.
*
* Use this method just before the customer confirms the appointment registration. If the selected date was reserved
* in the meanwhile, the customer must be prompted to select another time.
*
* @return int Returns the ID of the provider that is available for the appointment.
*
* @throws Exception
*/
protected function check_datetime_availability()
protected function check_datetime_availability(): ?int
{
$post_data = $this->input->post('post_data');
$post_data = request('post_data');
$appointment = $post_data['appointment'];
$appointment_start = new DateTime($appointment['start_datetime']);
$date = $appointment_start->format('Y-m-d');
$hour = $appointment_start->format('H:i');
if ($appointment['id_users_provider'] === ANY_PROVIDER)
@ -560,11 +584,11 @@ class Appointments extends EA_Controller {
return $appointment['id_users_provider'];
}
$service = $this->services_model->get_row($appointment['id_services']);
$service = $this->services_model->find($appointment['id_services']);
$exclude_appointment_id = isset($appointment['id']) ? $appointment['id'] : NULL;
$exclude_appointment_id = $appointment['id'] ?? NULL;
$provider = $this->providers_model->get_row($appointment['id_users_provider']);
$provider = $this->providers_model->find($appointment['id_users_provider']);
$available_hours = $this->availability->get_available_hours($date, $service, $provider, $exclude_appointment_id);
@ -597,11 +621,11 @@ class Appointments extends EA_Controller {
{
try
{
$provider_id = $this->input->get('provider_id');
$service_id = $this->input->get('service_id');
$appointment_id = $this->input->get_post('appointment_id');
$manage_mode = $this->input->get_post('manage_mode');
$selected_date_string = $this->input->get('selected_date');
$provider_id = request('provider_id');
$service_id = request('service_id');
$appointment_id = request('appointment_id');
$manage_mode = filter_var(request('manage_mode'), FILTER_VALIDATE_BOOLEAN);
$selected_date_string = request('selected_date');
$selected_date = new DateTime($selected_date_string);
$number_of_days_in_month = (int)$selected_date->format('t');
$unavailable_dates = [];
@ -613,7 +637,7 @@ class Appointments extends EA_Controller {
$exclude_appointment_id = $manage_mode ? $appointment_id : NULL;
// Get the service record.
$service = $this->services_model->get_row($service_id);
$service = $this->services_model->find($service_id);
for ($i = 1; $i <= $number_of_days_in_month; $i++)
{
@ -629,7 +653,7 @@ class Appointments extends EA_Controller {
// Finding at least one slot of availability.
foreach ($provider_ids as $current_provider_id)
{
$provider = $this->providers_model->get_row($current_provider_id);
$provider = $this->providers_model->find($current_provider_id);
$available_hours = $this->availability->get_available_hours(
$current_date->format('Y-m-d'),
@ -653,13 +677,13 @@ class Appointments extends EA_Controller {
$response = $unavailable_dates;
}
catch (Exception $exception)
catch (Throwable $e)
{
$this->output->set_status_header(500);
$response = [
'message' => $exception->getMessage(),
'trace' => config('debug') ? $exception->getTrace() : []
'message' => $e->getMessage(),
'trace' => config('debug') ? $e->getTrace() : []
];
}
@ -677,7 +701,7 @@ class Appointments extends EA_Controller {
*
* @return array Returns the ID of the provider that can provide the requested service.
*/
protected function search_providers_by_service($service_id)
protected function search_providers_by_service(int $service_id): array
{
$available_providers = $this->providers_model->get_available_providers();
$provider_list = [];

View File

@ -12,9 +12,9 @@
* ---------------------------------------------------------------------------- */
/**
* Backend Controller
* Backend controller
*
* @property CI_Session $session
* Handles the backend related operations.
*
* @package Controllers
*/
@ -26,64 +26,65 @@ class Backend extends EA_Controller {
{
parent::__construct();
$this->load->model('appointments_model');
$this->load->model('providers_model');
$this->load->model('services_model');
$this->load->model('customers_model');
$this->load->model('settings_model');
$this->load->model('roles_model');
$this->load->model('user_model');
$this->load->model('secretaries_model');
$this->load->model('admins_model');
$this->load->library('timezones');
$this->load->model('appointments_model');
$this->load->model('customers_model');
$this->load->model('providers_model');
$this->load->model('roles_model');
$this->load->model('secretaries_model');
$this->load->model('service_categories_model');
$this->load->model('services_model');
$this->load->model('settings_model');
$this->load->model('users_model');
$this->load->library('accounts');
$this->load->library('migration');
$this->load->library('timezones');
}
/**
* Display the main backend page.
*
* This method displays the main backend page. All users login permission can view this page which displays a
* This method displays the main backend page. All login permission can view this page which displays a
* calendar with the events of the selected provider or service. If a user has more privileges he will see more
* menus at the top of the page.
*
* @param string $appointment_hash Appointment edit dialog will appear when the page loads (default '').
*
* @throws Exception
*/
public function index($appointment_hash = '')
public function index(string $appointment_hash = '')
{
$this->session->set_userdata('dest_url', site_url('backend/index' . (! empty($appointment_hash) ? '/' . $appointment_hash : '')));
session(['dest_url' => site_url('backend/index' . (! empty($appointment_hash) ? '/' . $appointment_hash : ''))]);
if ( ! $this->has_privileges(PRIV_APPOINTMENTS))
if ( ! $this->has_permissions(PRIV_APPOINTMENTS))
{
return;
}
$calendar_view_query_param = $this->input->get('view');
$calendar_view_query_param = request('view');
$user_id = $this->session->userdata('user_id');
$user_id = session('user_id');
$user = $this->user_model->get_user($user_id);
$user = $this->users_model->find($user_id);
$view['base_url'] = config('base_url');
$view['page_title'] = lang('calendar');
$view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id'));
$view['user_display_name'] = $this->accounts->get_user_display_name($user_id);
$view['active_menu'] = PRIV_APPOINTMENTS;
$view['date_format'] = $this->settings_model->get_setting('date_format');
$view['time_format'] = $this->settings_model->get_setting('time_format');
$view['first_weekday'] = $this->settings_model->get_setting('first_weekday');
$view['company_name'] = $this->settings_model->get_setting('company_name');
$view['require_phone_number'] = $this->settings_model->get_setting('require_phone_number');
$view['date_format'] = setting('date_format');
$view['time_format'] = setting('time_format');
$view['first_weekday'] = setting('first_weekday');
$view['company_name'] = setting('company_name');
$view['require_phone_number'] = setting('require_phone_number');
$view['available_providers'] = $this->providers_model->get_available_providers();
$view['available_services'] = $this->services_model->get_available_services();
$view['customers'] = $this->customers_model->get_batch();
$view['customers'] = $this->customers_model->get();
$view['calendar_view'] = ! empty($calendar_view_query_param) ? $calendar_view_query_param : $user['settings']['calendar_view'];
$view['timezones'] = $this->timezones->to_array();
$this->set_user_data($view);
if ($this->session->userdata('role_slug') === DB_SLUG_SECRETARY)
if (session('role_slug') === DB_SLUG_SECRETARY)
{
$secretary = $this->secretaries_model->get_row($this->session->userdata('user_id'));
$secretary = $this->secretaries_model->find(session('user_id'));
$view['secretary_providers'] = $secretary['providers'];
}
else
@ -91,12 +92,12 @@ class Backend extends EA_Controller {
$view['secretary_providers'] = [];
}
$results = $this->appointments_model->get_batch(['hash' => $appointment_hash]);
$results = $this->appointments_model->get(['hash' => $appointment_hash]);
if ($appointment_hash !== '' && count($results) > 0)
{
$appointment = $results[0];
$appointment['customer'] = $this->customers_model->get_row($appointment['id_users_customer']);
$appointment['customer'] = $this->customers_model->find($appointment['id_users_customer']);
$view['edit_appointment'] = $appointment; // This will display the appointment edit dialog on page load.
}
else
@ -115,43 +116,40 @@ class Backend extends EA_Controller {
* The backend page requires different privileges from the users to display pages. Not all pages are available to
* all users. For example secretaries should not be able to edit the system users.
*
* @param string $page This argument must match the roles field names of each section (eg "appointments", "users"
* ...).
* @param bool $redirect If the user has not the required privileges (either not logged in or insufficient role
* privileges) then the user will be redirected to another page. Set this argument to FALSE when using ajax (default
* true).
* @param string $page This argument must match the roles field names of each section (e.g. "appointments").
* @param bool $redirect If the user has not the required privileges either not logged in or insufficient
* permissions then the user will be redirected to another page.
*
* @return bool Returns whether the user has the required privileges to view the page or not. If the user is not
* logged in then he will be prompted to log in. If he hasn't the required privileges then an info message will be
* displayed.
* @return bool Returns whether the user has the required privileges to view the page or not.
*/
protected function has_privileges($page, $redirect = TRUE)
protected function has_permissions(string $page, bool $redirect = TRUE): bool
{
// Check if user is logged in.
$user_id = $this->session->userdata('user_id');
$user_id = session('user_id');
if ($user_id == FALSE)
if ( ! $user_id)
{
// User not logged in, display the login view.
if ($redirect)
{
header('Location: ' . site_url('user/login'));
redirect('user/login');
}
return FALSE;
}
// Check if the user has the required privileges for viewing the selected page.
$role_slug = $this->session->userdata('role_slug');
$role_slug = session('role_slug');
$role_privileges = $this->db->get_where('roles', ['slug' => $role_slug])->row_array();
$role_permissions = $this->db->get_where('roles', ['slug' => $role_slug])->row_array();
if ($role_privileges[$page] < PRIV_VIEW)
if ($role_permissions[$page] < PRIV_VIEW)
{
// User does not have the permission to view the page.
if ($redirect)
{
header('Location: ' . site_url('user/no_privileges'));
redirect('user/no_permissions');
}
return FALSE;
}
@ -163,13 +161,13 @@ class Backend extends EA_Controller {
*
* @param array $view Contains the view data.
*/
protected function set_user_data(&$view)
protected function set_user_data(array &$view)
{
$view['user_id'] = $this->session->userdata('user_id');
$view['user_email'] = $this->session->userdata('user_email');
$view['timezone'] = $this->session->userdata('timezone');
$view['role_slug'] = $this->session->userdata('role_slug');
$view['privileges'] = $this->roles_model->get_privileges($this->session->userdata('role_slug'));
$view['user_id'] = session('user_id');
$view['user_email'] = session('user_email');
$view['timezone'] = session('timezone');
$view['role_slug'] = session('role_slug');
$view['privileges'] = $this->roles_model->get_permissions_by_slug(session('role_slug'));
}
/**
@ -179,30 +177,30 @@ class Backend extends EA_Controller {
*/
public function customers()
{
$this->session->set_userdata('dest_url', site_url('backend/customers'));
session(['dest_url' => site_url('backend/customers')]);
if ( ! $this->has_privileges(PRIV_CUSTOMERS))
if ( ! $this->has_permissions(PRIV_CUSTOMERS))
{
return;
}
$view['base_url'] = config('base_url');
$view['page_title'] = lang('customers');
$view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id'));
$view['user_display_name'] = $this->accounts->get_user_display_name(session('user_id'));
$view['active_menu'] = PRIV_CUSTOMERS;
$view['company_name'] = $this->settings_model->get_setting('company_name');
$view['date_format'] = $this->settings_model->get_setting('date_format');
$view['time_format'] = $this->settings_model->get_setting('time_format');
$view['first_weekday'] = $this->settings_model->get_setting('first_weekday');
$view['require_phone_number'] = $this->settings_model->get_setting('require_phone_number');
$view['customers'] = $this->customers_model->get_batch();
$view['company_name'] = setting('company_name');
$view['date_format'] = setting('date_format');
$view['time_format'] = setting('time_format');
$view['first_weekday'] = setting('first_weekday');
$view['require_phone_number'] = setting('require_phone_number');
$view['customers'] = $this->customers_model->get();
$view['available_providers'] = $this->providers_model->get_available_providers();
$view['available_services'] = $this->services_model->get_available_services();
$view['timezones'] = $this->timezones->to_array();
if ($this->session->userdata('role_slug') === DB_SLUG_SECRETARY)
if (session('role_slug') === DB_SLUG_SECRETARY)
{
$secretary = $this->secretaries_model->get_row($this->session->userdata('user_id'));
$secretary = $this->secretaries_model->find(session('user_id'));
$view['secretary_providers'] = $secretary['providers'];
}
else
@ -227,23 +225,23 @@ class Backend extends EA_Controller {
*/
public function services()
{
$this->session->set_userdata('dest_url', site_url('backend/services'));
session(['dest_url' => site_url('backend/services')]);
if ( ! $this->has_privileges(PRIV_SERVICES))
if ( ! $this->has_permissions(PRIV_SERVICES))
{
return;
}
$view['base_url'] = config('base_url');
$view['page_title'] = lang('services');
$view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id'));
$view['user_display_name'] = $this->accounts->get_user_display_name(session('user_id'));
$view['active_menu'] = PRIV_SERVICES;
$view['company_name'] = $this->settings_model->get_setting('company_name');
$view['date_format'] = $this->settings_model->get_setting('date_format');
$view['time_format'] = $this->settings_model->get_setting('time_format');
$view['first_weekday'] = $this->settings_model->get_setting('first_weekday');
$view['services'] = $this->services_model->get_batch();
$view['categories'] = $this->services_model->get_all_categories();
$view['company_name'] = setting('company_name');
$view['date_format'] = setting('date_format');
$view['time_format'] = setting('time_format');
$view['first_weekday'] = setting('first_weekday');
$view['services'] = $this->services_model->get();
$view['categories'] = $this->service_categories_model->get();
$view['timezones'] = $this->timezones->to_array();
$this->set_user_data($view);
@ -260,26 +258,26 @@ class Backend extends EA_Controller {
*/
public function users()
{
$this->session->set_userdata('dest_url', site_url('backend/users'));
session(['dest_url' => site_url('backend/users')]);
if ( ! $this->has_privileges(PRIV_USERS))
if ( ! $this->has_permissions(PRIV_USERS))
{
return;
}
$view['base_url'] = config('base_url');
$view['page_title'] = lang('users');
$view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id'));
$view['user_display_name'] = $this->accounts->get_user_display_name(session('user_id'));
$view['active_menu'] = PRIV_USERS;
$view['company_name'] = $this->settings_model->get_setting('company_name');
$view['date_format'] = $this->settings_model->get_setting('date_format');
$view['time_format'] = $this->settings_model->get_setting('time_format');
$view['first_weekday'] = $this->settings_model->get_setting('first_weekday');
$view['admins'] = $this->admins_model->get_batch();
$view['providers'] = $this->providers_model->get_batch();
$view['secretaries'] = $this->secretaries_model->get_batch();
$view['services'] = $this->services_model->get_batch();
$view['working_plan'] = $this->settings_model->get_setting('company_working_plan');
$view['company_name'] = setting('company_name');
$view['date_format'] = setting('date_format');
$view['time_format'] = setting('time_format');
$view['first_weekday'] = setting('first_weekday');
$view['admins'] = $this->admins_model->get();
$view['providers'] = $this->providers_model->get();
$view['secretaries'] = $this->secretaries_model->get();
$view['services'] = $this->services_model->get();
$view['working_plan'] = setting('company_working_plan');
$view['timezones'] = $this->timezones->to_array();
$view['working_plan_exceptions'] = '{}';
$this->set_user_data($view);
@ -294,34 +292,36 @@ class Backend extends EA_Controller {
*
* This page will display the user settings (name, password etc). If current user is an administrator, then he will
* be able to make change to the current Easy!Appointment installation (core settings like company name, book
* timeout etc).
* timeout).
*/
public function settings()
{
$this->session->set_userdata('dest_url', site_url('backend/settings'));
if ( ! $this->has_privileges(PRIV_SYSTEM_SETTINGS, FALSE)
&& ! $this->has_privileges(PRIV_USER_SETTINGS))
session(['dest_url' => site_url('backend/settings')]);
if (
! $this->has_permissions(PRIV_SYSTEM_SETTINGS, FALSE)
&& ! $this->has_permissions(PRIV_USER_SETTINGS))
{
return;
}
$user_id = $this->session->userdata('user_id');
$user_id = session('user_id');
$view['base_url'] = config('base_url');
$view['page_title'] = lang('settings');
$view['user_display_name'] = $this->user_model->get_user_display_name($user_id);
$view['user_display_name'] = $this->accounts->get_user_display_name($user_id);
$view['active_menu'] = PRIV_SYSTEM_SETTINGS;
$view['company_name'] = $this->settings_model->get_setting('company_name');
$view['date_format'] = $this->settings_model->get_setting('date_format');
$view['first_weekday'] = $this->settings_model->get_setting('first_weekday');
$view['time_format'] = $this->settings_model->get_setting('time_format');
$view['role_slug'] = $this->session->userdata('role_slug');
$view['system_settings'] = $this->settings_model->get_settings();
$view['user_settings'] = $this->user_model->get_user($user_id);
$view['company_name'] = setting('company_name');
$view['date_format'] = setting('date_format');
$view['first_weekday'] = setting('first_weekday');
$view['time_format'] = setting('time_format');
$view['role_slug'] = session('role_slug');
$view['system_settings'] = $this->settings_model->get();
$view['user_settings'] = $this->users_model->find($user_id);
$view['timezones'] = $this->timezones->to_array();
// book_advance_timeout preview
$book_advance_timeout = $this->settings_model->get_setting('book_advance_timeout');
$book_advance_timeout = setting('book_advance_timeout');
$hours = floor($book_advance_timeout / 60);
$minutes = $book_advance_timeout % 60;
$view['book_advance_timeout_preview'] = sprintf('%02d:%02d', $hours, $minutes);
@ -346,7 +346,7 @@ class Backend extends EA_Controller {
{
try
{
if ( ! $this->has_privileges(PRIV_SYSTEM_SETTINGS, TRUE))
if ( ! $this->has_permissions(PRIV_SYSTEM_SETTINGS))
{
throw new Exception('You do not have the required privileges for this task!');
}
@ -358,9 +358,9 @@ class Backend extends EA_Controller {
$view = ['success' => TRUE];
}
catch (Exception $exception)
catch (Throwable $e)
{
$view = ['success' => FALSE, 'exception' => $exception->getMessage()];
$view = ['success' => FALSE, 'exception' => $e->getMessage()];
}
$this->load->view('general/update', $view);

File diff suppressed because it is too large Load Diff

View File

@ -11,8 +11,12 @@
* @since v1.0.0
* ---------------------------------------------------------------------------- */
use Gregwar\Captcha\CaptchaBuilder;
/**
* Captcha Controller
* Captcha controller
*
* Handles the captcha operations.
*
* @package Controllers
*/
@ -22,10 +26,10 @@ class Captcha extends EA_Controller {
*/
public function index()
{
header('Content-type: image/jpeg');
$builder = new Gregwar\Captcha\CaptchaBuilder;
$builder = new CaptchaBuilder;
$builder->build();
$this->session->set_userdata('captcha_phrase', $builder->getPhrase());
session(['captcha_phrase' => $builder->getPhrase()]);
header('Content-type: image/jpeg');
$builder->output();
}
}

View File

@ -12,7 +12,7 @@
* ---------------------------------------------------------------------------- */
/**
* Class Consent
* Consents controller
*
* Handles user consent related operations.
*
@ -25,39 +25,31 @@ class Consents extends EA_Controller {
public function __construct()
{
parent::__construct();
$this->load->model('consents_model');
}
/**
* Save the user's consent.
* Save (insert or update) the consent
*/
public function ajax_save_consent()
{
try
{
$consent = $this->input->post('consent');
$consent = request('consent');
$consent['ip'] = $this->input->ip_address();
$consent['id'] = $this->consents_model->add($consent);
$consent['id'] = $this->consents_model->save($consent);
$response = [
json_response([
'success' => TRUE,
'id' => $consent['id']
];
]);
}
catch (Exception $exception)
catch (Throwable $e)
{
$this->output->set_status_header(500);
$response = [
'message' => $exception->getMessage(),
'trace' => config('debug') ? $exception->getTrace() : []
];
json_exception($e);
}
$this->output
->set_content_type('application/json')
->set_output(json_encode($response));
}
}

View File

@ -14,9 +14,9 @@
require_once __DIR__ . '/Google.php';
/**
* Class Console
* Console controller
*
* CLI commands of Easy!Appointments, can only be executed from a terminal and not with a direct request.
* Handles all the Console related operations.
*/
class Console extends EA_Controller {
/**
@ -32,8 +32,9 @@ class Console extends EA_Controller {
parent::__construct();
$this->load->dbutil();
$this->load->helper('file');
$this->load->library('migration');
$this->load->model('admins_model');
$this->load->model('customers_model');
$this->load->model('providers_model');
@ -53,8 +54,10 @@ class Console extends EA_Controller {
public function install()
{
$this->migrate('fresh');
$this->seed();
$this->output->set_output(PHP_EOL . '⇾ Installation completed, login with "administrator" / "administrator".' . PHP_EOL . PHP_EOL);
response(PHP_EOL . '⇾ Installation completed, login with "administrator" / "administrator".' . PHP_EOL . PHP_EOL);
}
/**
@ -75,9 +78,9 @@ class Console extends EA_Controller {
*
* @param string $type
*/
public function migrate($type = '')
public function migrate(string $type = '')
{
if ($type === 'fresh' && $this->migration->version(0) === FALSE)
if ($type === 'fresh' && ! $this->migration->version(0))
{
show_error($this->migration->error_string());
}
@ -100,12 +103,14 @@ class Console extends EA_Controller {
public function seed()
{
// Settings
$this->settings_model->set_setting('company_name', 'Company Name');
$this->settings_model->set_setting('company_email', 'info@example.org');
$this->settings_model->set_setting('company_link', 'https://example.org');
setting([
'company_name' => 'Company Name',
'company_email' => 'info@example.org',
'company_link' => 'https://example.org',
]);
// Admin
$this->admins_model->add([
$this->admins_model->save([
'first_name' => 'John',
'last_name' => 'Doe',
'email' => 'john@example.org',
@ -119,7 +124,7 @@ class Console extends EA_Controller {
]);
// Service
$service_id = $this->services_model->add([
$service_id = $this->services_model->save([
'name' => 'Service',
'duration' => '30',
'price' => '0',
@ -129,7 +134,7 @@ class Console extends EA_Controller {
]);
// Provider
$this->providers_model->add([
$this->providers_model->save([
'first_name' => 'Jane',
'last_name' => 'Doe',
'email' => 'jane@example.org',
@ -140,7 +145,7 @@ class Console extends EA_Controller {
'settings' => [
'username' => 'janedoe',
'password' => 'janedoe',
'working_plan' => $this->settings_model->get_setting('company_working_plan'),
'working_plan' => setting('company_working_plan'),
'notifications' => TRUE,
'google_sync' => FALSE,
'sync_past_days' => 30,
@ -150,7 +155,7 @@ class Console extends EA_Controller {
]);
// Customer
$this->customers_model->add([
$this->customers_model->save([
'first_name' => 'James',
'last_name' => 'Doe',
'email' => 'james@example.org',
@ -161,7 +166,7 @@ class Console extends EA_Controller {
/**
* Create a backup file.
*
* Use this method to backup your Easy!Appointments data.
* Use this method to back up your Easy!Appointments data.
*
* Usage:
*
@ -173,11 +178,11 @@ class Console extends EA_Controller {
*/
public function backup()
{
$path = isset($GLOBALS['argv'][3]) ? $GLOBALS['argv'][3] : APPPATH . '/../storage/backups';
$path = $GLOBALS['argv'][3] ?? APPPATH . '/../storage/backups';
if ( ! file_exists($path))
{
throw new Exception('The backup path does not exist: ' . $path);
throw new Exception('The backup path does not exist: ' . $path);
}
if ( ! is_writable($path))
@ -207,7 +212,7 @@ class Console extends EA_Controller {
*/
public function sync()
{
$providers = $this->providers_model->get_batch();
$providers = $this->providers_model->get();
foreach ($providers as $provider)
{
@ -252,6 +257,6 @@ class Console extends EA_Controller {
'',
];
$this->output->set_output(implode(PHP_EOL, $help));
response(implode(PHP_EOL, $help));
}
}

View File

@ -12,15 +12,20 @@
* ---------------------------------------------------------------------------- */
/**
* Errors Controller
* Errors controller
*
* Handles the app error related operations.
*
* @package Controllers
*/
class Errors extends EA_Controller {
/**
* Errors constructor.
*/
public function __construct()
{
parent::__construct();
$this->load->helper('google_analytics');
$this->load->model('settings_model');
}
@ -37,8 +42,8 @@ class Errors extends EA_Controller {
*/
public function error404()
{
$view['company_name'] = $this->settings_model->get_setting('company_name');
$this->load->view('general/error404', $view);
$this->load->view('general/error404', [
'company_name' => setting('company_name')
]);
}
}

View File

@ -12,9 +12,9 @@
* ---------------------------------------------------------------------------- */
/**
* Google Controller
* Google controller
*
* This controller handles the Google Calendar synchronization operations.
* Handles the Google Calendar synchronization related operations.
*
* @package Controllers
*/
@ -42,18 +42,10 @@ class Google extends EA_Controller {
{
try
{
/** @var EA_Controller $CI */
$CI = get_instance();
// The user must be logged in.
if ($CI->session->userdata('user_id') == FALSE && is_cli() === FALSE)
{
return;
}
if ($provider_id === NULL)
{
throw new Exception('Provider id not specified.');
}
$CI->load->library('google_sync');
$CI->load->model('appointments_model');
$CI->load->model('providers_model');
@ -61,38 +53,54 @@ class Google extends EA_Controller {
$CI->load->model('customers_model');
$CI->load->model('settings_model');
$provider = $CI->providers_model->get_row($provider_id);
$user_id = session('user_id');
// Check whether the selected provider has google sync enabled.
$google_sync = $CI->providers_model->get_setting('google_sync', $provider['id']);
if ( ! $user_id && ! is_cli())
{
return;
}
if ( ! $provider_id)
{
throw new InvalidArgumentException('No provider ID provided.');
}
$provider = $CI->providers_model->find($provider_id);
// Check whether the selected provider has the Google Sync enabled.
$google_sync = $CI->providers_model->get_setting($provider['id'], 'google_sync');
if ( ! $google_sync)
{
throw new Exception('The selected provider has not the google synchronization setting enabled.');
}
$google_token = json_decode($CI->providers_model->get_setting('google_token', $provider['id']));
$CI->load->library('google_sync');
$google_token = json_decode($CI->providers_model->get_setting($provider['id'], 'google_token'));
$CI->google_sync->refresh_token($google_token->refresh_token);
// Fetch provider's appointments that belong to the sync time period.
$sync_past_days = $CI->providers_model->get_setting('sync_past_days', $provider['id']);
$sync_future_days = $CI->providers_model->get_setting('sync_future_days', $provider['id']);
$sync_past_days = $CI->providers_model->get_setting($provider['id'], 'sync_past_days');
$sync_future_days = $CI->providers_model->get_setting($provider['id'], 'sync_future_days');
$start = strtotime('-' . $sync_past_days . ' days', strtotime(date('Y-m-d')));
$end = strtotime('+' . $sync_future_days . ' days', strtotime(date('Y-m-d')));
$where_clause = [
$where = [
'start_datetime >=' => date('Y-m-d H:i:s', $start),
'end_datetime <=' => date('Y-m-d H:i:s', $end),
'id_users_provider' => $provider['id']
];
$appointments = $CI->appointments_model->get_batch($where_clause);
$appointments = $CI->appointments_model->get($where);
$company_settings = [
'company_name' => $CI->settings_model->get_setting('company_name'),
'company_link' => $CI->settings_model->get_setting('company_link'),
'company_email' => $CI->settings_model->get_setting('company_email')
$settings = [
'company_name' => setting('company_name'),
'company_link' => setting('company_link'),
'company_email' => setting('company_email')
];
$provider_timezone = new DateTimeZone($provider['timezone']);
@ -102,8 +110,8 @@ class Google extends EA_Controller {
{
if ($appointment['is_unavailable'] == FALSE)
{
$service = $CI->services_model->get_row($appointment['id_services']);
$customer = $CI->customers_model->get_row($appointment['id_users_customer']);
$service = $CI->services_model->find($appointment['id_services']);
$customer = $CI->customers_model->find($appointment['id_users_customer']);
}
else
{
@ -114,14 +122,15 @@ class Google extends EA_Controller {
// If current appointment not synced yet, add to Google Calendar.
if ($appointment['id_google_calendar'] == NULL)
{
$google_event = $CI->google_sync->add_appointment($appointment, $provider,
$service, $customer, $company_settings);
$google_event = $CI->google_sync->add_appointment($appointment, $provider, $service, $customer, $settings);
$appointment['id_google_calendar'] = $google_event->id;
$CI->appointments_model->add($appointment); // Save the Google Calendar ID.
$CI->appointments_model->save($appointment); // Save the Google Calendar ID.
}
else
{
// Appointment is synced with google calendar.
// Appointment is synced with Google Calendar.
try
{
$google_event = $CI->google_sync->get_event($provider, $appointment['id_google_calendar']);
@ -134,33 +143,31 @@ class Google extends EA_Controller {
// If Google Calendar event is different from Easy!Appointments appointment then update
// Easy!Appointments record.
$is_different = FALSE;
$appt_start = strtotime($appointment['start_datetime']);
$appt_end = strtotime($appointment['end_datetime']);
$appointment_start = strtotime($appointment['start_datetime']);
$appointment_end = strtotime($appointment['end_datetime']);
$event_start = new DateTime($google_event->getStart()->getDateTime());
$event_start->setTimezone($provider_timezone);
$event_end = new DateTime($google_event->getEnd()->getDateTime());
$event_end->setTimezone($provider_timezone);
if ($appt_start != $event_start->getTimestamp() || $appt_end != $event_end->getTimestamp()
|| $appointment['notes'] !== $google_event->getDescription())
{
$is_different = TRUE;
}
$is_different = $appointment_start !== $event_start->getTimestamp()
|| $appointment_end !== $event_end->getTimestamp()
|| $appointment['notes'] !== $google_event->getDescription();
if ($is_different)
{
$appointment['start_datetime'] = $event_start->format('Y-m-d H:i:s');
$appointment['end_datetime'] = $event_end->format('Y-m-d H:i:s');
$appointment['notes'] = $google_event->getDescription();
$CI->appointments_model->add($appointment);
$CI->appointments_model->save($appointment);
}
}
catch (Exception $exception)
catch (Throwable $e)
{
// Appointment not found on Google Calendar, delete from Easy!Appoinmtents.
// Appointment not found on Google Calendar, delete from Easy!Appointments.
$CI->appointments_model->delete($appointment['id']);
$appointment['id_google_calendar'] = NULL;
}
}
@ -168,6 +175,7 @@ class Google extends EA_Controller {
// Add Google Calendar events that do not exist in Easy!Appointments.
$google_calendar = $provider['settings']['google_calendar'];
$google_events = $CI->google_sync->get_sync_events($google_calendar, $start, $end);
foreach ($google_events->getItems() as $google_event)
@ -197,14 +205,13 @@ class Google extends EA_Controller {
$event_end->setTimezone($provider_timezone);
}
$results = $CI->appointments_model->get_batch(['id_google_calendar' => $google_event->getId()]);
$results = $CI->appointments_model->get(['id_google_calendar' => $google_event->getId()]);
if ( ! empty($results))
{
continue;
}
// Record doesn't exist in the Easy!Appointments, so add the event now.
$appointment = [
'start_datetime' => $event_start->format('Y-m-d H:i:s'),
@ -218,24 +225,17 @@ class Google extends EA_Controller {
'id_services' => NULL,
];
$CI->appointments_model->add($appointment);
$CI->appointments_model->save($appointment);
}
$response = AJAX_SUCCESS;
json_response([
'success' => TRUE
]);
}
catch (Exception $exception)
catch (Throwable $e)
{
$CI->output->set_status_header(500);
$response = [
'message' => $exception->getMessage(),
'trace' => config('debug') ? $exception->getTrace() : []
];
json_exception($e);
}
$CI->output
->set_content_type('application/json')
->set_output(json_encode($response));
}
/**
@ -246,10 +246,10 @@ class Google extends EA_Controller {
*
* @param int $provider_id The provider id, for whom the sync authorization is made.
*/
public function oauth($provider_id)
public function oauth(int $provider_id)
{
// Store the provider id for use on the callback function.
$this->session->set_userdata('oauth_provider_id', $provider_id);
session(['oauth_provider_id' => $provider_id]);
// Redirect browser to google user content page.
header('Location: ' . $this->google_sync->get_auth_url());
@ -268,11 +268,12 @@ class Google extends EA_Controller {
*/
public function oauth_callback()
{
$code = $this->input->get('code');
$code = request('code');
if (empty($code))
{
$this->output->set_output('Code authorization failed.');
response('Code authorization failed.');
return;
}
@ -280,24 +281,23 @@ class Google extends EA_Controller {
if (empty($token))
{
$this->output->set_output('Token authorization failed.');
response('Token authorization failed.');
return;
}
// Store the token into the database for future reference.
$oauth_provider_id = $this->session->userdata('oauth_provider_id');
$oauth_provider_id = session('oauth_provider_id');
if ($oauth_provider_id)
{
$this->providers_model->set_setting('google_sync', TRUE, $oauth_provider_id);
$this->providers_model->set_setting('google_token', json_encode($token), $oauth_provider_id);
$this->providers_model->set_setting('google_calendar', 'primary', $oauth_provider_id);
$this->providers_model->set_setting($oauth_provider_id, 'google_sync', TRUE);
$this->providers_model->set_setting($oauth_provider_id, 'google_token', json_encode($token));
$this->providers_model->set_setting($oauth_provider_id, 'google_calendar', 'primary');
}
else
{
$this->output->set_output('Sync provider id not specified.');
response('Sync provider id not specified.');
}
}
}

View File

@ -12,9 +12,9 @@
* ---------------------------------------------------------------------------- */
/**
* Installation Controller
* Installation controller
*
* This controller will handle the installation procedure of Easy!Appointments.
* Handles the installation related operations.
*
* @package Controllers
*/
@ -25,14 +25,14 @@ class Installation extends EA_Controller {
public function __construct()
{
parent::__construct();
$this->load->model('admins_model');
$this->load->model('settings_model');
$this->load->model('services_model');
$this->load->model('providers_model');
$this->load->model('customers_model');
$this->load->library('migration');
$this->load->helper('installation');
$this->load->helper('string');
}
/**
@ -42,7 +42,7 @@ class Installation extends EA_Controller {
{
if (is_app_installed())
{
redirect('appointments');
redirect('');
return;
}
@ -63,8 +63,8 @@ class Installation extends EA_Controller {
return;
}
$admin = $this->input->post('admin');
$company = $this->input->post('company');
$admin = request('admin');
$company = request('company');
if ( ! $this->migration->current())
{
@ -78,21 +78,25 @@ class Installation extends EA_Controller {
$admin['settings']['notifications'] = TRUE;
$admin['settings']['calendar_view'] = CALENDAR_VIEW_DEFAULT;
unset($admin['username'], $admin['password']);
$admin['id'] = $this->admins_model->add($admin);
$admin['id'] = $this->admins_model->save($admin);
$this->session->set_userdata('user_id', $admin['id']);
$this->session->set_userdata('user_email', $admin['email']);
$this->session->set_userdata('role_slug', DB_SLUG_ADMIN);
$this->session->set_userdata('timezone', $admin['timezone']);
$this->session->set_userdata('username', $admin['settings']['username']);
session([
'user_id' => $admin['id'],
'user_email' => $admin['email'],
'role_slug' => DB_SLUG_ADMIN,
'timezone' => $admin['timezone'],
'username' => $admin['settings']['username']
]);
// Save company settings
$this->settings_model->set_setting('company_name', $company['company_name']);
$this->settings_model->set_setting('company_email', $company['company_email']);
$this->settings_model->set_setting('company_link', $company['company_link']);
setting([
'company_name' => $company['company_name'],
'company_email' => $company['company_email'],
'company_link' => $company['company_link'],
]);
// Service
$service_id = $this->services_model->add([
$service_id = $this->services_model->save([
'name' => 'Service',
'duration' => '30',
'price' => '0',
@ -102,7 +106,7 @@ class Installation extends EA_Controller {
]);
// Provider
$this->providers_model->add([
$this->providers_model->save([
'first_name' => 'Jane',
'last_name' => 'Doe',
'email' => 'jane@example.org',
@ -113,7 +117,7 @@ class Installation extends EA_Controller {
'settings' => [
'username' => 'janedoe',
'password' => 'janedoe',
'working_plan' => $this->settings_model->get_setting('company_working_plan'),
'working_plan' => setting('company_working_plan'),
'notifications' => TRUE,
'google_sync' => FALSE,
'sync_past_days' => 30,
@ -123,27 +127,20 @@ class Installation extends EA_Controller {
]);
// Customer
$this->customers_model->add([
$this->customers_model->save([
'first_name' => 'James',
'last_name' => 'Doe',
'email' => 'james@example.org',
'phone_number' => '+1 (000) 000-0000',
]);
$response = AJAX_SUCCESS;
json_response([
'success' => true
]);
}
catch (Exception $exception)
catch (Throwable $e)
{
$this->output->set_status_header(500);
$response = [
'message' => $exception->getMessage(),
'trace' => config('debug') ? $exception->getTrace() : []
];
json_exception($e);
}
$this->output
->set_content_type('application/json')
->set_output(json_encode($response));
}
}

View File

@ -12,7 +12,9 @@
* ---------------------------------------------------------------------------- */
/**
* Class Privacy
* Privacy controller
*
* Handles the privacy related operations.
*
* @package Controllers
*/
@ -23,18 +25,20 @@ class Privacy extends EA_Controller {
public function __construct()
{
parent::__construct();
$this->load->driver('cache', ['adapter' => 'file']);
$this->load->model('customers_model');
}
/**
* Remove all customer data (including appointments from the system).
* Remove all customer data (including appointments) from the system.
*/
public function ajax_delete_personal_information()
{
try
{
$customer_token = $this->input->post('customer_token');
$customer_token = request('customer_token');
if (empty($customer_token))
{
@ -45,28 +49,19 @@ class Privacy extends EA_Controller {
if (empty($customer_id))
{
throw new InvalidArgumentException('Customer ID could not be found, please reload the page '
throw new InvalidArgumentException('Customer ID does not exist, please reload the page '
. 'and try again.');
}
$this->customers_model->delete($customer_id);
$response = [
json_response([
'success' => TRUE
];
]);
}
catch (Exception $exception)
catch (Throwable $e)
{
$this->output->set_status_header(500);
$response = [
'message' => $exception->getMessage(),
'trace' => config('debug') ? $exception->getTrace() : []
];
json_exception($e);
}
$this->output
->set_content_type('application/json')
->set_output(json_encode($response));
}
}

View File

@ -16,7 +16,9 @@ use EA\Engine\Types\Email;
use EA\Engine\Types\NonEmptyText;
/**
* User Controller
* User controller
*
* Handles the user related operations.
*
* @package Controllers
*/
@ -27,38 +29,28 @@ class User extends EA_Controller {
public function __construct()
{
parent::__construct();
$this->load->model('settings_model');
$this->load->model('user_model');
$this->load->library('accounts');
}
/**
* Default Method
*
* The default method will redirect the browser to the user/login URL.
* Redirect to the login page.
*/
public function index()
{
header('Location: ' . site_url('user/login'));
redirect('user/login');
}
/**
* Display the login page.
*
* @throws Exception
*/
public function login()
{
$view['base_url'] = config('base_url');
$view['dest_url'] = $this->session->userdata('dest_url');
if ( ! $view['dest_url'])
{
$view['dest_url'] = site_url('backend');
}
$view['company_name'] = $this->settings_model->get_setting('company_name');
$this->load->view('user/login', $view);
$this->load->view('user/login', [
'base_url' => config('base_url'),
'company_name' => setting('company_name'),
'dest_url' => session('dest_url', site_url('backend'))
]);
}
/**
@ -66,62 +58,57 @@ class User extends EA_Controller {
*/
public function logout()
{
$this->session->unset_userdata('user_id');
$this->session->unset_userdata('user_email');
$this->session->unset_userdata('role_slug');
$this->session->unset_userdata('username');
$this->session->unset_userdata('dest_url');
$this->session->sess_destroy();
$view['base_url'] = config('base_url');
$view['company_name'] = $this->settings_model->get_setting('company_name');
$this->load->view('user/logout', $view);
$this->load->view('user/logout', [
'base_url' => config('base_url'),
'company_name' => setting('company_name')
]);
}
/**
* Display the "forgot password" page.
* @throws Exception
* Display the password recovery page.
*/
public function forgot_password()
{
$view['base_url'] = config('base_url');
$view['company_name'] = $this->settings_model->get_setting('company_name');
$this->load->view('user/forgot_password', $view);
$this->load->view('user/forgot_password', [
'base_url' => config('base_url'),
'company_name' => setting('company_name')
]);
}
/**
* Display the "not authorized" page.
* @throws Exception
* Display the no-permissions page.
*/
public function no_privileges()
public function no_permissions()
{
$view['base_url'] = config('base_url');
$view['company_name'] = $this->settings_model->get_setting('company_name');
$this->load->view('user/no_privileges', $view);
$this->load->view('user/no_privileges', [
'base_url' => config('base_url'),
'company_name' => setting('company_name')
]);
}
/**
* Check whether the user has entered the correct login credentials.
*
* The session data of a logged in user are the following:
* - 'user_id'
* - 'user_email'
* - 'role_slug'
* - 'dest_url'
* Validate the login credentials and if successful, log the user in.
*/
public function ajax_check_login()
{
try
{
if ( ! $this->input->post('username') || ! $this->input->post('password'))
if ( ! request('username') || ! request('password'))
{
throw new Exception('Invalid credentials given!');
}
$user_data = $this->user_model->check_login($this->input->post('username'), $this->input->post('password'));
$username = request('username');
$password = request('password');
$user_data = $this->accounts->check_login($username, $password);
if ($user_data)
{
$this->session->set_userdata($user_data); // Save data on user's session.
session($user_data); // Save data in the session.
$response = AJAX_SUCCESS;
}
@ -130,13 +117,13 @@ class User extends EA_Controller {
$response = AJAX_FAILURE;
}
}
catch (Exception $exception)
catch (Throwable $e)
{
$this->output->set_status_header(500);
$response = [
'message' => $exception->getMessage(),
'trace' => config('debug') ? $exception->getTrace() : []
'message' => $e->getMessage(),
'trace' => config('debug') ? $e->getTrace() : []
];
}
@ -146,59 +133,51 @@ class User extends EA_Controller {
}
/**
* Regenerate a new password for the current user, only if the username and
* email address given correspond to an existing user in db.
*
* Required POST Parameters:
*
* - string $_POST['username'] Username to be validated.
* - string $_POST['email'] Email to be validated.
* Recover the user password and notify the user via email.
*/
public function ajax_forgot_password()
{
try
{
if ( ! $this->input->post('username') || ! $this->input->post('email'))
$username = request('username');
if (empty($username))
{
throw new Exception('You must enter a valid username and email address in '
. 'order to get a new password!');
throw new InvalidArgumentException('No username value provided.');
}
$new_password = $this->user_model->regenerate_password(
$this->input->post('username'),
$this->input->post('email')
$email = request('email');
if (empty($email))
{
throw new InvalidArgumentException('No email value provided.');
}
$new_password = $this->accounts->regenerate_password(
$username,
$email
);
if ($new_password != FALSE)
if ($new_password)
{
$this->config->load('email');
$email = new EmailClient($this, $this->config->config);
$company_settings = [
'company_name' => $this->settings_model->get_setting('company_name'),
'company_link' => $this->settings_model->get_setting('company_link'),
'company_email' => $this->settings_model->get_setting('company_email')
$settings = [
'company_name' => setting('company_name'),
'company_link' => setting('company_link'),
'company_email' => setting('company_email')
];
$email->send_password(new NonEmptyText($new_password), new Email($this->input->post('email')),
$company_settings);
$email->send_password(new NonEmptyText($new_password), new Email(request('email')), $settings);
}
$response = $new_password != FALSE ? AJAX_SUCCESS : AJAX_FAILURE;
json_response([
'success' => TRUE
]);
}
catch (Exception $exception)
catch (Throwable $e)
{
$this->output->set_status_header(500);
$response = [
'message' => $exception->getMessage(),
'trace' => config('debug') ? $exception->getTrace() : []
];
json_exception($e);
}
$this->output
->set_content_type('application/json')
->set_output(json_encode($response));
}
}