src/Controller/ProductController.php line 128

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Enterprise License (PEL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PEL
  13.  */
  14. namespace App\Controller;
  15. use App\Model\Product\AbstractProduct;
  16. use App\Model\Product\AccessoryPart;
  17. use App\Model\Product\Category;
  18. use App\Model\Product\Toy;
  19. use App\Services\SegmentTrackingHelperService;
  20. use App\Website\LinkGenerator\ProductLinkGenerator;
  21. use App\Website\Navigation\BreadcrumbHelperService;
  22. use Knp\Component\Pager\Pagination\SlidingPagination;
  23. use Knp\Component\Pager\PaginatorInterface;
  24. use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
  25. use Pimcore\Bundle\EcommerceFrameworkBundle\FilterService\ListHelper;
  26. use Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\ProductList\DefaultMysql;
  27. use Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\ProductList\ElasticSearch\AbstractElasticSearch;
  28. use Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\ProductList\ProductListInterface;
  29. use Pimcore\Config;
  30. use Pimcore\Model\DataObject\AbstractObject;
  31. use Pimcore\Model\DataObject\Concrete;
  32. use Pimcore\Model\DataObject\Data\UrlSlug;
  33. use Pimcore\Model\DataObject\FilterDefinition;
  34. use Pimcore\Translation\Translator;
  35. use Pimcore\Twig\Extension\Templating\HeadTitle;
  36. use Pimcore\Twig\Extension\Templating\Placeholder;
  37. use Symfony\Component\HttpFoundation\JsonResponse;
  38. use Symfony\Component\HttpFoundation\Request;
  39. use Symfony\Component\HttpFoundation\Response;
  40. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  41. use Symfony\Component\Routing\Annotation\Route;
  42. class ProductController extends BaseController
  43. {
  44.     /**
  45.      * @param Request $request
  46.      * @param AbstractObject $object
  47.      * @param UrlSlug $urlSlug
  48.      *
  49.      * @return Response
  50.      */
  51.     public function productDetailSlugAction(Request $requestAbstractObject $objectUrlSlug $urlSlug)
  52.     {
  53.         return $this->forward('App\Controller\ProductController::detailAction', ['product' => $object]);
  54.     }
  55.     /**
  56.      * @Route("/shop/{path}{productname}~p{product}", name="shop-detail", defaults={"path"=""}, requirements={"path"=".*?", "productname"="[\w-]+", "product"="\d+"})
  57.      *
  58.      * @param Request $request
  59.      * @param HeadTitle $headTitleHelper
  60.      * @param BreadcrumbHelperService $breadcrumbHelperService
  61.      * @param Factory $ecommerceFactory
  62.      * @param SegmentTrackingHelperService $segmentTrackingHelperService
  63.      * @param Concrete $product built-in parameter conversion, please see https://github.com/pimcore/pimcore/pull/5554
  64.      * @param ProductLinkGenerator $productLinkGenerator
  65.      *
  66.      * @return Response
  67.      *
  68.      * @throws \Exception
  69.      */
  70.     public function detailAction(
  71.         Request $request,
  72.         HeadTitle $headTitleHelper,
  73.         BreadcrumbHelperService $breadcrumbHelperService,
  74.         Factory $ecommerceFactory,
  75.         SegmentTrackingHelperService $segmentTrackingHelperService,
  76.         Concrete $product,
  77.         ProductLinkGenerator $productLinkGenerator
  78.     ) {
  79.         if (!(
  80.                 $product && ($product->isPublished() && ( $product instanceof Toy) || $this->verifyPreviewRequest($request$product))
  81.             )
  82.         ) {
  83.             throw new NotFoundHttpException('Product not found.');
  84.         }
  85.         //redirect to main url
  86.         $generatorUrl $productLinkGenerator->generate($product);
  87.         if ($generatorUrl != $request->getPathInfo()) {
  88.             $queryString $request->getQueryString();
  89.             return $this->redirect($generatorUrl . ($queryString '?' $queryString ''));
  90.         }
  91.         $breadcrumbHelperService->enrichProductDetailPage($product);
  92.         $headTitleHelper($product->getOSName());
  93.         $paramBag $this->getAllParameters($request);
  94.         $paramBag['product'] = $product;
  95.         //track segments for personalization
  96.         $segmentTrackingHelperService->trackSegmentsForProduct($product);
  97.         $trackingManager $ecommerceFactory->getTrackingManager();
  98.         $trackingManager->trackProductView($product);
  99.             return $this->render('product/detail.html.twig'$paramBag);
  100.     }
  101.     /**
  102.      * @Route("/shop/{path}{categoryname}~c{category}", name="shop-category", defaults={"path"=""}, requirements={"path"=".*?", "categoryname"="[\w-]+", "category"="\d+"})
  103.      *
  104.      * @param Request $request
  105.      * @param HeadTitle $headTitleHelper
  106.      * @param BreadcrumbHelperService $breadcrumbHelperService
  107.      * @param Factory $ecommerceFactory
  108.      * @param SegmentTrackingHelperService $segmentTrackingHelperService
  109.      * @param ListHelper $listHelper
  110.      *
  111.      * @return Response
  112.      */
  113.     public function listingAction(Request $requestHeadTitle $headTitleHelperBreadcrumbHelperService $breadcrumbHelperServiceFactory $ecommerceFactorySegmentTrackingHelperService $segmentTrackingHelperServiceListHelper $listHelperPaginatorInterface $paginator)
  114.     {
  115.         $params array_merge($request->query->all(), $request->attributes->all());
  116.         //needed to make sure category filter filters for active category
  117.         $params['parentCategoryIds'] = $params['category'] ?? null;
  118.         $category Category::getById($params['category'] ?? null);
  119.         $params['category'] = $category;
  120.         if ($category) {
  121.             $headTitleHelper($category->getName());
  122.             $breadcrumbHelperService->enrichCategoryPage($category);
  123.         }
  124.         $indexService $ecommerceFactory->getIndexService();
  125.         $productListing $indexService->getProductListForCurrentTenant();
  126.         $productListing->setVariantMode(ProductListInterface::VARIANT_MODE_VARIANTS_ONLY);
  127.         $params['productListing'] = $productListing;
  128.         // load current filter
  129.         if ($category) {
  130.             $filterDefinition $category->getFilterdefinition();
  131.             //track segments for personalization
  132.             $segmentTrackingHelperService->trackSegmentsForCategory($category);
  133.             $trackingManager $ecommerceFactory->getTrackingManager();
  134.             $trackingManager->trackCategoryPageView($category->getName(), null);
  135.         }
  136.         if ($request->get('filterdefinition') instanceof FilterDefinition) {
  137.             $filterDefinition $request->get('filterdefinition');
  138.         }
  139.         if (empty($filterDefinition)) {
  140.             $filterDefinition Config::getWebsiteConfig()->get('fallbackFilterdefinition');
  141.         }
  142.         $filterService $ecommerceFactory->getFilterService();
  143.         $listHelper->setupProductList($filterDefinition$productListing$params$filterServicetrue);
  144.         $params['filterService'] = $filterService;
  145.         $params['filterDefinition'] = $filterDefinition;
  146.         /** @var SlidingPagination $paginator */
  147.         // init pagination
  148.         $paginator $paginator->paginate(
  149.             $productListing,
  150.             $request->get('page'1),
  151.             $filterDefinition->getPageLimit()
  152.         );
  153.         $params['results'] = $paginator;
  154.         $params['paginationVariables'] = $paginator->getPaginationData();
  155.         if ($request->attributes->get('noLayout')) {
  156.             return $this->render('product/listing_content.html.twig'$params);
  157.         }
  158.         // track product impressions
  159.         $trackingManager $ecommerceFactory->getTrackingManager();
  160.         foreach ($paginator as $product) {
  161.             $trackingManager->trackProductImpression($product'grid');
  162.         }
  163.         return $this->render('product/listing.html.twig'$params);
  164.     }
  165.     /**
  166.      * @param Request $request
  167.      * @param Factory $ecommerceFactory
  168.      *
  169.      * @return Response
  170.      */
  171.     public function productTeaserAction(Request $requestFactory $ecommerceFactory)
  172.     {
  173.         $paramsBag = [];
  174.         if ($request->get('type') == 'object') {
  175.             AbstractObject::setGetInheritedValues(true);
  176.             $product AbstractProduct::getById($request->get('id'));
  177.             $paramsBag['product'] = $product;
  178.             //track product impression
  179.             $trackingManager $ecommerceFactory->getTrackingManager();
  180.             $trackingManager->trackProductImpression($product'teaser');
  181.             return $this->render('product/product_teaser.html.twig'$paramsBag);
  182.         }
  183.         throw new NotFoundHttpException('Product not found.');
  184.     }
  185.     /**
  186.      * @Route("/search", name="search")
  187.      *
  188.      * @param Request $request
  189.      * @param ListHelper $listHelper
  190.      * @param Factory $ecommerceFactory
  191.      * @param ProductLinkGenerator $productLinkGenerator
  192.      * @param Translator $translator
  193.      * @param BreadcrumbHelperService $breadcrumbHelperService
  194.      * @param HeadTitle $headTitleHelper
  195.      * @param Placeholder $placeholder
  196.      *
  197.      * @return Response|JsonResponse
  198.      */
  199.     public function searchAction(Request $requestListHelper $listHelperFactory $ecommerceFactoryProductLinkGenerator $productLinkGeneratorTranslator $translatorBreadcrumbHelperService $breadcrumbHelperServiceHeadTitle $headTitleHelperPlaceholder $placeholderPaginatorInterface $paginator)
  200.     {
  201.         $params $request->query->all();
  202.         $params['category'] = Category::getById($params['category'] ?? null);
  203.         $indexService $ecommerceFactory->getIndexService();
  204.         $productListing $indexService->getProductListForCurrentTenant();
  205.         $productListing->setVariantMode(ProductListInterface::VARIANT_MODE_VARIANTS_ONLY);
  206.         $term strip_tags($request->get('term'));
  207.         if ($productListing instanceof AbstractElasticSearch) {
  208.             // simple elastic search query - uses multi-match query on all defined search_attributes
  209. //            $productListing->addQueryCondition($term);
  210.             //sample for a more specific elastic search query - not considers search_attributes but provides full flexibility
  211.             // this query weights cars more that accessories
  212.             $query = [
  213.                 'function_score' => [
  214.                     'query' => [
  215.                         'multi_match' => [
  216.                             'query' => $term,
  217.                             'type' => 'cross_fields',
  218.                             'operator' => 'and',
  219.                             'fields' => [
  220.                                 'attributes.name^4',
  221.                                 'attributes.name.analyzed',
  222.                                 'attributes.name.analyzed_ngram',
  223.                                 'attributes.manufacturer_name^3',
  224.                                 'attributes.manufacturer_name.analyzed',
  225.                                 'attributes.manufacturer_name.analyzed_ngram',
  226.                                 'attributes.color',
  227.                                 'attributes.color.analyzed',
  228.                                 'attributes.color.analyzed_ngram',
  229.                             ]
  230.                         ]
  231.                     ],
  232.                     'functions' => [
  233.                         [
  234.                             'filter' => ['match' => ['system.o_classId' => 'AP']],
  235.                             'weight' => 1
  236.                         ],
  237.                         [
  238.                             'filter' => ['match' => ['system.o_classId' => 'Toy']],
  239.                             'weight' => 2
  240.                         ]
  241.                     ],
  242.                     'boost_mode' => 'multiply'
  243.                 ]
  244.             ];
  245.             $productListing->addQueryCondition($query'searchTerm');
  246.         } else {
  247.             //default mysql search query condition - would also work for elastic search in that way
  248.             $term trim(preg_replace('/\s+/'' '$term));
  249.             if (!empty($term)) {
  250.                 foreach (explode(' '$term) as $t) {
  251.                     $productListing->addQueryCondition($t);
  252.                 }
  253.             }
  254.         }
  255.         if (isset($params['autocomplete'])) {
  256.             $resultset = [];
  257.             $productListing->setLimit(10);
  258.             foreach ($productListing as $product) {
  259.                 $result['href'] = $productLinkGenerator->generateWithMockup($product, []);
  260.                 $result['product'] = $product->getOSName() ?? '';
  261.                 if ($product instanceof Toy) {
  262.                     $result['product'] .= ' ' $product->getColor()[0] . ', ' $product->getName();
  263.                 }
  264.                 $resultset[] = $result;
  265.             }
  266.             return $this->json($resultset);
  267.         }
  268.         $filterDefinition $params['filterDefinition'] = Config::getWebsiteConfig()->get('fallbackFilterdefinition');
  269.         // create and init filter service
  270.         $filterService Factory::getInstance()->getFilterService();
  271.         $listHelper->setupProductList($filterDefinition$productListing$params$filterServicetrue);
  272.         $params['filterService'] = $filterService;
  273.         $params['products'] = $productListing;
  274.         // init pagination
  275.         $paginator $paginator->paginate(
  276.             $productListing,
  277.             $request->get('page'1),
  278.             $filterDefinition->getPageLimit()
  279.         );
  280.         $params['results'] = $paginator;
  281.         $params['paginationVariables'] = $paginator->getPaginationData();
  282.         $trackingManager $ecommerceFactory->getTrackingManager();
  283.         foreach ($paginator as $product) {
  284.             $trackingManager->trackProductImpression($product'search-results');
  285.         }
  286.         //breadcrumbs
  287.         $placeholder('addBreadcrumb')->append([
  288.             'parentId' => $this->document->getId(),
  289.             'id' => 'search-result',
  290.             'label' => $translator->trans('shop.search-result', [$term])
  291.         ]);
  292.         $params['language'] = $request->getLocale();
  293.         $params['term'] = $term;
  294.         $breadcrumbHelperService->enrichGenericDynamicPage($translator->trans('shop.search-result', [$term]));
  295.         $headTitleHelper($translator->trans('shop.search-result', [$term]));
  296.         return $this->render('product/search.html.twig'$params);
  297.     }
  298. }