<?php
namespace App\Controller\User;
use App\Entity\Account;
use App\Entity\Member;
use App\Exception\AlreadyHasMemberException;
use App\Service\MemberService;
use App\Service\User\Layer\RegistrationLayer;
use App\Service\User\LoginService;
use App\StructSerializer\Main\StructGroup;
use App\StructSerializer\Main\StructOptions;
use App\StructSerializer\Main\StructSerializer;
use App\Subscriber\User\Registration\EmailSubscriber;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Doctrine\Persistence\ManagerRegistry;
use Nelmio\ApiDocBundle\Annotation\Model;
use Swagger\Annotations as SWG;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/api/public/user/member")
*/
class PublicMemberController extends AbstractController
{
protected MemberService $service;
protected RegistrationLayer $layer;
protected LoginService $loginService;
protected StructSerializer $structSerializer;
public function __construct(MemberService $service, StructSerializer $structSerializer,
RegistrationLayer $layer, LoginService $loginService)
{
$this->service = $service;
$this->layer = $layer;
$this->loginService = $loginService;
$this->structSerializer = $structSerializer;
}
/**
* @SWG\Get(
* tags={"User", "Member"},
*
* @SWG\Response(response=200, description="Member details for the given ID",
*
* @SWG\Schema(ref=@Model(type=App\Entity\Member::class, groups={"adminindex", "memberdetail", "memberfrontendindex", "membermainphoto"}))),
*
* @SWG\Response(response=404, description="Member not found at all or inactive, if activeOnly param is set"),
*
* @SWG\Parameter(name="member", in="path", type="integer", required=true, description="ID of the member in question"),
* @SWG\Parameter(name="activeOnly", in="query", type="boolean", required=false, default=false, description="Check active flag of the member")
* )
*
* @Route("/{member}", methods={"GET"}, requirements={"member": "\d+"})
*/
public function detail(Request $request, Member $member): JsonResponse
{
$activeOnly = $request->query->getBoolean('activeOnly');
if ($activeOnly) {
if (!$member->getIsActive()) {
throw $this->createNotFoundException('Member is inactive');
}
}
$options = StructOptions::create();
$options->loadMemberLikes(true);
$options->loadMemberProfileValues(true);
$options->loadMemberPerson(true);
$options->loadMemberInfo($request->query->getBoolean('withMemberInfo'));
return new JsonResponse($this->structSerializer->toArray($options, $member));
}
/**
* @SWG\Get(
* tags={"User", "Member"},
*
* @SWG\Response(response=200, description="Member details for the given username",
*
* @SWG\Schema(ref=@Model(type=App\Entity\Member::class, groups={"adminindex", "memberdetail", "memberfrontendindex", "membermainphoto"}))),
*
* @SWG\Response(response=404, description="Member not found at all or inactive, if activeOnly param is set"),
*
* @SWG\Parameter(name="username", in="path", type="string", required=true, description="Exact username (case insensitive)"),
* @SWG\Parameter(name="activeOnly", in="query", type="boolean", required=false, default=false, description="Check active flag of the member")
* )
*
* @Route("/username/{username}", methods={"GET"})
*/
public function byusername(Request $request, string $username): JsonResponse
{
if (!$member = $this->service->getMemberByUsername($username, false)) {
// does not exist at all
throw $this->createNotFoundException();
}
$activeOnly = $request->query->getBoolean('activeOnly');
if ($activeOnly) {
if (!$this->service->getMemberByUsername($username, true)) {
throw $this->createNotFoundException('Member is inactive');
}
}
$options = StructOptions::create();
$options->loadMemberLikes(true);
$options->loadMemberProfileValues(true);
$options->loadMemberInfo(true);
$options->loadMemberPerson(true);
$options->loadMemberInfo($request->query->getBoolean('withMemberInfo'));
return new JsonResponse($this->structSerializer->toArray($options, $member));
}
/**
* @SWG\Get(tags={"Account"},
*
* @SWG\Response(response=201, description="A member was created successfully",
* @SWG\Response(response=400, description="This account email is already confirmed"),
* @SWG\Response(response=404, description="Unknown channel or confirmationToken"),
*
* @SWG\Schema(ref=@Model(type=App\Entity\Member::class, groups={"memberfrontendindex", "commonids"}))),
*
* @SWG\Parameter(name="confirmationToken", in="path", type="string", description="base64 encoded confirmationToken")
* )
*
* @Route("/confirm/{confirmationToken}", methods={"GET"}, requirements={"confirmationToken": ".{4,24}"})
*/
public function confirm(ManagerRegistry $managerRegistry, string $confirmationToken)
{
if (!$accountIdToken = base64_decode(urldecode($confirmationToken), true)) {
throw $this->createNotFoundException();
}
$accountIdToken = explode(EmailSubscriber::ID_TOKEN_SEPARATOR, $accountIdToken, 2);
if (!is_array($accountIdToken) || 2 !== count($accountIdToken)) {
throw $this->createNotFoundException();
}
$account = $managerRegistry->getRepository(Account::class)->findOneBy(['id' => $accountIdToken[0], 'email_token' => $accountIdToken[1]]);
if (!$account instanceof Account) {
throw $this->createNotFoundException();
}
try {
$member = $this->layer->confirmEmail($account);
} catch (AlreadyHasMemberException $e) {
throw new BadRequestHttpException();
}
$options = StructOptions::create(StructGroup::SHORT);
return new JsonResponse($this->structSerializer->toArray($options, $member),
Response::HTTP_CREATED);
}
/**
* @SWG\Get(tags={"Login"},
*
* @SWG\Response(
* response=200, description="Last login data for given username.",
* response=404, description="When user is not found, is not active or has no logins.",
*
* @SWG\Schema(ref=@Model(type=App\Entity\Login::class, groups={"logindetails"})))
* )
*
* @Route("/lastlogin/{username}", methods={"GET"})
*/
public function lastlogin(string $username): JsonResponse
{
if (!$user = $this->service->getMemberByUsername($username, true)) {
return new JsonResponse([], Response::HTTP_NOT_FOUND);
}
/** @var Paginator $paginator */
$paginator = $this->loginService->getAccountIndex($user->getAccount(), 1, 1);
if ($paginator->count() < 1) {
return new JsonResponse([], Response::HTTP_NOT_FOUND);
}
$logins = [];
foreach ($paginator as $login) {
$logins[] = $login;
}
return new JsonResponse(
$this->structSerializer->multipleToArray(StructOptions::create(), $logins)
);
}
}