custom/plugins/NimbitsPriceOnRequestNext/src/Controller/PriceRequestController.php line 88

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Nimbits\NimbitsPriceOnRequestNext\Controller;
  3. use Nimbits\NimbitsPriceOnRequestNext\Events\MailBeforeSendEvent;
  4. use Nimbits\NimbitsPriceOnRequestNext\Setting\Service\SettingService;
  5. use Shopware\Core\Checkout\Cart\Price\Struct\CartPrice;
  6. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  7. use Shopware\Core\Content\Mail\Service\AbstractMailService;
  8. use Shopware\Core\Content\Mail\Service\MailService;
  9. use Shopware\Core\Content\MailTemplate\MailTemplateEntity;
  10. use Shopware\Core\Framework\Adapter\Translation\Translator;
  11. use Shopware\Core\Framework\Context;
  12. use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
  13. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  16. use Shopware\Core\Framework\Event\BusinessEventDispatcher;
  17. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  18. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  19. use Shopware\Storefront\Controller\StorefrontController;
  20. use Shopware\Storefront\Framework\Captcha\Annotation\Captcha;
  21. use Symfony\Component\HttpFoundation\RedirectResponse;
  22. use Symfony\Component\HttpFoundation\Request;
  23. use Symfony\Component\HttpFoundation\Response;
  24. use Symfony\Component\Routing\Annotation\Route;
  25. /**
  26.  * @RouteScope(scopes={"storefront"})
  27.  */
  28. class PriceRequestController extends StorefrontController
  29. {
  30.     private $recaptchaverifyurl "https://www.google.com/recaptcha/api/siteverify";
  31.     /**
  32.      * @var SettingService
  33.      */
  34.     private SettingService $settingService;
  35.     /**
  36.      * @var CartService
  37.      */
  38.     private CartService $cartService;
  39.     /**
  40.      * @var MailService
  41.      */
  42.     private $mailService;
  43.     /**
  44.      * @var \Twig\Environment $twig
  45.      */
  46.     private $twig;
  47.     /**
  48.      * @var BusinessEventDispatcher
  49.      */
  50.     private BusinessEventDispatcher $businesseventdispatcher;
  51.     private Translator $translation;
  52.     /**
  53.      * @var EntityRepositoryInterface
  54.      */
  55.     private EntityRepositoryInterface $mailTemplateRepository;
  56.     public function __construct(
  57.         SettingService            $settingService,
  58.         CartService               $cartService,
  59.         AbstractMailService       $mailService,
  60.         \Twig\Environment         $twig,
  61.         BusinessEventDispatcher   $businesseventdispatcher,
  62.         Translator                $translation,
  63.         EntityRepositoryInterface $mailTemplateRepository
  64.     )
  65.     {
  66.         $this->settingService $settingService;
  67.         $this->cartService $cartService;
  68.         $this->mailService $mailService;
  69.         $this->twig $twig;
  70.         $this->businesseventdispatcher $businesseventdispatcher;
  71.         $this->translation $translation;
  72.         $this->mailTemplateRepository $mailTemplateRepository;
  73.     }
  74.     /**
  75.      * @Route("/nimbits/pricerequest/finish", name="frontend.action.nimbits.price-request-finish", options={"seo"="false"}, methods={"GET"})
  76.      */
  77.     public function priceRequestFinished(Request $requestSalesChannelContext $context): Response
  78.     {
  79.         return $this->renderStorefront('@NimbitsPriceOnRequestNext/storefront/page/pricerequest/finish.html.twig', []);
  80.     }
  81.     /**
  82.      * @Route("/nimbits/pricerequest/fail", name="frontend.action.nimbits.price-request-fail", options={"seo"="false"}, methods={"GET"})
  83.      */
  84.     public function priceRequestFailed(Request $requestSalesChannelContext $context): Response
  85.     {
  86.         return $this->renderStorefront('@NimbitsPriceOnRequestNext/storefront/page/pricerequest/fail.html.twig', []);
  87.     }
  88.     private function getMailTemplate(SalesChannelContext $salesChannelContextstring $technicalName)
  89.     {
  90.         $criteria = new Criteria();
  91.         $criteria->addFilter(new EqualsFilter('mailTemplateType.technicalName'$technicalName));
  92.         $criteria->setLimit(1);
  93.         /** @var MailTemplateEntity|null $mailTemplate */
  94.         $mailTemplate $this->mailTemplateRepository->search($criteria$salesChannelContext->getContext())->first();
  95.         return $mailTemplate;
  96.     }
  97.     private function getProductIdByNumber($productNumber)//return id or null
  98.     {
  99.         /** @var EntityRepositoryInterface $productRepository */
  100.         $productRepository $this->container->get('product.repository');
  101.         $product $productRepository->search(
  102.             (
  103.             new Criteria()
  104.             )->addFilter(new EqualsFilter('productNumber'$productNumber)),
  105.             \Shopware\Core\Framework\Context::createDefaultContext()
  106.         )->first();
  107.         if ($product == NULL)
  108.             return NULL;
  109.         return $product->getId();
  110.     }
  111.     private function insertRequest(array $requestData)
  112.     {
  113.         /** @var EntityRepositoryInterface $nimbits_pricerequest */
  114.         $nimbits_pricerequests $this->container->get('nimbits_pricerequests.repository');
  115.         $retval $nimbits_pricerequests->create(
  116.             [
  117.                 [
  118.                     'salutation' => $requestData["salutation"],
  119.                     'firstname' => $requestData["firstname"],
  120.                     'surname' => $requestData["surname"],
  121.                     'mail' => $requestData["mail"],
  122.                     'desiredprice' => $requestData["desiredprice"],
  123.                     'desiredpricecurrency' => $requestData["desiredpricecurrency"],
  124.                     'address' => $requestData["address"],
  125.                     'company' => $requestData["company"],
  126.                     'comment' => $requestData["comment"],
  127.                     'phonenumber' => $requestData["phonenumber"],
  128.                     'additional_info' => Null,
  129.                 ],
  130.             ],
  131.             \Shopware\Core\Framework\Context::createDefaultContext()
  132.         );
  133.         $nimbits_pricerequest_uuid $retval->getEvents()->getElements()[0]->getIds()[0];
  134.         foreach ($requestData["lineItems"] as $item) {
  135.             $nimbits_pricerequests_baskets $this->container->get('nimbits_pricerequests_baskets.repository');
  136.             $name $item->name;
  137.             if (!empty($item->variant)) {
  138.                 $name $name " (" $item->variant ")";
  139.             }
  140.             $retval_basket $nimbits_pricerequests_baskets->create(
  141.                 [
  142.                     [
  143.                         'pricerequest_id' => $nimbits_pricerequest_uuid,
  144.                         'article_name' => $name,
  145.                         'article_amount' => "" $item->quantity,
  146.                         'article_ordernumber' => $item->number,
  147.                         'article_id' => $this->getProductIdByNumber($item->number),
  148.                         'additional_info' => NULL,
  149.                     ],
  150.                 ],
  151.                 \Shopware\Core\Framework\Context::createDefaultContext()
  152.             );
  153.             if (count($retval_basket->getEvents()->getElements()) > && count($retval_basket->getEvents()->getElements()[0]->getPayloads()) > 0) {
  154.                 $insertData = [];
  155.                 $parentId $retval_basket->getEvents()->getElements()[0]->getPayloads()[0]['id'];
  156.                 if (isset($item->children)) {
  157.                     foreach ($item->children as $child) {
  158.                         $name $child->name;
  159.                         if (!empty($child->variant)) {
  160.                             $name $name " (" $child->variant ")";
  161.                         }
  162.                         $insertData[] = [
  163.                             'pricerequest_id' => $nimbits_pricerequest_uuid,
  164.                             'parentId' => $parentId,
  165.                             'article_name' => $name,
  166.                             'article_amount' => "" $child->quantity,
  167.                             'article_ordernumber' => $child->number,
  168.                             'article_id' => $this->getProductIdByNumber($child->number),
  169.                             'additional_info' => NULL,
  170.                         ];
  171.                     }
  172.                     $nimbits_pricerequests_baskets->create(
  173.                         $insertData,
  174.                         \Shopware\Core\Framework\Context::createDefaultContext()
  175.                     );
  176.                 }
  177.             }
  178.         }
  179.         return $nimbits_pricerequest_uuid;
  180.     }
  181.     private function sendCustomerMail(SalesChannelContext $salesChannelContextContext $context, array $settings, array $requestData)
  182.     {
  183.         if (!$settings["nbporsendmailtocustomer"]) {
  184.             return;
  185.         }
  186.         //mail validation
  187.         if (!isset($requestData["mail"]) || !filter_var($requestData["mail"], FILTER_VALIDATE_EMAIL)) {
  188.             return;
  189.         }
  190.         $receiver "";
  191.         if (!empty($requestData["firstname"])) {
  192.             $receiver $requestData["firstname"];
  193.         }
  194.         if (!empty($requestData["surname"])) {
  195.             $receiver $receiver " " $requestData["surname"];
  196.         }
  197.         if (empty($receiver)) {
  198.             $receiver "Anonym";
  199.         }
  200.         $mailsendbeforeevent = new MailBeforeSendEvent($salesChannelContext$requestData);
  201.         $this->businesseventdispatcher->dispatch($mailsendbeforeevent);
  202.         $requestData $mailsendbeforeevent->getMailvars();
  203.         $data = [];
  204.         $data['recipients'] = [$requestData["mail"] => $receiver];
  205.         $mailtemplate $this->getMailTemplate($salesChannelContext"nimbits_por_emailcustomer");
  206.         $data['contentHtml'] = $mailtemplate->getContentHtml() ?? $mailtemplate->getTranslated()['contentHtml'];
  207.         $data['contentPlain'] = $mailtemplate->getContentPlain() ?? $mailtemplate->getTranslated()['contentPlain'];
  208.         $data['subject'] = $mailtemplate->getSubject() ?? $mailtemplate->getTranslated()['subject'];
  209.         $data['salesChannelId'] = $salesChannelContext->getSalesChannel()->getId();
  210.         //sender name
  211.         $data['senderName'] = $this->translation->trans("nimbits-pricerequest.mail.customersendername");
  212.         if ($this->getMailTemplate($salesChannelContext"nimbits_por_emailcustomer")->getSenderName() !== null) {
  213.             $data['senderName'] = $this->getMailTemplate($salesChannelContext"nimbits_por_emailcustomer")->getSenderName();
  214.         }
  215.         $this->mailService->send(
  216.             $data,
  217.             $context,
  218.             [
  219.                 'salesChannelId' => $salesChannelContext->getSalesChannel()->getId(),
  220.                 'requestData' => $requestData
  221.             ]
  222.         );
  223.     }
  224.     private function sendRequestMail(SalesChannelContext $salesChannelContextContext $context, array $settings, array $requestData)
  225.     {
  226.         //mail validation
  227.         if (!isset($settings['requestmail']) || !filter_var($settings['requestmail'], FILTER_VALIDATE_EMAIL)) {
  228.             return;
  229.         }
  230.         $mailsendbeforeevent = new MailBeforeSendEvent($salesChannelContext$requestData);
  231.         $this->businesseventdispatcher->dispatch($mailsendbeforeevent);
  232.         $requestData $mailsendbeforeevent->getMailvars();
  233.         $data = [];
  234.         $data['recipients'] = [];
  235.         $data['recipients'][$settings['requestmail']] = $this->translation->trans("nimbits-pricerequests.mail.shopownersendername");
  236.         if (isset($settings['requestmail2']) && filter_var($settings['requestmail2'], FILTER_VALIDATE_EMAIL)) {
  237.             $data['recipients'][$settings['requestmail2']] = $this->translation->trans("nimbits-pricerequests.mail.shopownersendername");
  238.         }
  239.         if (isset($settings['requestmail3']) && filter_var($settings['requestmail3'], FILTER_VALIDATE_EMAIL)) {
  240.             $data['recipients'][$settings['requestmail3']] = $this->translation->trans("nimbits-pricerequests.mail.shopownersendername");
  241.         }
  242.         $mailtemplate $this->getMailTemplate($salesChannelContext"nimbits_por_emailshopowner");
  243.         $data['contentHtml'] = $mailtemplate->getContentHtml() ?? $mailtemplate->getTranslated()['contentHtml'];
  244.         $data['contentPlain'] = $mailtemplate->getContentPlain() ?? $mailtemplate->getTranslated()['contentPlain'];
  245.         $data['subject'] = $mailtemplate->getSubject() ?? $mailtemplate->getTranslated()['subject'];
  246.         $data['salesChannelId'] = $salesChannelContext->getSalesChannel()->getId();
  247.         //sender name
  248.         $data['senderName'] = $this->translation->trans("nimbits-pricerequests.mail.shopownersendername");
  249.         if ($this->getMailTemplate($salesChannelContext"nimbits_por_emailshopowner")->getSenderName() !== null) {
  250.             $data['senderName'] = $this->getMailTemplate($salesChannelContext"nimbits_por_emailcustomer")->getSenderName();
  251.         }
  252.         $this->mailService->send(
  253.             $data,
  254.             $context,
  255.             [
  256.                 'salesChannelId' => $salesChannelContext->getSalesChannel()->getId(),
  257.                 'requestData' => $requestData
  258.             ]
  259.         );
  260.     }
  261.     private function getAttributesByNumber($number)
  262.     {
  263.         /** @var EntityRepositoryInterface $productRepository */
  264.         $productRepository $this->container->get('product.repository');
  265.         /** @var EntityCollection $entities */
  266.         $products $productRepository->search(
  267.             (
  268.             new Criteria()
  269.             )->addFilter(new EqualsFilter('productNumber'$number)),
  270.             \Shopware\Core\Framework\Context::createDefaultContext()
  271.         );
  272.         $product $products->getEntities()->getElements();
  273.         return $product;
  274.     }
  275.     private function doPricingForItem($salesChannelContext$context$item)
  276.     {
  277.         $productID array_key_first($item->attributes);
  278.         //no valid product ID => virtual product
  279.         if (empty($productID)) {
  280.             $item->netprice 0;
  281.             $item->grossprice 0;
  282.             $currency $salesChannelContext->getCurrency();
  283.             $item->currencysymbol $currency->getSymbol();
  284.             return $item;
  285.         }
  286.         //CartPrice::TAX_STATE_GROSS, CartPrice::TAX_STATE_NET, CartPrice::TAX_STATE_FREE
  287.         $taxState $context->getTaxState();
  288.         if ($taxState == CartPrice::TAX_STATE_NET && property_exists($item"netprice")) {
  289.             $item->grossprice $item->netprice;
  290.         }
  291.         $currency $salesChannelContext->getCurrency();
  292.         $price $item->attributes[$productID]->getPrice();
  293.         if (!empty($price)) {
  294.             foreach ($price as $p) {
  295.                 if ($p->getCurrencyId() == $currency->getId()) {
  296.                     $item->netprice round($p->getNet(), 2);
  297.                     $item->grossprice round($p->getGross(), 2);
  298.                 }
  299.             }
  300.         }
  301.         $item->currencysymbol $currency->getSymbol();
  302.         return $item;
  303.     }
  304.     /**
  305.      * @Route("/nimbits/pricerequest/request", name="frontend.action.nimbits.price-request-request", options={"seo"="false"}, methods={"POST"}, defaults={"_captcha"=true})
  306.      */
  307.     public function priceRequest(Request $requestSalesChannelContext $salesChannelContextContext $context): Response
  308.     {
  309.         $finishUrl $request->get('nbpr_form_sourceurl');
  310.         $settings $this->settingService->getSettingsAsArray($salesChannelContext->getSalesChannel()->getId());
  311.         $lineitems json_decode($request->get('nb_pricerequest_form_lineitems'));
  312.         foreach ($lineitems as &$item) {
  313.             if (isset($item->children)) {
  314.                 foreach ($item->children as &$child) {
  315.                     $child->attributes $this->getAttributesByNumber($child->number);
  316.                     $child $this->doPricingForItem($salesChannelContext$context$child);
  317.                 }
  318.             }
  319.             $item->attributes $this->getAttributesByNumber($item->number);
  320.             $item $this->doPricingForItem($salesChannelContext$context$item);
  321.         }
  322.         $isCartRequest true;
  323.         $productID null;
  324.         $cartItems $this->cartService->getCart($salesChannelContext->getToken(), $salesChannelContext)->getLineItems()->getElements();
  325.         if (count($lineitems) == 1) {
  326.             $isCartRequest false;
  327.             foreach ($lineitems as &$item) {
  328.                 $productID array_key_first($item->attributes);
  329.             }
  330.         }
  331.         $address json_encode([
  332.             "street" => $request->get('nbpr_street'),
  333.             "housenumber" => $request->get('nbpr_housenumber'),
  334.             "zipcode" => $request->get('nbpr_zipcode'),
  335.             "city" => $request->get('nbpr_city'),
  336.             "country" => $request->get('nbpr_country')
  337.         ]);
  338.         $requestData = [
  339.             'lineItems' => $lineitems,
  340.             'isCartRequest' => $isCartRequest,
  341.             'salutation' => $request->get('nbpr_salutation'),
  342.             'company' => $request->get('nbpr_company'),
  343.             'firstname' => $request->get('nbpr_firstname'),
  344.             'surname' => $request->get('nbpr_surname'),
  345.             'mail' => $request->get('nbpr_mail'),
  346.             'desiredprice' => $request->get('nbpr_desiredprice'),
  347.             'desiredpricecurrency' => $request->get('nbpr_desiredpricecurrency'),
  348.             'address' => $address,
  349.             'comment' => $request->get('nbpr_comment'),
  350.             'phonenumber' => $request->get('nbpr_phonenumber'),
  351.             'vars' => $request->request->all()
  352.         ];
  353.         //try inserting request but fail if it doesnt work
  354.         try{
  355.             $poruuid $this->insertRequest($requestData);
  356.         }
  357.         catch (\Exception $e){
  358.             return new RedirectResponse($finishUrl."?nb_por_success=0");
  359.         }
  360.         $requestData["uuid"] = $poruuid;
  361.         $requestData["date"] = date('d.m.Y H:i:s');
  362.         $addressdata json_decode($requestData["address"], true);
  363.         $addresscleaned $addressdata["street"] . " " $addressdata["housenumber"] . ", " $addressdata["zipcode"] . " " $addressdata["city"] . ", " $addressdata["country"];
  364.         $tmpaddress preg_replace('/\s+/'''$addresscleaned);
  365.         if (strlen(str_replace(','''$tmpaddress)) > 0) {
  366.             $requestData["address"] = $addresscleaned;
  367.         } else {
  368.             $requestData["address"] = "";
  369.         }
  370.         try{
  371.             $this->sendRequestMail($salesChannelContext$context$settings$requestData);
  372.         }
  373.         catch (\Exception $e){
  374.         }
  375.         try{
  376.             $this->sendCustomerMail($salesChannelContext$context$settings$requestData);
  377.         }
  378.         catch (\Exception $e){
  379.         }
  380.         if ($request->get('nbpr_deletecart') == "1") {
  381.             $this->cartService->deleteCart($salesChannelContext);
  382.         }
  383.         if (isset($settings["nbproredirecturlcartsuccess"])) {
  384.             if (filter_var($settings["nbproredirecturlcartsuccess"], FILTER_VALIDATE_URL) !== FALSE) {
  385.                 $finishUrl $settings["nbproredirecturlcartsuccess"];
  386.             }
  387.         }
  388.         if (!$isCartRequest && !empty($productID)) {
  389.             $finishUrl $this->getRedirectForArticle($item->attributes[array_key_first($item->attributes)], $productID);
  390.         }
  391.         if ($finishUrl == "") {
  392.             $finishUrl $this->generateUrl('frontend.action.nimbits.price-request-finish');
  393.         }
  394.         return new RedirectResponse($finishUrl."?nb_por_success=1");
  395.     }
  396.     public function getRedirectForArticle($attributes$productID)
  397.     {
  398.         $finishUrl $this->generateUrl('frontend.detail.page', ['productId' => $productID]);
  399.         //check if individual redirect is set for category
  400.         try {
  401.             $categoryTree $attributes->getCategoryTree();
  402.             foreach ($categoryTree as $categoryid) {
  403.                 //the lower we find a redirect the more imporant it is
  404.                 $tmpfinish $this->checkCategoryForRedirectURL($categoryid);
  405.                 if ($tmpfinish != false) {
  406.                     $finishUrl $this->generateUrl($tmpfinish);
  407.                 }
  408.             }
  409.         } catch (\Exception $e) {
  410.         }
  411.         //check if individual redirect is set for article
  412.         try {
  413.             $finishUrlArticle $attributes->getCustomFields()["custom_nimbits_priceonrequest_redirectarticle"];
  414.             if (filter_var($finishUrlArticleFILTER_VALIDATE_URL)) {
  415.                 $finishUrl $this->generateUrl($finishUrlArticle);
  416.             }
  417.         } catch (\Exception $e) {
  418.         }
  419.         return $finishUrl;
  420.     }
  421.     public function checkCategoryForRedirectURL($categoryid)
  422.     {
  423.         /** @var EntityRepositoryInterface $categoryRepository */
  424.         $categoryRepository $this->container->get('category.repository');
  425.         /** @var EntityCollection $entities */
  426.         $category $categoryRepository->search(
  427.             (
  428.             new Criteria()
  429.             )->addFilter(new EqualsFilter('id'$categoryid)),
  430.             \Shopware\Core\Framework\Context::createDefaultContext()
  431.         );
  432.         $category $category->getEntities()->getElements();
  433.         $finishUrlCategory $category[array_key_first($category)]->getCustomFields()["custom_nimbits_priceonrequest_customredirectarticle"];
  434.         if (filter_var($finishUrlCategoryFILTER_VALIDATE_URL)) {
  435.             return $finishUrlCategory;
  436.         }
  437.         return false;
  438.     }
  439. }