src/AppBundle/Controller/ProductController.php line 181

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