311 lines
11 KiB
PHP
311 lines
11 KiB
PHP
<?php namespace services\apis\CalendarSync;
|
|
/**
|
|
* Copyright 2017 OpenStack Foundation
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
**/
|
|
use models\summit\CalendarSync\CalendarSyncInfo;
|
|
use models\summit\CalendarSync\CalendarSyncInfoOAuth2;
|
|
use models\summit\CalendarSync\ScheduleCalendarSyncInfo;
|
|
use models\summit\CalendarSync\WorkQueue\MemberCalendarScheduleSummitActionSyncWorkRequest;
|
|
use models\summit\CalendarSync\WorkQueue\MemberEventScheduleSummitActionSyncWorkRequest;
|
|
use models\summit\SummitEvent;
|
|
use models\summit\SummitGeoLocatedLocation;
|
|
use models\summit\SummitVenueRoom;
|
|
use OutlookRestClient\Facade\OutlookRestClient;
|
|
use OutlookRestClient\Facade\Requests\AddressVO;
|
|
use OutlookRestClient\Facade\Requests\CalendarVO;
|
|
use OutlookRestClient\Facade\Requests\EventVO;
|
|
use OutlookRestClient\Facade\Requests\LocationVO;
|
|
use OutlookRestClient\Facade\Responses\CalendarResponse;
|
|
use OutlookRestClient\Facade\Responses\ErrorResponse;
|
|
use OutlookRestClient\IOutlookRestClient;
|
|
use Exception;
|
|
use LogicException;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
/**
|
|
* Class OutlookCalendarSyncRemoteFacade
|
|
* @package services\apis\CalendarSync
|
|
*/
|
|
final class OutlookCalendarSyncRemoteFacade
|
|
extends AbstractCalendarSyncRemoteFacade
|
|
{
|
|
|
|
/**
|
|
* @var IOutlookRestClient
|
|
*/
|
|
private $client;
|
|
|
|
const MaxRetriesAttempt = 5;
|
|
|
|
/**
|
|
* OutlookCalendarSyncRemoteFacade constructor.
|
|
* @param CalendarSyncInfoOAuth2 $sync_calendar_info
|
|
*/
|
|
public function __construct(CalendarSyncInfoOAuth2 $sync_calendar_info)
|
|
{
|
|
parent::__construct($sync_calendar_info);
|
|
|
|
$this->client = new OutlookRestClient();
|
|
$this->client->setAccessToken($sync_calendar_info->getAccessToken());
|
|
$this->client->setTokenCallback(function($access_token){
|
|
|
|
$this->sync_calendar_info->setAccessToken($access_token);
|
|
|
|
if(isset($access_token['refresh_token']))
|
|
$this->sync_calendar_info->setRefreshToken($access_token['refresh_token']);
|
|
});
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* @param SummitEvent $summit_event
|
|
* @param bool $update
|
|
* @return EventVO
|
|
*/
|
|
private function buildEventVO(SummitEvent $summit_event, $update = false){
|
|
|
|
try {
|
|
$location_name = null;
|
|
$location_title = null;
|
|
$location_lat = null;
|
|
$location_lng = null;
|
|
$location_street = null;
|
|
$location_city = null;
|
|
$location_state = null;
|
|
$location_country = null;
|
|
$location_postal_code = null;
|
|
|
|
if ($summit_event->hasLocation()) {
|
|
$venue = $summit_event->getLocation();
|
|
$room = null;
|
|
if ($venue instanceof SummitVenueRoom) {
|
|
$room = $venue;
|
|
$venue = $venue->getVenue();
|
|
}
|
|
$location_full_name = $venue->getName();
|
|
if (!is_null($room)) {
|
|
if ($room->hasFloor()) {
|
|
$location_full_name .= ', ' . $room->getFloor()->getName();
|
|
}
|
|
$location_full_name .= ', ' . $room->getName();
|
|
}
|
|
|
|
$location_name = $location_full_name;
|
|
$location_title = $location_full_name;
|
|
if ($venue instanceof SummitGeoLocatedLocation) {
|
|
$location_lat = $venue->getLat();
|
|
$location_lng = $venue->getLng();
|
|
$location_street = $venue->getAddress1();
|
|
$location_city = $venue->getCity();
|
|
$location_state = $venue->getState();
|
|
$location_country = $venue->getCountry();
|
|
$location_postal_code = $venue->getZipCode();
|
|
}
|
|
}
|
|
$title = $summit_event->getTitle();
|
|
if($update) $title = "{$title} [UPDATED]";
|
|
return new EventVO(
|
|
$title,
|
|
$summit_event->getAbstract(),
|
|
$summit_event->getLocalStartDate(),
|
|
$summit_event->getLocalEndDate(),
|
|
$summit_event->getSummit()->getTimeZone(),
|
|
new LocationVO
|
|
(
|
|
$location_name,
|
|
new AddressVO
|
|
(
|
|
$location_street,
|
|
$location_city,
|
|
$location_state,
|
|
$location_country,
|
|
$location_postal_code
|
|
),
|
|
$location_lat,
|
|
$location_lng
|
|
)
|
|
);
|
|
}
|
|
catch (Exception $ex){
|
|
Log::error($ex);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param MemberEventScheduleSummitActionSyncWorkRequest $request
|
|
* @return ScheduleCalendarSyncInfo
|
|
*/
|
|
public function addEvent(MemberEventScheduleSummitActionSyncWorkRequest $request)
|
|
{
|
|
try {
|
|
$summit_event = $request->getSummitEvent();
|
|
$vo = $this->buildEventVO($summit_event);
|
|
if(is_null($vo)) throw new LogicException();
|
|
$calendar_id = $this->sync_calendar_info->getExternalId();
|
|
$created_event = $this->client->createEvent($calendar_id, $vo);
|
|
// new schedule sync info
|
|
$sync_info = new ScheduleCalendarSyncInfo();
|
|
// primitives
|
|
$sync_info->setEtag($created_event->getEtag());
|
|
$sync_info->setExternalId($created_event->getId());
|
|
$sync_info->setExternalUrl($created_event->getDataId());
|
|
// relationships
|
|
$sync_info->setSummitEventId($summit_event->getId());
|
|
$sync_info->setCalendarSyncInfo($this->sync_calendar_info);
|
|
$sync_info->setLocationId($summit_event->getLocationId());
|
|
return $sync_info;
|
|
}
|
|
catch (Exception $ex){
|
|
Log::error($ex);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param MemberEventScheduleSummitActionSyncWorkRequest $request
|
|
* @param ScheduleCalendarSyncInfo $schedule_sync_info
|
|
* @return bool
|
|
*/
|
|
public function deleteEvent
|
|
(
|
|
MemberEventScheduleSummitActionSyncWorkRequest $request,
|
|
ScheduleCalendarSyncInfo $schedule_sync_info
|
|
)
|
|
{
|
|
try {
|
|
$res = $this->client->deleteEvent($schedule_sync_info->getExternalId());
|
|
return !($res instanceof ErrorResponse);
|
|
}
|
|
catch (Exception $ex){
|
|
Log::error($ex);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param MemberEventScheduleSummitActionSyncWorkRequest $request
|
|
* @param ScheduleCalendarSyncInfo $schedule_sync_info
|
|
* @return bool
|
|
*/
|
|
public function updateEvent
|
|
(
|
|
MemberEventScheduleSummitActionSyncWorkRequest $request,
|
|
ScheduleCalendarSyncInfo $schedule_sync_info
|
|
)
|
|
{
|
|
try {
|
|
$summit_event = $request->getSummitEvent();
|
|
$vo = $this->buildEventVO($summit_event, true);
|
|
if(is_null($vo)) throw new LogicException();
|
|
$event_id = $schedule_sync_info->getExternalId();
|
|
$updated_event = $this->client->updateEvent($event_id, $vo);
|
|
// primitives
|
|
$schedule_sync_info->setEtag($updated_event->getEtag());
|
|
// relationships
|
|
$schedule_sync_info->setLocationId($summit_event->getLocationId());
|
|
return true;
|
|
}
|
|
catch (Exception $ex){
|
|
Log::error($ex);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param MemberCalendarScheduleSummitActionSyncWorkRequest $request
|
|
* @param CalendarSyncInfo $calendar_sync_info
|
|
* @return bool
|
|
*/
|
|
public function createCalendar
|
|
(
|
|
MemberCalendarScheduleSummitActionSyncWorkRequest $request,
|
|
CalendarSyncInfo $calendar_sync_info
|
|
)
|
|
{
|
|
try {
|
|
$res = $this->client->createCalendar(new CalendarVO
|
|
(
|
|
$request->getCalendarName()
|
|
));
|
|
|
|
if ($res instanceof CalendarResponse) {
|
|
|
|
$this->sync_calendar_info->setExternalId($res->getId());
|
|
$this->sync_calendar_info->setEtag($res->getChangeKey());
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
catch (Exception $ex){
|
|
Log::error($ex);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param MemberCalendarScheduleSummitActionSyncWorkRequest $request
|
|
* @param CalendarSyncInfo $calendar_sync_info
|
|
* @return bool
|
|
*/
|
|
public function deleteCalendar
|
|
(
|
|
MemberCalendarScheduleSummitActionSyncWorkRequest $request,
|
|
CalendarSyncInfo $calendar_sync_info
|
|
)
|
|
{
|
|
try {
|
|
$calendar_id = $calendar_sync_info->getExternalId();
|
|
$counter = 1;
|
|
do {
|
|
$res = $this->client->deleteCalendar($calendar_id);
|
|
$deleted = is_bool($res) ? $res : false;
|
|
if ($res instanceof ErrorResponse) {
|
|
log::warning(sprintf("OutlookCalendarSyncRemoteFacade::deleteCalendar: error deleting calendar id %s", $calendar_id));
|
|
if($res->getErrorCode() == "ErrorItemNotFound"){
|
|
log::info("OutlookCalendarSyncRemoteFacade::deleteCalendar: ErrorItemNotFound");
|
|
break;
|
|
}
|
|
// @see https://stackoverflow.com/questions/31923669/office-365-unified-api-error-when-deleting-a-calendar
|
|
// @see https://stackoverflow.com/questions/44597230/office365-calendar-rest-api-cannot-delete-calendars
|
|
// change name ...
|
|
log::info(sprintf("OutlookCalendarSyncRemoteFacade::deleteCalendar: renaming calendar id %s", $calendar_id));
|
|
$this->client->updateCalendar($calendar_id, new CalendarVO(
|
|
md5(uniqid(mt_rand(), true))
|
|
));
|
|
$exp = $this->getSleepInterval() * (pow(2, $counter) - 1);
|
|
log::info(sprintf("OutlookCalendarSyncRemoteFacade::deleteCalendar: retrying calendar id %s on %s ms", $calendar_id, $exp));
|
|
usleep($exp);
|
|
}
|
|
++$counter;
|
|
if($counter == self::MaxRetriesAttempt){
|
|
log::warning(sprintf("OutlookCalendarSyncRemoteFacade::deleteCalendar: error deleting calendar id %s (MaxRetriesAttempt reached !)", $calendar_id));
|
|
break;
|
|
}
|
|
} while (!$deleted);
|
|
return $deleted;
|
|
}
|
|
catch (Exception $ex){
|
|
Log::error($ex);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return mixed
|
|
*/
|
|
public function getSleepInterval()
|
|
{
|
|
return 500;
|
|
}
|
|
} |