<?php
declare(strict_types=1);
namespace EconsorCrowdfunding\Subscriber;
use EconsorCrowdfunding\Services\CrowdfundingMailService;
use Shopware\Core\Framework\Context;
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\Uuid\Uuid;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\RouterInterface;
/**
* Class CheckoutSubscriber
* @package EconsorCrowdfunding\Subscriber
*/
class CheckoutSubscriber implements EventSubscriberInterface
{
/**
* @var Session
*/
private $session;
/**
* @var EntityRepositoryInterface
*/
private $campaignRepo;
/**
* @var EntityRepositoryInterface
*/
private $orderRepo;
/**
* @var EntityRepositoryInterface
*/
private $orderHistoryRepo;
/**
* @var RouterInterface
*/
private $router;
/**
* @var EntityRepositoryInterface
*/
private $goodieRepository;
/**
* @var EntityRepositoryInterface
*/
private $orderBundleRepo;
/**
* @var EntityRepositoryInterface
*/
private $bundleRepo;
/**
* @var CrowdfundingMailService
*/
private $mailService;
/**
* @var SystemConfigService
*/
private $configService;
/**
* @var SystemConfigService
*/
private $ownSponsorRepository;
/**
* @var EntityRepositoryInterface
*/
private $validationRepo;
/**
* @var EntityRepositoryInterface
*/
private $shirtConfigRepo;
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => 'handleRequest'
];
}
public function __construct(
Session $session,
EntityRepositoryInterface $campaignRepository,
EntityRepositoryInterface $orderRepository,
EntityRepositoryInterface $orderHistoryRepository,
EntityRepositoryInterface $goodieRepository,
RouterInterface $router,
EntityRepositoryInterface $tempBundles, // TODO !!!!!!!!!!!!!!!!!!!!!!
EntityRepositoryInterface $orderBundles,
CrowdfundingMailService $mailService,
SystemConfigService $configService,
EntityRepositoryInterface $ownSponsor,
EntityRepositoryInterface $validation,
EntityRepositoryInterface $shirtConfig
) {
$this->session = $session;
$this->campaignRepo = $campaignRepository;
$this->orderRepo = $orderRepository;
$this->orderHistoryRepo = $orderHistoryRepository;
$this->goodieRepository = $goodieRepository;
$this->router = $router;
$this->bundleRepo = $tempBundles;
$this->orderBundleRepo = $orderBundles;
$this->mailService = $mailService;
$this->configService = $configService;
$this->ownSponsorRepository = $ownSponsor;
$this->validationRepo = $validation;
$this->shirtConfigRepo = $shirtConfig;
}
/**
* @param RequestEvent $event
*/
public function handleRequest(RequestEvent $event)
{
$route = $event->getRequest()->attributes->get('_route');
$oID = $event->getRequest()->query->get('orderId');
if ('frontend.checkout.finish.page' === $route) {
if ($this->session->has('campaignID')) {
$redirect = $this->processCrowdfundingOrder($oID);
$this->saveBundleData($oID);
if($this->session->has('own-sponsor'))
{
$params = $this->session->get('params');
$c = new Criteria();
$c->setIds([$this->session->get('campaignID')]);
$campaign = $this->campaignRepo->search($c, Context::createDefaultContext())->getEntities()->first();
$this->mailService->sendSponsor(
$this->mailService->getMail($this->configService->get('EconsorCrowdfunding.config.campaignAwaitConfirmationSponsor')),
$params['ownsponsorid'],
$campaign->getSaleschannelid()
);
$this->campaignRepo->update([['id' => $campaign->getId(), 'status' => 6]], Context::createDefaultContext());
$this->session->remove('own-sponsor');
$this->session->remove('params');
}
$this->session->remove('campaignID');
$this->session->remove('slug');
$this->session->remove('sponsor');
$event->setResponse($redirect);
}
//##########################################################################################################
if ($this->session->has('cartExtensions')) {
if (null !== $this->session->get('cartExtensions')) {
$this->processOrderExtensions(
$oID,
$this->session->get('cartExtensions')
);
}
$this->session->remove('cartExtensions');
}
//##########################################################################################################
if ($this->session->has('shirtExtensions')) {
$params = $this->session->get('shirtExtensions');
if($params)
{
$params = $params[array_key_first($params)];
$id = $params['campaign'];
$campaign = $this->getCampaign($id);
if (null !== $this->session->get('shirtExtensions')) {
$this->processShirtExtensions(
$oID,
$this->session->get('shirtExtensions'),
$campaign
);
}
}
$this->session->remove('shirtExtensions');
}
//##########################################################################################################
if ($this->session->has('sponsor-validate')) {
$params = $this->session->get('sponsor-validate');
//delete validation flag
$this->ownSponsorRepository->update(
[
[
'id' => $params['sponsor'],
'hash' => null,
'confirmed' => true,
'orderid' => $oID
]
],
Context::createDefaultContext()
);
//change campaign status, substract from goal
$c = new Criteria();
$c->setIds([$params['campaign']]);
$campaign = $this->campaignRepo->search($c, Context::createDefaultContext())->getEntities()->first();
$c = new Criteria();
$c->setIds([$params['sponsor']]);
$sponsor = $this->ownSponsorRepository->search($c, Context::createDefaultContext())->getEntities(
)->first();
$this->campaignRepo->update(
[
[
'id' => $params['campaign'],
'fundinggoal' => ($campaign->getFundingGoal()) - (float)$params['amount'],
'status' => 5
]
],
Context::createDefaultContext()
);
//send mail to sponsor that he confirmed the campaign
$this->mailService->sendCustomMail(
$this->mailService->getMail(
$this->configService->get('EconsorCrowdfunding.config.campaignSponsorConfirmed')
),
false,
[],
[
'email' => $sponsor->getEmail(),
'firstname' => $sponsor->getName(),
'lastname' => ''
],
$campaign->getSaleschannelid()
);
$id = Uuid::randomHex();
$hash = md5($id . $sponsor->getEmail());
//create submit page for trainer
$this->validationRepo->create(
[
[
'id' => $id,
'hash' => $hash,
'campaignid' => $params['campaign'],
'values' => null
]
],
Context::createDefaultContext()
);
//trainer mail, submit to admin there
$this->mailService->send(
$this->mailService->getMail(
$this->configService->get(
'EconsorCrowdfunding.config.campaignValidateCampaignTrainerAfterSponsor'
)
),
true,
['hash' => $hash],
$campaign->getCustomer(),
$campaign->getSaleschannelid()
);
}
}
}
//##################################################################################################################
/**
* @param $oID
*/
private function saveBundleData($oID)
{
$sessionId = $this->session->get('sessionId');
$c = new Criteria();
$c->addFilter(new EqualsFilter('sessionId', $sessionId));
$tempBundle = $this->bundleRepo->search($c, Context::createDefaultContext())->getEntities();
$bundle = $this->createBundle($tempBundle->first());
$this->orderBundleRepo->upsert(
[
[
'id' => Uuid::randomHex(),
'orderid' => $oID,
'bundlecontent' => $bundle
]
],
Context::createDefaultContext()
);
}
/**
* @param $tempbundle
* @return array
*/
private function createBundle($tempbundle): array
{
return [
'products' => [
'shirtId' => $tempbundle->getShirtId(),
'trousersId' => $tempbundle->getTrousersId(),
'clipsId' => $tempbundle->getClipsId(),
'keeperShirtId' => $tempbundle->getKeeperShirtId(),
'keeperTrousersId' => $tempbundle->getKeeperTrousersId(),
'keeperClipsId' => $tempbundle->getKeeperClipsId(),
],
'configuration' => $tempbundle->getConfiguration(),
'clubData' => $tempbundle->getClubData()
];
}
/**
* @param $orderID
* @param $extensions
*/
private function processOrderExtensions($orderID, $extensions)
{
$lineItems = $this->getOrderLineItems($orderID);
$campaigns = [];
//dd($this->session);
foreach ($lineItems as $index => $item) {
$identifier = $item->getIdentifier();
if (array_key_exists((string)$identifier, $extensions)) {
$campaigns[$extensions[$identifier]['campaignid']] = true;
$this->processItem($extensions[$identifier], $orderID, $index);
$this->addToOrderHistory($extensions[$identifier]['campaignid'], $orderID, $item->getId());
}
}
if ([] !== $campaigns) {
$this->processCampaigns($campaigns, $orderID);
}
}
/**
* @param $orderID
* @param $extensions
* @param $campaign
*/
private function processShirtExtensions($orderID, $extensions, $campaign)
{
$lineItems = $this->getOrderLineItems($orderID);
$array = [];
foreach ($lineItems as $index => $item) {
$identifier = $item->getProductId();
if (array_key_exists((string)$identifier, $extensions)) {
$array[$extensions[$identifier]['campaign']][$identifier] = $extensions[$identifier];
$this->addAmountToGoal($campaign, [
'amount' => $item->getTotalPrice()
]);
$this->addShirtConfig($campaign, $extensions[$identifier], $orderID, $identifier);
$this->addToOrderHistory($extensions[$identifier]['campaign'], $orderID, $item->getId());
}
}
if ([] !== $array) {
$this->processCampaigns($array, $orderID);
}
}
/**
* @param $campaign
* @param $params
* @param $orderID
* @param $product
*/
private function addShirtConfig($campaign, $params, $orderID, $product)
{
$this->shirtConfigRepo->upsert([[
'id' => Uuid::randomHex(),
'orderid' => $orderID,
'campaignid' => $campaign->getId(),
'productid' => $product,
'configuration' => $params
]], Context::createDefaultContext());
}
/**
* @param $params
* @param $orderID
* @param $orderLineItemId
*/
private function processItem($params, $orderID, $orderLineItemId)
{
$campaign = $this->getCampaign($params['campaignid']);
$this->addAmountToGoal($campaign, $params);
$this->addItemToHistory($params, $orderID, $orderLineItemId);
if (array_key_exists('goodieid', $params)) {
$goodie = $this->getGoodie($params['goodieid']);
$this->updateGoodieStock($goodie, $params);
}
}
/**
* @param $goodie
* @param $params
*/
private function updateGoodieStock($goodie, $params)
{
$this->goodieRepository->update(
[
[
'id' => $params['goodieid'],
'stock' => $goodie->getStock() - 1
]
],
Context::createDefaultContext()
);
}
/**
* @param $id
* @return mixed|null
*/
private function getGoodie($id)
{
$c = new Criteria();
$c->setIds([$id]);
return $this->goodieRepository->search($c, Context::createDefaultContext())->getEntities()->first();
}
/**
* @param $params
* @param $orderID
* @param $orderLineItemId
*/
private function addItemToHistory($params, $orderID, $orderLineItemId)
{
$this->orderHistoryRepo->upsert(
[
[
'id' => Uuid::randomHex(),
'campaignid' => $params['campaignid'],
'orderid' => $orderID,
'itemid' => $orderLineItemId
]
],
Context::createDefaultContext()
);
}
/**
* @param $campaign
* @param $params
*/
private function addAmountToGoal($campaign, $params)
{
$this->campaignRepo->update(
[
[
'id' => $campaign->getId(),
'fundinggoal' => ($campaign->getFundingGoal()) - (float)$params['amount']
]
],
Context::createDefaultContext()
);
}
/**
* @param $orderID
* @return mixed
*/
private function getOrderLineItems($orderID)
{
$c = new Criteria();
$c->setIds([$orderID]);
$c->addAssociation('lineItems');
return $this->orderRepo->search($c, Context::createDefaultContext())->getEntities()->first()->getLineItems();
}
/**
* @param $id
* @return mixed|null
*/
private function getCampaign($id)
{
$c = new Criteria();
$c->setIds([$id]);
return $this->campaignRepo->search($c, Context::createDefaultContext())->getEntities()->first();
}
/**
* @param $campaigns
* @param $oID
*/
private function processCampaigns($campaigns, $oID)
{
foreach ($campaigns as $id => $dummy) {
$campaign = $this->getCampaign($id);
$this->addOneSupporter($campaign);
}
}
/**
* @param $cID
* @param $oID
* @param $pID
*/
private function addToOrderHistory($cID, $oID, $pID)
{
$c = new Criteria();
$c->addFilter(new EqualsFilter('campaignid', $cID));
$c->addFilter(new EqualsFilter('itemid', $pID));
$c->addFilter(new EqualsFilter('orderid', $oID));
$check = $this->orderHistoryRepo->search($c, Context::createDefaultContext())->getEntities()->first();
if(!$check)
{
$this->orderHistoryRepo->upsert(
[
[
'id' => Uuid::randomHex(),
'campaignid' => $cID,
'itemid' => $pID,
'orderid' => $oID
]
],
Context::createDefaultContext()
);
}
}
/**
* @param $campaign
*/
private function addOneSupporter($campaign)
{
$this->campaignRepo->update(
[
[
'id' => $campaign->getId(),
'supporters' => $campaign->getSupporters() + 1
]
],
Context::createDefaultContext()
);
}
//##################################################################################################################
/**
* @param $oID
* @return RedirectResponse
*/
private function processCrowdfundingOrder($oID): RedirectResponse
{
$this->session->remove('fee');
$cID = $this->session->get('campaignID');
$this->campaignRepo->update(
[
[
'id' => $cID,
'confirmed' => false,
'status' => 9,
'initialorderid' => $oID
],
],
Context::createDefaultContext()
);
$this->orderHistoryRepo->upsert(
[
[
'id' => Uuid::randomHex(),
'campaignid' => $cID,
'orderid' => $oID
]
],
Context::createDefaultContext()
);
$slug = $this->session->get('slug');
if(!$this->session->has('own-sponsor'))
{
$c = new Criteria();
$c->setIds([$cID]);
$campaign = $this->campaignRepo->search($c, Context::createDefaultContext())->getEntities()->first();
$this->mailService->sendAdmin(
$this->mailService->getMail(
$this->configService->get('EconsorCrowdfunding.config.campaignAwaitConfirmationAdmin')
),
false,
null,
$campaign->getSaleschannelid()
);
$customer = $campaign->getCustomer();
$this->mailService->send(
$this->mailService->getMail(
$this->configService->get('EconsorCrowdfunding.config.campaignAwaitConfirmationTrainer')
),
true,
[
'slug' => $slug
],
$customer,
$campaign->getSaleschannelid()
);
}
return new RedirectResponse(
$this->router->generate('frontend.crowdfunding.campaign', ['slug' => $slug])
);
}
//##################################################################################################################
//##################################################################################################################
//##################################################################################################################
//##################################################################################################################
//##################################################################################################################
//##################################################################################################################
//##################################################################################################################
//##################################################################################################################
//##################################################################################################################
/**
* @param $oID
* @param $name
*/
private function processOrder($oID, $name)
{
$params = $this->session->get($name);
$c = new Criteria();
$c->setIds([$params['campaignid']]);
$campaign = $this->campaignRepo->search($c, Context::createDefaultContext())->getEntities()->first();
$this->campaignRepo->update(
[
[
'id' => $campaign->getId(),
'supporters' => $campaign->getSupporters() + 1,
'fundinggoal' => ($campaign->getFundingGoal()) - (float)$params['amount']
]
],
Context::createDefaultContext()
);
//update order history repo
$this->orderHistoryRepo->upsert(
[
[
'id' => Uuid::randomHex(),
'campaignid' => $params['campaignid'],
'orderid' => $oID
]
],
Context::createDefaultContext()
);
$this->session->remove($name);
}
private function processGoodie()
{
$params = $this->session->get('goodie');
$c = new Criteria();
$c->setIds([$params['goodieid']]);
$goodie = $this->goodieRepository->search($c, Context::createDefaultContext())->getEntities()->first();
$this->goodieRepository->update(
[
[
'id' => $params['goodieid'],
'stock' => $goodie->getStock() - 1
]
],
Context::createDefaultContext()
);
}
}