<?php declare(strict_types=1);
namespace Dtgs\DeliveryDate\Subscriber;
use Dtgs\DeliveryDate\Components\Helper\CalculationHelper;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Core\Framework\Validation\BuildValidationEvent;
use Shopware\Core\Framework\Validation\DataValidationDefinition;
use Shopware\Core\Framework\Validation\DataValidator;
use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
use Shopware\Core\PlatformRequest;
use Shopware\Core\System\Language\LanguageCollection;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPage;
use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Swag\PayPal\OrdersApi\Builder\Event\PayPalV2ItemFromOrderEvent;
class CheckoutSubscriber implements EventSubscriberInterface
{
/**
* @var SystemConfigService
*/
private $systemConfigService;
/**
* @var Session
*/
private $session;
/**
* @var RequestStack
*/
private $requestStack;
/**
* @var DataValidator
*/
private $validator;
/**
* @var CalculationHelper
*/
private $calculationHelper;
/**
* @var EntityRepositoryInterface
*/
private $languageRepository;
/**
* CheckoutSubscriber constructor.
* @param SystemConfigService $systemConfigService
* @param Session $session
* @param RequestStack $requestStack
* @param DataValidator $validator
* @param CalculationHelper $calculationHelper
* @param EntityRepositoryInterface $languageRepository
*/
public function __construct(SystemConfigService $systemConfigService,
Session $session,
RequestStack $requestStack,
DataValidator $validator,
CalculationHelper $calculationHelper,
EntityRepositoryInterface $languageRepository)
{
$this->systemConfigService = $systemConfigService;
$this->session = $session;
$this->requestStack = $requestStack;
$this->validator = $validator;
$this->calculationHelper = $calculationHelper;
$this->languageRepository = $languageRepository;
}
public static function getSubscribedEvents(): array
{
return [
CheckoutConfirmPageLoadedEvent::class => 'onConfirmPageLoaded',
CheckoutFinishPageLoadedEvent::class => 'onFinishPageLoaded',
'framework.validation.order.create' => 'onValidateOrder',
];
}
/**
* Wenn das DeliveryDate ein Pflichtfeld ist, prüfen wir hier ob es gesetzt ist
*
* @param BuildValidationEvent $event
*/
public function onValidateOrder($event)
{
$salesChannelId = $this->requestStack->getCurrentRequest()->attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_ID);
$deliveryDateConfig = $this->systemConfigService->get('DtgsDeliveryDateSw6.config', $salesChannelId);
if(!isset($deliveryDateConfig['deliveryDateRequired']) || $deliveryDateConfig['deliveryDateRequired'] === false || $deliveryDateConfig['deliveryDateActive'] === false) {
return;
}
$data = [];
$data['deliverydate'] = $this->session->get('deliverydate', null);
$definition = new DataValidationDefinition('checkout.deliverydate');
$definition->add('deliverydate', new NotBlank());
$violations = $this->validator->getViolations($data, $definition);
if (!$violations->count()) {
return;
}
$violations = new ConstraintViolationList();
$violations->add(new ConstraintViolation(
'Delivery Date not set',
'Delivery Date not set',
[],
'',
'deliverydate',
$data['deliverydate'],
null,
'dtgs-delivery-date-null'
));
// wirf diese Exception und du kommst zurück zur confirm seite
throw new ConstraintViolationException($violations, $data);
}
/**
* Event für Confirm Seite
*
* @param CheckoutConfirmPageLoadedEvent $event
* @throws \Exception
*/
public function onConfirmPageLoaded($event)
{
/** @var CheckoutConfirmPageLoadedEvent $page */
$page = $event->getPage();
$salesChannelId = $event->getSalesChannelContext()->getSalesChannel()->getId();
$deliveryDateConfig = $this->systemConfigService->get('DtgsDeliveryDateSw6.config', $salesChannelId);
#var_dump($deliveryDateConfig); exit;
//since V6.0.15
$this->calculationHelper->loadConfig($deliveryDateConfig);
if(isset($deliveryDateConfig['deliveryDateTimeZone']) && $deliveryDateConfig['deliveryDateTimeZone'] != '') $this->calculationHelper->setTimezone($deliveryDateConfig['deliveryDateTimeZone']);
if(isset($deliveryDateConfig['deliveryDateMaxTime'])) $this->calculationHelper->setMaxTime($deliveryDateConfig['deliveryDateMaxTime']);
//Included days
$deliveryDateConfig['includedDays'] = json_encode($this->calculationHelper->getIncludedDays());
//Excluded days
$deliveryDateConfig['excludedDates'] = json_encode($this->calculationHelper->getExcludedDates());
if(!$deliveryDateConfig['deliveryDateUseBlockedDaysForCalculation']) {
$this->calculationHelper->setIncludedDays(array(1,2,3,4,5,6,7));
$this->calculationHelper->setExcludedDates(array());
}
//Inline Picker
$inlinePickerAsString = ($deliveryDateConfig['deliveryDateInlinePicker']) ? 'true' : 'false';
$deliveryDateConfig['deliveryDateInlinePickerAsString'] = $inlinePickerAsString;
//Calendar weeks
$showWeeksAsString = ($deliveryDateConfig['deliveryDateShowWeeks']) ? 'true' : 'false';
$deliveryDateConfig['deliveryDateShowWeeksAsString'] = $showWeeksAsString;
//this seems to be a bug...
if(!isset($deliveryDateConfig['deliveryDateMinDaysBefore'])) $deliveryDateConfig['deliveryDateMinDaysBefore'] = 0;
if(!isset($deliveryDateConfig['deliveryDateMaxDaysAfter'])) $deliveryDateConfig['deliveryDateMaxDaysAfter'] = 0;
//Earliest and latest date
$deliveryDateConfig['deliveryDateMinDaysBefore'] = $this->calculationHelper->calculateMinDate($deliveryDateConfig['deliveryDateMinDaysBefore']);
$deliveryDateConfig['deliveryDateMaxDaysAfter'] = $this->calculationHelper->calculateMaxDate($deliveryDateConfig['deliveryDateMaxDaysAfter']);
//Ajax URL
$deliveryDateConfig['deliveryDateAjaxUrl'] = $event->getSalesChannelContext()->getSalesChannel()->getDomains()->first()->getUrl();
//Check if there is a delivery date in session already
if($this->session->get('deliverydate', null) !== null) {
$deliveryDateConfig['deliveryDateInSession'] = $this->session->get('deliverydate', null);
}
$deliveryDateConfig['deliveryDateLocale'] = $this->getLanguageCode($event->getContext());
//Time picker
$timePickerAsString = ($deliveryDateConfig['deliveryDateEnableTimePicker']) ? 'true' : 'false';
$deliveryDateConfig['deliveryDateEnableTimePickerAsString'] = $timePickerAsString;
$page->addExtension('DeliveryDateConfig', new ArrayEntity([
'data' => $deliveryDateConfig
]));
}
/**
* Event für Finish Seite
*
* @param CheckoutFinishPageLoadedEvent $event
* @throws \Exception
*/
public function onFinishPageLoaded($event)
{
/** @var CheckoutFinishPage $page */
$page = $event->getPage();
$salesChannelId = $event->getSalesChannelContext()->getSalesChannel()->getId();
$deliveryDateConfig = $this->systemConfigService->get('DtgsDeliveryDateSw6.config', $salesChannelId);
$order = $page->getOrder();
$customFields = $order->getCustomFields();
if(isset($customFields['dtgs_delivery_date']) && $customFields['dtgs_delivery_date'] != '') {
$format = ($deliveryDateConfig['deliveryDateEnableTimePicker']) ? 'd.m.Y H:i' : 'd.m.Y';
$deliveryDateAsString = date($format, strtotime($customFields['dtgs_delivery_date']));
$page->addExtension('DeliveryDateConfig', new ArrayEntity([
'asString' => $deliveryDateAsString
]));
}
}
private function getLanguageCode(Context $context): string
{
$language = $this->getLanguage($context);
if ($language === null) {
return 'en';
}
return $language->getName();
}
private function getLanguage(Context $context)
{
$languageId = $context->getLanguageId();
$criteria = new Criteria([$languageId]);
$criteria->addAssociation('locale');
/** @var LanguageCollection $languageCollection */
$languageCollection = $this->languageRepository->search($criteria, $context)->getEntities();
return $languageCollection->get($languageId);
}
}