<?php
/**
* @author <akartis-dev>
*/
namespace App\Controller\App;
use App\Controller\AppAbstractController;
use App\Entity\Application\ShippingMethod;
use App\Entity\Blog\Blog;
use App\Entity\Orders\OrdersProducts;
use App\Entity\Products\Categories\ProductsCategories;
use App\Entity\Products\ProductBrand;
use App\Entity\Products\Products;
use App\ObjectManager\EntityObjectManager;
use App\Repository\Products\Categories\ProductsCategoriesRepository;
use App\Repository\Products\ProductsRepository;
use App\Service\Cart\CartService;
use App\Service\Filter\FilterServices;
use App\Service\Hci\HciService;
use App\Service\Newletter\NewletterService;
use App\Service\Reporting\ReportingService;
use App\Service\Utils\StrService;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Translation\TranslatableMessage;
use Symfony\Contracts\Translation\TranslatorInterface;
#[Route('/{_locale}')]
class PagesController extends AppAbstractController
{
public function __construct(
private ReportingService $reportingService,
private EntityObjectManager $em,
private FilterServices $filterServices,
private CartService $cartService,
private HciService $hciService,
private TranslatorInterface $translator
)
{
}
#[Route('/', name: "app_index")]
public function index(): Response
{
$productRepository = $this->em->getEm()->getRepository(Products::class);
$bestSellerProductEntity = $this->reportingService->getBestSellingProductsByTag(limit: 12);
$recommandedProductEntity = $this->reportingService->getRecommandedProducts(limit: 12);
$categories = $this->em->getEm()
->getRepository(OrdersProducts::class)->getBestCategoriesSeller(limit: 7);
$blogs = $this->em->getEm()->getRepository(Blog::class)
->getLastInsert(limit: 3);
// dd($bestSellerProductEntity);
return $this->render('pages/index.html.twig', [
'bestSellerProduct' => $bestSellerProductEntity,
'recommanded' => $recommandedProductEntity,
"categories" => $categories,
'blogs' => $blogs
]);
}
#[Route('/shop', name: 'app_shop')]
public function onlineShop(Request $request): Response
{
// Sanitize the query parameter
$q_search = $request->query->get('q', '');
// Encode special HTML characters
$q_search = htmlspecialchars($q_search, ENT_QUOTES, 'UTF-8');
// Remove potentially harmful attributes like "onfocus", "onclick", "style", etc.
$q_search = preg_replace('/\s*on\w+\s*=\s*"[^"]*"/i', '', $q_search); // Double quotes
$q_search = preg_replace("/\s*on\w+\s*=\s*'[^']*'/i", '', $q_search); // Single quotes
$q_search = preg_replace('/\s*on\w+\s*=\s*[^\s>]*/i', '', $q_search); // No quotes
// Remove inline styles
$q_search = preg_replace('/\s*style\s*=\s*"[^"]*"/i', '', $q_search);
$q_search = preg_replace("/\s*style\s*=\s*'[^']*'/i", '', $q_search);
// Remove "javascript:" or other potentially harmful protocols
$q_search = preg_replace('/javascript:/i', '', $q_search);
$q_search = preg_replace('/vbscript:/i', '', $q_search);
$q_search = preg_replace('/data:/i', '', $q_search);
// Strip additional HTML tags if needed (optional, for strict filtering)
$q_search = strip_tags($q_search);
// Decode categories and brands safely
try {
$q_categories = json_decode($request->get('categories', '[]'), true, 512, JSON_THROW_ON_ERROR);
$q_brands = json_decode($request->get('brands', '[]'), true, 512, JSON_THROW_ON_ERROR);
} catch (\JsonException $e) {
$q_categories = [];
$q_brands = [];
}
// Sanitize and validate price parameters
$q_min = filter_var($request->get('min', 1), FILTER_VALIDATE_FLOAT, ['options' => ['default' => 1]]);
$q_max = filter_var($request->get('max', 100), FILTER_VALIDATE_FLOAT, ['options' => ['default' => 100]]);
// Validate order parameter
$q_order = filter_var($request->get('order', 0), FILTER_VALIDATE_INT, ['options' => ['default' => 0]]);
// Call the shop filter service
$query = $this->filterServices->shopFilter(
categories: $q_categories,
brands: $q_brands,
minPrice: $q_min,
maxPrice: $q_max,
order: $q_order,
q: $q_search
);
// Paginate products
$products = $this->em->paginate($query, $request, 20);
// Render the template
return $this->render('pages/online_shop.html.twig', [
'products' => $products,
'categories' => $q_categories,
'brands' => $q_brands,
'q_order' => $q_order,
'q_search' => $q_search,
]);
}
#[Route('/product/{id}-{brand}-{slug}', name: "product_detail")]
public function productDetail(Request $request, int $id, string $slug, ProductsRepository $repository, ProductsCategoriesRepository $productsCategoriesRepository): RedirectResponse|Response
{
$product = $repository->find($id);
if ($product && $slug) {
$translated = $product->translate($request->getLocale());
if ($translated->getSlug() !== $slug) {
return $this->redirectToRoute("product_detail", [
'id' => $id,
'brand' => StrService::urlSanitizer($product->getBrand()->getName()),
'slug' => $translated->getSlug()
]);
}
}
$categories = [];
if ($product->getProductsCategories()->first()) {
$categories = $productsCategoriesRepository->findOneCategoryWithChild(
$product->getProductsCategories()->first()->getId()
);
}
$withThisProducts = $repository->findOftenBuyProducts($product);
$hciInformation = $this->hciService->getCompediumInformation($product->getPharmacode());
$patient = $this->hciService->formatCompediumHtml($hciInformation['content']);
$pro = $this->hciService->formatCompediumHtml($hciInformation['pro']);
$recommandedProduct = $repository->findBy([], [], 3);
$attributs = $repository->getProductAttributsTerms(productId: $id);
return $this->render("pages/product_detail.html.twig", [
'product' => $product,
'attributs' => $attributs,
'recommandedProduct' => $recommandedProduct,
'patient' => $patient,
'pro' => $pro,
'withProducts' => $withThisProducts,
'categories' => $categories
]);
}
#[Route('/cart', name: "app_cart")]
public function cart(): Response
{
$cart = $this->cartService->getHydratedCartNoSerializable();
$coupons = $this->cartService->getCouponCode();
$shippings = $this->em->getEm()->getRepository(ShippingMethod::class)->findAll();
$prestations = $this->cartService->getCartPrestation();
return $this->render('pages/cart.html.twig', [
'totalBrut' => $this->cartService->getTotalBrut(),
'cart' => $cart,
'coupons' => $coupons,
'shippings' => $shippings,
'prestations' => $prestations
]);
}
#[Route('/choose-pharmacy', name: "choose_pharmacy")]
public function choosePharmacy(Request $request)
{
$referer = $request->headers->get('referer');
$refererSession = $request->getSession()->get('session_referer', null);
if (!$refererSession) {
$request->getSession()->set('session_referer', $referer);
}
if (str_contains($referer, "choose-pharmacy")) {
$request->getSession()->set('session_referer', '/');
}
if (!$referer) {
return $this->redirect('/');
}
if (Request::METHOD_POST === $request->getMethod()) {
$product = $request->query->get('product', null);
$qt = $request->query->get('qt', 1);
$result = $this->cartService->setPharmacyCart($request->get('selected_pharmacy'));
$modal = "";
if ($product) {
$this->cartService->addInCart($product, 1, null, $qt);
$this->addFlash('success', $this->translator->trans("Produit ajouté avec succès"));
$modal = "#panier_pharmacy";
}
$request->getSession()->set('session_referer', null);
if ($result) {
if (str_contains($refererSession, "choose-pharmacy")) {
return $this->redirectToRoute('app_index');
}
return new RedirectResponse(sprintf("%s%s", $refererSession, $modal));
}
}
return $this->render('pages/choosePharmacy.twig');
}
#[Route('/contact', name: "app_contact")]
public function contact()
{
return $this->render('pages/contact.html.twig');
}
#[Route('/unsubscribe/{token}', name: "app_unsubscribe_newletter")]
public function unsubscribeNewletter(string $token, NewletterService $newletterService)
{
$res = $newletterService->unsubscribe($token);
if ($res) {
$this->addFlash('success', $this->translator->trans('Désabonnement du newletter avec succès'));
} else {
$this->addFlash('error', $this->translator->trans('Une erreur s\'est produite'));
}
return $this->redirectToRoute('app_index');
}
#[Route('/pharmacy', name: "app_pharmacy")]
public function pharmacy()
{
return $this->render('pages/pharmacy.html.twig');
}
#[Route("/cgu", name: "cgu")]
public function cgu(Request $request)
{
$locale = $request->getLocale();
return $this->render("pages/cgu_{$locale}.html.twig");
}
#[Route("/privacy", name: "privacy")]
public function privacy(Request $request)
{
$locale = $request->getLocale();
return $this->render("pages/privacy_{$locale}.html.twig");
}
}