<?php
namespace App\Controller\Front;
use App\Entity\Course;
use App\Entity\Live;
use App\Entity\ModuleParticipation;
use App\Entity\Program;
use App\Entity\Quiz;
use App\Entity\Module;
use App\Form\ProgramType;
use App\Helper\ControllerHelper;
use App\Repository\CourseRepository;
use App\Repository\JitsiParameterRepository;
use App\Repository\LiveRepository;
use App\Repository\ModuleItemRepository;
use App\Repository\ModuleParticipationRepository;
use App\Repository\ProgramRepository;
use App\Repository\QuizRepository;
use App\Service\HelperService;
use DateInterval;
use DateTime;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\JsonResponse;
use Jose\Component\KeyManagement\JWKFactory;
use Jose\Component\Core\AlgorithmManager;
use Jose\Component\Signature\Algorithm\RS256;
use Jose\Component\Signature\JWSBuilder;
use Jose\Component\Signature\Serializer\CompactSerializer;
/**
* Require ROLE_EMPLOYEE for all the actions of this controller
*
* @IsGranted("ROLE_EMPLOYEE")
*
* @Route("/live")
*/
class LiveController extends AbstractController
{
use ControllerHelper;
/**
* @Route("/{id}/meeting", name="app_front_live_meet_page")
* @Route("/{id}/{module_slug}/meeting", name="app_front_live_module_meet_page")
* @ParamConverter("module", options={"mapping": {"module_slug": "slug"}})
*/
public function index(Request $request, JitsiParameterRepository $jitsiParameterRepository, ModuleParticipationRepository $moduleParticipationRepository, ModuleItemRepository $moduleItemRepository, CourseRepository $courseRepository, QuizRepository $quizRepository, LiveRepository $liveRepository, Live $live, HelperService $helperService, Module $module = null): Response
{
$currentUser = $this->getUser();
if ($live === null) throw $this->createAccessDeniedException("Accès non autorisé");
if ($module === null) $module = $this->getActiveModule($live, $currentUser);
$program = new Program();
$form = $this->createForm(ProgramType::class, $program);
$form->handleRequest($request);
$jitsiParameter = $jitsiParameterRepository->findOneBy(['isActive' => true]);
// $module = $this->getActiveModule($live);
if ($jitsiParameter === null || $module === null) {
throw $this->createAccessDeniedException("Impossible de demarrer la conférence. Veuillez contacter l'administrateur !");
}
$isModerator = (($live->getCoaches()->count() > 0 && $live->getCoaches()->contains($currentUser)) || $this->isGranted('ROLE_INTEGRATOR') || $this->isGranted('ROLE_ADMIN'));
// $module = $this->getActiveModule($live);
$_program = $this->getActiveProgram($module, true, $currentUser);
$moduleParticipation = $moduleParticipationRepository->findOneBy(['program' => $_program, 'module' => $module, 'live' => $live, 'createdBy' => $currentUser]);
if ($moduleParticipation === null) {
$moduleParticipation = new ModuleParticipation();
$moduleParticipation->setModule($module);
$moduleParticipation->setLive($live);
$moduleParticipation->setProgram($_program);
$moduleParticipationRepository->add($moduleParticipation, true);
}
$startDate = clone $live->getStartAt();
$endDate = clone $live->getEndAt();
// $liveStartAt = $live->getStartAt()->format('d/m/Y');
// $liveEndAt = $live->getEndAt()->format('d/m/Y');
$liveStartAt = ($startDate !== null) ? $startDate : new DateTime();
$liveEndAt = ($endDate !== null) ? $endDate->add(new DateInterval('P1D')) : $startDate->add(new DateInterval('P1D'));
$liveStartAt->setTime(0, 0, 0);
$liveEndAt->setTime(23, 59, 59);
$nbf = $liveStartAt->format('U');
$exp = $liveEndAt->format('U');
$items = $moduleItemRepository->findItems($module);
$keys = [];
$keys = array_keys(array_column($items, 'live_id'), $live->getId());
$currentItemKey = isset($keys[0]) ? $keys[0] : 0;
$currentItemAsArray = $items[$currentItemKey];
$prevItemAsArray = (isset($items[$currentItemKey - 1])) ? $items[$currentItemKey - 1] : null;
$nextItemAsArray = (isset($items[$currentItemKey + 1])) ? $items[$currentItemKey + 1] : null;
$prevItem = null;
$nextItem = null;
if ($prevItemAsArray !== null && isset($prevItemAsArray['type'])) {
// $prevItem = ($prevItemAsArray['type'] === 'course') ? $courseRepository->findOneById($prevItemAsArray['course_id']) : $quizRepository->findOneById($prevItemAsArray['quiz_id']);
switch ($prevItemAsArray['type']) {
case 'course':
$prevItem = $courseRepository->findOneById($prevItemAsArray['course_id']);
break;
case 'quiz':
$prevItem = $quizRepository->findOneById($prevItemAsArray['quiz_id']);
break;
default:
$prevItem = $liveRepository->findOneById($prevItemAsArray['live_id']);
break;
}
// $prevItem = $quizRepository->findOneById($prevItemAsArray[$prevItemAsArray['type'].'_id']);
}
if ($nextItemAsArray !== null && isset($nextItemAsArray['type'])) {
// $nextItem = ($nextItemAsArray['type'] === 'course') ? $courseRepository->findOneById($nextItemAsArray['course_id']) : $quizRepository->findOneById($nextItemAsArray['quiz_id']);
switch ($nextItemAsArray['type']) {
case 'course':
$nextItem = $courseRepository->findOneById($nextItemAsArray['course_id']);
break;
case 'quiz':
$nextItem = $quizRepository->findOneById($nextItemAsArray['quiz_id']);
break;
default:
$nextItem = $liveRepository->findOneById($nextItemAsArray['live_id']);
break;
}
// $nextItem = $courseRepository->findOneById($nextItemAsArray[$nextItemAsArray['type'].'_id']);
}
$prevItemType = ($prevItem !== null) ? (($prevItem instanceof Course) ? 'course' : (($prevItem instanceof Quiz) ? 'quiz' : 'live')) : null;
$nextItemType = ($nextItem !== null) ? (($nextItem instanceof Course) ? 'course' : (($nextItem instanceof Quiz) ? 'quiz' : 'live')) : null;
// Jaas Token generation
$token = $helperService->getJaasToken($currentUser, $jitsiParameter, $isModerator, $nbf, $exp);
$isQuizzAlreadyStarted = false;
if ($prevItemType === 'quiz' || $nextItemType === 'quiz') {
$moduleParticipation = ($prevItemType === 'quiz') ? $moduleParticipationRepository->findOneBy(['program' => $program, 'module' => $module, 'quiz' => $prevItem, 'createdBy' => $currentUser]) : $moduleParticipationRepository->findOneBy(['module' => $module, 'quiz' => $nextItem, 'createdBy' => $currentUser]);
$isQuizzAlreadyStarted = ($moduleParticipation !== null);
}
return $this->render('front/pages/live/index.html.twig', [
'program' => $program,
'live' => $live,
'form' => $form,
'jitsiParameter' => $jitsiParameter,
'isModerator' => $isModerator,
'nbf' => $nbf,
'exp' => $exp,
'module' => $module,
'prevItem' => $prevItem,
'prevItemType' => $prevItemType,
'nextItem' => $nextItem,
'nextItemType' => $nextItemType,
'token' => $token,
'isJaas' => $jitsiParameter->isIsJaas(),
'canAccess' => $liveStartAt <= (new DateTime())->setTime(0,0,0) && $liveEndAt >= (new DateTime())->setTime(0,0,0),
'isQuizzAlreadyStarted' => $isQuizzAlreadyStarted
]);
}
/**
* @Route("/{slug}/meeting-cofilive", name="app_front_cofi_live_meet_page")
* @ParamConverter("live", options={"mapping": {"slug": "slug"}})
*/
public function cofilive(Request $request, JitsiParameterRepository $jitsiParameterRepository, LiveRepository $liveRepository, Live $live): Response
{
if ($live === null) throw $this->createAccessDeniedException("Accès non autorisé");
$program = new Program();
$form = $this->createForm(ProgramType::class, $program);
$form->handleRequest($request);
$jitsiParameter = $jitsiParameterRepository->findOneBy(['isActive' => true]);
// $module = $this->getActiveModule($live);
if ($jitsiParameter === null) {
throw $this->createAccessDeniedException("Impossible de demarrer la conférence. Veuillez contacter l'administrateur !");
}
$isModerator = (($live->getCoaches()->count() > 0 && $live->getCoaches()->contains($this->getUser())) || $this->isGranted('ROLE_INTEGRATOR') || $this->isGranted('ROLE_ADMIN'));
$startDate = clone $live->getStartAt();
$endDate = clone $live->getEndAt();
$liveStartAt = ($startDate !== null) ? $startDate : new DateTime();
$liveEndAt = ($endDate !== null) ? $endDate->add(new DateInterval('P1D')) : $startDate->add(new DateInterval('P1D'));
$liveStartAt->setTime(0, 0, 0);
$liveEndAt->setTime(23, 59, 59);
$nbf = $liveStartAt->format('U');
$exp = $liveEndAt->format('U');
$jwk = JWKFactory::createFromKeyFile($this->getParameter('kernel.project_dir').'/jitsi/Cofina.pk');
/**
* Setup the algoritm used to sign the token.
* @var \Jose\Component\Core\AlgorithmManager $algorithm
*/
$algorithm = new AlgorithmManager([
new RS256()
]);
/**
* The builder will create and sign the token.
* @var \Jose\Component\Signature\JWSBuilder $jwsBuilder
*/
$jwsBuilder = new JWSBuilder($algorithm);
$currentUser = $this->getUser();
/**
* Must setup JaaS payload!
* Change the claims below or using the variables from above!
*/
$payload = json_encode([
'iss' => 'chat',
'aud' => 'jitsi',
'exp' => (int)$exp,
'nbf' => (int)$nbf,
'room'=> '*',
'sub' => $jitsiParameter->getAppId(),
'context' => [
'user' => [
'moderator' => $isModerator ? "true" : "false",
'email' => $currentUser->getEmail(),
'name' => $currentUser->getFullName(),
'avatar' => '/assets/front/img/LOGO COFINA ACADEMY 1.png',
'id' => $currentUser->getId()
],
'features' => [
'recording' => "true",
'livestreaming' => "true",
'transcription' => "true",
'outbound-call' => "false"
]
]
]);
/**
* Create a JSON Web Signature (https://tools.ietf.org/html/rfc7515)
* using the payload created above and the api key specified for the kid claim.
* 'alg' (RS256) and 'typ' claims are also needed.
*/
$jws = $jwsBuilder
->create()
->withPayload($payload)
->addSignature($jwk, [
'alg' => 'RS256',
'kid' => $jitsiParameter->getAppSecret(),
'typ' => 'JWT'
])
->build();
/**
* We use the serializer to base64 encode into the final token.
* @var \Jose\Component\Signature\Serializer\CompactSerializer $serializer
*/
$serializer = new CompactSerializer();
$token = $serializer->serialize($jws, 0);
//dd(, (new DateTime())->setTime(0,0,0));
//dd((new DateTime())->setTime(0,0,0));
//dd($liveStartAt <= (new DateTime())->setTime(0,0,0) && $liveEndAt >= (new DateTime())->setTime(0,0,0));
return $this->render('front/pages/live/index.html.twig', [
'program' => $program,
'live' => $live,
'form' => $form,
'jitsiParameter' => $jitsiParameter,
'isModerator' => $isModerator,
'nbf' => $nbf,
'exp' => $exp,
'module' => null,
'prevItem' => null,
'prevItemType' => null,
'nextItem' => null,
'nextItemType' => null,
'token' => $token,
'isJaas' => $jitsiParameter->isIsJaas(),
'canAccess' => $liveStartAt <= (new DateTime())->setTime(0,0,0) && $liveEndAt >= (new DateTime())->setTime(0,0,0)
]);
}
/**
* @Route("/{profil}/page", name="app_front_lives_page")
*/
public function live(Request $request, LiveRepository $liveRepository): Response
{
// {
// id: 'a',
// start: '2023-02-03 02:30:00',
// url: "javascript:void(0)",
// link: "{{ url('app_front_homepage') }}",
// classNames: "text-center fw-bold w-100",
// title: "Academy UPB",
// backgroundColor: "transparent",
// borderColor: "transparent",
// textColor: "#000",
// imgUrl: `{{ asset("assets/front/img/users.jpg") }}`,
// imgBackgroundColor: function (){
// const palette = getPalette(this.imgUrl)
// return `repeating-linear-gradient( -45deg, rgb(${palette[0]}) 0 50px, rgb(${palette[1]}) 20px 90px);`
// },
// coachName: "Test",
// coachImg: "{{ asset("assets/front/img/users.jpg") }}"
// }
$lives = $liveRepository->findViewLive($this->getUser());
$liveDate = [];
foreach ($lives as $key => $live) {
$data ['id'] = $live->getId();
$data ['start'] = $live->getStartAt()->format('Y-m-d H:i:s');
$data ['end'] = $live->getEndAt()->format('Y-m-d H:i:s');
//$data ['url'] = $this->generateUrl('app_front_live_meet_page', ['id' => $live->getId()], UrlGeneratorInterface::ABSOLUTE_URL);;
$data ['classNames'] = 'text-center fw-bold w-100';
$data ['title'] = $live->getTitle();
$data ['backgroundColor'] = 'transparent';
$data ['borderColor'] = 'transparent';
$data ['textColor'] = '#000';
$data ['imgUrl'] = ($live->getCover() !== null) ? '/files/images/'.$live->getCover()->getFileName() : '';
$data ['imgBackgroundColor'] = '';
$data ['coachName'] = (!$live->getCoaches()->isEmpty() ? $live->getCoaches()->first()->getFullname() : '');
$data ['coachImg'] = (!$live->getCoaches()->isEmpty() && $live->getCoaches()->first()->getPhoto() !== null ? '/files/images/'.$live->getCoaches()->first()->getPhoto()->getFileName() : '');
$_modules = [];
foreach($live->getModules() as $_module) {
$_modules[] = array('id' => $_module->getId(), 'name' => $_module->getName(), 'slug' => $_module->getSlug(), 'cover' => $_module->getCover());
}
$data['modules'] = $_modules;
$data['slug'] = $live->getSlug();
$liveDate [] = $data;
}
// dump($liveDate); die;
$futureLives = $liveRepository->findFutureLives($this->getUser());
return $this->render('front/pages/live/live.html.twig', [
'future_lives' => $futureLives,
'live_data' => $liveDate,
'lives' => $lives,
]);
}
/**
* @Route("/{profil}/has-running-live", name="app_front_has_running_live", methods={"GET"})
*/
public function hasRunningLive(Request $request, LiveRepository $liveRepository): Response
{
if(!$this->getUser()) {
return null;
}
$lives = $liveRepository->hasCurrentLive($this->getUser());
//dd($lives);
return new JsonResponse(array('runningLive' => count($lives)));
}
}