iflrandevu/src/application/controllers/google.php

188 lines
8.5 KiB
PHP
Raw Normal View History

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Google extends CI_Controller {
/**
* Authorize Google Calendar API usage for a specific provider.
*
* Since it is required to follow the web application flow, in order to retrieve
* a refresh token from the Google API service, this method is going to authorize
* the given provider.
*
* @param int $provider_id The provider id, for whom the sync authorization is
* made.
*/
public function oauth($provider_id) {
// Store the provider id for use on the callback function.
if (!isset($_SESSION)) {
@session_start();
}
$_SESSION['oauth_provider_id'] = $provider_id;
// Redirect browser to google user content page.
$this->load->library('Google_Sync');
header('Location: ' . $this->google_sync->get_auth_url());
}
/**
* Callback method for the Google Calendar API authorization process.
*
* Once the user grants consent with his Google Calendar data usage, the Google
* OAuth service will redirect him back in this page. Here we are going to store
* the refresh token, because this is what will be used to generate access tokens
* in the future.
*
* <strong>IMPORTANT!</strong> 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.
*/
public function oauth_callback() {
if (isset($_GET['code'])) {
$this->load->library('Google_Sync');
$token = $this->google_sync->authenticate($_GET['code']);
// Store the token into the database for future reference.
if (!isset($_SESSION)) {
@session_start();
}
if (isset($_SESSION['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']);
} else {
echo '<h1>Sync provider id not specified!</h1>';
}
} else {
echo '<h1>Authorization Failed!</h1>';
}
}
/**
* Complete synchronization of appointments between Google Calendar and Easy!Appointments.
*
* This method will completely sync the appointments of a provider with his Google Calendar
* account. The sync period needs to be relatively small, because a lot of API calls might
* be necessary and this will lead to consuming the Google limit for the Calendar API usage.
*
* @param numeric $provider_id Provider record to be synced.
*
* @task This method must be executed only by the system and noone else outside. It is a big security issue.
*/
public function sync($provider_id = NULL) {
try {
if ($provider_id === NULL) {
throw new Exception('Provider id not specified.');
}
$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');
$provider = $this->providers_model->get_row($provider_id);
// Check whether the selected provider has google sync enabled.
$google_sync = $this->providers_model->get_setting('google_sync', $provider['id']);
if (!$google_sync) {
throw new Exception('The selected provider has not the google synchronization '
. 'setting enabled.');
}
$google_token = json_decode($this->providers_model->get_setting('google_token', $provider['id']));
$this->load->library('google_sync');
$this->google_sync->refresh_token($google_token->refresh_token);
// Fetch provider's appointments that belong to the sync time period.
$sync_past_days = $this->providers_model->get_setting('sync_past_days', $provider['id']);
$sync_future_days = $this->providers_model->get_setting('sync_future_days', $provider['id']);
$start = strtotime('-' . $sync_past_days . ' days', strtotime(date('Y-m-d')));
$end = strtotime('+' . $sync_future_days . ' days', strtotime(date('Y-m-d')));
$where_clause = array(
'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'],
'is_unavailable' => FALSE
);
$appointments = $this->appointments_model->get_batch($where_clause);
$company_settings = array(
'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')
);
// Sync each appointment with Google Calendar by following the project's sync
// protocol (see documentation).
foreach($appointments as $appointment) {
$service = $this->services_model->get_row($appointment['id_services']);
$customer = $this->customers_model->get_row($appointment['id_users_customer']);
// :: APPOINTMENT WITH NO GCAL_ID -> ADD TO GCAL
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
}
// :: SYNCED APPOINTMENT NOT FOUND ON GCAL -> DELETE E!A RECORD
if ($appointment['id_google_calendar'] != NULL) {
try {
$google_event = $this->google_sync->get_event($appointment['id_google_calendar']);
} catch(Exception $exc) {
$this->appointments_model->delete($appointment['id']);
$appointment['id_google_calendar'] = NULL; // Do not proceed with the rest sync actions.
}
}
// :: SYNCED APPOINTMENT DIFFERENT FROM GCAL EVENT -> UPDATE E!A RECORD
if ($appointment['id_google_calendar'] != NULL) {
$is_different = FALSE;
$appt_start = strtotime($appointment['start_datetime']);
$appt_end = strtotime($appointment['end_datetime']);
$event_start = strtotime($google_event->getStart()->getDateTime());
$event_end = strtotime($google_event->getEnd()->getDateTime());
if ($appt_start != $event_start
|| $appt_end != $event_end) {
$is_different = TRUE;
}
if ($is_different) {
$appointment['start_datetime'] = date('Y-m-d H:i:s', $event_start);
$appointment['end_datetime'] = date('Y-m-d H:i:s', $event_end);
$this->appointments_model->add($appointment);
}
}
// @task :: GCAL EVENT NOT FOUND ON E!A -> ADD EVENT TO E!A
}
// @task Sync unavailable periods with Google Calendar
echo json_encode('SUCCESS');
} catch(Exception $exc) {
echo json_encode(array(
'exceptions' => array($exc)
));
}
}
}
/* End of file google.php */
/* Location: ./application/controllers/google.php */