<?php
namespace App\Controller;
use App\Model\DataObject\AbstractProduct;
use App\Model\ShopCategory;
use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
use Pimcore\Bundle\EcommerceFrameworkBundle\FilterService\ListHelper;
use Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\ProductList\ProductListInterface;
use Pimcore\Config;
use Pimcore\Controller\FrontendController;
use Pimcore\Model\DataObject\Product;
use Pimcore\Model\DataObject\ProductCategory;
use Pimcore\Model\DataObject\ProductMarca;
use Pimcore\Model\Document;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
class DefaultController extends FrontendController
{
private function getCategories(Factory $ecommerceFactory, $parentId, $level = 1, $values = null): array
{
if ($values === null){
$indexService = $ecommerceFactory->getIndexService();
$products = $indexService->getProductListForCurrentTenant();
$products->setVariantMode(ProductListInterface::VARIANT_MODE_HIDE);
$products->addCondition("productstatus NOT IN ('new', 'decatelogized', 'for_delete') OR productstatus IS NULL", 'productstatus');
$filterService = $ecommerceFactory->getFilterService();
$filterDefinition = Config::getWebsiteConfig()->get('fallbackFilterdefinition');
$listHelper = new ListHelper();
$listHelper->setupProductList($filterDefinition, $products, $params, $filterService, true);
$rawValues = $filterService->getFilterValues($filterDefinition->getFilters()->getItems()[1], $products, ['parentCategoryIds' => null])['values'];
$values = [];
foreach ($rawValues as $entry) {
$values[$entry['value']] = $entry['count'];
}
}
$categoryList = new ProductCategory\Listing();
$categoryList->setUnpublished(false);
$categoryList->setOrderKey("o_key");
$categoryList->setOrder("ASC");
$categoryList->setCondition("o_parentId = ?", [$parentId]);
$loadedCategories = $categoryList->load();
$result = [];
foreach ($loadedCategories as $category) {
if (!isset($values[$category->getId()])) {
continue;
}
$subcategories = [];
if ($level < 3) {
$subcategories = $this->getCategories($ecommerceFactory, $category->getId(), $level + 1, $values);
}
$result[] = [
'category' => $category,
'children' => $subcategories,
];
}
return $result;
}
public function navbarAction(Factory $ecommerceFactory): Response
{
$categories = $this->getCategories($ecommerceFactory, 10);
return $this->render('layout/includes/navegation/navbar.html.twig', [
'categories' => $categories
]);
}
#[Route('/featuredProducts/{categoryId}', name: 'featured_products', methods: ['GET'])]
public function featuredProductAction($categoryId, Request $request):Response
{
$category = ProductCategory::getById($categoryId);
$featuredProduct = $category->getFeaturedproduct();
if ($request->getLocale() === 'en') {
$document = Document::getById(8);// English Document
}else{
$document = Document::getById(1);// Spanish Document
}
return $this->render('layout/includes/navegation/featuredProduct.html.twig',[
'featuredProduct' => $featuredProduct,
'title' => $category->getFeaturedProductTitle(),
'document' => $document,
'prefix' => $request->getLocale(),
]);
}
private function getBrandListResponse(?int $categoryId, Request $request, Factory $ecommerceFactory): JsonResponse
{
$locale = $request->getLocale();
$prefix = $locale === 'en' ? 'en' : 'es';
$params = ['prefix' => $prefix];
$document = $locale === 'en' ? Document::getById(8) : Document::getById(1);
$params['document'] = $document;
$indexService = $ecommerceFactory->getIndexService();
$productListing = $indexService->getProductListForCurrentTenant();
$productListing->setVariantMode(ProductListInterface::VARIANT_MODE_HIDE);
$productListing->addCondition("productstatus NOT IN ('new', 'decatelogized', 'for_delete') OR productstatus IS NULL", 'productstatus');
$categoryUrl = null;
if ($categoryId !== null) {
$category = ShopCategory::getById($categoryId);
if ($category) {
// Always filter by category
$params['parentCategoryIds'] = $categoryId;
$params['rootCategory'] = $category;
$params['document'] = $document;
// Include parentCategoryIds in the URL only if it's a subcategory
$urlParams = [
'rootCategory' => $category,
'document' => $document,
];
if ($this->hasParentCategory($category)) {
$urlParams['parentCategoryIds'] = $categoryId;
}
// Generate the final category URL with the appropriate parameters
$categoryUrl = $category->getDetailUrl($urlParams);
}
}
$filterDefinition = Config::getWebsiteConfig()->get('fallbackFilterdefinition');
$filterService = $ecommerceFactory->getFilterService();
(new ListHelper())->setupProductList($filterDefinition, $productListing, $params, $filterService, true);
$brandFilter = null;
foreach ($filterDefinition->getFilters() as $filter) {
if ($filter instanceof \Pimcore\Model\DataObject\Fieldcollection\Data\FilterMultiSelectBrand) {
$brandFilter = $filter;
break;
}
}
if (!$brandFilter) {
throw new \RuntimeException('Brand filter not found in FilterDefinition');
}
$brandData = $filterService->getFilterValues($brandFilter, $productListing, ['marca' => null]);
$brands = [];
foreach ($brandData['values'] as $value) {
$brand = ProductMarca::getById($value['value']);
if (!$brand || !$brand->isPublished()) {
continue;
}
$url = $categoryId
? $categoryUrl . (str_contains($categoryUrl, '?') ? '&' : '?') . 'marca[]=' . $brand->getId()
: '/' . $prefix . '/productos/marcas/' .
preg_replace('/[^a-zA-Z0-9\-]/', '', str_replace(' ', '', $brand->getName())) . '_m' . $brand->getId();
$brands[] = [
'id' => $brand->getId(),
'name' => $brand->getName(),
'url' => $url,
'image' => $brand->getLogo()
? $brand->getLogo()->getThumbnail('navbar-brands')->getPath()
: null,
];
}
usort($brands, static fn($a, $b) => strcmp($a['name'], $b['name']));
return new JsonResponse(['brands' => $brands]);
}
private function hasParentCategory(ShopCategory $category): bool
{
$parent = $category->getParent();
return $parent instanceof \App\Model\ShopCategory;
}
#[Route('/load-brands/{categoryId}', name: 'load_brands', methods: ['GET'])]
public function loadBrandsAction(Request $request, int $categoryId, Factory $ecommerceFactory): JsonResponse
{
return $this->getBrandListResponse($categoryId, $request, $ecommerceFactory);
}
#[Route('/load-brands', name: 'load_all_brands', methods: ['GET'])]
public function loadAllBrandsAction(Request $request, Factory $ecommerceFactory): JsonResponse
{
return $this->getBrandListResponse(null, $request, $ecommerceFactory);
}
public function usermanualAction(){
return $this->render('layout/includes/user-manual-links.html.twig');
}
public function addProductAction(Request $request){
if($request->get('type') == 'object')
{
if($object = AbstractProduct::getById($request->get('id'))){
return $this->render('Content/newsProduct.html.twig',['object' => $object]);
}
}
throw new NotFoundHttpException('Object not found.');
}
#[Route('/admin/send-registration-emails', name: 'send_emails', methods: ['POST'])]
#[IsGranted('ROLE_PIMCORE_USER')]
public function sendEmails(): JsonResponse
{
try {
$projectDir = $this->getParameter('kernel.project_dir');
$process = new Process(['php', $projectDir . '/bin/console', 'send-registration-mail']);
$process->setTimeout(300); // 5 minutes
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
$outputLines = explode("\n", trim($process->getOutput()));
$lastLine = end($outputLines);
$summary = json_decode($lastLine, true);
if (!is_array($summary) || !isset($summary['total'], $summary['successful'], $summary['failed'])) {
throw new \Exception('Invalid output from command');
}
return new JsonResponse([
'success' => true,
'message' => 'Emails sent successfully',
'summary' => $summary
]);
} catch (\Exception $e) {
return new JsonResponse([
'success' => false,
'error' => $e->getMessage()
], 500);
}
}
}