src/Service/GoogleCalendarService.php line 239

Open in your IDE?
  1. <?php
  2. namespace App\Service;
  3. use App\Entity\Child;
  4. use App\Entity\Guardian;
  5. use App\Entity\Lesson;
  6. use App\Entity\Teacher;
  7. use Doctrine\ORM\EntityManagerInterface;
  8. use Google_Client;
  9. use Google_Service_Calendar;
  10. use Google_Service_Calendar_Event;
  11. use Google_Service_Calendar_EventDateTime;
  12. use Google_Service_Exception;
  13. use Psr\Container\ContainerInterface;
  14. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  15. use Psr\Log\LoggerInterface;
  16. class GoogleCalendarService
  17. {
  18. private $client;
  19. private EntityManagerInterface $entityManager;
  20. private $user = null;
  21. private UrlGeneratorInterface $urlGenerator;
  22. private ContainerInterface $container;
  23. private LoggerInterface $calendarLogger;
  24. public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, ContainerInterface $container, LoggerInterface $calendarLogger)
  25. {
  26. $this->calendarLogger = $calendarLogger;
  27. $this->client = new Google_Client();
  28. $this->client->setClientId($_ENV['GOOGLE_ID']);
  29. $this->client->setClientSecret($_ENV['GOOGLE_SECRET']);
  30. $this->client->addScope('https://www.googleapis.com/auth/calendar');
  31. $this->client->addScope('https://www.googleapis.com/auth/calendar.events');
  32. // $this->client->addScope(Google_Service_Calendar::CALENDAR);
  33. $this->entityManager = $entityManager;
  34. $this->urlGenerator = $urlGenerator;
  35. $this->container = $container;
  36. }
  37. public function authenticate($authCode)
  38. {
  39. $accessToken = $this->client->fetchAccessTokenWithAuthCode($authCode);
  40. $this->client->setAccessToken($accessToken);
  41. return $accessToken;
  42. }
  43. public function setAccessToken($accessToken)
  44. {
  45. $this->client->setAccessToken($accessToken);
  46. }
  47. public function setUser($user)
  48. {
  49. $this->client = new Google_Client();
  50. $this->client->setClientId($_ENV['GOOGLE_ID']);
  51. $this->client->setClientSecret($_ENV['GOOGLE_SECRET']);
  52. $this->client->addScope('https://www.googleapis.com/auth/calendar');
  53. $this->client->addScope('https://www.googleapis.com/auth/calendar.events');
  54. if (!$user->getGoogleAccessToken()) {
  55. $this->user = null;
  56. }
  57. $this->user = $user;
  58. $this->client->setAccessToken($user->getGoogleAccessToken());
  59. if ($this->client->isAccessTokenExpired()) {
  60. // Refresh the token if it's expired
  61. $refreshToken = $user->getGoogleRefreshToken();
  62. if ($refreshToken) {
  63. $this->client->fetchAccessTokenWithRefreshToken($refreshToken);
  64. $newAccessToken = $this->client->getAccessToken();
  65. $user->setGoogleAccessToken($newAccessToken);
  66. $this->client->setAccessToken($newAccessToken);
  67. $this->entityManager->persist($user);
  68. $this->entityManager->flush();
  69. } else {
  70. $this->user = null;
  71. }
  72. }
  73. }
  74. public function manageLessonEvent(Lesson $lesson)
  75. {
  76. try {
  77. if ($this->user instanceof Teacher) {
  78. if (!$lesson->getGoogleCalendarIdTeacher()) {
  79. $calendarId = 'primary';
  80. // dump('event create');
  81. $response = $this->createEvent($calendarId, $this->formatLessonEvent($lesson));
  82. if($response) {
  83. $lesson->setGoogleCalendarIdTeacher($response->getId());
  84. }
  85. $this->entityManager->persist($lesson);
  86. $this->entityManager->flush();
  87. if($lesson->getGoogleCalendarIdTeacher()) {
  88. $this->checkForDuplicates($lesson, $lesson->getGoogleCalendarIdTeacher());
  89. }
  90. } else {
  91. $calendarId = 'primary';
  92. $response = $this->updateEvent($calendarId, $lesson->getGoogleCalendarIdTeacher(), $this->formatLessonEvent($lesson));
  93. // dump($response);
  94. // die();
  95. if($response) {
  96. $lesson->setGoogleCalendarIdTeacher($response->getId());
  97. }
  98. $this->entityManager->persist($lesson);
  99. $this->entityManager->flush();
  100. if($lesson->getGoogleCalendarIdTeacher()) {
  101. $this->checkForDuplicates($lesson, $lesson->getGoogleCalendarIdTeacher());
  102. }
  103. }
  104. }
  105. if ($this->user instanceof Child) {
  106. if (!$lesson->getGoogleCalendarIdChild()) {
  107. $calendarId = 'primary';
  108. $response = $this->createEvent($calendarId, $this->formatLessonEvent($lesson));
  109. if($response) {
  110. $lesson->setGoogleCalendarIdChild($response->getId());
  111. }
  112. $this->entityManager->persist($lesson);
  113. $this->entityManager->flush();
  114. if($lesson->getGoogleCalendarIdChild()) {
  115. $this->checkForDuplicates($lesson, $lesson->getGoogleCalendarIdChild());
  116. }
  117. } else {
  118. $calendarId = 'primary';
  119. $response = $this->updateEvent($calendarId, $lesson->getGoogleCalendarIdChild(), $this->formatLessonEvent($lesson));
  120. if($response) {
  121. $lesson->setGoogleCalendarIdChild($response->getId());
  122. }
  123. $this->entityManager->persist($lesson);
  124. $this->entityManager->flush();
  125. if($lesson->getGoogleCalendarIdChild()) {
  126. $this->checkForDuplicates($lesson, $lesson->getGoogleCalendarIdChild());
  127. }
  128. }
  129. }
  130. if ($this->user instanceof Guardian) {
  131. if (!$lesson->getGoogleCalendarIdGuardian()) {
  132. $calendarId = 'primary';
  133. $response = $this->createEvent($calendarId, $this->formatLessonEvent($lesson));
  134. if($response) {
  135. $lesson->setGoogleCalendarIdGuardian($response->getId());
  136. }
  137. $this->entityManager->persist($lesson);
  138. $this->entityManager->flush();
  139. if($lesson->getGoogleCalendarIdGuardian()) {
  140. $this->checkForDuplicates($lesson, $lesson->getGoogleCalendarIdGuardian());
  141. }
  142. } else {
  143. $calendarId = 'primary';
  144. $response = $this->updateEvent($calendarId, $lesson->getGoogleCalendarIdGuardian(), $this->formatLessonEvent($lesson));
  145. if($response) {
  146. $lesson->setGoogleCalendarIdGuardian($response->getId());
  147. }
  148. $this->entityManager->persist($lesson);
  149. $this->entityManager->flush();
  150. if($lesson->getGoogleCalendarIdGuardian()) {
  151. $this->checkForDuplicates($lesson, $lesson->getGoogleCalendarIdGuardian());
  152. }
  153. }
  154. }
  155. } catch (\Exception $e) {
  156. $this->logFailure(__METHOD__, $e);
  157. return null;
  158. }
  159. }
  160. public function formatLessonEvent(Lesson $lesson)
  161. {
  162. if ($this->user instanceof Teacher) {
  163. $child = $lesson->getChild();
  164. $name = '';
  165. if ($child) {
  166. $name = $child->getFullname();
  167. }
  168. $summary = "{$lesson->getDiscipline()->getName()} - {$lesson->getClass()} - {$name} | COREPETITUS";
  169. $location = "https://app.corepetitus.lt";
  170. }
  171. if ($this->user instanceof Child || $this->user instanceof Guardian) {
  172. $summary = "{$lesson->getDiscipline()->getName()} - {$lesson->getClass()} - {$lesson->getTeacher()->getFullname()} | COREPETITUS";
  173. $location = $this->container->getParameter('domain') . $this->urlGenerator->generate('unicko_public_router', ['token' => $lesson->getPublicToken()]);
  174. }
  175. $event = [
  176. 'status' => "confirmed",
  177. 'summary' => $summary,
  178. 'location' => $location,
  179. 'start' => new Google_Service_Calendar_EventDateTime([
  180. 'dateTime' => $lesson->getStartTime()->format(\DateTime::RFC3339),
  181. 'timeZone' => 'Europe/Vilnius',
  182. ]),
  183. 'end' => new Google_Service_Calendar_EventDateTime([
  184. 'dateTime' => $lesson->getEndTime()->format(\DateTime::RFC3339),
  185. 'timeZone' => 'Europe/Vilnius',
  186. ]),
  187. ];
  188. return $event;
  189. }
  190. public function createEvent($calendarId = 'primary', $eventData)
  191. {
  192. $service = new Google_Service_Calendar($this->client);
  193. $event = new Google_Service_Calendar_Event($eventData);
  194. try {
  195. return $service->events->insert($calendarId, $event);
  196. } catch (\Exception $e) {
  197. $this->logFailure(__METHOD__, $e);
  198. return null;
  199. }
  200. }
  201. public function updateEvent($calendarId = 'primary', $eventId, $eventData)
  202. {
  203. $service = new Google_Service_Calendar($this->client);
  204. $event = $service->events->get($calendarId, $eventId);
  205. foreach ($eventData as $key => $value) {
  206. $event->$key = $value;
  207. }
  208. try {
  209. return $service->events->update($calendarId, $event->getId(), $event);
  210. } catch (\Exception $e) {
  211. $this->logFailure(__METHOD__, $e);
  212. return null;
  213. }
  214. }
  215. public function deleteEvent($calendarId = 'primary', $eventId)
  216. {
  217. $service = new Google_Service_Calendar($this->client);
  218. try {
  219. return $service->events->delete($calendarId, $eventId);
  220. } catch (\Exception $e) {
  221. $this->logFailure(__METHOD__, $e);
  222. return null;
  223. }
  224. }
  225. public function checkForDuplicates($lesson,$googleCalendarId)
  226. {
  227. $calendarId = 'primary';
  228. $service = new Google_Service_Calendar($this->client);
  229. $summary = '';
  230. if ($this->user instanceof Teacher) {
  231. $child = $lesson->getChild();
  232. $name = '';
  233. if ($child) {
  234. $name = $child->getFullname();
  235. }
  236. $summary = "{$lesson->getDiscipline()->getName()} - {$lesson->getClass()} - {$name} | COREPETITUS";
  237. }
  238. if ($this->user instanceof Child || $this->user instanceof Guardian) {
  239. $summary = "{$lesson->getDiscipline()->getName()} - {$lesson->getClass()} - {$lesson->getTeacher()->getFullname()} | COREPETITUS";
  240. }
  241. if ($this->user instanceof Teacher) {
  242. try {
  243. $events = $service->events->listEvents($calendarId, [
  244. 'q' => "https://app.corepetitus.lt",
  245. 'timeMin' => $lesson->getStartTime()->format(\DateTime::RFC3339),
  246. 'timeMax' => $lesson->getEndTime()->format(\DateTime::RFC3339),
  247. ]);
  248. $items = $events->getItems();
  249. if ($items > 1) {
  250. foreach ($items as $item) {
  251. if ($item->getId() != $googleCalendarId && $item->getLocation() == 'https://app.corepetitus.lt' && $item->getSummary() == $summary) {
  252. $this->deleteEvent($calendarId, $item->getId());
  253. }
  254. }
  255. }
  256. } catch (\Exception $e) {
  257. $this->logFailure(__METHOD__, $e);
  258. return null;
  259. }
  260. }
  261. if ($this->user instanceof Child or $this->user instanceof Guardian) {
  262. try {
  263. $events = $service->events->listEvents($calendarId, [
  264. 'q' => "https://app.corepetitus.lt/pamoka/{$lesson->getPublicToken()}",
  265. 'timeMin' => $lesson->getStartTime()->format(\DateTime::RFC3339),
  266. 'timeMax' => $lesson->getEndTime()->format(\DateTime::RFC3339),
  267. ]);
  268. $items = $events->getItems();
  269. if ($items > 1) {
  270. foreach ($items as $item) {
  271. if ($item->getId() != $googleCalendarId && $item->getSummary() == $summary) {
  272. $this->deleteEvent($calendarId, $item->getId());
  273. }
  274. }
  275. }
  276. } catch (\Exception $e) {
  277. $this->logFailure(__METHOD__, $e);
  278. return null;
  279. }
  280. }
  281. }
  282. public function deleteEverything()
  283. {
  284. $calendarId = 'primary';
  285. $service = new Google_Service_Calendar($this->client);
  286. try {
  287. $events = $service->events->listEvents($calendarId, [
  288. 'q' => "https://app.corepetitus.lt",
  289. ]);
  290. $items = $events->getItems();
  291. foreach ($items as $item) {
  292. $this->deleteEvent($calendarId, $item->getId());
  293. usleep(500000);
  294. }
  295. } catch (\Exception $e) {
  296. $this->logFailure(__METHOD__, $e);
  297. return null;
  298. }
  299. }
  300. private function logFailure(string $method, \Throwable $exception): void
  301. {
  302. $this->calendarLogger->warning('Google Calendar request failed', [
  303. 'method' => $method,
  304. 'exception' => $exception,
  305. ]);
  306. }
  307. }