File: /home/dh_3gsgvh/noortax.net/wp-content/plugins/bookly-addon-pro/lib/google/Calendar.php
<?php
namespace BooklyPro\Lib\Google;
use Bookly\Lib as BooklyLib;
use Bookly\Lib\Config;
use Bookly\Lib\Entities\Appointment;
use Bookly\Lib\Entities\Service;
use Bookly\Lib\Entities\Staff;
use Bookly\Lib\Slots\Booking;
use Bookly\Lib\Slots\DatePoint;
class Calendar
{
const EVENTS_PER_REQUEST = 250;
/** @var Client */
protected $client;
/** @var string */
protected $timezone;
/**
* Constructor.
*
* @param Client $client
*/
public function __construct( Client $client )
{
$this->client = $client;
}
/**
* Synchronize Google Calendar with given appointment.
*
* @param Appointment $appointment
* @return bool
*/
public function syncAppointment( Appointment $appointment )
{
if ( ! $this->_hasCalendar() ) {
return true;
}
try {
$event = $this->_populateEvent( new \BooklyGoogle_Service_Calendar_Event(), $appointment );
// Add Google Meet event to calendar
$opt_params = array();
$service = Service::find( $appointment->getServiceId() );
$set_google_meet = $service && $service->getOnlineMeetings() === 'google_meet' && $appointment->getOnlineMeetingProvider() !== 'google_meet';
if ( $set_google_meet ) {
$conference_data = new \BooklyGoogle_Service_ConferenceData();
$request = new \BooklyGoogle_Service_CreateConferenceRequest();
$solution_key = new \BooklyGoogle_Service_ConferenceSolutionKey();
$solution_key->setType( 'hangoutsMeet' );
$request->setConferenceSolutionKey( $solution_key );
$request->setRequestId( md5( uniqid( time(), true ) ) );
$conference_data->setCreateRequest( $request );
$event->setConferenceData( $conference_data );
$opt_params = array(
'conferenceDataVersion' => 1,
);
}
if ( $appointment->hasGoogleCalendarEvent() ) {
// Update event.
$event = $this->client->service()->events->patch( $this->_getCalendarId(), $appointment->getGoogleEventId(), $event, $opt_params );
} else {
// Create event.
$event = $this->client->service()->events->insert( $this->_getCalendarId(), $event, $opt_params );
}
$appointment
->setGoogleEventId( $event->getId() )
->setGoogleEventETag( $event->getEtag() );
if ( $set_google_meet ) {
$appointment
->setOnlineMeetingProvider( 'google_meet' )
->setOnlineMeetingId( $event->getHangoutLink() );
}
$appointment->save();
return true;
} catch ( \Exception $e ) {
$this->client->addError( $e->getMessage() );
}
return false;
}
/**
* Delete Google Calendar event by ID.
*
* @param string $event_id
* @return bool
*/
public function deleteEvent( $event_id )
{
if ( ! $this->_hasCalendar() ) {
return true;
}
try {
$this->client->service()->events->delete( $this->_getCalendarId(), $event_id );
return true;
} catch ( \Exception $e ) {
$this->client->addError( $e->getMessage() );
}
return false;
}
/**
* Get bookings created from Google Calendar events.
*
* @param DatePoint $start_date
* @return Booking[]|false
*/
public function getBookings( DatePoint $start_date )
{
if ( ! $this->_hasCalendar() ) {
return array();
}
try {
$result = array();
$limit_events = get_option( 'bookly_gc_limit_events' );
$time_min = $start_date->format( \DateTime::RFC3339 );
$params = array(
'singleEvents' => true,
'orderBy' => 'startTime',
'timeMin' => $time_min,
'maxResults' => $limit_events ?: self::EVENTS_PER_REQUEST,
);
do {
// Fetch events.
$events = $this->client->service()->events->listEvents( $this->_getCalendarId(), $params );
/** @var \BooklyGoogle_Service_Calendar_Event $event */
foreach ( $events->getItems() as $event ) {
if ( ! $this->_isTransparentEvent( $event ) ) {
$ext_properties = $event->getExtendedProperties();
if ( $ext_properties !== null ) {
$private = $ext_properties['private'];
if (
is_array( $private ) && (
array_key_exists( 'bookly', $private ) ||
array_key_exists( 'appointment_id', $private ) // Backward compatibility
)
) {
// Skip events created by Bookly.
continue;
}
}
// Get start/end dates of event and transform them into WP timezone (Google doesn't transform whole day events into our timezone).
$event_start = $event->getStart();
$event_end = $event->getEnd();
if ( $event_start['dateTime'] == null ) {
// All day event.
$event_start_date = new \DateTime( $event_start['date'], new \DateTimeZone( $this->_getTimeZone() ) );
$event_end_date = new \DateTime( $event_end['date'], new \DateTimeZone( $this->_getTimeZone() ) );
} else {
// Regular event.
$event_start_date = new \DateTime( $event_start['dateTime'] );
$event_end_date = new \DateTime( $event_end['dateTime'] );
}
// Convert to WP time zone.
$event_start_date = date_timestamp_set( date_create( Config::getWPTimeZone() ), $event_start_date->getTimestamp() );
$event_end_date = date_timestamp_set( date_create( Config::getWPTimeZone() ), $event_end_date->getTimestamp() );
// Populate result.
$result[] = new Booking(
0,
0,
1,
0,
$event_start_date->format( 'Y-m-d H:i:s' ),
$event_end_date->format( 'Y-m-d H:i:s' ),
0,
0,
0,
0,
true
);
}
}
$params['pageToken'] = $events->getNextPageToken();
} while ( ! $limit_events && $params['pageToken'] !== null );
return $result;
} catch ( \Exception $e ) {
$this->client->addError( $e->getMessage() );
}
return false;
}
/**
* Populate Google Calendar event with data from given appointment.
*
* @param \BooklyGoogle_Service_Calendar_Event $event
* @param Appointment $appointment
* @return \BooklyGoogle_Service_Calendar_Event
*/
protected function _populateEvent( \BooklyGoogle_Service_Calendar_Event $event, Appointment $appointment )
{
// Set start and end dates.
$start_datetime = new \BooklyGoogle_Service_Calendar_EventDateTime();
$start_datetime->setDateTime(
DatePoint::fromStr( $appointment->getStartDate() )->format( \DateTime::RFC3339 )
);
$end_datetime = new \BooklyGoogle_Service_Calendar_EventDateTime();
$end_datetime->setDateTime(
DatePoint::fromStr( $appointment->getEndDate() )->modify( (int) $appointment->getExtrasDuration() )->format( \DateTime::RFC3339 )
);
$event->setStart( $start_datetime );
$event->setEnd( $end_datetime );
// Set other fields.
if ( $appointment->getCreatedFrom() === 'bookly' || get_option( 'bookly_gc_force_update_description' ) ) {
// Populate event created from Bookly.
$event->setSummary( $this->_getTitle( $appointment ) );
$event->setDescription( BooklyLib\Utils\Codes::replace( get_option( 'bookly_gc_event_description' ), BooklyLib\Utils\Codes::getAppointmentCodes( $appointment ), false ) );
$extended_property = new \BooklyGoogle_Service_Calendar_EventExtendedProperties();
$extended_property->setPrivate( array(
'bookly' => 1,
'bookly_appointment_id' => $appointment->getId(),
) );
$event->setExtendedProperties( $extended_property );
} else if ( get_option( 'bookly_gc_full_sync_titles', 1 ) ) {
// Populate event created from Google Calendar.
$event->setSummary( $this->_getTitle( $appointment ) );
}
return $event;
}
/**
* Get Google Calendar ID.
*
* @return string
*/
public function _getCalendarId()
{
return $this->client->data()->calendar->id;
}
/**
* Get title for summary
*
* @param Appointment $appointment
* @return string
*/
protected function _getTitle( $appointment )
{
$client_names = array();
$staff = Staff::find( $appointment->getStaffId() );
$category_name = '';
if ( $appointment->getServiceId() ) {
$service = Service::find( $appointment->getServiceId() );
if ( $service->getCategoryId() ) {
$category = BooklyLib\Entities\Category::find( $service->getCategoryId() );
if ( $category ) {
$category_name = $category->getName();
}
}
} else {
// Custom service.
$service = new Service();
$service
->setTitle( $appointment->getCustomServiceName() );
}
foreach ( $appointment->getCustomerAppointments() as $ca ) {
$client_names[] = $ca->customer->getFullName();
}
return strtr( get_option( 'bookly_gc_event_title', '{service_name}' ), array(
'{service_name}' => $service->getTitle(),
'{client_names}' => implode( ', ', $client_names ),
'{staff_name}' => $staff->getFullName(),
'{category_name}' => $category_name,
) );
}
/**
* Get Google Calendar time zone.
*
* @return string
*/
protected function _getTimeZone()
{
if ( $this->timezone === null ) {
$this->timezone = $this->client->service()->calendarList->get( $this->_getCalendarId() )->getTimeZone();
}
return $this->timezone;
}
/**
* Tells whether there is a selected calendar.
*
* @return bool
*/
protected function _hasCalendar()
{
return $this->_getCalendarId() != '';
}
/**
* Tells whether given event is transparent (does not block time on Google Calendar).
*
* @param \BooklyGoogle_Service_Calendar_Event $event
* @return bool
*/
protected function _isTransparentEvent( \BooklyGoogle_Service_Calendar_Event $event )
{
return $event->getTransparency() == 'transparent';
}
}