<?php declare(strict_types=1);
namespace Cogi\CogiAdvancedDeliveryDate\Subscriber;
use Exception;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Cart\Order\CartConvertedEvent;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Checkout\Order\OrderEvents;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use webkon\ClickAndCollect\webkonClickAndCollect6;
class OrderSubscriber implements EventSubscriberInterface {
/**
* @var SystemConfigService
*/
private $systemConfigService;
/**
* @var EntityRepositoryInterface
*/
private $orderRepository;
/**
* @var EntityRepositoryInterface
*/
private $customerRepository;
/**
* @var Session
*/
private $session;
public function __construct(SystemConfigService $systemConfigService,
Session $session,
EntityRepositoryInterface $orderRepository,
EntityRepositoryInterface $customerRepository) {
$this->systemConfigService = $systemConfigService;
$this->session = $session;
$this->orderRepository = $orderRepository;
$this->customerRepository = $customerRepository;
}
public static function getSubscribedEvents(): array {
return [
CartConvertedEvent::class => 'onOrderPlaced',
OrderEvents::ORDER_WRITTEN_EVENT => "onOrderWritten"
];
}
/**
* @param CartConvertedEvent $event
* @deprecated Replaced with onOrderWritten event
*/
public function onOrderPlaced(CartConvertedEvent $event) {
$convertedCart = $event->getConvertedCart();
$config = $this->systemConfigService->get('CogiAdvancedDeliveryDate.config', $convertedCart['salesChannelId']);
$currentContext = $event->getContext();
// this event is just for shops with pickup
if ($config['pickupActive'] !== true) return;
$customer = $this->getCustomer($convertedCart['orderCustomer']['customerId'], $currentContext);
$shippingMethodIds = array_filter(array_map(function (array $orderDelivery) {
return $orderDelivery['shippingMethodId'];
}, $convertedCart['deliveries']));
$deliveryDate = $this->session->get('cogiAdvancedDeliveryDate', null);
// region validate config rules
if (in_array($customer->getGroupId(), $config['disabledCustomerGroups'] ?? []))
$deliveryDate = null;
if (in_array(array_values($shippingMethodIds)[0], $config['disabledShippingMethods'] ?? []))
$deliveryDate = null;
// endregion
// set default date if necessary
if ($config['setDefaultDate'] && !$deliveryDate) {
$startTime = time() + ($config['minDays'] * 86400);
// skip to next day if hour is exceeded
if (isset($config['timeExceeded']) && strtotime(date('H:i')) > strtotime(date($config['timeExceeded']))) {
$startTime += 86400;
}
$deliveryDate = date('d.m.Y', $startTime);
}
if ($deliveryDate) {
$customFields = array();
$customFields['cogiAdvancedDeliveryDate'] = date('Y-m-d', strtotime($deliveryDate));
// check for pickup
if ($this->isPickupActive($config, array_values($shippingMethodIds)[0])) {
$deliveryPickupHour = $this->session->get('cogiAdvancedDeliveryPickupHour', null);
$customFields['cogiAdvancedDeliveryDateIsPickup'] = true;
$customFields['cogiAdvancedDeliveryDate'] .= " {$deliveryPickupHour}";
}
$convertedCart['customFields'] = $customFields;
$event->setConvertedCart($convertedCart);
}
$this->session->remove('cogiAdvancedDeliveryDate');
$this->session->remove('cogiAdvancedDeliveryPickupHour');
}
/**
* @param EntityWrittenEvent $event
* @deprecated Replaced with onOrderWritten event
*/
public function onOrderWritten(EntityWrittenEvent $event) {
$context = $event->getContext();
// hast writeResult
foreach ($event->getWriteResults() as $_key => $writeResult) {
if ($writeResult->getExistence() !== null && $writeResult->getExistence()->exists()) {
break;
}
$payload = $writeResult->getPayload();
if (empty($payload)) {
continue;
}
/** @var EntitySearchResult $orderResult */
$orderResult = $this->orderRepository->search(
(new Criteria([$payload['id']]))->addAssociation('orderCustomer'),
$context
);
/** @var OrderEntity $order */
$order = $orderResult->first();
$config = $this->systemConfigService->get('CogiAdvancedDeliveryDate.config', $order->getSalesChannelId());
// this event is just for shops WITHOUT pickup
if ($config['pickupActive'] === true) return;
$customer = $this->getCustomer($order->getOrderCustomer()->getCustomerId(), $context);
$deliveryDate = $this->session->get('cogiAdvancedDeliveryDate');
// validate customer group
if (in_array($customer->getGroupId(), $config['disabledCustomerGroups'] ?? []))
$deliveryDate = null;
// set default date if necessary
if ($config['setDefaultDate'] && !$deliveryDate) {
$startTime = time() + ($config['minDays'] * 86400);
// skip to next day if hour is exceeded
if (isset($config['timeExceeded']) && strtotime(date('H:i')) > strtotime(date($config['timeExceeded']))) {
$startTime += 86400;
}
$deliveryDate = date('d.m.Y', $startTime);
}
if ($deliveryDate) {
$customFields = $order->getCustomFields();
$customFields['cogiAdvancedDeliveryDate'] = date('Y-m-d', strtotime($deliveryDate));
$data = [
'id' => $payload['id'],
'customFields' => $customFields
];
$this->orderRepository->update([$data], $event->getContext());
}
$this->session->remove('cogiAdvancedDeliveryDate');
$this->session->remove('cogiAdvancedDeliveryPickupHour');
}
return;
}
private function getDisabledDays(array $config) {
$disabledHolidayDates = [];
foreach (json_decode(file_get_contents(__DIR__ . '/../Resources/holidays.json')) as $key => $item) {
if (in_array($item, $config['holidayDatesDisabled'] ?? [])) {
$disabledHolidayDates[] = date('d.m.Y', strtotime($key));
}
}
return array_merge($disabledHolidayDates, explode("\n", $config['datesDisabled']));
}
/**
* @param array $config
* @param $currentShippingMethodId
* @return bool
*/
private function isPickupActive(array $config, $currentShippingMethodId) {
return $config['pickupActive'] === true && $currentShippingMethodId === $config['pickupShippingMethod'];
}
/**
* @param string $id
* @param Context $context
* @return false|CustomerEntity
*/
private function getCustomer(string $id, Context $context) {
$customerData = $this->customerRepository->search(new Criteria([$id]), $context);
if ($customerData->getTotal() === 0) return false;
return $customerData->first();
}
}