<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Doctrine\Persistence\ManagerRegistry;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use App\Security\Voter\ProductVoter;
use App\Repository\UserRepository;
use App\Repository\OrderRepository;
use App\Repository\BannerRepository;
use App\Repository\ProductRepository;
use App\Repository\ShoppingCartRepository;
use App\Service\ActionService;
use App\Service\UserSharedService;
use App\Service\ShoppingCartService;
use App\Entity\User;
use App\Entity\Product;
use App\Entity\UserShared;
use Psr\Log\LoggerInterface;
#[Route('/product')]
class ProductController extends AbstractController
{
private $logger;
private $translator;
public function __construct(
LoggerInterface $logger,
TranslatorInterface $translator
) {
$this->logger = $logger;
$this->translator = $translator;
}
#[Route('/', name: 'app_product_index', methods: ['GET'])]
public function index(): Response
{
$this->logger->debug(__METHOD__);
return $this->redirectToRoute('app_index', [], 301);
}
#[Route('/favourite', name: 'app_product_favourite', methods: ['GET'])]
public function getAddressData(Request $request, ProductRepository $productRepository, ManagerRegistry $manager): JsonResponse
{
$this->logger->debug(__METHOD__);
$productId = $request->get('productId');
if (!$productId) {
return new JsonResponse([], Response::HTTP_BAD_REQUEST);
}
$product = $productRepository->find($productId);
if (!$product) {
return new JsonResponse([], Response::HTTP_NOT_FOUND);
}
$result = [];
if ($this->getUser()->getFavouriteProducts()->contains($product)) {
$this->getUser()->removeFavouriteProduct($product);
$result = false;
} else {
$this->getUser()->addFavouriteProduct($product);
$result = true;
}
$manager->getManager()->flush();
return new JsonResponse($result, Response::HTTP_OK, []);
}
#[Route('/{slug}', name: 'app_product_show', methods: ['GET'])]
public function show(
Product $product,
ActionService $actionService,
OrderRepository $orderRepository,
UserRepository $userRepository,
BannerRepository $bannerRepository,
AuthorizationCheckerInterface $authorizationChecker
): Response {
$this->logger->debug(__METHOD__, ["id" => $product->getId()]);
try {
//$this->denyAccessUnlessGranted(ProductVoter::CAN_SHOW_PRODUCT, $product);
if (!$authorizationChecker->isGranted(ProductVoter::CAN_SHOW_PRODUCT, $product)) {
throw new AccessDeniedException('No tienes permiso para ver este producto.');
}
$hasAlreadyBought = $orderRepository->existsAnOrderForThisProduct($this->getUser(), $product);
$parameters = [
'product' => $product,
'hasAlreadyBought' => $hasAlreadyBought,
'footerBanner' => $bannerRepository->findByKey('footer_banner')->getQuery()->getOneOrNullResult(),
'differentProducer' => false,
];
/** @var \App\Entity\User */
$user = $this->getUser();
if ($user) {
$actionService->saveProductVisualizationAction($user, $product);
$cart = $user->getShoppingCart();
if ($cart) {
foreach ($cart->getShoppingCartDetails() as $item) {
if ($product->getProducer()->getId() !== $item->getProduct()->getProducer()->getId()) {
$parameters['differentProducer'] = true;
}
}
}
}
$parameters['friendUsersFavourites'] = $userRepository->getTriweersWhoHaveProductAsFavourite($product);
$parameters['friendUsersWhoBought'] = array_unique(
array_merge($userRepository->getTriweersWhoBought($product), $product->getFakeTriweersInOffer()->toArray()),
SORT_REGULAR
);
return $this->render('product/show.html.twig', $parameters);
}catch (AccessDeniedException $e) {
return $this->redirectToRoute('app_index', [], 301);
} catch (AuthenticationException $e) {
return $this->redirectToRoute('login');
}
}
/**
* Validates the token
*/
#[Route('/{slug}/{token}', name: 'app_product_show_with_token')]
public function showWithToken(
Request $request,
Product $product,
UserSharedService $userSharedService,
string $token
): Response {
$this->denyAccessUnlessGranted(ProductVoter::CAN_SHOW_PRODUCT, $product);
if (!$token) {
throw $this->createNotFoundException('No token found in the URL.');
}
if (!$userSharedService->checkIfTokenIsValid($token)) {
throw $this->createNotFoundException('Invalid token found in the URL.');
}
$request->getSession()->set(UserShared::TOKEN_NAME, $token);
return $this->redirectToRoute('app_product_show', ['slug' => $product->getSlug()]);
}
/**
* Add a product to the shopping cart and go to shoppingcart view
*/
#[Route('/shopping-cart/{id}', priority: 10, name: 'app_product_add_to_shopping_cart', methods: ['GET'])]
#[IsGranted('buy_product', subject: 'product')]
public function addProductToShoppingCart(
Product $product,
ShoppingCartService $shoppingCartService,
ShoppingCartRepository $shoppingCartRepository,
Request $request
): Response {
/** @var User */
$loggedUser = $this->getUser();
$this->logger->debug(__METHOD__, ["userId" => $loggedUser->getId(), "productId" => $product->getId()]);
$betterPrice = $request->cookies->get('better_price') == 'yes';
$cart = $loggedUser->getShoppingCart();
if ($cart) {
if ($request->get('newCart')) {
$shoppingCartRepository->remove($loggedUser->getShoppingCart(), true);
$loggedUser->emptyShoppingCart();
$shoppingCartService->createShoppingCart($loggedUser, $product, $betterPrice, $request->get('isIndividual'));
} else {
$shoppingCartService->addProductToCart($cart, $product);
}
} else {
$shoppingCartService->createShoppingCart($loggedUser, $product, $betterPrice, $request->get('isIndividual'));
}
return $this->redirectToRoute("app_shopping_cart");
}
/**
* Add a product to the shopping cart and go to shoppingcart view
*/
#[Route('/shopping-cart/{id}/ajax', priority: 10, name: 'app_product_add_to_shopping_cart_ajax', methods: ['POST'])]
#[IsGranted('buy_product', subject: 'product')]
public function addProductToShoppingCartAjax(
Product $product,
ShoppingCartService $shoppingCartService,
Request $request
): Response {
/** @var User */
$loggedUser = $this->getUser();
$this->logger->debug(__METHOD__, ["userId" => $loggedUser->getId(), "productId" => $product->getId()]);
$betterPrice = $request->cookies->get('better_price') == 'yes';
$cart = $loggedUser->getShoppingCart();
$cart
? $shoppingCartService->addProductToCart($cart, $product)
: $shoppingCartService->createShoppingCart($loggedUser, $product, $betterPrice, 0);
$qtyCount = ($loggedUser && $loggedUser->getShoppingCart())
? $loggedUser->getShoppingCart()->getShoppingCartDetails()->reduce(fn($sum, $i) => $sum + $i->getQuantity())
: 0;
return new JsonResponse($qtyCount, Response::HTTP_OK, []);
}
}