<?php
declare(strict_types=1);
namespace App\Controller\ECommerce\App;
use App\Controller\ControllerTrait;
use App\DTO\ECommerce\ProductFilterBySizeDTO;
use App\Entity\ECommerce\Product;
use App\Form\ECommerce\Filter\ProductFilterByCategory;
use App\Form\ECommerce\Filter\ProductFilterByName;
use App\Form\ECommerce\Filter\ProductFilterBySize;
use App\Form\ECommerce\Filter\ProductFilterType;
use App\Form\ECommerce\Filter\ProductSortType;
use App\Helper\CacheHelper;
use App\Model\ECommerce\Index;
use App\Repository\ECommerce\ProductCategoryRepository;
use App\Service\ECommerce\ProductTwigExtension;
use DateTime;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\EntityManagerInterface;
use Knp\Component\Pager\PaginatorInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
#[Route('/{_locale}/product', requirements: ['_locale' => '\w{2}'])]
class ProductController extends AbstractController
{
const INDEX_ROUTE = 'mdl_app_product_index';
use ControllerTrait;
#[Route('/index', name: 'mdl_app_product_index')]
#[Cache(maxage: 2592000, smaxage: 2592000, public: true)]
public function indexAction(
Request $request,
PaginatorInterface $paginator,
ProductTwigExtension $productTwigExtension,
EntityManagerInterface $entityManager
): Response {
$form = $this->createForm(ProductFilterType::class)->handleRequest($request);
$formData = $form->getData();
$filters = $form->isSubmitted() && $form->isValid()
? $formData
: [];
$user = $this->getUser();
$reverseRate = $productTwigExtension->currencyReverseRateFunction($user);
if (!empty($filters['min'])) {
$filters['min'] /= $reverseRate;
}
if (!empty($filters['max'])) {
$filters['max'] /= $reverseRate;
}
$isLargeView = $request->query->get('view') === 'large-icons';
$products = $paginator->paginate(
$entityManager->getRepository(Product::class)->findAllInStockWithFilter($filters),
$request->query->getInt('page', 1),
$request->query->getInt('limit', $isLargeView ? 8 : 6)
);
return $this->render(
$this->isFragment($request)
? 'ECommerce/App/Product/index.ajax.twig'
: ($isLargeView ? 'ECommerce/App/Product/large_icons.html.twig' : 'ECommerce/App/Product/index.html.twig'),
[
'products' => $products,
'form' => $form->createView(),
]
);
}
#[Route('/{id}', name: 'mdl_app_product_show', requirements: ['id' => '\d+'], methods: ['GET'])]
#[Cache(maxage: 2592000, smaxage: 2592000, public: true)]
public function showAction(Product $product): Response
{
$breadcrumbs = [
['label' => 'product.index', 'url' => $this->generateUrl('public_index_localized')],
['label' => 'product.shop', 'url' => $this->generateUrl('mdl_app_product_index')],
[
'label' => $product->getCategory()->translate()->getName(),
'url' => $this->generateUrl('mdl_app_product_index',
['categories' => [$product->getCategory()->getId()]]
)
],
];
if ($product->getSubCategory() instanceof \App\Entity\ECommerce\ProductSubCategory) {
$breadcrumbs[] = [
'label' => $product->getSubCategory()->getName(),
'url' => $this->generateUrl(
'mdl_app_product_index',
['subCategories' => [$product->getSubCategory()?->getId()]]
)
];
}
$breadcrumbs[] = ['label' => $product->getTitle()];
return $this->render('ECommerce/App/Product/show.html.twig', [
'product' => $product,
'breadcrumbs' => $breadcrumbs,
]);
}
#[Route('/remote/{remoteId}', name: 'mdl_app_remote_product_show', requirements: ['remoteId' => '\d+'], methods: ['GET'])]
#[Cache(maxage: 2592000, smaxage: 2592000, public: true)]
public function showByRemoteId(Product $product): Response
{
return $this->render('ECommerce/App/Product/show.html.twig', ['product' => $product]);
}
#[Route('/filter', name: 'mdl_app_product_filter', methods: ['GET'])]
#[Cache(maxage: 2592000, smaxage: 2592000, public: true)]
public function filterAction(
Request $request,
PaginatorInterface $paginator,
CacheHelper $cacheHelper,
EntityManagerInterface $entityManager,
RequestStack $requestStack
): Response {
$masterRequest = $requestStack->getMainRequest();
$form = $this->createForm(ProductFilterBySize::class, null, [
'action' => $this->generateUrl('mdl_app_product_filter'),
'method' => 'GET'
])->handleRequest($masterRequest);
if ($this->isFragment($request)) {
return $cacheHelper::responseCached(
$this->render('ECommerce/App/Product/filter.form.twig', [
'form' => $form->createView(),
])
);
}
$sort = $request->query->get('sortBy') ?: '';
$sortForm = $this->createForm(ProductSortType::class, null, [
'sortBy' => $sort,
'action' => $this->generateUrl('mdl_app_product_filter'),
'method' => 'GET',
])->handleRequest($request);
/** @var ProductFilterBySizeDTO $data */
$data = $form->getNormData();
$productsQuery = $entityManager->getRepository(Product::class)->createBySizeQuery($data, $sort);
$products = $paginator->paginate(
$productsQuery,
(int) $request->get('page', 1),
(int) $request->get('itemsPerPage', 20)
);
$responseData = [
'form' => $form->createView(),
'sortForm' => $sortForm->createView(),
'products' => $products,
'title' => $data->getTitle(),
];
if ($request->isXmlHttpRequest() && $request->query->get('view') !== 'large-icons') {
return $cacheHelper::responseCached(
$this->render('ECommerce/App/Product/filter_by_name.ajax.twig', $responseData)
);
}
if ($request->isXmlHttpRequest()) {
return $cacheHelper::responseCached(
$this->render('ECommerce/App/Product/large_icons.ajax.twig', $responseData)
);
}
$responseData['sortForm'] = $this->createForm(ProductSortType::class, null, [
'action' => $this->generateUrl('mdl_app_product_filter'),
'method' => 'GET'
])->handleRequest($masterRequest)->createView();
return $cacheHelper::responseCached(
$this->render('ECommerce/App/Product/filter.html.twig', $responseData)
);
}
#[Route('/filter_by_name', name: 'mdl_app_product_filter_by_name')]
#[Cache(maxage: 2592000, smaxage: 2592000, public: true)]
public function filterByNameAction(
Request $request,
PaginatorInterface $paginator,
CacheHelper $cacheHelper,
RequestStack $requestStack
): Response {
$searchTitle = $requestStack->getMainRequest()->get('title', '');
preg_match('/^\*.*/', (string) $searchTitle, $minQuantity);
$data = [
'title' => $searchTitle
];
$form = $this->createForm(ProductFilterByName::class, $data, [
'action' => $this->generateUrl('mdl_app_product_filter_by_name'),
'method' => 'GET'
])->handleRequest($request);
$title = ltrim(Index::index($form->getNormData()['title']), '*');
$minQuantity = (int)(count($minQuantity) < 1);
$responseData = [
'form' => $form->createView(),
'products' => $paginator->paginate(
[],
(int) $request->get('page', 1),
(int) $request->get('itemsPerPage', 20)
),
'title' => $searchTitle,
'initialTitle' => $title,
];
if ($this->isFragment($request)) {
return $cacheHelper::responseCached(
$this->render('ECommerce/App/Product/filter_by_name.form.twig', $responseData)
->setExpires(new DateTime('+2 days'))
);
}
if (!$form->isSubmitted() || !$form->isValid()) {
return $cacheHelper::responseCached(
$this->render('ECommerce/App/Product/filter.html.twig', $responseData)
->setExpires(new DateTime('+2 days'))
);
}
$responseData['products'] = $paginator->paginate(
$this->getDoctrine()
->getRepository(Product::class)
->createLikeSearchTitleQueryBuilder($title, $minQuantity),
$request->query->getInt('page', 1),
$request->query->getInt('itemsPerPage', 20)
);
if ($request->isXmlHttpRequest() && $request->query->get('view') !== 'largeIcons') {
return $cacheHelper::responseCached(
$this->render('ECommerce/App/Product/filter_by_name.ajax.twig', $responseData)
->setExpires(new DateTime('+2 days'))
);
}
return $cacheHelper::responseCached(
$this->render('ECommerce/App/Product/filter.html.twig', $responseData)
->setExpires(new DateTime('+2 days'))
);
}
#[Route('/filter_by_category', name: 'mdl_app_product_filter_by_category')]
#[Cache(maxage: 2592000, smaxage: 2592000, public: true)]
public function filterByCategoryAction(
// Request $request,
// PaginatorInterface $paginator,
// CacheHelper $cacheHelper,
// RequestStack $requestStack,
// ProductCategoryRepository $categoryRepository
): Response {
return new Response();
// $category = $requestStack->getMainRequest()->get('category');
// $data = array(
// 'category' => !empty($category) ? $categoryRepository->find($category) : null,
// );
//
// $form = $this->createForm(ProductFilterByCategory::class, $data, array(
// 'action' => $this->generateUrl('mdl_app_product_filter_by_category'),
// 'method' => 'GET',
// ))->handleRequest($request);
//
// if ($this->isFragment($request)) {
// return $cacheHelper::responseCached(
// $this->render('ECommerce/App/Product/filter_by_category.form.twig', array(
// 'categoryForm' => $form->createView(),
// ))
// );
// }
//
// if (!$form->isSubmitted() || !$form->isValid()) {
// return $cacheHelper::responseCached(
// $this->render('ECommerce/App/Product/filter_by_category.html.twig', [
// 'categoryForm' => $form->createView(),
// 'products' => $responseData['products'] = $paginator->paginate(
// [],
// (int) $request->get('page', 1),
// (int) $request->get('itemsPerPage', 20)
// ),
// 'title' => null,
// ])
// );
// }
//
// $response = array(
// 'categoryForm' => $form->createView(),
// 'products' => $responseData['products'] = $paginator->paginate(
// $this->getDoctrine()->getRepository(Product::class)->createByCategoryQueryBuilder($form->getNormData()['category']),
// (int) $request->get('page', 1),
// (int) $request->get('itemsPerPage', 20)
// ),
// 'title' => null,
// );
//
// if ($request->isXmlHttpRequest()) {
// return $cacheHelper::responseCached(
// $this->render('ECommerce/App/Product/filter_by_category.ajax.twig', $response)
// );
// }
//
// return $cacheHelper::responseCached(
// $this->render('ECommerce/App/Product/filter_by_category.html.twig', $response)
// );
}
}