735 lines
22 KiB
PHP
735 lines
22 KiB
PHP
<?php
|
|
/**
|
|
*
|
|
* @since 6.6.5
|
|
* @package Simply_Schedule_Appointments
|
|
*
|
|
*/
|
|
|
|
class SSA_Google_Calendar_Client {
|
|
|
|
private $access_token = false;
|
|
|
|
private $client_id = false;
|
|
|
|
private $client_secret = false;
|
|
|
|
private $redirect_uri = false;
|
|
|
|
private $quotaUser = null;
|
|
|
|
|
|
/**
|
|
* Parent plugin class.
|
|
*
|
|
* @since 0.6.0
|
|
*
|
|
* @var Simply_Schedule_Appointments
|
|
*/
|
|
protected $plugin = null;
|
|
|
|
protected $staff_id = 0;
|
|
|
|
/**
|
|
* @since 6.6.5
|
|
*/
|
|
public function __construct( $plugin ) {
|
|
$this->plugin = $plugin;
|
|
$this->hooks();
|
|
}
|
|
|
|
/**
|
|
* Initiate our hooks.
|
|
*
|
|
* @since 0.6.0
|
|
*/
|
|
public function hooks() {
|
|
//
|
|
}
|
|
|
|
public function client_init() {
|
|
if ( !empty($this->client_id) || !empty($this->client_secret) ) {
|
|
return $this;
|
|
}
|
|
|
|
$settings = ssa()->settings->get();
|
|
$google_calendar_settings = $settings['google_calendar'];
|
|
|
|
// Only initialize if we're not using the new ssa_quick_connect auth flow
|
|
// any method besides this one should access the client_id and client_secret directly on this class
|
|
if( !$google_calendar_settings['quick_connect_gcal_mode'] ){
|
|
$this->client_id = $this->plugin->google_calendar->get_client_id();
|
|
$this->client_secret = $this->plugin->google_calendar->get_client_secret();
|
|
} else {
|
|
// if ssa_quick_connect enabled get our own client_id
|
|
if( !defined( 'SSA_QUICK_CONNECT_GCAL_CLIENT_ID' ) ){
|
|
ssa_debug_log( 'SSA_QUICK_CONNECT_GCAL_CLIENT_ID not defined!', 10 );
|
|
return false;
|
|
}
|
|
$this->client_id = SSA_QUICK_CONNECT_GCAL_CLIENT_ID;
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function service_init( $staff_id = 0 ) {
|
|
$client = (new self( $this->plugin ))->client_init();
|
|
$client->staff_id = $staff_id;
|
|
$client->authorize();
|
|
return $client;
|
|
}
|
|
|
|
/**
|
|
* Call this to authorize the client
|
|
* updates the access token in the settings as well
|
|
*
|
|
* @since 6.6.5
|
|
*
|
|
* @return void
|
|
*/
|
|
private function authorize() {
|
|
$staff_access_token = $this->get_access_token_for_staff_id();
|
|
if( $staff_access_token != $this->access_token ) {
|
|
$this->access_token = $staff_access_token;
|
|
}
|
|
|
|
// check also if the access token is the correct one
|
|
if( !$this->is_access_token_expired( $this->access_token ) ) {
|
|
// no need to refresh access token
|
|
return;
|
|
}
|
|
|
|
// if quick connect enabled, get quick connect access token
|
|
|
|
$google_calendar_settings = $this->plugin->google_calendar_settings->get();
|
|
|
|
$google_quick_connect_gcal_mode = $google_calendar_settings['quick_connect_gcal_mode'] == true;
|
|
|
|
if( true == $google_quick_connect_gcal_mode ){
|
|
$this->authorize_with_quick_connect( $this->staff_id );
|
|
} else {
|
|
$this->authorize_with_client_id_and_secret();
|
|
}
|
|
|
|
if ( empty( $this->access_token ) ) {
|
|
ssa_debug_log( 'missing_access_token for staff id '.$this->staff_id, 10 );
|
|
return;
|
|
}
|
|
|
|
// if still expired
|
|
if( $this->is_access_token_expired( $this->access_token ) ) {
|
|
ssa_debug_log( 'expired_access_token for staff id '.$this->staff_id, 10 );
|
|
ssa_debug_log( ssa_get_stack_trace(), 10 );
|
|
throw new Exception( 'Failed to authorize with Google Calendar' );
|
|
}
|
|
}
|
|
|
|
private function authorize_with_client_id_and_secret() {
|
|
$access_token = $this->get_access_token_for_staff_id();
|
|
// throwing the exception here to avoid fatal error of accessing an offset on a non-array
|
|
if( empty( $access_token ) || !is_array( $access_token ) ) {
|
|
throw new Exception( 'Empty access token for staff id '.$this->staff_id );
|
|
}
|
|
|
|
if( $this->is_access_token_expired( $access_token ) ) {
|
|
$this->access_token = $this->refresh_access_token( $access_token );
|
|
$this->update_token_in_database();
|
|
} else {
|
|
$this->access_token = $access_token;
|
|
}
|
|
}
|
|
|
|
private function get_access_token_for_staff_id() {
|
|
// get access token from settings
|
|
if( empty( $this->staff_id ) ) {
|
|
$google_calendar_settings = $this->plugin->google_calendar_settings->get();
|
|
return $google_calendar_settings['access_token'];
|
|
} else {
|
|
$staff = SSA_Staff_Object::instance( $this->staff_id );
|
|
return $staff->google_access_token;
|
|
}
|
|
}
|
|
/**
|
|
* Quick Connect is assumed to always return a valid access token
|
|
* This should shortcut the method that sets the access token and just set the access token directly
|
|
*
|
|
* @param [type] $staff_id
|
|
* @return void
|
|
*/
|
|
private function authorize_with_quick_connect() {
|
|
$this->access_token = $this->plugin->google_calendar->get_quick_connect_access_token( $this->staff_id );
|
|
// no need to update the token in database, because get_quick_connect_access_token handles that
|
|
}
|
|
|
|
private function get_request_headers( ){
|
|
if( empty( $this->access_token ) ) {
|
|
$this->authorize();
|
|
}
|
|
$headers = array(
|
|
'Content-Type' => 'application/json',
|
|
'Authorization' => 'Bearer ' . $this->access_token['access_token'],
|
|
);
|
|
return $headers;
|
|
}
|
|
|
|
/**
|
|
* Test and confirm that the access token
|
|
* Makes an API call and confirms that the access token is valid
|
|
*
|
|
* @param array $options
|
|
* @return void
|
|
*/
|
|
public function validate_access_token( array $access_token ) {
|
|
$gcal_api_endpoint = 'https://www.googleapis.com/calendar/v3/users/me/calendarList';
|
|
|
|
$response = wp_remote_get(
|
|
$gcal_api_endpoint,
|
|
array(
|
|
'headers' => array(
|
|
'Content-Type' => 'application/json',
|
|
'Authorization' => 'Bearer ' . $access_token['access_token'],
|
|
),
|
|
'timeout' => 60
|
|
)
|
|
);
|
|
|
|
if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) > 299 ) {
|
|
if( wp_remote_retrieve_response_code( $response ) == 401 ){
|
|
// expired token
|
|
return false;
|
|
}
|
|
ssa_debug_log( print_r( $response, true ), 10); // phpcs:ignore
|
|
throw new Exception( 'Failed to validate Google Calendar access token' );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
/**
|
|
* use in place of ->calendarList->listCalendarList( $options = array() ) {}
|
|
* this method will return all calendars, not just the first page
|
|
*
|
|
* @since 6.6.5
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_calendar_list( $options = array() ) {
|
|
$calendar_list = array();
|
|
$gcal_api_endpoint = 'https://www.googleapis.com/calendar/v3/users/me/calendarList' . '?' . $this->get_params_from_options( $options );
|
|
$current_endpoint = $gcal_api_endpoint;
|
|
|
|
// get all pages of calendar list
|
|
while(true){
|
|
try {
|
|
$response = wp_remote_get(
|
|
$current_endpoint,
|
|
array(
|
|
'headers' => $this->get_request_headers(),
|
|
'timeout' => 60
|
|
)
|
|
);
|
|
|
|
if ( is_wp_error($response) || wp_remote_retrieve_response_code($response) > 299 ) {
|
|
ssa_debug_log( print_r( $response, true ), 10); // phpcs:ignore
|
|
return false;
|
|
}
|
|
|
|
$data = json_decode( wp_remote_retrieve_body( $response ) );
|
|
|
|
// add calendar list to array
|
|
$calendar_list = array_merge( $calendar_list, $data->items );
|
|
|
|
if(empty($data->items)){
|
|
ssa_debug_log( 'No calendars found in calendar list', 10 );
|
|
ssa_debug_log( print_r( $response, true ), 10); // phpcs:ignore
|
|
}
|
|
|
|
if ( empty( $data->nextPageToken ) ) {
|
|
break;
|
|
} else {
|
|
$current_endpoint = $gcal_api_endpoint . '&pageToken=' . $data->nextPageToken;
|
|
}
|
|
} catch ( \Throwable $th ) {
|
|
ssa_debug_log( print_r( $th, true ), 10 ); // phpcs:ignore
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Success
|
|
// return calendar list
|
|
return $calendar_list;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* use in place of ->calendarList->get( $calendar_id, $options = array() ) {}
|
|
*/
|
|
public function get_calendar_from_calendar_list ( $calendar_id, $options = array() ) {
|
|
$gcal_api_endpoint = "https://www.googleapis.com/calendar/v3/users/me/calendarList/" . urlencode( $calendar_id ) . "?" . $this->get_params_from_options( $options );
|
|
try {
|
|
$response = wp_remote_get(
|
|
$gcal_api_endpoint,
|
|
array(
|
|
'headers' => $this->get_request_headers(),
|
|
'timeout' => 60
|
|
)
|
|
);
|
|
|
|
// we don't want to log 404 errors, because we expect them if the calendar is not found
|
|
if ( is_wp_error( $response ) || ( wp_remote_retrieve_response_code( $response ) > 299 && wp_remote_retrieve_response_code( $response ) != 404 ) ) {
|
|
ssa_debug_log( print_r( $response, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
|
|
$data = json_decode( wp_remote_retrieve_body( $response ) );
|
|
// Success
|
|
return $data;
|
|
} catch ( \Throwable $th ) {
|
|
ssa_debug_log( print_r( $th, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* use in place of ->events->listEvents( $calendar_id, $options = array() ) {}
|
|
|
|
*/
|
|
public function get_events_from_calendar( $calendar_id, $options = array() ) {
|
|
// if is a holiday caledar, pull events in english locale so that we have a way to identiy public holidays
|
|
if( false !== strpos( $calendar_id, 'holiday' ) ){
|
|
$calendar_id_parts = explode( '.', $calendar_id );
|
|
array_shift( $calendar_id_parts );
|
|
$calendar_id = 'en.' . implode( '.', $calendar_id_parts );
|
|
}
|
|
|
|
// exclude workingLocation events - these are not useful for availability
|
|
$event_types_query = 'eventTypes=default&eventTypes=outOfOffice&eventTypes=focusTime&eventTypes=fromGmail';
|
|
|
|
$gcal_api_endpoint = "https://www.googleapis.com/calendar/v3/calendars/" . urlencode( $calendar_id ) . "/events?" . $event_types_query . '&' . $this->get_params_from_options( $options );
|
|
|
|
try {
|
|
$response = wp_remote_get(
|
|
$gcal_api_endpoint,
|
|
array(
|
|
'headers' => $this->get_request_headers(),
|
|
'timeout' => 60
|
|
)
|
|
);
|
|
|
|
if ( is_wp_error($response) || wp_remote_retrieve_response_code($response) > 299 ) {
|
|
if( wp_remote_retrieve_response_code($response) == 404 ){
|
|
ssa_debug_log( 'Received 404, getting events for ' . $calendar_id . " from " . $gcal_api_endpoint . " working with staff id " . $this->staff_id ); // phpcs:ignore
|
|
ssa_debug_log( ssa_get_stack_trace(), 10 );
|
|
} else {
|
|
ssa_debug_log( print_r( $response, true ), 10 ); // phpcs:ignore
|
|
}
|
|
return [];
|
|
}
|
|
|
|
$data = json_decode( wp_remote_retrieve_body( $response ) );
|
|
|
|
// Success
|
|
return $data->items;
|
|
} catch ( \Throwable $th ) {
|
|
ssa_debug_log( print_r( $th, true ), 10 ); // phpcs:ignore
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* use in place of ->events->insert( $calendar_id, $event, $options = array() ) {}
|
|
*
|
|
*/
|
|
public function insert_event_into_calendar( $calendar_id, $event, $options = array() ) {
|
|
$gcal_api_endpoint = "https://www.googleapis.com/calendar/v3/calendars/" . urlencode( $calendar_id ) . "/events?" . $this->get_params_from_options( $options );
|
|
|
|
try {
|
|
$response = wp_remote_post(
|
|
$gcal_api_endpoint,
|
|
array(
|
|
'headers' => $this->get_request_headers(),
|
|
'timeout' => 60,
|
|
'body' => json_encode($event),
|
|
)
|
|
);
|
|
|
|
if ( is_wp_error($response) || wp_remote_retrieve_response_code($response) > 299 ) {
|
|
ssa_debug_log( print_r( $response, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
|
|
$event = json_decode(wp_remote_retrieve_body($response) );
|
|
|
|
// Success
|
|
// return event ID
|
|
return $event;
|
|
} catch ( \Throwable $th ) {
|
|
ssa_debug_log( print_r( $th, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* use in place of ->events->get( $calendar_id, $event_id, $options = array() ) {}
|
|
*
|
|
*/
|
|
public function get_event_from_calendar( $calendar_id, $event_id, $options = array() ) {
|
|
if(empty($calendar_id) || empty($event_id)){
|
|
ssa_debug_log( 'Warning: called get_event_from_calendar with calendar_id:' . $calendar_id . ' & event_id:' . $event_id , 10 );
|
|
return false;
|
|
}
|
|
$gcal_api_endpoint = "https://www.googleapis.com/calendar/v3/calendars/" . urlencode( $calendar_id ) . "/events/" . $event_id . "?" . $this->get_params_from_options( $options );
|
|
|
|
try {
|
|
$response = wp_remote_get(
|
|
$gcal_api_endpoint,
|
|
array(
|
|
'headers' => $this->get_request_headers(),
|
|
'timeout' => 60
|
|
)
|
|
);
|
|
|
|
if ( is_wp_error($response) || wp_remote_retrieve_response_code($response) > 299 ) {
|
|
ssa_debug_log( print_r( $response, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
|
|
$data = json_decode(wp_remote_retrieve_body($response) );
|
|
|
|
// Success
|
|
return $data;
|
|
} catch ( \Throwable $th ) {
|
|
ssa_debug_log( print_r( $th, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* use in place of ->events->update( $calendar_id, $event_id, $event_updated, $options = array() ) { }
|
|
*/
|
|
public function update_event_in_calendar( $calendar_id, $event_id, $event_updated, $options = array() ) {
|
|
$gcal_api_endpoint = "https://www.googleapis.com/calendar/v3/calendars/" . urlencode( $calendar_id ) . "/events/" . $event_id . "?" . $this->get_params_from_options( $options );
|
|
|
|
try {
|
|
$response = wp_remote_request(
|
|
$gcal_api_endpoint,
|
|
array(
|
|
'headers' => $this->get_request_headers(),
|
|
'timeout' => 60,
|
|
'body' => json_encode( $event_updated ),
|
|
'method' => 'PUT'
|
|
)
|
|
);
|
|
|
|
if ( is_wp_error($response) || wp_remote_retrieve_response_code($response) > 299 ) {
|
|
ssa_debug_log( print_r( $response, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
|
|
$data = json_decode(wp_remote_retrieve_body($response) );
|
|
|
|
// Success
|
|
return $data;
|
|
} catch ( \Throwable $th ) {
|
|
ssa_debug_log( print_r( $th, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* use in place of ->events->delete( $calendar_id, $event_id, $options = array() ) {}
|
|
*/
|
|
public function delete_event_from_calendar( $calendar_id, $event_id, $options = array() ) {
|
|
$gcal_api_endpoint = "https://www.googleapis.com/calendar/v3/calendars/" . urlencode( $calendar_id ) . "/events/" . $event_id . "?" . $this->get_params_from_options( $options );
|
|
|
|
try {
|
|
$response = wp_remote_request(
|
|
$gcal_api_endpoint,
|
|
array(
|
|
'headers' => $this->get_request_headers(),
|
|
'timeout' => 60,
|
|
'method' => 'DELETE'
|
|
)
|
|
);
|
|
|
|
if ( is_wp_error($response) || wp_remote_retrieve_response_code($response) > 299 ) {
|
|
ssa_debug_log( print_r( $response, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
|
|
// Success
|
|
// the delete method returns an empty body
|
|
return true;
|
|
} catch ( \Throwable $th ) {
|
|
ssa_debug_log( print_r( $th, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* description: this is the same logic used by the PHP OAuth client
|
|
* with a minor difference, this takes the $token as an argument
|
|
*
|
|
* @param array $token
|
|
* @return bool Returns True if the access_token is expired.
|
|
*/
|
|
public function is_access_token_expired( $token ) {
|
|
if ( !$token ) {
|
|
return true;
|
|
}
|
|
|
|
if ( is_object( $token ) ) {
|
|
$token = (array) $token;
|
|
}
|
|
|
|
// if less than 300 seconds remaining, refresh the token anyways
|
|
$created = 0;
|
|
if ( isset( $token['created'] ) ) {
|
|
$created = $token['created'];
|
|
} elseif ( isset( $token['id_token'] ) ) {
|
|
// check the ID token for "iat"
|
|
// signature verification is not required here, as we are just
|
|
// using this for convenience to save a round trip request
|
|
// to the Google API server
|
|
$idToken = $token['id_token'];
|
|
if ( substr_count( $idToken, '.' ) == 2 ) {
|
|
$parts = explode( '.', $idToken );
|
|
$payload = json_decode( base64_decode( $parts[1] ), true );
|
|
if ( $payload && isset( $payload['iat'] ) ) {
|
|
$created = $payload['iat'];
|
|
}
|
|
}
|
|
}
|
|
|
|
if( $created > 0 ){
|
|
$buffer = 300;
|
|
$expires_in = 3599;
|
|
// access tokens usually expire in 3599 seconds
|
|
if( $created + $expires_in - $buffer < time() ){
|
|
// consider expired to stay on the safe side
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// invert
|
|
return ! $this->validate_access_token( $token );
|
|
}
|
|
|
|
/**
|
|
* Exchange the refresh token for an access token
|
|
*
|
|
* @param string $client_id
|
|
* @param string $client_secret
|
|
* @param string $refresh_token
|
|
* @return bool|array
|
|
*/
|
|
private function exchange_refresh_token( $client_id, $client_secret, $refresh_token ){
|
|
$gcal_api_endpoint = 'https://www.googleapis.com/oauth2/v4/token';
|
|
|
|
try {
|
|
$response = wp_remote_post(
|
|
$gcal_api_endpoint,
|
|
array(
|
|
'body' => array(
|
|
'refresh_token' => $refresh_token,
|
|
'client_id' => $client_id,
|
|
'client_secret' => $client_secret,
|
|
'grant_type' => 'refresh_token',
|
|
// return also the refresh token
|
|
'access_type' => 'offline',
|
|
),
|
|
'timeout' => 60
|
|
)
|
|
);
|
|
|
|
if ( is_wp_error($response) || wp_remote_retrieve_response_code($response) > 299 ) {
|
|
ssa_debug_log( print_r( $response, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
|
|
$data = json_decode(wp_remote_retrieve_body($response), true);
|
|
|
|
if( empty( $data['refresh_token'] ) ) {
|
|
// attach the refresh token to the access token
|
|
$data['refresh_token'] = $refresh_token;
|
|
}
|
|
|
|
// Success
|
|
return $data;
|
|
} catch ( \Throwable $th ) {
|
|
ssa_debug_log( print_r( $th, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* We never call this with the quick connect flow, because we don't have a refresh token
|
|
*
|
|
* @return void
|
|
*/
|
|
private function refresh_access_token($access_token) {
|
|
$client_id = $this->client_id;
|
|
$client_secret = $this->client_secret;
|
|
$refresh_token = $access_token['refresh_token'];
|
|
$response = $this->exchange_refresh_token( $client_id, $client_secret, $refresh_token );
|
|
if( empty( $response ) || ! is_array( $response ) || empty( $response['access_token'] ) ) {
|
|
ssa_debug_log( 'Failed to refresh access token for staff id ' . (string) $this->staff_id . print_r($response, true), 10); // phpcs:ignore
|
|
throw new Exception( 'Failed to refresh access token' );
|
|
}
|
|
return $response;
|
|
}
|
|
|
|
private function update_token_in_database(){
|
|
$staff_id = $this->staff_id;
|
|
$access_token = $this->access_token;
|
|
if(empty($staff_id)){
|
|
if(empty($access_token['refresh_token'])){
|
|
// log that we received an access token without a refresh token
|
|
ssa_debug_log('Received an access token without a refresh token ' . ' for staff id ' . (string) $staff_id . print_r($access_token, true), 10 ); // phpcs:ignore
|
|
$google_calendar_settings = $this->plugin->google_calendar_settings->get();
|
|
$access_token['refresh_token'] = !empty($google_calendar_settings['access_token']['refresh_token']) ? $google_calendar_settings['access_token']['refresh_token'] : '';
|
|
}
|
|
$this->plugin->google_calendar_settings->update( array( 'access_token' => $access_token ) );
|
|
} else {
|
|
if(empty($access_token['refresh_token'])){
|
|
// log that we received an access token without a refresh token
|
|
ssa_debug_log('Received an access token without a refresh token ' . ' for staff id ' . (string) $staff_id . print_r($access_token, true), 10 ); // phpcs:ignore
|
|
$staff = $this->plugin->staff_model->get( $staff_id );
|
|
$access_token['refresh_token'] = !empty($staff['google_access_token']['refresh_token']) ? $staff['google_access_token']['refresh_token'] : '';
|
|
}
|
|
$this->plugin->staff_model->update( $staff_id, array(
|
|
'google_access_token' => $access_token,
|
|
) );
|
|
}
|
|
}
|
|
|
|
public function get_auth_url( $staff_id, $wp_next_ssa_uri = null, $wp_next_base_uri = null ) {
|
|
$this->client_init();
|
|
$gcal_api_endpoint = 'https://accounts.google.com/o/oauth2/auth?';
|
|
// need to store the exact home url returned at this point
|
|
// because some plugins can affect the home url, causing the quick-connect domain to be invalid
|
|
$site_home_url = get_home_url();
|
|
$this->plugin->google_calendar_settings->update( array(
|
|
'quick_connect_home_url' => $site_home_url,
|
|
) );
|
|
|
|
$license_settings = $this->plugin->license_settings->get();
|
|
$license = '';
|
|
|
|
// https://accounts.google.com/o/oauth2/auth?
|
|
$params = array(
|
|
'response_type'=>'code',
|
|
'client_id'=> $this->client_id,
|
|
'redirect_uri'=> $this->plugin->google_calendar->get_redirect_uri(),
|
|
'scope'=> 'https://www.googleapis.com/auth/calendar openid',
|
|
'approval_prompt'=>'force',
|
|
'access_type'=>'offline',
|
|
);
|
|
|
|
if ( empty( $wp_next_ssa_uri ) ) {
|
|
$wp_next_ssa_uri = 'ssa/settings/google-calendar';
|
|
}
|
|
if ( empty( $wp_next_base_uri ) ) {
|
|
$wp_next_base_uri = $this->plugin->wp_admin->url();
|
|
}
|
|
|
|
$params['state'] = strtr( base64_encode( json_encode( array(
|
|
'authorize' => 'google',
|
|
'staff_id' => $staff_id,
|
|
'staff_token' => SSA_Utils::site_unique_hash( $staff_id ),
|
|
'token' => $license,
|
|
'redirect_uri' => $this->plugin->google_calendar->get_redirect_uri(),
|
|
'wp_callback_uri' => $this->plugin->google_calendar::get_wp_callback_uri(),
|
|
'wp_next_ssa_uri' => $wp_next_ssa_uri,
|
|
'wp_next_base_uri' => $wp_next_base_uri, // grab from the parent page (example: /my-account/), like we do for booking_url in booking-app
|
|
// used for ssa_quick_connect - staff_id as well
|
|
'domain' => $site_home_url,
|
|
'license_key'=> $license_settings['license_filtered'],
|
|
) ) ), '+/=', '-_,' );
|
|
|
|
return $gcal_api_endpoint . $this->get_params_from_options( $params );
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @since 6.6.5
|
|
*
|
|
* @return bool
|
|
|
|
*/
|
|
public function exchange_auth_code( $code ) {
|
|
$this->client_init();
|
|
$gcal_api_endpoint = 'https://www.googleapis.com/oauth2/v4/token?';
|
|
$params = array(
|
|
'code' => $code,
|
|
'grant_type' => 'authorization_code',
|
|
'client_id' => $this->client_id,
|
|
'client_secret' => $this->client_secret,
|
|
'redirect_uri' => $this->plugin->google_calendar->get_redirect_uri(),
|
|
);
|
|
|
|
|
|
try {
|
|
$response = wp_remote_post( $gcal_api_endpoint . $this->get_params_from_options( $params ), array(
|
|
'timeout' => 20
|
|
));
|
|
|
|
if ( is_wp_error($response) || wp_remote_retrieve_response_code($response) > 299 ) {
|
|
throw new \Throwable( $response );
|
|
}
|
|
|
|
$data = json_decode(wp_remote_retrieve_body($response), true);
|
|
|
|
$this->access_token = $data;
|
|
|
|
return true;
|
|
} catch ( \Throwable $th ) {
|
|
ssa_debug_log( print_r( $th, true ), 10 ); // phpcs:ignore
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
public function get_exchange_response() {
|
|
return $this->access_token;
|
|
}
|
|
|
|
public function get_access_token()
|
|
{
|
|
return $this->access_token;
|
|
}
|
|
|
|
public function get_params_from_options ( $options ) {
|
|
if( empty( $options ) ) {
|
|
return '';
|
|
}
|
|
$params_string = '';
|
|
// avoid $this->get_params_from_options( $options ); it will convert true to 1, and google api does not like that
|
|
foreach( $options as $key => $value ) {
|
|
// if boolean replace with string equivalent
|
|
if( is_bool( $value ) ) {
|
|
$value = $value ? 'true' : 'false';
|
|
}
|
|
$params_string .= http_build_query([$key => $value]) . '&';
|
|
}
|
|
return $params_string;
|
|
}
|
|
|
|
public function revoke_token( $token ) {
|
|
$response = wp_remote_post(
|
|
'https://oauth2.googleapis.com/revoke',
|
|
array(
|
|
'body' => array(
|
|
'token' => $token,
|
|
),
|
|
)
|
|
);
|
|
|
|
}
|
|
}
|