Snippets

Andrew Stark How NOT to write a Symfony or whatever code!

Created by Andrew Stark
<?php

namespace App\Controller\Profile;

use App\Controller\AbstractController;
use App\Entity\Notification\Action\ProfileViewed;
use App\Entity\User\Report;
use App\Entity\User\User;
use App\EventListener\Events\NotificationEvent;
use App\Exception\Message\DailyLimitExceededException;
use App\Exception\Message\UnauthorizedToReplyException;
use App\Exception\Message\UnauthorizedToStartException;
use App\Form\MessageFormType;
use App\Form\ReviewType;
use App\Form\UserReportType;
use App\Manager\MailService;
use App\Manager\User\MessageManager;
use App\Manager\User\SessionActionManager;
use App\Repository\Pro6PP\CityRepository;
use App\Repository\ThreadRepository;
use App\Repository\User\UserRepository;
use App\Traits\UserTrait;
use App\Traits\UserTypeTrait;
use Doctrine\ORM\NonUniqueResultException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

/**
 * Class ProfileController.
 */
final class ProfileController extends AbstractController
{
    use UserTrait;
    use UserTypeTrait;

    /**
     * @var MessageManager
     */
    private $messageManager;

    /**
     * @var UserRepository
     */
    private $userRepository;

    /**
     * @var ThreadRepository
     */
    private $threadRepository;

    /**
     * @var CityRepository
     */
    private $cityRepository;

    /**
     * @var MailService
     */
    private $mailService;

    /**
     * @var EventDispatcherInterface
     */
    private $eventDispatcher;

    /**
     * @var SessionActionManager
     */
    private $sessionActionManager;

    /**
     * ProfileController constructor.
     *
     * @param EventDispatcherInterface $eventDispatcher
     * @param MailService              $mailService
     * @param MessageManager           $messageManager
     * @param UserRepository           $userRepository
     * @param ThreadRepository         $threadRepository
     * @param SessionActionManager     $sessionActionManager
     * @param CityRepository           $cityRepository
     */
    public function __construct(
        EventDispatcherInterface $eventDispatcher,
        MailService $mailService,
        MessageManager $messageManager,
        UserRepository $userRepository,
        ThreadRepository $threadRepository,
        SessionActionManager $sessionActionManager,
        CityRepository $cityRepository
    ) {
        $this->messageManager       = $messageManager;
        $this->userRepository       = $userRepository;
        $this->threadRepository     = $threadRepository;
        $this->cityRepository       = $cityRepository;
        $this->mailService          = $mailService;
        $this->eventDispatcher      = $eventDispatcher;
        $this->sessionActionManager = $sessionActionManager;
    }

    /**
     * profile Shows a profile page of a user.
     *
     * @Route("/oppas/{city}/{slug}", name="profile.babysitter.noname", requirements={"slug": "[a-f0-9]{6,8}"})
     * @Route("/oppaswerk/{city}/{slug}", name="profile.parent.noname", requirements={"slug": "[a-f0-9]{6,8}"})
     * @Route("/gastouderbureau/{city}/{slug}", name="profile.guestparentbureau.noname", requirements={"slug": "[a-f0-9]{6,8}"})
     * @Route("/gastouder/{city}/{slug}", name="profile.guestparent.noname", requirements={"slug": "[a-f0-9]{6,8}"})
     * @Route("/oppas/{city}/{slug}/{firstName}", name="profile.babysitter", requirements={"slug": "[a-f0-9]{6,8}"})
     * @Route("/oppaswerk/{city}/{slug}/{firstName}", name="profile.parent", requirements={"slug": "[a-f0-9]{6,8}"})
     * @Route("/gastouderbureau/{city}/{slug}/{firstName}", name="profile.guestparentbureau", requirements={"slug": "[a-f0-9]{6,8}"})
     * @Route("/gastouder/{city}/{slug}/{firstName}", name="profile.guestparent", requirements={"slug": "[a-f0-9]{6,8}"})
     *
     * @param Request $request
     * @param string  $city
     * @param string  $slug
     * @param string  $firstName
     *
     * @throws NonUniqueResultException
     * @throws DailyLimitExceededException
     * @throws UnauthorizedToReplyException
     * @throws UnauthorizedToStartException
     *
     * @return Response
     *
     * @todo refactor this file, there is no need to check 5 times if a user is a user...
     */
    public function profile(Request $request, string $city, string $slug, ?string $firstName = null): Response
    {
        $routeName = $request->attributes->get('_route');

        if (6 === mb_strlen($slug)) {
            $slug .= '00';
        }
        $user = $this->userRepository->findOneBySlug($slug);

        // user not found/inactive, render 404/410 page
        if (null === $user || User::STATUS_ACTIVE !== $user->getStatus() &&
            User::STATUS_DELETED_FULFILLED !== $user->getStatus()) {
            $userTypeId = $this->getUserTypeId($routeName);
            $users      = $this->userRepository->findActiveUsersByCityAndType($city, $userTypeId, 6);

            $httpStatus = Response::HTTP_NOT_FOUND;
            if (null === $user || User::STATUS_DELETED === $user->getStatus()) {
                $httpStatus = Response::HTTP_GONE;
            }

            return new Response(
                $this->renderView(
                    'profile/404.html.twig',
                    [
                        'firstName'    => $firstName,
                        'userTypeName' => $this->getUserTypeName($routeName),
                        'city'         => $this->cityRepository->findOneBySlug($city),
                        'users'        => $users,
                    ]
                ),
                $httpStatus
            );
        }

        // redirect to correct url if url doesn't match profile url
        if ($request->getPathInfo() !== $this->urlToProfile($user)) {
            return $this->redirect($this->urlToProfile($user), Response::HTTP_MOVED_PERMANENTLY);
        }

        /** @var User|null $loginUser */
        $loginUser = $this->getUser();

        if (true === ($loginUser instanceof \App\Entity\User)) {
            $loginUser = null;
        }

        // default
        $canContact    = true;
        if (true === $user->isFulfilled()) {
            $canContact = false;
        }
        $urlToMessages = null;

        // params for logged in user
        if (true === ($loginUser instanceof User)) {
            $canContact = $loginUser->canContact($user);

            // handle daily limit
            if ($this->messageManager->reachedDailyLimit($loginUser)) {
                $this->addFlash('warning', 'profile.flash.toomanysent');
                $canContact = false;
            }

            if (true === $canContact) {
                $threadId = $this->messageManager->getThreadIdByUserAndParticipant($loginUser, $user);
                if (null !== $threadId) {
                    // User is in conversation link to thread
                    $urlToMessages = $this->generateUrl('account.messages.view', ['id' => $threadId]);
                }
            }
        }
        $report = new Report();
        $report->setReportedUser($user);
        if (true === ($loginUser instanceof User) && true === $loginUser->canContact($user)) {
            $report->setOwner($loginUser);
            $this->eventDispatcher->dispatch(
                NotificationEvent::NAME,
                new NotificationEvent(new ProfileViewed($user->getId(), $loginUser->getId()))
            );
        }
        $reportUserForm = $this->createForm(UserReportType::class, $report);

        // Handle first message from profile page
        $messageForm          = null;
        $isUserViewingHimself = true === ($loginUser instanceof User) &&
            $user->getId()           === $loginUser->getId();
        if (null === $urlToMessages && false === $isUserViewingHimself) {
            if (true === ($loginUser instanceof \App\Entity\User)) {
                $loginUser = null;
            }
            $messageForm = $this->createForm(
                MessageFormType::class,
                null,
                ['recipient' => $user, 'sender' => $loginUser, 'initialMessage' => true]
            );
        }
        $isMessageFormCreated          = true === ($messageForm instanceof Form);
        if ($isMessageFormCreated &&
            true === ($messageForm->handleRequest($request) instanceof Form) &&
            true === $messageForm->isSubmitted() &&
            true === $messageForm->isValid()
        ) {
            if (null === $loginUser) {
                // prefill message taken from cookie set with JS
                return $this->redirect($this->urlToContactProfile($user));
            }
            $message = $messageForm->get('body')->getData();
            if (true === ($loginUser instanceof User)) {
                if (false === $this->isGranted(User::ROLE_PREMIUM)) {
                    // message will be sent after successful upgrade confirmation
                    $this->sessionActionManager->setMessageAction(
                        $message,
                        $user->getSlug()
                    );

                    return $this->redirectToRoute('upgrade.view', ['slug' => $user->getSlug()]);
                }
                // User is premium.
                $this->messageManager->sendMessage($loginUser, $user, $message);
                $this->entityManager->flush();
                $threadId = $this->messageManager->getThreadIdByUserAndParticipant($loginUser, $user);

                if (null === $threadId) {
                    return $this->redirectToRoute('account.messages.inbox');
                }

                return $this->redirectToRoute('account.messages.view', ['id' => $threadId]);
            }
        }

        $reportUserForm->handleRequest($request);
        if (true === $reportUserForm->isSubmitted() && true === $reportUserForm->isValid()) {
            $report = $reportUserForm->getData();
            $this->entityManager->persist($report);
            $this->entityManager->flush();
            if (true === $this->mailService->sendUserReported($report)) {
                $this->addFlash('success', 'form.report.success');
            }

            return $this->redirect($this->urlToProfile($user), Response::HTTP_MOVED_PERMANENTLY);
        }

        return $this->render(
            'profile/profile.html.twig',
            [
                'user'              => $user,
                'canContact'        => $canContact,
                'reportUserForm'    => $reportUserForm->createView(),
                'messageForm'       => true === $isMessageFormCreated ? $messageForm->createView() : null,
                'urlToMessages'     => $urlToMessages,
                'reviewForm'        => $this->createForm(ReviewType::class)->createView(),
            ]
        );
    }
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.