<?php
declare(strict_types=1);
namespace App\Controller\ECommerce\App;
use App\Controller\ControllerTrait;
use App\Entity\ECommerce\Product;
use App\Entity\ECommerce\ProductCategory;
use App\Form\ECommerce\Filter\ProductFilterByCategory;
use App\Form\ECommerce\Filter\ProductFilterByName;
use App\Form\ECommerce\Filter\ProductFilterBySize;
use App\Helper\CacheHelper;
use App\Model\ECommerce\Index;
use App\Repository\ECommerce\ProductCategoryRepository;
use DateTime;
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;
/**
* Product controller.
*
* @package App\Controller\ECommerce\App
*
* @Route("/{_locale}/product", requirements={"_locale": "\w{2}"})
*/
class ProductController extends AbstractController
{
const INDEX_ROUTE = 'mdl_app_product_index';
use ControllerTrait;
/**
* Lists all product entities.
*
* @Route("/index", name="mdl_app_product_index")
*
* @Cache(expires="+2 days", public=true)
*
* @param Request $request
* @param PaginatorInterface $paginator
*
* @return Response
*/
public function indexAction(Request $request, PaginatorInterface $paginator): Response
{
$products = $paginator->paginate(
$this->getDoctrine()->getRepository(Product::class)->findAllInStock(),
$request->query->getInt('page', 1),
$request->query->getInt('limit', 6)
);
if ($request->query->get('view') === 'largeIcons') {
return $this->render(
$this->isFragment($request)
? 'ECommerce/App/Product/index.ajax.twig'
: 'ECommerce/App/Product/large_icons.html.twig', [
'products' => $products,
]);
} else {
return $this->render(
$this->isFragment($request)
? 'ECommerce/App/Product/index.ajax.twig'
: 'ECommerce/App/Product/index.html.twig', [
'products' => $products,
]);
}
}
/**
* Finds and displays a product entity.
*
* @Route("/{id}", name="mdl_app_product_show", requirements={
* "id"="\d+"
* }, methods="GET")
*
* @Cache(etag="product.getUpdatedAt().getTimestamp()", expires="+2 days", public=true)
*
* @param Product $product
*
* @return Response
*/
public function showAction(Product $product): Response
{
return $this->render('ECommerce/App/Product/show.html.twig', ['product' => $product]);
}
/**
* Finds and displays a product entity.
*
* @Route("/remote/{remoteId}", name="mdl_app_remote_product_show", requirements={
* "remoteId"="\d+"
* }, methods="GET")
*
* @Cache(etag="product.getUpdatedAt().getTimestamp()", expires="+2 days", public=true)
*
* @param Product $product
*
* @return Response
*/
public function showByRemoteId(Product $product): Response
{
return $this->render('ECommerce/App/Product/show.html.twig', ['product' => $product]);
}
/**
* Lists all product entities by size filter.
*
* @Route("/filter_by_size", name="mdl_app_product_filter_by_size", methods={"GET", "POST"})
*
* @param Request $request
* @param PaginatorInterface $paginator
* @param CacheHelper $cacheHelper
*
* @return Response
*/
public function filterBySizeAction(
Request $request,
PaginatorInterface $paginator,
CacheHelper $cacheHelper
): Response {
$form = $this->createForm(ProductFilterBySize::class, null, array(
'action' => $this->generateUrl('mdl_app_product_filter_by_size'),
'method' => 'GET'
))->handleRequest($this->get('request_stack')->getMasterRequest());
if ($this->isFragment($request)) {
return $cacheHelper::responseCached(
$this->render('ECommerce/App/Product/filter_by_size.form.twig', [
'form' => $form->createView(),
])
);
}
$data = $form->getNormData();
unset($data['precision']);
$responseData = [
'form' => $form->createView(),
'products' => $paginator->paginate(
$this->getDoctrine()->getRepository(Product::class)
->createBySizeQuery($form->getNormData()),
(int) $request->get('page', 1),
(int) $request->get('itemsPerPage', 20)
),
'title' => implode('x', array_values($data)),
];
if ($request->isXmlHttpRequest()) {
return $cacheHelper::responseCached(
$this->render('ECommerce/App/Product/filter_by_name.ajax.twig', $responseData)
);
}
return $cacheHelper::responseCached(
$this->render('ECommerce/App/Product/filter_by_name.html.twig', $responseData)
);
}
/**
* Lists all product entities by name filter.
*
* @Route("/filter_by_name", name="mdl_app_product_filter_by_name")
*
* @Cache(expires="+2 days", public=true)
*
* @param Request $request
* @param PaginatorInterface $paginator
* @param CacheHelper $cacheHelper
*
* @return Response
*
* @throws \Doctrine\DBAL\DBALException
*/
public function filterByNameAction(
Request $request,
PaginatorInterface $paginator,
CacheHelper $cacheHelper
): Response {
$searchTitle = $this->get('request_stack')->getMasterRequest()->get('title', '');
preg_match('/^\*.*/', $searchTitle, $minQuantity);
$data = array(
'title' => $searchTitle
);
$form = $this->createForm(ProductFilterByName::class, $data, array(
'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_by_name.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_by_name.html.twig', $responseData)
->setExpires(new DateTime('+2 days'))
);
}
/**
* Lists all product entities by category.
*
* @Route("/filter_by_category", name="mdl_app_product_filter_by_category")
*
* @param Request $request
* @param PaginatorInterface $paginator
* @param CacheHelper $cacheHelper
*
* @return Response
*/
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)
);
}
public function show(Product $product): Response
{
return $this->render(':ECommerce/App/Product:show.html.twig', [
'product' => $product,
]);
}
}