src/AppBundle/Controller/ProductController.php line 119

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 AppBundle\Controller;
  15. use AppBundle\Model\Product\AbstractProduct;
  16. use AppBundle\Model\Product\AccessoryPart;
  17. use AppBundle\Model\Product\Car;
  18. use AppBundle\Model\Product\Category;
  19. use AppBundle\Services\SegmentTrackingHelperService;
  20. use AppBundle\Website\LinkGenerator\ProductLinkGenerator;
  21. use AppBundle\Website\Navigation\BreadcrumbHelperService;
  22. use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
  23. use Pimcore\Bundle\EcommerceFrameworkBundle\FilterService\Helper;
  24. use Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\ProductList\DefaultMysql;
  25. use Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\ProductList\ElasticSearch\AbstractElasticSearch;
  26. use Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\ProductList\ProductListInterface;
  27. use Pimcore\Config;
  28. use Pimcore\Model\DataObject\AbstractObject;
  29. use Pimcore\Model\DataObject\Concrete;
  30. use Pimcore\Model\DataObject\FilterDefinition;
  31. use Pimcore\Templating\Helper\HeadTitle;
  32. use Pimcore\Templating\Model\ViewModel;
  33. use Pimcore\Translation\Translator;
  34. use Symfony\Component\HttpFoundation\Request;
  35. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  36. use Symfony\Component\Routing\Annotation\Route;
  37. use Zend\Paginator\Paginator;
  38. class ProductController extends BaseController
  39. {
  40.     /**
  41.      * @Route("/shop/{path}{productname}~p{product}", name="shop-detail", defaults={"path"=""}, requirements={"path"=".*?", "productname"="[\w-]+", "product"="\d+"})
  42.      *
  43.      * @param Request $request
  44.      * @param HeadTitle $headTitleHelper
  45.      * @param BreadcrumbHelperService $breadcrumbHelperService
  46.      * @param Factory $ecommerceFactory
  47.      * @param SegmentTrackingHelperService $segmentTrackingHelperService
  48.      *
  49.      * @return \Symfony\Component\HttpFoundation\Response
  50.      *
  51.      * @throws \Exception
  52.      */
  53.     public function detailAction(Request $requestHeadTitle $headTitleHelperBreadcrumbHelperService $breadcrumbHelperServiceFactory $ecommerceFactorySegmentTrackingHelperService $segmentTrackingHelperService)
  54.     {
  55.         $product Concrete::getById($request->get('product'));
  56.         if (!(
  57.                 $product && ($product->isPublished() && (($product instanceof Car && $product->getObjectType() == Car::OBJECT_TYPE_ACTUAL_CAR) || $product instanceof AccessoryPart) || $this->verifyPreviewRequest($request$product))
  58.             )
  59.         ) {
  60.             throw new NotFoundHttpException('Product not found.');
  61.         }
  62.         $breadcrumbHelperService->enrichProductDetailPage($product);
  63.         $headTitleHelper($product->getOSName());
  64.         $paramBag $this->view->getAllParameters();
  65.         $paramBag['product'] = $product;
  66.         //track segments for personalization
  67.         $segmentTrackingHelperService->trackSegmentsForProduct($product);
  68.         $trackingManager $ecommerceFactory->getTrackingManager();
  69.         $trackingManager->trackProductView($product);
  70.         if ($product instanceof Car) {
  71.             foreach ($product->getAccessories() as $accessory) {
  72.                 $trackingManager->trackProductImpression($accessory'crosssells');
  73.             }
  74.             return $this->render('product/detail.html.twig'$paramBag);
  75.         } elseif ($product instanceof AccessoryPart) {
  76.             // get all compatible products
  77.             $productList $ecommerceFactory->getIndexService()->getProductListForCurrentTenant();
  78.             $productList->setVariantMode(ProductListInterface::VARIANT_MODE_VARIANTS_ONLY);
  79.             if($productList instanceof DefaultMysql) {
  80.                 $productList->addCondition('o_id IN (' implode(','$product->getCompatibleToProductIds()) . ')''o_id');
  81.             } else if($productList instanceof AbstractElasticSearch) {
  82.                 $productList->addCondition(['terms' => ['system.o_id' => $product->getCompatibleToProductIds()]], 'o_id');
  83.             }
  84.             foreach($productList as $compatibleProduct) {
  85.                 $trackingManager->trackProductImpression($compatibleProduct'crosssells');
  86.             }
  87.             $paramBag['compatibleTo'] = $productList;
  88.             return $this->render('product/detail_accessory.html.twig'$paramBag);
  89.         }
  90.     }
  91.     /**
  92.      * @Route("/shop/{path}{categoryname}~c{category}", name="shop-category", defaults={"path"=""}, requirements={"path"=".*?", "categoryname"="[\w-]+", "category"="\d+"})
  93.      *
  94.      * @param Request $request
  95.      * @param HeadTitle $headTitleHelper
  96.      * @param BreadcrumbHelperService $breadcrumbHelperService
  97.      * @param Factory $ecommerceFactory
  98.      * @param SegmentTrackingHelperService $segmentTrackingHelperService
  99.      *
  100.      * @return array|\Symfony\Component\HttpFoundation\Response
  101.      */
  102.     public function listingAction(Request $requestHeadTitle $headTitleHelperBreadcrumbHelperService $breadcrumbHelperServiceFactory $ecommerceFactorySegmentTrackingHelperService $segmentTrackingHelperService)
  103.     {
  104.         $viewModel = new ViewModel();
  105.         $params array_merge($request->query->all(), $request->attributes->all());
  106.         //needed to make sure category filter filters for active category
  107.         $params['parentCategoryIds'] = $params['category'] ?? null;
  108.         $category Category::getById($params['category'] ?? null);
  109.         $viewModel->category $category;
  110.         if ($category) {
  111.             $headTitleHelper($category->getName());
  112.             $breadcrumbHelperService->enrichCategoryPage($category);
  113.         }
  114.         $indexService $ecommerceFactory->getIndexService();
  115.         $productListing $indexService->getProductListForCurrentTenant();
  116.         $productListing->setVariantMode(ProductListInterface::VARIANT_MODE_VARIANTS_ONLY);
  117.         $viewModel->productListing $productListing;
  118.         // load current filter
  119.         if ($category) {
  120.             $filterDefinition $category->getFilterdefinition();
  121.             //track segments for personalization
  122.             $segmentTrackingHelperService->trackSegmentsForCategory($category);
  123.             $trackingManager $ecommerceFactory->getTrackingManager();
  124.             $trackingManager->trackCategoryPageView($category->getName(), null);
  125.         }
  126.         if ($request->get('filterdefinition') instanceof FilterDefinition) {
  127.             $filterDefinition $request->get('filterdefinition');
  128.         }
  129.         if (empty($filterDefinition)) {
  130.             $filterDefinition Config::getWebsiteConfig()->get('fallbackFilterdefinition');
  131.         }
  132.         $filterService $ecommerceFactory->getFilterService();
  133.         Helper::setupProductList($filterDefinition$productListing$params$viewModel$filterServicetrue);
  134.         $viewModel->filterService $filterService;
  135.         $viewModel->filterDefinition $filterDefinition;
  136.         // init pagination
  137.         $paginator = new Paginator($productListing);
  138.         $paginator->setCurrentPageNumber($request->get('page'));
  139.         $paginator->setItemCountPerPage(18);
  140.         $paginator->setPageRange(5);
  141.         $viewModel->results $paginator;
  142.         $viewModel->paginationVariables $paginator->getPages('Sliding');
  143.         if ($request->attributes->get('noLayout')) {
  144.             return $this->render('/product/listing_content.html.twig'array_merge($this->view->getAllParameters(), $viewModel->getAllParameters()));
  145.         }
  146.         // track product impressions
  147.         $trackingManager $ecommerceFactory->getTrackingManager();
  148.         foreach ($paginator as $product) {
  149.             $trackingManager->trackProductImpression($product'grid');
  150.         }
  151.         return $viewModel->getAllParameters();
  152.     }
  153.     /**
  154.      * @param Request $request
  155.      * @param Factory $ecommerceFactory
  156.      *
  157.      * @return \Symfony\Component\HttpFoundation\Response
  158.      */
  159.     public function productTeaserAction(Request $requestFactory $ecommerceFactory)
  160.     {
  161.         $paramsBag = [];
  162.         if ($request->get('type') == 'object') {
  163.             AbstractObject::setGetInheritedValues(true);
  164.             $product AbstractProduct::getById($request->get('id'));
  165.             $paramsBag['product'] = $product;
  166.             //track product impression
  167.             $trackingManager $ecommerceFactory->getTrackingManager();
  168.             $trackingManager->trackProductImpression($product'teaser');
  169.             return $this->render('/product/product_teaser.html.twig'$paramsBag);
  170.         }
  171.         throw new NotFoundHttpException('Product not found.');
  172.     }
  173.     /**
  174.      * @Route("/search", name="search")
  175.      *
  176.      * @param Request $request
  177.      * @param Factory $ecommerceFactory
  178.      * @param ProductLinkGenerator $productLinkGenerator
  179.      * @param Translator $translator
  180.      * @param BreadcrumbHelperService $breadcrumbHelperService
  181.      * @param HeadTitle $headTitleHelper
  182.      *
  183.      * @return array|\Symfony\Component\HttpFoundation\JsonResponse
  184.      */
  185.     public function searchAction(Request $requestFactory $ecommerceFactoryProductLinkGenerator $productLinkGeneratorTranslator $translatorBreadcrumbHelperService $breadcrumbHelperServiceHeadTitle $headTitleHelper)
  186.     {
  187.         $params $request->query->all();
  188.         $viewModel = new ViewModel();
  189.         $viewModel->category Category::getById($params['category'] ?? null);
  190.         $indexService $ecommerceFactory->getIndexService();
  191.         $productListing $indexService->getProductListForCurrentTenant();
  192.         $productListing->setVariantMode(ProductListInterface::VARIANT_MODE_VARIANTS_ONLY);
  193.         $term strip_tags($request->get('term'));
  194.         if($productListing instanceof AbstractElasticSearch) {
  195.             // simple elastic search query - uses multi-match query on all defined search_attributes
  196. //            $productListing->addQueryCondition($term);
  197.             //sample for a more specific elastic search query - not considers search_attributes but provides full flexibility
  198.             // this query weights cars more that accessries
  199.             $query = [
  200.                 'function_score' => [
  201.                     'query' => [
  202.                         'multi_match' => [
  203.                             "query" => $term,
  204.                             "type" => "cross_fields",
  205.                             "operator" => "and",
  206.                             "fields" => [
  207.                                 "attributes.name^4",
  208.                                 "attributes.name.analyzed",
  209.                                 "attributes.name.analyzed_ngram",
  210.                                 "attributes.manufacturer_name^3",
  211.                                 "attributes.manufacturer_name.analyzed",
  212.                                 "attributes.manufacturer_name.analyzed_ngram",
  213.                                 "attributes.color",
  214.                                 "attributes.carClass"
  215.                             ]
  216.                         ]
  217.                     ],
  218.                     'functions' => [
  219.                         [
  220.                             'filter' => ['match' => ['system.o_classId' => 'AP']],
  221.                             'weight' => 1
  222.                         ],
  223.                         [
  224.                             'filter' => ['match' => ['system.o_classId' => 'CAR']],
  225.                             'weight' => 2
  226.                         ]
  227.                     ],
  228.                     'boost_mode' => 'multiply'
  229.                 ]
  230.             ];
  231.             $productListing->addQueryCondition($query'searchTerm');
  232.         } else {
  233.             //default mysql search query condition - would also work for elastic search in that way
  234.             $term trim(preg_replace('/\s+/'' '$term));
  235.             if (!empty($term)) {
  236.                 foreach (explode(' '$term) as $t) {
  237.                     $productListing->addQueryCondition($t);
  238.                 }
  239.             }
  240.         }
  241.         if ($params['autocomplete']) {
  242.             $resultset = [];
  243.             $productListing->setLimit(10);
  244.             foreach ($productListing as $product) {
  245.                 $result['href'] = $productLinkGenerator->generateWithMockup($product, []);
  246.                 if ($product instanceof Car) {
  247.                     $result['product'] = $product->getOSName() . ' ' $product->getColor()[0] . ', ' $product->getCarClass();
  248.                 } else {
  249.                     $result['product'] = $product->getOSName();
  250.                 }
  251.                 $resultset[] = $result;
  252.             }
  253.             return $this->json($resultset);
  254.         }
  255.         $filterDefinition $viewModel->filterDefinition Config::getWebsiteConfig()->get('fallbackFilterdefinition');
  256.         // create and init filter service
  257.         $filterService Factory::getInstance()->getFilterService();
  258.         Helper::setupProductList($filterDefinition$productListing$params$viewModel$filterServicetrue);
  259.         $viewModel->filterService $filterService;
  260.         $viewModel->products $productListing;
  261.         // init pagination
  262.         $paginator = new Paginator($productListing);
  263.         $paginator->setCurrentPageNumber($request->get('page'));
  264.         $paginator->setItemCountPerPage(18);
  265.         $paginator->setPageRange(5);
  266.         $viewModel->results $paginator;
  267.         $viewModel->paginationVariables $paginator->getPages('Sliding');
  268.         $trackingManager $ecommerceFactory->getTrackingManager();
  269.         foreach ($paginator as $product) {
  270.             $trackingManager->trackProductImpression($product'search-results');
  271.         }
  272.         //breadcrumbs
  273.         $placeholder $this->get('pimcore.templating.view_helper.placeholder');
  274.         $placeholder('addBreadcrumb')->append([
  275.             'parentId' => $this->document->getId(),
  276.             'id' => 'search-result',
  277.             'label' => $translator->trans('shop.search-result', [$term])
  278.         ]);
  279.         $viewModel->language $request->getLocale();
  280.         $viewModel->term $term;
  281.         $breadcrumbHelperService->enrichGenericDynamicPage($translator->trans('shop.search-result', [$term]));
  282.         $headTitleHelper($translator->trans('shop.search-result', [$term]));
  283.         return $viewModel->getAllParameters();
  284.     }
  285. }