<?php
namespace CodersLab\Lms\UserInterface\Rest\Controller;
use CodersLab\Lms\Modules\IdentityAccess\Application\IContentAccessContext;
use CodersLab\Lms\Modules\IdentityAccess\Application\ICourseInstanceContext;
use CodersLab\Lms\Modules\IdentityAccess\Application\Query\Model\User\LastSeenMaterial;
use CodersLab\Lms\Modules\IdentityAccess\Application\Query\ProgressQuery;
use CodersLab\Lms\Modules\IdentityAccess\Application\Query\UserAccessQuery;
use CodersLab\Lms\Modules\Materials\Application\Query\CourseQuery;
use CodersLab\Lms\Modules\Materials\Application\Query\Model\Course;
use CodersLab\Lms\SharedKernel\Application\Response\LmsApiResponse;
use CodersLab\Lms\SharedKernel\Application\SecurityContext;
use CodersLab\Lms\SharedKernel\Common\Exception\AccessDeniedHttpException;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerInterface;
use Nelmio\ApiDocBundle\Annotation\Model;
use OpenApi\Annotations as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
/**
* @OA\Tag(name="Course")
*/
final class CourseController
{
public function __construct(
private CourseQuery $courseQuery,
private SecurityContext $security,
private IContentAccessContext $accessContext,
private ICourseInstanceContext $instanceContext,
private SerializerInterface $serializer,
private UserAccessQuery $userAccessQuery,
private ProgressQuery $progressQuery
) {
}
/**
* @Route("/course/{instanceId}", name="course_single_id", methods={"GET"}, requirements={"instanceId"="\d+"})
* @OA\Parameter(name="instanceId", in="path", @OA\Schema(type="string"))
* @OA\Response(
* response=200,
* description="Single course by instance id",
* @OA\Schema(ref=@Model(type="CodersLab\Lms\Modules\Materials\Application\Query\Model\Course"))
* )
*/
public function getSingleById(string $instanceId): JsonResponse
{
$course = $this->courseQuery->getByInstanceId($instanceId);
return $this->proceedResponse($course, (int)$instanceId);
}
/**
* @Route("/course/{signature}", name="course_single_signature", methods={"GET"})
* @OA\Parameter(name="signature", in="path", @OA\Schema(type="string"))
* @OA\Response(
* response=200,
* description="Single course by instance id",
* @OA\Schema(ref=@Model(type="CodersLab\Lms\Modules\Materials\Application\Query\Model\Course"))
* )
*/
public function getSingleBySignature(string $signature): JsonResponse
{
$course = $this->courseQuery->getBySignature($signature);
$instanceId = $this->courseQuery->findInstanceIdForSignature($signature);
return $this->proceedResponse($course, (int)$instanceId);
}
/**
* @Route("/course/{instanceId}/progress", name="course_single_id_progress", methods={"GET"}, requirements={"instanceId"="\d+"})
* @OA\Parameter(name="instanceId", in="path", @OA\Schema(type="string"))
* @OA\Response(
* response=200,
* description="Single course by instance id",
* @OA\Schema(ref=@Model(type="CodersLab\Lms\Modules\Materials\Application\Query\Model\Course"))
* )
*/
public function getSingleResultsById(string $instanceId): JsonResponse
{
$course = $this->courseQuery->getByInstanceId($instanceId);
$course->addProgress($this->progressQuery->forCourseInstance(
(string)$instanceId,
(string)$this->security->getLoggedUser()->id()
));
$context = SerializationContext::create()->setSerializeNull(true);
$context->setGroups(['progress', 'Default']);
return LmsApiResponse::createFromJsonString($this->serializer->serialize(
['data' => $course],
'json',
$context
));
}
/**
* @Route("/course/{signature}/progress", name="course_single_signature_progress", methods={"GET"})
* @OA\Parameter(name="signature", in="path", @OA\Schema(type="string"))
* @OA\Response(
* response=200,
* description="Single course by instance id",
* @OA\Schema(ref=@Model(type="CodersLab\Lms\Modules\Materials\Application\Query\Model\Course"))
* )
*/
public function getSingleResultsBySignature(string $signature): JsonResponse
{
$course = $this->courseQuery->getBySignature($signature);
$course->addProgress($this->progressQuery->forCourseInstance(
(string)$this->courseQuery->findInstanceIdForSignature($signature),
(string)$this->security->getLoggedUser()->id()
));
$context = SerializationContext::create()->setSerializeNull(true);
$context->setGroups(['progress', 'Default']);
return LmsApiResponse::createFromJsonString($this->serializer->serialize(
['data' => $course],
'json',
$context
));
}
/**
* @Route("/directAccess/course/{courseId}", name="direct_access_course_single", methods={"GET"})
* @OA\Parameter(name="courseId", in="path", @OA\Schema(type="string"))
* @OA\Response(
* response=200,
* description="Single course by instance id",
* @OA\Schema(ref=@Model(type="CodersLab\Lms\Modules\Materials\Application\Query\Model\Course"))
* )
*/
public function getSingleDirectAccess(string $courseId): JsonResponse
{
$course = $this->courseQuery->getById($courseId);
$user = $this->security->getLoggedUser();
$directAccess = $this->accessContext->hasDirectAccess($user->id(), $course->getProduct()->getId());
if ($directAccess === false) {
throw new AccessDeniedHttpException();
}
$context = SerializationContext::create()->setSerializeNull(true);
$context->setGroups(['details', 'progress', 'Default']);
return LmsApiResponse::createFromJsonString($this->serializer->serialize(
['data' => $course],
'json',
$context
));
}
private function proceedResponse(Course $course, int $instanceId): JsonResponse
{
$user = $this->security->getLoggedUser();
if (!$this->accessContext->hasAccessToCourseInstance($user->id(), $instanceId)) {
$directAccess = $this->accessContext->hasDirectAccess($user->id(), $course->getProduct()->getId());
if ($directAccess === true) {
return new LmsApiResponse($course);
}
throw new AccessDeniedHttpException();
}
$lastSeenMaterial = $this->instanceContext->getLastSeenMaterial((string)$user->id(), (string)$instanceId);
if ($lastSeenMaterial instanceof LastSeenMaterial) {
$course->markLastSeenMaterial($lastSeenMaterial);
}
$moduleLecturers = $this->instanceContext->getModulesLecturers((string)$instanceId);
$course->setLecturers($moduleLecturers);
$chaptersStatistics = $this->courseQuery->getChaptersMaterialsStatistics((string)$instanceId);
$course->addChaptersStatistics($chaptersStatistics);
$access = $this->userAccessQuery->findChaptersAccessOnCourse((string)$instanceId, (string)$user->id());
$course->setAccess($access);
$context = SerializationContext::create()->setSerializeNull(true);
$context->setGroups(['details', 'Default']);
return LmsApiResponse::createFromJsonString($this->serializer->serialize(
['data' => $course],
'json',
$context
));
}
}