--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Controller;
+
+use Google\Service\Calendar;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+use Symfony\Component\Cache\Adapter\FilesystemAdapter;
+
+#use Rapsys\AirBundle\Entity\Slot;
+#use Rapsys\AirBundle\Entity\Session;
+#use Rapsys\AirBundle\Entity\Location;
+#use Rapsys\AirBundle\Entity\User;
+#use Rapsys\AirBundle\Entity\Snippet;
+
+class CalendarController extends DefaultController {
+ /**
+ * Calendar authorization
+ *
+ * @desc Initiate calendar oauth process
+ *
+ * @param Request $request The request instance
+ *
+ * @return Response The rendered view
+ */
+ public function index(Request $request): Response {
+ //Prevent non-admin to access here
+ $this->denyAccessUnlessGranted('ROLE_ADMIN', null, $this->translator->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator->trans('Admin')]));
+
+ //Fetch doctrine
+ #$doctrine = $this->getDoctrine();
+
+ //Set section
+ $section = $this->translator->trans('Calendar oauth form');
+
+ //Set description
+ $this->context['description'] = $this->translator->trans('Initiate calendar oauth process');
+
+ //Set title
+ $title = $this->translator->trans($this->config['site']['title']).' - '.$section;
+
+ //Create the form according to the FormType created previously.
+ //And give the proper parameters
+ $form = $this->createForm('Rapsys\AirBundle\Form\CalendarType', ['calendar' => $this->config['calendar']['calendar'], 'prefix' => $this->config['calendar']['prefix']], [
+ 'action' => $this->generateUrl('rapsys_air_calendar'),
+ 'method' => 'POST'
+ ]);
+
+ if ($request->isMethod('POST')) {
+ // Refill the fields in case the form is not valid.
+ $form->handleRequest($request);
+
+ if ($form->isValid()) {
+ //Get data
+ $data = $form->getData();
+
+ //When empty use config project
+ $data['project'] = $data['project']?:$this->config['calendar']['project'];
+
+ //When empty use config client
+ $data['client'] = $data['client']?:$this->config['calendar']['client'];
+
+ //When empty use config secret
+ $data['secret'] = $data['secret']?:$this->config['calendar']['secret'];
+
+ //Get google client
+ $googleClient = new \Google\Client(
+ [
+ 'application_name' => $data['project'],
+ 'client_id' => $data['client'],
+ 'client_secret' => $data['secret'],
+ 'redirect_uri' => $redirect = $this->generateUrl('rapsys_air_calendar_callback', [], UrlGeneratorInterface::ABSOLUTE_URL),
+ 'scopes' => [Calendar::CALENDAR, Calendar::CALENDAR_EVENTS],
+ 'access_type' => 'offline',
+ 'approval_prompt' => 'force'
+ ]
+ );
+
+# //Set application name
+# $googleClient->setApplicationName($data['project']);
+#
+# //Set client
+# $googleClient->setClientId($data['client']);
+#
+# //Set client secret
+# $googleClient->setClientSecret($data['secret']);
+#
+# //Add calendar scope
+# //XXX: required to create the airlibre calendar ?
+# $googleClient->addScope(Calendar::CALENDAR);
+# //Add calendar events scope
+# $googleClient->addScope(Calendar::CALENDAR_EVENTS);
+#
+# //Set redirect uri
+# $googleClient->setRedirectUri($redirect = $this->generateUrl('rapsys_air_calendar_callback', [], UrlGeneratorInterface::ABSOLUTE_URL));
+#
+# //Set offline access
+# $googleClient->setAccessType('offline');
+#
+# //Set included scopes
+# //TODO: remove that useless of check scopes in callback
+# $googleClient->setIncludeGrantedScopes(true);
+
+ //Set login hint
+ #$googleClient->setLoginHint('rapsys.eu@gmail.com');
+
+ //Set prompt
+ //TODO: force refresh token creation with approval prompt
+ #$googleClient->setApprovalPrompt('consent');
+
+ //Get auth url
+ $authUrl = $googleClient->createAuthUrl();
+
+ //Get session
+ $session = $request->getSession();
+
+ //Store calendar, prefix, project, client and secret in session
+ $session->set('calendar.calendar', $data['calendar']);
+ $session->set('calendar.prefix', $data['prefix']);
+ $session->set('calendar.project', $data['project']);
+ $session->set('calendar.client', $data['client']);
+ $session->set('calendar.secret', $data['secret']);
+ $session->set('calendar.redirect', $redirect);
+
+ //Redirect externally
+ return $this->redirect($authUrl);
+ }
+ }
+
+ //Render template
+ return $this->render('@RapsysAir/calendar/index.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView()]+$this->context);
+ }
+
+ /**
+ * List all sessions for the organizer
+ *
+ * @desc Display all sessions for the user with an application or login form
+ *
+ * @param Request $request The request instance
+ *
+ * @return Response The rendered view
+ */
+ public function callback(Request $request) {
+ //Set section
+ $section = $this->translator->trans('Calendar callback');
+
+ //Set description
+ $this->context['description'] = $this->translator->trans('Finish calendar oauth process');
+
+ //Set title
+ $title = $this->translator->trans($this->config['site']['title']).' - '.$section;
+
+ //With code
+ if (!empty($code = $request->get('code'))) {
+ //Get session
+ $session = $request->getSession();
+
+ //Retrieve calendar
+ $calendar = $session->get('calendar.calendar');
+
+ //Retrieve prefix
+ $prefix = $session->get('calendar.prefix');
+
+ //Retrieve project
+ $project = $session->get('calendar.project');
+
+ //Retrieve client id
+ $client = $session->get('calendar.client');
+
+ //Retrieve secret
+ $secret = $session->get('calendar.secret');
+
+ //Retrieve redirect
+ $redirect = $session->get('calendar.redirect');
+
+ //Get google client
+ #$googleClient = new \Google\Client(['application_name' => $project, 'client_id' => $client, 'client_secret' => $secret, 'redirect_uri' => $redirect]);
+ $googleClient = new \Google\Client(
+ [
+ 'application_name' => $project,
+ 'client_id' => $client,
+ 'client_secret' => $secret,
+ 'redirect_uri' => $redirect,
+ 'scopes' => [Calendar::CALENDAR, Calendar::CALENDAR_EVENTS],
+ 'access_type' => 'offline',
+ 'approval_prompt' => 'force'
+ ]
+ );
+
+ //Authenticate with code
+ if (!empty($token = $googleClient->authenticate($code))) {
+ //With error
+ if (!empty($token['error'])) {
+ $this->context['error'] = $this->translator->trans(ucfirst(str_replace('_', ' ', $token['error'])));
+ //Without refresh token
+ } elseif (empty($token['refresh_token'])) {
+ $this->context['error'] = $this->translator->trans('Missing refresh token');
+ //With valid token
+ } else {
+ //Retrieve cache object
+ $cache = new FilesystemAdapter($this->config['cache']['namespace'], $this->config['cache']['lifetime'], $this->config['cache']['directory']);
+
+ //Retrieve calendars
+ $cacheCalendars = $cache->getItem('calendars');
+
+ //Init calendar
+ $calendars = [];
+
+ //With calendars
+ if ($cacheCalendars->isHit()) {
+ //Retrieve calendar
+ $calendars = $cacheCalendars->get();
+ }
+
+ //With empty client
+ if (empty($calendars[$client])) {
+ //Store client
+ $calendars[$client] = [
+ 'project' => $project,
+ 'secret' => $secret,
+ 'redirect' => $redirect,
+ 'tokens' => []
+ ];
+ }
+
+ //Add token
+ $calendars[$client]['tokens'][$token['access_token']] = [
+ 'calendar' => $calendar,
+ 'prefix' => $prefix,
+ 'refresh' => $token['refresh_token'],
+ 'expire' => $token['expires_in'],
+ 'scope' => $token['scope'],
+ 'type' => $token['token_type'],
+ 'created' => $token['created']
+ ];
+
+ //Store calendar
+ $cacheCalendars->set($calendars);
+
+ //Save calendar
+ $cache->save($cacheCalendars);
+
+ //Set message
+ $this->context['message'] = $this->translator->trans('Token stored for project '.$project);
+ }
+ //With failed authenticate
+ } else {
+ $this->context['error'] = $this->translator->trans('Client authenticate failed');
+ }
+ //With error
+ } elseif (!empty($error = $request->get('error'))) {
+ $this->context['error'] = $this->translator->trans(ucfirst(str_replace('_', ' ', $error)));
+ }
+
+ //Render template
+ return $this->render('@RapsysAir/calendar/callback.html.twig', ['title' => $title, 'section' => $section]+$this->context);
+ }
+}