From a895343e0a8cdf75403dcb69699139f2a3088104 Mon Sep 17 00:00:00 2001 From: Patrick Zeitz Date: Fri, 23 Aug 2024 13:56:21 +0200 Subject: [PATCH] format --- application/libraries/Google_sync.php | 635 ++++++++++++-------------- 1 file changed, 282 insertions(+), 353 deletions(-) diff --git a/application/libraries/Google_sync.php b/application/libraries/Google_sync.php index bb2bc236..d8507504 100644 --- a/application/libraries/Google_sync.php +++ b/application/libraries/Google_sync.php @@ -1,155 +1,139 @@ +* @copyright Copyright (c) Alex Tselegidis +* @license https://opensource.org/licenses/GPL-3.0 - GPLv3 +* @link https://easyappointments.org +* @since v1.0.0 +* ---------------------------------------------------------------------------- */ -/* ---------------------------------------------------------------------------- - * Easy!Appointments - Online Appointment Scheduler - * - * @package EasyAppointments - * @author A.Tselegidis - * @copyright Copyright (c) Alex Tselegidis - * @license https://opensource.org/licenses/GPL-3.0 - GPLv3 - * @link https://easyappointments.org - * @since v1.0.0 - * ---------------------------------------------------------------------------- */ - -use Google\Service\Calendar\Event; +use Google\Service\Calendar\Event; use Google\Service\Calendar\Events; -/** - * Google sync library. - * - * Handles Google Calendar API related functionality. - * - * @package Libraries - */ -class Google_sync -{ - /** - * @var EA_Controller|CI_Controller - */ +/** + * Google sync library. + * + * Handles Google Calendar API related functionality. + * + * @package Libraries + */ +class Google_sync +{ + /** + * @var EA_Controller|CI_Controller + */ protected EA_Controller|CI_Controller $CI; - - /** - * @var Google_Client - */ + /** + * @var Google_Client + */ protected Google_Client $client; - - /** - * @var Google_Service_Calendar - */ + /** + * @var Google_Service_Calendar + */ protected Google_Service_Calendar $service; - - /** - * Google_sync constructor. - * - * This method initializes the Google client class and the Calendar service class so that they can be used by the - * other methods. - */ - public function __construct() - { + /** + * Google_sync constructor. + * + * This method initializes the Google client class and the Calendar service class so that they can be used by the + * other methods. + */ + public function __construct() + { $this->CI = &get_instance(); - - $this->CI->load->model('appointments_model'); - $this->CI->load->model('customers_model'); - $this->CI->load->model('providers_model'); + $this->CI->load->model('appointments_model'); + $this->CI->load->model('customers_model'); + $this->CI->load->model('providers_model'); $this->CI->load->model('services_model'); - - $this->initialize_clients(); - } - - /** - * Initialize the client, so that existing execution errors are not passed from one provider to another. - */ - public function initialize_clients(): void - { - $http = new GuzzleHttp\Client([ - 'verify' => false, - ]); - - $this->client = new Google_Client(); - $this->client->setHttpClient($http); - $this->client->setApplicationName('Easy!Appointments'); - $this->client->setClientId(config('google_client_id')); - $this->client->setClientSecret(config('google_client_secret')); - $this->client->setRedirectUri(site_url('google/oauth_callback')); - $this->client->setPrompt('consent'); - $this->client->setAccessType('offline'); - $this->client->addScope([Google_Service_Calendar::CALENDAR]); - - $this->service = new Google_Service_Calendar($this->client); - } - - /** - * Get Google OAuth authorization url. - * - * This url must be used to redirect the user to the Google user consent page, - * where the user grants access to his data for the Easy!Appointments app. - */ - public function get_auth_url(): string - { - // The "max_auth_age" is needed because the user needs to always log in and not use an existing session. - return $this->client->createAuthUrl() . '&max_auth_age=0'; - } - - /** - * Authenticate the Google API usage. - * - * When the user grants consent for his data usage, Google is going to redirect the browser back to the given - * redirect URL. There an authentication code is provided. Using this code, we can authenticate the API usage and - * store the token information to the database. - * - * @param string $code - * - * @return array - * - * @throws Exception - */ - public function authenticate(string $code): array - { - $response = $this->client->fetchAccessTokenWithAuthCode($code); - - if (isset($response['error'])) { - throw new RuntimeException( - 'Google Authentication Error (' . $response['error'] . '): ' . $response['error_description'], - ); - } - - return $response; - } - - /** - * Refresh the Google Client access token. - * - * This method must be executed every time we need to make actions on a provider's Google Calendar account. A new - * token is necessary and the only way to get it is to use the stored refresh token that was provided when the - * provider granted consent to Easy!Appointments for use his Google Calendar account. - * - * @param string $refresh_token The provider's refresh token. This value is stored in the database and used every - * time we need to make actions to his Google Calendar account. - */ - public function refresh_token(string $refresh_token): void - { $this->initialize_clients(); - - $this->client->refreshToken($refresh_token); } - - /** - * 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. - * - * @param array $appointment Appointment data. - * @param array $provider Provider data. - * @param array $service Service data. - * @param array $customer Customer data. - * @param array $settings Required settings. - * - * @return Event Returns the Google_Event class object. - * - * @throws Exception - */ + /** + * Initialize the client, so that existing execution errors are not passed from one provider to another. + */ + public function initialize_clients(): void + { + $http = new GuzzleHttp\Client([ + 'verify' => false, + ]); + $this->client = new Google_Client(); + $this->client->setHttpClient($http); + $this->client->setApplicationName('Easy!Appointments'); + $this->client->setClientId(config('google_client_id')); + $this->client->setClientSecret(config('google_client_secret')); + $this->client->setRedirectUri(site_url('google/oauth_callback')); + $this->client->setPrompt('consent'); + $this->client->setAccessType('offline'); + $this->client->addScope([Google_Service_Calendar::CALENDAR]); + $this->service = new Google_Service_Calendar($this->client); + } + /** + * Get Google OAuth authorization url. + * + * This url must be used to redirect the user to the Google user consent page, + * where the user grants access to his data for the Easy!Appointments app. + */ + public function get_auth_url(): string + { + // The "max_auth_age" is needed because the user needs to always log in and not use an existing session. + return $this->client->createAuthUrl() . '&max_auth_age=0'; + } + /** + * Authenticate the Google API usage. + * + * When the user grants consent for his data usage, Google is going to redirect the browser back to the given + * redirect URL. There an authentication code is provided. Using this code, we can authenticate the API usage and + * store the token information to the database. + * + * @param string $code + * + * @return array + * + * @throws Exception + */ + public function authenticate(string $code): array + { + $response = $this->client->fetchAccessTokenWithAuthCode($code); + if (isset($response['error'])) { + throw new RuntimeException( + 'Google Authentication Error (' . $response['error'] . '): ' . $response['error_description'], + ); + } + return $response; + } + /** + * Refresh the Google Client access token. + * + * This method must be executed every time we need to make actions on a provider's Google Calendar account. A new + * token is necessary and the only way to get it is to use the stored refresh token that was provided when the + * provider granted consent to Easy!Appointments for use his Google Calendar account. + * + * @param string $refresh_token The provider's refresh token. This value is stored in the database and used every + * time we need to make actions to his Google Calendar account. + */ + public function refresh_token(string $refresh_token): void + { + $this->initialize_clients(); + $this->client->refreshToken($refresh_token); + } + /** + * 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. + * + * @param array $appointment Appointment data. + * @param array $provider Provider data. + * @param array $service Service data. + * @param array $customer Customer data. + * @param array $settings Required settings. + * + * @return Event Returns the Google_Event class object. + * + * @throws Exception + */ public function add_appointment( array $appointment, array $provider, @@ -161,33 +145,26 @@ class Google_sync $event->setSummary(!empty($service) ? $service['name'] : 'Unavailable'); $event->setDescription($appointment['notes']); $event->setLocation($appointment['location'] ?? $settings['company_name']); - $timezone = new DateTimeZone($provider['timezone']); - $start = new Google_Service_Calendar_EventDateTime(); $start->setDateTime( (new DateTime($appointment['start_datetime'], $timezone))->format(DateTimeInterface::RFC3339), ); $event->setStart($start); - $end = new Google_Service_Calendar_EventDateTime(); $end->setDateTime((new DateTime($appointment['end_datetime'], $timezone))->format(DateTimeInterface::RFC3339)); $event->setEnd($end); - $event->attendees = []; - $event_provider = new Google_Service_Calendar_EventAttendee(); $event_provider->setDisplayName($provider['first_name'] . ' ' . $provider['last_name']); $event_provider->setEmail($provider['email']); $event->attendees[] = $event_provider; - if (!empty($customer['first_name']) && !empty($customer['last_name']) && !empty($customer['email'])) { $event_customer = new Google_Service_Calendar_EventAttendee(); $event_customer->setDisplayName($customer['first_name'] . ' ' . $customer['last_name']); $event_customer->setEmail($customer['email']); $event->attendees[] = $event_customer; } - // Add Google Meet link $conferenceData = new Google_Service_Calendar_ConferenceData(); $createRequest = new Google_Service_Calendar_CreateConferenceRequest(); @@ -197,7 +174,6 @@ class Google_sync $createRequest->setConferenceSolutionKey($solutionKey); $conferenceData->setCreateRequest($createRequest); $event->setConferenceData($conferenceData); - // Add the new event to the Google Calendar. return $this->service->events->insert( $provider['settings']['google_calendar'], @@ -205,24 +181,22 @@ class Google_sync ['conferenceDataVersion' => 1] ); } - - - /** - * Update an existing appointment that is already synced with Google Calendar. - * - * This method updates the Google Calendar event item that is connected with the provided appointment record of - * Easy!Appointments. - * - * @param array $appointment Appointment data. - * @param array $provider Provider data. - * @param array $service Service data. - * @param array $customer Customer data. - * @parma array $settings Required settings. - * - * @return Event Returns the Google_Service_Calendar_Event class object. - * - * @throws Exception - */ + /** + * Update an existing appointment that is already synced with Google Calendar. + * + * This method updates the Google Calendar event item that is connected with the provided appointment record of + * Easy!Appointments. + * + * @param array $appointment Appointment data. + * @param array $provider Provider data. + * @param array $service Service data. + * @param array $customer Customer data. + * @parma array $settings Required settings. + * + * @return Event Returns the Google_Service_Calendar_Event class object. + * + * @throws Exception + */ public function update_appointment( array $appointment, array $provider, @@ -234,37 +208,29 @@ class Google_sync $provider['settings']['google_calendar'], $appointment['id_google_calendar'], ); - $event->setSummary($service['name']); $event->setDescription($appointment['notes']); $event->setLocation($appointment['location'] ?? $settings['company_name']); - $timezone = new DateTimeZone($provider['timezone']); - $start = new Google_Service_Calendar_EventDateTime(); $start->setDateTime( (new DateTime($appointment['start_datetime'], $timezone))->format(DateTimeInterface::RFC3339), ); $event->setStart($start); - $end = new Google_Service_Calendar_EventDateTime(); $end->setDateTime((new DateTime($appointment['end_datetime'], $timezone))->format(DateTimeInterface::RFC3339)); $event->setEnd($end); - $event->attendees = []; - $event_provider = new Google_Service_Calendar_EventAttendee(); $event_provider->setDisplayName($provider['first_name'] . ' ' . $provider['last_name']); $event_provider->setEmail($provider['email']); $event->attendees[] = $event_provider; - if (!empty($customer['first_name']) && !empty($customer['last_name']) && !empty($customer['email'])) { $event_customer = new Google_Service_Calendar_EventAttendee(); $event_customer->setDisplayName($customer['first_name'] . ' ' . $customer['last_name']); $event_customer->setEmail($customer['email']); $event->attendees[] = $event_customer; } - // Add or update Google Meet link if (!$event->getConferenceData()) { $conferenceData = new Google_Service_Calendar_ConferenceData(); @@ -276,7 +242,6 @@ class Google_sync $conferenceData->setCreateRequest($createRequest); $event->setConferenceData($conferenceData); } - return $this->service->events->update( $provider['settings']['google_calendar'], $event->getId(), @@ -284,213 +249,177 @@ class Google_sync ['conferenceDataVersion' => 1] ); } - - /** - * Delete an existing appointment from Google Calendar. - * - * @param array $provider Provider data. - * @param string $google_event_id The Google Calendar event ID to be removed. - */ - public function delete_appointment(array $provider, string $google_event_id): void - { - $this->service->events->delete($provider['settings']['google_calendar'], $google_event_id); + /** + * Delete an existing appointment from Google Calendar. + * + * @param array $provider Provider data. + * @param string $google_event_id The Google Calendar event ID to be removed. + */ + public function delete_appointment(array $provider, string $google_event_id): void + { + $this->service->events->delete($provider['settings']['google_calendar'], $google_event_id); } - - /** - * Add unavailability period event to Google Calendar. - * - * @param array $provider Provider data. - * @param array $unavailability Unavailable data. - * - * @return Google_Service_Calendar_Event Returns the Google event. - * - * @throws Exception - */ - public function add_unavailability(array $provider, array $unavailability): Google_Service_Calendar_Event - { - $event = new Google_Service_Calendar_Event(); - $event->setSummary('Unavailable'); + /** + * Add unavailability period event to Google Calendar. + * + * @param array $provider Provider data. + * @param array $unavailability Unavailable data. + * + * @return Google_Service_Calendar_Event Returns the Google event. + * + * @throws Exception + */ + public function add_unavailability(array $provider, array $unavailability): Google_Service_Calendar_Event + { + $event = new Google_Service_Calendar_Event(); + $event->setSummary('Unavailable'); $event->setDescription($unavailability['notes']); - $timezone = new DateTimeZone($provider['timezone']); - - $start = new Google_Service_Calendar_EventDateTime(); - $start->setDateTime( - (new DateTime($unavailability['start_datetime'], $timezone))->format(DateTimeInterface::RFC3339), - ); - $event->setStart($start); - - $end = new Google_Service_Calendar_EventDateTime(); - $end->setDateTime( - (new DateTime($unavailability['end_datetime'], $timezone))->format(DateTimeInterface::RFC3339), - ); - $event->setEnd($end); - - // Add the new event to the Google Calendar. - return $this->service->events->insert($provider['settings']['google_calendar'], $event); - } - - /** - * Update Google Calendar unavailability period event. - * - * @param array $provider Provider data. - * @param array $unavailability Unavailability data. - * - * @return Google_Service_Calendar_Event Returns the Google_Service_Calendar_Event object. - * - * @throws Exception - */ - public function update_unavailability(array $provider, array $unavailability): Google_Service_Calendar_Event - { - $event = $this->service->events->get( - $provider['settings']['google_calendar'], - $unavailability['id_google_calendar'], + $start = new Google_Service_Calendar_EventDateTime(); + $start->setDateTime( + (new DateTime($unavailability['start_datetime'], $timezone))->format(DateTimeInterface::RFC3339), ); - - $event->setSummary('Unavailable'); - $event->setDescription($unavailability['notes']); - - $timezone = new DateTimeZone($provider['timezone']); - - $start = new Google_Service_Calendar_EventDateTime(); - $start->setDateTime( - (new DateTime($unavailability['start_datetime'], $timezone))->format(DateTimeInterface::RFC3339), - ); $event->setStart($start); - - $end = new Google_Service_Calendar_EventDateTime(); - $end->setDateTime( - (new DateTime($unavailability['end_datetime'], $timezone))->format(DateTimeInterface::RFC3339), - ); + $end = new Google_Service_Calendar_EventDateTime(); + $end->setDateTime( + (new DateTime($unavailability['end_datetime'], $timezone))->format(DateTimeInterface::RFC3339), + ); $event->setEnd($end); - - return $this->service->events->update($provider['settings']['google_calendar'], $event->getId(), $event); + // Add the new event to the Google Calendar. + return $this->service->events->insert($provider['settings']['google_calendar'], $event); } - - /** - * Delete unavailability period event from Google Calendar. - * - * @param array $provider Provider data. - * @param string $google_event_id Google Calendar event ID to be removed. - */ - public function delete_unavailability(array $provider, string $google_event_id): void - { - $this->service->events->delete($provider['settings']['google_calendar'], $google_event_id); + /** + * Update Google Calendar unavailability period event. + * + * @param array $provider Provider data. + * @param array $unavailability Unavailability data. + * + * @return Google_Service_Calendar_Event Returns the Google_Service_Calendar_Event object. + * + * @throws Exception + */ + public function update_unavailability(array $provider, array $unavailability): Google_Service_Calendar_Event + { + $event = $this->service->events->get( + $provider['settings']['google_calendar'], + $unavailability['id_google_calendar'], + ); + $event->setSummary('Unavailable'); + $event->setDescription($unavailability['notes']); + $timezone = new DateTimeZone($provider['timezone']); + $start = new Google_Service_Calendar_EventDateTime(); + $start->setDateTime( + (new DateTime($unavailability['start_datetime'], $timezone))->format(DateTimeInterface::RFC3339), + ); + $event->setStart($start); + $end = new Google_Service_Calendar_EventDateTime(); + $end->setDateTime( + (new DateTime($unavailability['end_datetime'], $timezone))->format(DateTimeInterface::RFC3339), + ); + $event->setEnd($end); + return $this->service->events->update($provider['settings']['google_calendar'], $event->getId(), $event); } - - /** - * Get a Google Calendar event. - * - * @param array $provider Provider data. - * @param string $google_event_id Google Calendar event ID. - * - * @return Event Returns the Google Calendar event. - */ - public function get_event(array $provider, string $google_event_id): Event - { - return $this->service->events->get($provider['settings']['google_calendar'], $google_event_id); + /** + * Delete unavailability period event from Google Calendar. + * + * @param array $provider Provider data. + * @param string $google_event_id Google Calendar event ID to be removed. + */ + public function delete_unavailability(array $provider, string $google_event_id): void + { + $this->service->events->delete($provider['settings']['google_calendar'], $google_event_id); } - - /** - * Get all the events between the sync period. - * - * @param string $google_calendar The name of the Google Calendar to be used. - * @param string $start The start date of sync period. - * @param string $end The end date of sync period. - * - * @return Events Returns a collection of events. - */ - public function get_sync_events(string $google_calendar, string $start, string $end): Events - { - $params = [ - 'timeMin' => date(DateTimeInterface::RFC3339, $start), - 'timeMax' => date(DateTimeInterface::RFC3339, $end), - 'singleEvents' => true, + /** + * Get a Google Calendar event. + * + * @param array $provider Provider data. + * @param string $google_event_id Google Calendar event ID. + * + * @return Event Returns the Google Calendar event. + */ + public function get_event(array $provider, string $google_event_id): Event + { + return $this->service->events->get($provider['settings']['google_calendar'], $google_event_id); + } + /** + * Get all the events between the sync period. + * + * @param string $google_calendar The name of the Google Calendar to be used. + * @param string $start The start date of sync period. + * @param string $end The end date of sync period. + * + * @return Events Returns a collection of events. + */ + public function get_sync_events(string $google_calendar, string $start, string $end): Events + { + $params = [ + 'timeMin' => date(DateTimeInterface::RFC3339, $start), + 'timeMax' => date(DateTimeInterface::RFC3339, $end), + 'singleEvents' => true, ]; - - return $this->service->events->listEvents($google_calendar, $params); + return $this->service->events->listEvents($google_calendar, $params); } - - /** - * Return available Google Calendars for specific user. - * - * The given user's token must already exist in db in order to get access to his - * Google Calendar account. - * - * @return array Returns an array with the available calendars. - */ - public function get_google_calendars(): array - { + /** + * Return available Google Calendars for specific user. + * + * The given user's token must already exist in db in order to get access to his + * Google Calendar account. + * + * @return array Returns an array with the available calendars. + */ + public function get_google_calendars(): array + { $calendar_list = $this->service->calendarList->listCalendarList(); - $calendars = []; - - foreach ($calendar_list->getItems() as $google_calendar) { - if ($google_calendar->getAccessRole() === 'reader') { - continue; + foreach ($calendar_list->getItems() as $google_calendar) { + if ($google_calendar->getAccessRole() === 'reader') { + continue; } - - $calendars[] = [ - 'id' => $google_calendar->getId(), - 'summary' => $google_calendar->getSummary(), - ]; + $calendars[] = [ + 'id' => $google_calendar->getId(), + 'summary' => $google_calendar->getSummary(), + ]; } - - return $calendars; + return $calendars; } - - /** - * Get the Add-To-Google-URL, that can be used by anyone to quickly add the event to Google Calendar (no API needed). - * - * @param int $appointment_id - * - * @return string - * - * @throws Exception - */ - public function get_add_to_google_url(int $appointment_id): string - { + /** + * Get the Add-To-Google-URL, that can be used by anyone to quickly add the event to Google Calendar (no API needed). + * + * @param int $appointment_id + * + * @return string + * + * @throws Exception + */ + public function get_add_to_google_url(int $appointment_id): string + { $appointment = $this->CI->appointments_model->find($appointment_id); - $service = $this->CI->services_model->find($appointment['id_services']); - $provider = $this->CI->providers_model->find($appointment['id_users_provider']); - $customer = $this->CI->customers_model->find($appointment['id_users_customer']); - $provider_timezone_instance = new DateTimeZone($provider['timezone']); - $utc_timezone_instance = new DateTimeZone('UTC'); - $appointment_start_instance = new DateTime($appointment['start_datetime'], $provider_timezone_instance); - $appointment_start_instance->setTimezone($utc_timezone_instance); - $appointment_end_instance = new DateTime($appointment['end_datetime'], $provider_timezone_instance); - $appointment_end_instance->setTimezone($utc_timezone_instance); - $add = [$provider['email']]; - - if (!empty($customer['email'])) { - $add[] = $customer['email']; + if (!empty($customer['email'])) { + $add[] = $customer['email']; } - - $add_to_google_url_params = [ - 'action' => 'TEMPLATE', - 'text' => $service['name'], - 'dates' => - $appointment_start_instance->format('Ymd\THis\Z') . - '/' . - $appointment_end_instance->format('Ymd\THis\Z'), - 'location' => setting('company_name'), - 'details' => 'View/Change Appointment: ' . site_url('appointments/index/' . $appointment['hash']), - 'add' => implode(', ', $add), + $add_to_google_url_params = [ + 'action' => 'TEMPLATE', + 'text' => $service['name'], + 'dates' => + $appointment_start_instance->format('Ymd\THis\Z') . + '/' . + $appointment_end_instance->format('Ymd\THis\Z'), + 'location' => setting('company_name'), + 'details' => 'View/Change Appointment: ' . site_url('appointments/index/' . $appointment['hash']), + 'add' => implode(', ', $add), ]; - - return 'https://calendar.google.com/calendar/render?' . http_build_query($add_to_google_url_params); + return 'https://calendar.google.com/calendar/render?' . http_build_query($add_to_google_url_params); } - /** * Get the Google Meet link from an event. *