<?php declare(strict_types=1);
namespace Nimbits\NimbitsPriceOnRequestNext\Controller;
use Nimbits\NimbitsPriceOnRequestNext\Events\MailBeforeSendEvent;
use Nimbits\NimbitsPriceOnRequestNext\Setting\Service\SettingService;
use Shopware\Core\Checkout\Cart\Price\Struct\CartPrice;
use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
use Shopware\Core\Content\Mail\Service\AbstractMailService;
use Shopware\Core\Content\Mail\Service\MailService;
use Shopware\Core\Content\MailTemplate\MailTemplateEntity;
use Shopware\Core\Framework\Adapter\Translation\Translator;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Event\BusinessEventDispatcher;
use Shopware\Core\Framework\Routing\Annotation\RouteScope;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Controller\StorefrontController;
use Shopware\Storefront\Framework\Captcha\Annotation\Captcha;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* @RouteScope(scopes={"storefront"})
*/
class PriceRequestController extends StorefrontController
{
private $recaptchaverifyurl = "https://www.google.com/recaptcha/api/siteverify";
/**
* @var SettingService
*/
private SettingService $settingService;
/**
* @var CartService
*/
private CartService $cartService;
/**
* @var MailService
*/
private $mailService;
/**
* @var \Twig\Environment $twig
*/
private $twig;
/**
* @var BusinessEventDispatcher
*/
private BusinessEventDispatcher $businesseventdispatcher;
private Translator $translation;
/**
* @var EntityRepositoryInterface
*/
private EntityRepositoryInterface $mailTemplateRepository;
public function __construct(
SettingService $settingService,
CartService $cartService,
AbstractMailService $mailService,
\Twig\Environment $twig,
BusinessEventDispatcher $businesseventdispatcher,
Translator $translation,
EntityRepositoryInterface $mailTemplateRepository
)
{
$this->settingService = $settingService;
$this->cartService = $cartService;
$this->mailService = $mailService;
$this->twig = $twig;
$this->businesseventdispatcher = $businesseventdispatcher;
$this->translation = $translation;
$this->mailTemplateRepository = $mailTemplateRepository;
}
/**
* @Route("/nimbits/pricerequest/finish", name="frontend.action.nimbits.price-request-finish", options={"seo"="false"}, methods={"GET"})
*/
public function priceRequestFinished(Request $request, SalesChannelContext $context): Response
{
return $this->renderStorefront('@NimbitsPriceOnRequestNext/storefront/page/pricerequest/finish.html.twig', []);
}
/**
* @Route("/nimbits/pricerequest/fail", name="frontend.action.nimbits.price-request-fail", options={"seo"="false"}, methods={"GET"})
*/
public function priceRequestFailed(Request $request, SalesChannelContext $context): Response
{
return $this->renderStorefront('@NimbitsPriceOnRequestNext/storefront/page/pricerequest/fail.html.twig', []);
}
private function getMailTemplate(SalesChannelContext $salesChannelContext, string $technicalName)
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('mailTemplateType.technicalName', $technicalName));
$criteria->setLimit(1);
/** @var MailTemplateEntity|null $mailTemplate */
$mailTemplate = $this->mailTemplateRepository->search($criteria, $salesChannelContext->getContext())->first();
return $mailTemplate;
}
private function getProductIdByNumber($productNumber)//return id or null
{
/** @var EntityRepositoryInterface $productRepository */
$productRepository = $this->container->get('product.repository');
$product = $productRepository->search(
(
new Criteria()
)->addFilter(new EqualsFilter('productNumber', $productNumber)),
\Shopware\Core\Framework\Context::createDefaultContext()
)->first();
if ($product == NULL)
return NULL;
return $product->getId();
}
private function insertRequest(array $requestData)
{
/** @var EntityRepositoryInterface $nimbits_pricerequest */
$nimbits_pricerequests = $this->container->get('nimbits_pricerequests.repository');
$retval = $nimbits_pricerequests->create(
[
[
'salutation' => $requestData["salutation"],
'firstname' => $requestData["firstname"],
'surname' => $requestData["surname"],
'mail' => $requestData["mail"],
'desiredprice' => $requestData["desiredprice"],
'desiredpricecurrency' => $requestData["desiredpricecurrency"],
'address' => $requestData["address"],
'company' => $requestData["company"],
'comment' => $requestData["comment"],
'phonenumber' => $requestData["phonenumber"],
'additional_info' => Null,
],
],
\Shopware\Core\Framework\Context::createDefaultContext()
);
$nimbits_pricerequest_uuid = $retval->getEvents()->getElements()[0]->getIds()[0];
foreach ($requestData["lineItems"] as $item) {
$nimbits_pricerequests_baskets = $this->container->get('nimbits_pricerequests_baskets.repository');
$name = $item->name;
if (!empty($item->variant)) {
$name = $name . " (" . $item->variant . ")";
}
$retval_basket = $nimbits_pricerequests_baskets->create(
[
[
'pricerequest_id' => $nimbits_pricerequest_uuid,
'article_name' => $name,
'article_amount' => "" . $item->quantity,
'article_ordernumber' => $item->number,
'article_id' => $this->getProductIdByNumber($item->number),
'additional_info' => NULL,
],
],
\Shopware\Core\Framework\Context::createDefaultContext()
);
if (count($retval_basket->getEvents()->getElements()) > 0 && count($retval_basket->getEvents()->getElements()[0]->getPayloads()) > 0) {
$insertData = [];
$parentId = $retval_basket->getEvents()->getElements()[0]->getPayloads()[0]['id'];
if (isset($item->children)) {
foreach ($item->children as $child) {
$name = $child->name;
if (!empty($child->variant)) {
$name = $name . " (" . $child->variant . ")";
}
$insertData[] = [
'pricerequest_id' => $nimbits_pricerequest_uuid,
'parentId' => $parentId,
'article_name' => $name,
'article_amount' => "" . $child->quantity,
'article_ordernumber' => $child->number,
'article_id' => $this->getProductIdByNumber($child->number),
'additional_info' => NULL,
];
}
$nimbits_pricerequests_baskets->create(
$insertData,
\Shopware\Core\Framework\Context::createDefaultContext()
);
}
}
}
return $nimbits_pricerequest_uuid;
}
private function sendCustomerMail(SalesChannelContext $salesChannelContext, Context $context, array $settings, array $requestData)
{
if (!$settings["nbporsendmailtocustomer"]) {
return;
}
//mail validation
if (!isset($requestData["mail"]) || !filter_var($requestData["mail"], FILTER_VALIDATE_EMAIL)) {
return;
}
$receiver = "";
if (!empty($requestData["firstname"])) {
$receiver = $requestData["firstname"];
}
if (!empty($requestData["surname"])) {
$receiver = $receiver . " " . $requestData["surname"];
}
if (empty($receiver)) {
$receiver = "Anonym";
}
$mailsendbeforeevent = new MailBeforeSendEvent($salesChannelContext, $requestData);
$this->businesseventdispatcher->dispatch($mailsendbeforeevent);
$requestData = $mailsendbeforeevent->getMailvars();
$data = [];
$data['recipients'] = [$requestData["mail"] => $receiver];
$mailtemplate = $this->getMailTemplate($salesChannelContext, "nimbits_por_emailcustomer");
$data['contentHtml'] = $mailtemplate->getContentHtml() ?? $mailtemplate->getTranslated()['contentHtml'];
$data['contentPlain'] = $mailtemplate->getContentPlain() ?? $mailtemplate->getTranslated()['contentPlain'];
$data['subject'] = $mailtemplate->getSubject() ?? $mailtemplate->getTranslated()['subject'];
$data['salesChannelId'] = $salesChannelContext->getSalesChannel()->getId();
//sender name
$data['senderName'] = $this->translation->trans("nimbits-pricerequest.mail.customersendername");
if ($this->getMailTemplate($salesChannelContext, "nimbits_por_emailcustomer")->getSenderName() !== null) {
$data['senderName'] = $this->getMailTemplate($salesChannelContext, "nimbits_por_emailcustomer")->getSenderName();
}
$this->mailService->send(
$data,
$context,
[
'salesChannelId' => $salesChannelContext->getSalesChannel()->getId(),
'requestData' => $requestData
]
);
}
private function sendRequestMail(SalesChannelContext $salesChannelContext, Context $context, array $settings, array $requestData)
{
//mail validation
if (!isset($settings['requestmail']) || !filter_var($settings['requestmail'], FILTER_VALIDATE_EMAIL)) {
return;
}
$mailsendbeforeevent = new MailBeforeSendEvent($salesChannelContext, $requestData);
$this->businesseventdispatcher->dispatch($mailsendbeforeevent);
$requestData = $mailsendbeforeevent->getMailvars();
$data = [];
$data['recipients'] = [];
$data['recipients'][$settings['requestmail']] = $this->translation->trans("nimbits-pricerequests.mail.shopownersendername");
if (isset($settings['requestmail2']) && filter_var($settings['requestmail2'], FILTER_VALIDATE_EMAIL)) {
$data['recipients'][$settings['requestmail2']] = $this->translation->trans("nimbits-pricerequests.mail.shopownersendername");
}
if (isset($settings['requestmail3']) && filter_var($settings['requestmail3'], FILTER_VALIDATE_EMAIL)) {
$data['recipients'][$settings['requestmail3']] = $this->translation->trans("nimbits-pricerequests.mail.shopownersendername");
}
$mailtemplate = $this->getMailTemplate($salesChannelContext, "nimbits_por_emailshopowner");
$data['contentHtml'] = $mailtemplate->getContentHtml() ?? $mailtemplate->getTranslated()['contentHtml'];
$data['contentPlain'] = $mailtemplate->getContentPlain() ?? $mailtemplate->getTranslated()['contentPlain'];
$data['subject'] = $mailtemplate->getSubject() ?? $mailtemplate->getTranslated()['subject'];
$data['salesChannelId'] = $salesChannelContext->getSalesChannel()->getId();
//sender name
$data['senderName'] = $this->translation->trans("nimbits-pricerequests.mail.shopownersendername");
if ($this->getMailTemplate($salesChannelContext, "nimbits_por_emailshopowner")->getSenderName() !== null) {
$data['senderName'] = $this->getMailTemplate($salesChannelContext, "nimbits_por_emailcustomer")->getSenderName();
}
$this->mailService->send(
$data,
$context,
[
'salesChannelId' => $salesChannelContext->getSalesChannel()->getId(),
'requestData' => $requestData
]
);
}
private function getAttributesByNumber($number)
{
/** @var EntityRepositoryInterface $productRepository */
$productRepository = $this->container->get('product.repository');
/** @var EntityCollection $entities */
$products = $productRepository->search(
(
new Criteria()
)->addFilter(new EqualsFilter('productNumber', $number)),
\Shopware\Core\Framework\Context::createDefaultContext()
);
$product = $products->getEntities()->getElements();
return $product;
}
private function doPricingForItem($salesChannelContext, $context, $item)
{
$productID = array_key_first($item->attributes);
//no valid product ID => virtual product
if (empty($productID)) {
$item->netprice = 0;
$item->grossprice = 0;
$currency = $salesChannelContext->getCurrency();
$item->currencysymbol = $currency->getSymbol();
return $item;
}
//CartPrice::TAX_STATE_GROSS, CartPrice::TAX_STATE_NET, CartPrice::TAX_STATE_FREE
$taxState = $context->getTaxState();
if ($taxState == CartPrice::TAX_STATE_NET && property_exists($item, "netprice")) {
$item->grossprice = $item->netprice;
}
$currency = $salesChannelContext->getCurrency();
$price = $item->attributes[$productID]->getPrice();
if (!empty($price)) {
foreach ($price as $p) {
if ($p->getCurrencyId() == $currency->getId()) {
$item->netprice = round($p->getNet(), 2);
$item->grossprice = round($p->getGross(), 2);
}
}
}
$item->currencysymbol = $currency->getSymbol();
return $item;
}
/**
* @Route("/nimbits/pricerequest/request", name="frontend.action.nimbits.price-request-request", options={"seo"="false"}, methods={"POST"}, defaults={"_captcha"=true})
*/
public function priceRequest(Request $request, SalesChannelContext $salesChannelContext, Context $context): Response
{
$finishUrl = $request->get('nbpr_form_sourceurl');
$settings = $this->settingService->getSettingsAsArray($salesChannelContext->getSalesChannel()->getId());
$lineitems = json_decode($request->get('nb_pricerequest_form_lineitems'));
foreach ($lineitems as &$item) {
if (isset($item->children)) {
foreach ($item->children as &$child) {
$child->attributes = $this->getAttributesByNumber($child->number);
$child = $this->doPricingForItem($salesChannelContext, $context, $child);
}
}
$item->attributes = $this->getAttributesByNumber($item->number);
$item = $this->doPricingForItem($salesChannelContext, $context, $item);
}
$isCartRequest = true;
$productID = null;
$cartItems = $this->cartService->getCart($salesChannelContext->getToken(), $salesChannelContext)->getLineItems()->getElements();
if (count($lineitems) == 1) {
$isCartRequest = false;
foreach ($lineitems as &$item) {
$productID = array_key_first($item->attributes);
}
}
$address = json_encode([
"street" => $request->get('nbpr_street'),
"housenumber" => $request->get('nbpr_housenumber'),
"zipcode" => $request->get('nbpr_zipcode'),
"city" => $request->get('nbpr_city'),
"country" => $request->get('nbpr_country')
]);
$requestData = [
'lineItems' => $lineitems,
'isCartRequest' => $isCartRequest,
'salutation' => $request->get('nbpr_salutation'),
'company' => $request->get('nbpr_company'),
'firstname' => $request->get('nbpr_firstname'),
'surname' => $request->get('nbpr_surname'),
'mail' => $request->get('nbpr_mail'),
'desiredprice' => $request->get('nbpr_desiredprice'),
'desiredpricecurrency' => $request->get('nbpr_desiredpricecurrency'),
'address' => $address,
'comment' => $request->get('nbpr_comment'),
'phonenumber' => $request->get('nbpr_phonenumber'),
'vars' => $request->request->all()
];
//try inserting request but fail if it doesnt work
try{
$poruuid = $this->insertRequest($requestData);
}
catch (\Exception $e){
return new RedirectResponse($finishUrl."?nb_por_success=0");
}
$requestData["uuid"] = $poruuid;
$requestData["date"] = date('d.m.Y H:i:s');
$addressdata = json_decode($requestData["address"], true);
$addresscleaned = $addressdata["street"] . " " . $addressdata["housenumber"] . ", " . $addressdata["zipcode"] . " " . $addressdata["city"] . ", " . $addressdata["country"];
$tmpaddress = preg_replace('/\s+/', '', $addresscleaned);
if (strlen(str_replace(',', '', $tmpaddress)) > 0) {
$requestData["address"] = $addresscleaned;
} else {
$requestData["address"] = "";
}
try{
$this->sendRequestMail($salesChannelContext, $context, $settings, $requestData);
}
catch (\Exception $e){
}
try{
$this->sendCustomerMail($salesChannelContext, $context, $settings, $requestData);
}
catch (\Exception $e){
}
if ($request->get('nbpr_deletecart') == "1") {
$this->cartService->deleteCart($salesChannelContext);
}
if (isset($settings["nbproredirecturlcartsuccess"])) {
if (filter_var($settings["nbproredirecturlcartsuccess"], FILTER_VALIDATE_URL) !== FALSE) {
$finishUrl = $settings["nbproredirecturlcartsuccess"];
}
}
if (!$isCartRequest && !empty($productID)) {
$finishUrl = $this->getRedirectForArticle($item->attributes[array_key_first($item->attributes)], $productID);
}
if ($finishUrl == "") {
$finishUrl = $this->generateUrl('frontend.action.nimbits.price-request-finish');
}
return new RedirectResponse($finishUrl."?nb_por_success=1");
}
public function getRedirectForArticle($attributes, $productID)
{
$finishUrl = $this->generateUrl('frontend.detail.page', ['productId' => $productID]);
//check if individual redirect is set for category
try {
$categoryTree = $attributes->getCategoryTree();
foreach ($categoryTree as $categoryid) {
//the lower we find a redirect the more imporant it is
$tmpfinish = $this->checkCategoryForRedirectURL($categoryid);
if ($tmpfinish != false) {
$finishUrl = $this->generateUrl($tmpfinish);
}
}
} catch (\Exception $e) {
}
//check if individual redirect is set for article
try {
$finishUrlArticle = $attributes->getCustomFields()["custom_nimbits_priceonrequest_redirectarticle"];
if (filter_var($finishUrlArticle, FILTER_VALIDATE_URL)) {
$finishUrl = $this->generateUrl($finishUrlArticle);
}
} catch (\Exception $e) {
}
return $finishUrl;
}
public function checkCategoryForRedirectURL($categoryid)
{
/** @var EntityRepositoryInterface $categoryRepository */
$categoryRepository = $this->container->get('category.repository');
/** @var EntityCollection $entities */
$category = $categoryRepository->search(
(
new Criteria()
)->addFilter(new EqualsFilter('id', $categoryid)),
\Shopware\Core\Framework\Context::createDefaultContext()
);
$category = $category->getEntities()->getElements();
$finishUrlCategory = $category[array_key_first($category)]->getCustomFields()["custom_nimbits_priceonrequest_customredirectarticle"];
if (filter_var($finishUrlCategory, FILTER_VALIDATE_URL)) {
return $finishUrlCategory;
}
return false;
}
}