<?php
namespace CodersLab\Lms\UserInterface\Rest\Controller;
use CodersLab\Lms\Modules\Courses\Application\Query\CourseInstanceFilter;
use CodersLab\Lms\Modules\Courses\Application\Query\CourseInstanceQuery;
use CodersLab\Lms\Modules\IdentityAccess\Application\IContentAccessContext;
use CodersLab\Lms\Modules\Learning\Application\Query\StudentQuery;
use CodersLab\Lms\SharedKernel\Application\Response\CourseMetadata;
use CodersLab\Lms\SharedKernel\Application\Response\LmsApiResponse;
use CodersLab\Lms\SharedKernel\Application\Response\Metadata;
use CodersLab\Lms\SharedKernel\Application\SecurityContext;
use CodersLab\Lms\SharedKernel\Common\Exception\AccessDeniedHttpException;
use CodersLab\Lms\SharedKernel\Common\Exception\BadRequestHttpException;
use CodersLab\Lms\SharedKernel\Common\Exception\NotFoundException;
use CodersLab\Lms\SharedKernel\Domain\Courses\MemberType;
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\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
/**
* @OA\Tag(name="Course Instance")
*/
final class CourseInstanceController
{
public function __construct(
private CourseInstanceQuery $courseInstanceQuery,
private StudentQuery $studentQuery,
private SecurityContext $securityContext,
private IContentAccessContext $accessContext,
private SerializerInterface $serializer
) {
}
/**
* @Route("/course_instance", name="course_instance_details", methods={"GET"})
* @OA\Parameter(name="id", in="query", @OA\Schema(type="string"))
* @OA\Parameter(name="signature", in="query", @OA\Schema(type="string"))
* @OA\Response(
* response=200,
* description="Single course instance",
* @OA\Schema(ref=@Model(type="CodersLab\Lms\Modules\Courses\Application\Query\Model\CourseInstance"))
* )
*/
public function getSingle(Request $request): LmsApiResponse
{
$params = $request->query->all();
if (!isset($params['id']) && !isset($params['signature'])) {
throw new BadRequestHttpException('Instance id or signature is required');
}
if (isset($params['id'])) {
$instance = $this->courseInstanceQuery->getById((int)$params['id']);
} else {
$instance = $this->courseInstanceQuery->getBySignature($params['signature']);
}
$instance->setAccess($this->courseInstanceQuery->getAccess(
(string)$instance->getId(),
$this->securityContext->getLoggedUserId()
));
$user = $this->securityContext->getLoggedUser();
$access = $this->accessContext->hasAccessToCourseInstance(
$user->id(),
$instance->getId()
);
if (!$access) {
throw new AccessDeniedHttpException();
}
$metadata = CourseMetadata::create($this->accessContext->getUserCourseInstanceRoles($user->id(), (string)$instance->getId()));
return new LmsApiResponse($instance, $metadata);
}
/**
* @Route("/course_instances", name="course_instance_list", methods={"GET"})
* @OA\Parameter(name="signature", in="query", @OA\Schema(type="string"))
* @OA\Parameter(name="page", in="query", @OA\Schema(type="string"))
* @OA\Response(
* response=200,
* description="Single course instance",
* @OA\JsonContent(
* type="array",
* @OA\Items(ref=@Model(type="CodersLab\Lms\Modules\Courses\Application\Query\Model\CourseInstance"))
* )
* )
*/
public function getList(Request $request): LmsApiResponse
{
$filter = CourseInstanceFilter::fromRequest($request, $this->securityContext->getLoggedUserId());
$data = $this->courseInstanceQuery->find($filter);
$total = $this->courseInstanceQuery->count($filter);
foreach ($data as $courseInstance) {
$roles = $this->accessContext->getUserCourseInstanceRoles($this->securityContext->getLoggedUserId(), (string)$courseInstance->getId());
$courseInstance->setRoles($roles);
}
return new LmsApiResponse($data, Metadata::forList($filter->getFilter()->page(), $filter->getFilter()->limit(), $total));
}
/**
* @Route(
* "/course_instance/{courseInstanceId}/students",
* name="course_instance_students",
* methods={"GET"},
* requirements={"courseInstanceId"="\d+"}
* )
* @OA\Parameter(name="courseInstanceId", in="path", @OA\Schema(type="integer"))
* @OA\Response(
* response=200,
* description="Course instance students list",
* @OA\JsonContent(
* type="array",
* @OA\Items(ref=@Model(type="CodersLab\Lms\Modules\Learning\Application\Query\Model\Student", groups={"InstanceStudents"}))
* )
* )
*
*/
public function getStudents(int $courseInstanceId): JsonResponse
{
try {
$courseInstance = $this->courseInstanceQuery->getById($courseInstanceId);
} catch (NotFoundException $ex) {
throw new BadRequestHttpException($ex->getMessage());
}
$hasAccess = $this->accessContext->hasAccessToCourseInstance(
$this->securityContext->getLoggedUser()->id(),
$courseInstance->getId(),
[MemberType::MENTOR()->getValue(), MemberType::LECTURER()->getValue()]
);
if ($hasAccess === false) {
throw new AccessDeniedHttpException('Only mentor and lecturer has access to course instance students list');
}
$students = $this->studentQuery->findByCourseInstance($courseInstanceId);
$context = SerializationContext::create();
$context->setGroups('InstanceStudents');
return LmsApiResponse::createFromJsonString(
$this->serializer->serialize(
['data' => $students, 'metadata' => []],
'json',
$context
)
);
}
/**
* @Route("/course-instance/{instanceId}/side-menu", name="instance_side_menu", methods={"GET"})
* @OA\Response(
* response=200,
* description="Course Instance side menu",
* @OA\Schema(ref=@Model(type="CodersLab\Lms\Modules\Courses\Application\Query\Model\CourseInstance\CourseInstanceSideMenu"))
* )
*/
public function sideMenu(string $instanceId): LmsApiResponse
{
// TODO remove with new UI
$courseInstance = $this->courseInstanceQuery->getForSideMenu(
$instanceId,
(string)$this->securityContext->getLoggedUserId()
);
return LmsApiResponse::create($courseInstance->toArray());
}
}