src/EcommerceShopBundle/Controller/ProductController.php line 50

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 EcommerceShopBundle\Controller;
  15. use EcommerceShopBundle\Model\Product\AbstractProduct;
  16. use EcommerceShopBundle\Model\Product\ShopCategory;
  17. use EcommerceShopBundle\Model\Product\ShopProduct;
  18. use EcommerceShopBundle\Services\SegmentTrackingHelperService;
  19. use EcommerceShopBundle\Website\LinkGenerator\ProductLinkGenerator;
  20. use EcommerceShopBundle\Website\Navigation\BreadcrumbHelperService;
  21. use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
  22. use Pimcore\Bundle\EcommerceFrameworkBundle\FilterService\Helper;
  23. use Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\ProductList\DefaultMysql;
  24. use Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\ProductList\ElasticSearch\AbstractElasticSearch;
  25. use Pimcore\Bundle\EcommerceFrameworkBundle\IndexService\ProductList\ProductListInterface;
  26. use Pimcore\Config;
  27. use Pimcore\Model\DataObject\AbstractObject;
  28. use Pimcore\Model\DataObject\Concrete;
  29. use Pimcore\Model\DataObject\FilterDefinition;
  30. use Pimcore\Templating\Helper\HeadTitle;
  31. use Pimcore\Templating\Helper\Placeholder;
  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. use Pimcore\Localization;
  39. use \Pimcore\Model\DataObject;
  40. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  41. use Pimcore\Model\Document;
  42. use MembersBundle\Manager\RestrictionManager;
  43. use MembersBundle\Security\RestrictionUri;
  44. use Pimcore\Model\Asset;
  45. class ProductController extends BaseController {
  46.     /**
  47.      * @param Request $request
  48.      * @param Factory $ecommerceFactory
  49.      *
  50.      * @return \Symfony\Component\HttpFoundation\Response
  51.      */
  52.     public function indexAction(
  53.         Request $request
  54.         SessionInterface $session
  55.         Factory $ecommerceFactory
  56.     ) {
  57.         $this->view->isShop true;
  58.         // show price
  59.         $countryListing = new DataObject\ShopKonfiguration\Listing();
  60.         $showPrice false;
  61.         foreach ($countryListing as $country) {
  62.             if (strtolower($country->getShortname()) == $session->get('country') || strtolower($country->getShortname()) == $request->get('country')) {
  63.                 $showPrice true;
  64.             }
  65.         }
  66.         $this->view->showPrice $showPrice;
  67.         return $this->render('EcommerceShopBundle:index:index.html.twig'array_merge($this->view->getAllParameters()));
  68.     }
  69.     /**
  70.      * @Route("/shop/{path}{productname}~p{product}", name="shop-detail", defaults={"path"=""}, requirements={"path"=".*?", "productname"="[\w-]+", "product"="\d+"})
  71.      *
  72.      * @param Request                 $request
  73.      * @param HeadTitle               $headTitleHelper
  74.      * @param BreadcrumbHelperService $breadcrumbHelperService
  75.      * @param Factory                 $ecommerceFactory
  76.      * @param SessionInterface        $session
  77.      *
  78.      * @return \Symfony\Component\HttpFoundation\Response
  79.      *
  80.      * @throws \Exception
  81.      */
  82.     public function detailAction(
  83.         Request $request
  84.         HeadTitle $headTitleHelper
  85.         BreadcrumbHelperService $breadcrumbHelperService
  86.         SessionInterface $session
  87.         Factory $ecommerceFactory,
  88.         RestrictionUri $restrictionUri,
  89.         \Pimcore\Config\Config $websiteConfig
  90.     ) {
  91.         //Members RestrictionManager
  92.         if (!$this->editmode) {
  93.             $element Document::getById($this->document->getId());
  94.               $restriction $this->container->get(RestrictionManager::class)->getElementRestrictionStatus($element);
  95.           
  96.             if ($restriction->getState() == 'members.restriction.logged_in') {
  97.                 $isLoggedin true;
  98.             } else {
  99.                 $isLoggedin false;
  100.             }
  101.               
  102.             $this->view->isLoggedin $isLoggedin;
  103.     
  104.               $userRoles = [];
  105.               $user $this->getUser();
  106.               
  107.             if ($user) {
  108.                    $userGroups $user->getGroups()[0];
  109.                    if ($userGroups) {
  110.                     $userRoles $user->getGroups()[0]->getRoles();
  111.                    }
  112.               }
  113.         }
  114.         
  115.         $this->view->user $user;
  116.         $this->view->userRoles $userRoles;
  117.         $this->view->isShop true;
  118.         // show price
  119.         $countryListing = new DataObject\ShopKonfiguration\Listing();
  120.         $showPrice false;
  121.         foreach ($countryListing as $country) {
  122.             if (strtolower($country->getShortname()) == $session->get('country') || strtolower($country->getShortname()) == $request->get('country')) {
  123.                 $showPrice true;
  124.             }
  125.         }
  126.         $this->view->showPrice $showPrice;
  127.         $reveal $request->get('reveal');
  128.         // clear or save country
  129.         if ($_REQUEST['country'] == 'null') {
  130.             $session->set("country"null);
  131.         } else if ($_REQUEST['country']) {
  132.             $session->set("country"$_REQUEST['country']);
  133.         }
  134.         // show or hide country popup
  135.         if ($session->get('country') !== null) {
  136.             $showCountryPopup false;
  137.         } else {
  138.             $showCountryPopup true;
  139.         }
  140.         $this->view->showCountryPopup $showCountryPopup;
  141.         $countryNames = \Pimcore::getContainer()->get('pimcore.locale')->getDisplayRegions();
  142.         $arrCountries = [];
  143.         if ($countryNames) {
  144.             $i=0;
  145.             foreach ($countryNames as $key => $value) {
  146.                 $i++;
  147.                 $arrCountries[$i]['code'] = $key;
  148.                 $arrCountries[$i]['name'] = $value;
  149.             }
  150.         }
  151.         
  152.         $this->view->arrCountries $arrCountries;
  153.         $product Concrete::getById($request->get('product'));
  154.         if (!($product && ($product->isPublished() && ($product instanceof ShopProduct && $product->getObjectType() == ShopProduct::OBJECT_TYPE_ACTUAL_PRODUCT) || $this->verifyPreviewRequest($request$product)))) {
  155.             throw new NotFoundHttpException('Product not found.');
  156.         }
  157.         $breadcrumbHelperService->enrichProductDetailPage($product);
  158.         $headTitleHelper($product->getOSName());
  159.         $paramBag $this->view->getAllParameters();
  160.         $paramBag['product'] = $product;
  161.         $trackingManager $ecommerceFactory->getTrackingManager();
  162.         $trackingManager->trackProductView($product);
  163.         // store current page for add-to-cart redirect
  164.         $currentUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' "https" "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
  165.         $session->set("add-to-cart-return"$currentUrl);
  166.         //$cleanCurrentUrl = strtok($currentUrl, '?');
  167.         //$paramBag['returnUrl'] = $cleanCurrentUrl;
  168.         $paramBag['isProductDetail'] = true;
  169.         $paramBag['isReveal'] = $reveal;
  170.         // filtered products
  171.         $filteredProducts $session->get('filteredProducts');
  172.         $paramBag['filteredProducts'] = $filteredProducts;
  173.         // restricted asset
  174.         $key substr($product->getSku(), strpos($product->getSku(), "-") + 1);
  175.         $operatingManualsFolder $websiteConfig->get('operatingManualsFolder');
  176.         //$assetPath = $operatingManualsFolder . '/' . $key . '.pdf';
  177.         if ($product->getDownloadDoc()) {
  178.             $assetPathDownloadDoc $operatingManualsFolder '/' $product->getDownloadDoc() . '.pdf';
  179.             $assetDownloadDoc Asset::getByPath($assetPathDownloadDoc);
  180.         }
  181.         if ($product->getSku()) {
  182.             $assetPathIdent $operatingManualsFolder '/' $key '.pdf';
  183.             $assetIdent Asset::getByPath($assetPathIdent);
  184.         }
  185.         if ($assetDownloadDoc || $assetIdent) {
  186.             $hasAsset true;
  187.         } else {
  188.             $hasAsset false;
  189.         }
  190.         // MembersBundle/Security
  191.         //$asset = Asset::getByPath($assetPath);
  192.         //$restrictedAsset = $restrictionUri->generateAssetUrl($asset, false, true);
  193.         //$restrictedAsset = $asset;
  194.         /* if ($asset) {
  195.             $hasAsset = true;
  196.         } else {
  197.             $hasAsset = false;
  198.         } */
  199.         // file icon
  200.         //$fileExtension = strtoupper(explode('.', substr(basename($asset), -5))[1]);
  201.         if ($assetDownloadDoc) {
  202.             $fileExtension strtoupper(explode('.'substr(basename($assetDownloadDoc), -5))[1]);
  203.         } else if ($assetIdent) {
  204.             $fileExtension strtoupper(explode('.'substr(basename($assetIdent), -5))[1]);
  205.         }
  206.         $this->view->hasAsset $hasAsset;
  207.         //$this->view->restrictedAsset = $restrictedAsset;
  208.         $this->view->fileExtension $fileExtension;
  209.         // download link
  210.         $downloadLink $this->generateUrl('shop-download', ['productId' => base64_encode($product->getId())]);
  211.         $paramBag['hasAsset'] = $hasAsset;
  212.         //$paramBag['restrictedAsset'] = $restrictedAsset;
  213.         $paramBag['fileExtension'] = $fileExtension;
  214.         $paramBag['downloadLink'] = $downloadLink;
  215.         if ($product instanceof ShopProduct) {
  216.             return $this->render('EcommerceShopBundle:product:detail.html.twig'$paramBag);
  217.         }
  218.     }
  219.     /**
  220.      * @Route("/shop/{path}{categoryname}~c{category}", name="shop-category", defaults={"path"=""}, requirements={"path"=".*?", "categoryname"="[\w-]+", "category"="\d+"})
  221.      *
  222.      * @param Request                 $request
  223.      * @param HeadTitle               $headTitleHelper
  224.      * @param BreadcrumbHelperService $breadcrumbHelperService
  225.      * @param Factory                 $ecommerceFactory
  226.      * @param SessionInterface        $session
  227.      *
  228.      * @return array|\Symfony\Component\HttpFoundation\Response
  229.      */
  230.     public function listingAction(
  231.         Request $request
  232.         HeadTitle $headTitleHelper
  233.         BreadcrumbHelperService $breadcrumbHelperService
  234.         Factory $ecommerceFactory,
  235.         SessionInterface $session
  236.     ) {
  237.         //Members RestrictionManager
  238.         if (!$this->editmode) {
  239.             $element Document::getById($this->document->getId());
  240.               $restriction $this->container->get(RestrictionManager::class)->getElementRestrictionStatus($element);
  241.           
  242.             if ($restriction->getState() == 'members.restriction.logged_in') {
  243.                 $isLoggedin true;
  244.             } else {
  245.                 $isLoggedin false;
  246.             }
  247.               
  248.             $this->view->isLoggedin $isLoggedin;
  249.     
  250.               $userRoles = [];
  251.               $user $this->getUser();
  252.               
  253.             if ($user) {
  254.                    $userGroups $user->getGroups()[0];
  255.                    if ($userGroups) {
  256.                     $userRoles $user->getGroups()[0]->getRoles();
  257.                    }
  258.               }
  259.         } 
  260.         
  261.         $this->view->user $user;
  262.         $this->view->userRoles $userRoles;
  263.         $this->view->isShop true;
  264.         // ajax
  265.         $ajax $request->get('ajax');
  266.         if ($ajax == 'true') { 
  267.             $isAjax true;
  268.         }
  269.         $viewModel = new ViewModel();
  270.         $params array_merge($request->query->all(), $request->attributes->all());
  271.         // search text
  272.         $searchText $request->get('title');
  273.         $viewModel->searchText $searchText;
  274.         // needed to make sure category filter filters for active category
  275.         $params['parentCategoryIds'] = $params['category'] ?? null;
  276.         $category ShopCategory::getById($params['category'] ?? null);
  277.         $viewModel->category $category;
  278.         if ($category) {
  279.             $headTitleHelper($category->getName());
  280.             $breadcrumbHelperService->enrichCategoryPage($category);
  281.         }
  282.         $indexService $ecommerceFactory->getIndexService();
  283.         $productListing $indexService->getProductListForCurrentTenant();
  284.         $productListing->setOrder("ASC");
  285.         $productListing->setOrderKey('sku');
  286.         // search product title and sku
  287.         $term strip_tags($request->get('title'));
  288.         $term trim(preg_replace('/\s+/'' '$term));
  289.         if (!empty($term)) {
  290.             foreach (explode(' '$term) as $t) {
  291.                 $productListing->addQueryCondition($t);
  292.             }
  293.         }
  294.         
  295.         $viewModel->productListing $productListing;
  296.         // load current filter
  297.         if ($category) {
  298.             $filterDefinition $category->getFilterdefinition();
  299.             $trackingManager $ecommerceFactory->getTrackingManager();
  300.             $trackingManager->trackCategoryPageView($category->getName(), null);
  301.         }
  302.         if ($request->get('filterdefinition') instanceof FilterDefinition) {
  303.             $filterDefinition $request->get('filterdefinition');
  304.         }
  305.         if (empty($filterDefinition)) {
  306.             $filterDefinition Config::getWebsiteConfig()->get('fallbackFilterdefinition');
  307.         }
  308.         if (empty($filterDefinition)) {
  309.             echo 'Filter Definition fehlt';
  310.             die;
  311.         }
  312.         $filterService $ecommerceFactory->getFilterService();
  313.         Helper::setupProductList($filterDefinition$productListing$params$viewModel$filterServicetrue);
  314.         $viewModel->filterService $filterService;
  315.         $viewModel->filterDefinition $filterDefinition;
  316.         // filtered products
  317.         $filteredProducts = [];
  318.         foreach ($productListing as $product) {
  319.             $filteredProducts[$product->getTitle()] = $product->getId();
  320.         }
  321.         $session->set("filteredProducts"$filteredProducts);
  322.         // pagination
  323.         $perPage 12;
  324.         $paginator = new Paginator($productListing);
  325.         $paginator->setCurrentPageNumber($request->get('page'));
  326.         $paginator->setItemCountPerPage($perPage);
  327.         //$paginator->setPageRange(5);
  328.         $viewModel->results $paginator;
  329.         $viewModel->paginationVariables $paginator->getPages('Sliding');
  330.         // total
  331.         if ($productListing) {
  332.          $total count($productListing);
  333.         } 
  334.         $viewModel->total $total;
  335.         $viewModel->perPage $perPage;
  336.         $viewModel->isAjax $isAjax;
  337.         // clear or save country
  338.         if ($_REQUEST['country'] == 'null') {
  339.             $session->set("country"null);
  340.         } else if ($_REQUEST['country']) {
  341.             $session->set("country"$_REQUEST['country']);
  342.         }
  343.         // show or hide country popup
  344.         if ($session->get('country') !== null) {
  345.             $showCountryPopup false;
  346.         } else {
  347.             $showCountryPopup true;
  348.         }
  349.         $viewModel->showCountryPopup $showCountryPopup;
  350.         $countryNames = \Pimcore::getContainer()->get('pimcore.locale')->getDisplayRegions();
  351.         $arrCountries = [];
  352.         if ($countryNames) {
  353.             $i=0;
  354.             foreach ($countryNames as $key => $value) {
  355.                 $i++;
  356.                 $arrCountries[$i]['code'] = $key;
  357.                 $arrCountries[$i]['name'] = $value;
  358.             }
  359.         }
  360.         
  361.         $viewModel->arrCountries $arrCountries;
  362.         // show price
  363.         $countryListing = new DataObject\ShopKonfiguration\Listing();
  364.         $showPrice false;
  365.         foreach ($countryListing as $country) {
  366.             if (strtolower($country->getShortname()) == $session->get('country') || strtolower($country->getShortname()) == $request->get('country')) {
  367.                 $showPrice true;
  368.             }
  369.         }
  370.         $this->view->showPrice $showPrice;
  371.     
  372.         // store current page for add-to-cart redirect
  373.         $currentUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' "https" "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
  374.         //$session->set("add-to-cart-return", $currentUrl);
  375.         //$viewModel->returnUrl = $currentUrl;
  376.         if ($request->attributes->get('noLayout')) {
  377.             return $this->render('EcommerceShopBundle:product:listing_content.html.twig'array_merge($this->view->getAllParameters(), $viewModel->getAllParameters()));
  378.         }
  379.         return $viewModel->getAllParameters();
  380.     }
  381.     /**
  382.      * @param Request $request
  383.      * @param Factory $ecommerceFactory
  384.      *
  385.      * @return \Symfony\Component\HttpFoundation\Response
  386.      */
  387.     public function productTeaserAction(
  388.         Request $request
  389.         Factory $ecommerceFactory
  390.     ) {
  391.         $paramsBag = [];
  392.         if ($request->get('type') == 'object') {
  393.             AbstractObject::setGetInheritedValues(true);
  394.             $product AbstractProduct::getById($request->get('id'));
  395.             $paramsBag['product'] = $product;
  396.             // track product impression
  397.             $trackingManager $ecommerceFactory->getTrackingManager();
  398.             $trackingManager->trackProductImpression($product'teaser');
  399.             return $this->render('EcommerceShopBundle:product:product_teaser.html.twig'$paramsBag);
  400.         }
  401.         throw new NotFoundHttpException('Product not found.');
  402.     }
  403.     /**
  404.      * @Route("/search", name="search")
  405.      *
  406.      * @param Request                 $request
  407.      * @param Factory                 $ecommerceFactory
  408.      * @param ProductLinkGenerator    $productLinkGenerator
  409.      * @param Translator              $translator
  410.      * @param BreadcrumbHelperService $breadcrumbHelperService
  411.      * @param HeadTitle               $headTitleHelper
  412.      *
  413.      * @return array|\Symfony\Component\HttpFoundation\JsonResponse
  414.      */
  415.     public function searchAction(
  416.         Request $request
  417.         Factory $ecommerceFactory
  418.         ProductLinkGenerator $productLinkGenerator
  419.         Translator $translator
  420.         BreadcrumbHelperService $breadcrumbHelperService
  421.         HeadTitle $headTitleHelper
  422.     ) {
  423.         $params $request->query->all();
  424.         $viewModel = new ViewModel();
  425.         $this->view->isShop true;
  426.         $viewModel->category ShopCategory::getById($params['category'] ?? null);
  427.         $indexService $ecommerceFactory->getIndexService();
  428.         $productListing $indexService->getProductListForCurrentTenant();
  429.         $productListing->setVariantMode(ProductListInterface::VARIANT_MODE_VARIANTS_ONLY);
  430.         $term strip_tags($request->get('term'));
  431.         if ($productListing instanceof AbstractElasticSearch) {
  432.             // simple elastic search query - uses multi-match query on all defined search_attributes
  433.             // $productListing->addQueryCondition($term);
  434.             // sample for a more specific elastic search query - not considers search_attributes but provides full flexibility
  435.             // this query weights cars more that accessries
  436.             $query = [
  437.                 'function_score' => [
  438.                     'query'      => [
  439.                         'multi_match' => [
  440.                             "query"    => $term,
  441.                             "type"     => "cross_fields",
  442.                             "operator" => "and",
  443.                             "fields"   => [
  444.                                 "attributes.name^4",
  445.                                 "attributes.name.analyzed",
  446.                                 "attributes.name.analyzed_ngram",
  447.                                 "attributes.manufacturer_name^3",
  448.                                 "attributes.manufacturer_name.analyzed",
  449.                                 "attributes.manufacturer_name.analyzed_ngram",
  450.                                 "attributes.color",
  451.                                 "attributes.carClass"
  452.                             ]
  453.                         ]
  454.                     ],
  455.                     'functions'  => [
  456.                         [
  457.                             'filter' => ['match' => ['system.o_classId' => 'AP']],
  458.                             'weight' => 1
  459.                         ],
  460.                         [
  461.                             'filter' => ['match' => ['system.o_classId' => 'CAR']],
  462.                             'weight' => 2
  463.                         ]
  464.                     ],
  465.                     'boost_mode' => 'multiply'
  466.                 ]
  467.             ];
  468.             $productListing->addQueryCondition($query'searchTerm');
  469.         } else {
  470.             // default mysql search query condition - would also work for elastic search in that way
  471.             $term trim(preg_replace('/\s+/'' '$term));
  472.             if (!empty($term)) {
  473.                 foreach (explode(' '$term) as $t) {
  474.                     $productListing->addQueryCondition($t);
  475.                 }
  476.             }
  477.         }
  478.         if ($params['autocomplete']) {
  479.             $resultset = [];
  480.             $productListing->setLimit(10);
  481.             foreach ($productListing as $product) {
  482.                 $result['href'] = $productLinkGenerator->generateWithMockup($product, []);
  483.                 $result['product'] = $product->getOSName();
  484.                 $resultset[] = $result;
  485.             }
  486.             return $this->json($resultset);
  487.         }
  488.         $filterDefinition $viewModel->filterDefinition Config::getWebsiteConfig()->get('fallbackFilterdefinition');
  489.         // create and init filter service
  490.         $filterService Factory::getInstance()->getFilterService();
  491.         Helper::setupProductList($filterDefinition$productListing$params$viewModel$filterServicetrue);
  492.         $viewModel->filterService $filterService;
  493.         $viewModel->products $productListing;
  494.         // init pagination
  495.         $paginator = new Paginator($productListing);
  496.         $paginator->setCurrentPageNumber($request->get('page'));
  497.         $paginator->setItemCountPerPage(18);
  498.         $paginator->setPageRange(5);
  499.         $viewModel->results $paginator;
  500.         $viewModel->paginationVariables $paginator->getPages('Sliding');
  501.         $trackingManager $ecommerceFactory->getTrackingManager();
  502.         foreach ($paginator as $product) {
  503.             $trackingManager->trackProductImpression($product'search-results');
  504.         }
  505.         // breadcrumbs
  506.         /** @var Placeholder $placeholder */
  507.         $placeholder $this->get('pimcore.templating.view_helper.placeholder');
  508.         $placeholder('addBreadcrumb')->append([
  509.             'parentId' => $this->document->getId(),
  510.             'id'       => 'search-result',
  511.             'label'    => $translator->trans('shop.search-result', [$term])
  512.         ]);
  513.         $viewModel->language $request->getLocale();
  514.         $viewModel->term $term;
  515.         $breadcrumbHelperService->enrichGenericDynamicPage($translator->trans('shop.search-result', [$term]));
  516.         $headTitleHelper($translator->trans('shop.search-result', [$term]));
  517.         return $viewModel->getAllParameters();
  518.     }
  519. }