custom/plugins/CogiAdvancedDeliveryDate/src/Subscriber/CheckoutSubscriber.php line 78

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Cogi\CogiAdvancedDeliveryDate\Subscriber;
  3. use Exception;
  4. use Shopware\Core\Framework\Struct\ArrayEntity;
  5. use Shopware\Core\Framework\Validation\BuildValidationEvent;
  6. use Shopware\Core\Framework\Validation\DataValidationDefinition;
  7. use Shopware\Core\Framework\Validation\DataValidator;
  8. use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
  9. use Shopware\Core\PlatformRequest;
  10. use Shopware\Core\System\SystemConfig\SystemConfigService;
  11. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
  12. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. use Symfony\Component\HttpFoundation\RequestStack;
  15. use Symfony\Component\HttpFoundation\Session\Session;
  16. use Symfony\Component\Validator\Constraints\NotBlank;
  17. use Symfony\Component\Validator\ConstraintViolation;
  18. use Symfony\Component\Validator\ConstraintViolationList;
  19. class CheckoutSubscriber implements EventSubscriberInterface {
  20.     /**
  21.      * @var SystemConfigService
  22.      */
  23.     private $systemConfigService;
  24.     /**
  25.      * @var Session
  26.      */
  27.     private $session;
  28.     /**
  29.      * @var RequestStack
  30.      */
  31.     private $requestStack;
  32.     /**
  33.      * @var DataValidator
  34.      */
  35.     private $validator;
  36.     /**
  37.      * CheckoutSubscriber constructor.
  38.      * @param SystemConfigService $systemConfigService
  39.      * @param Session $session
  40.      * @param RequestStack $requestStack
  41.      * @param DataValidator $validator
  42.      */
  43.     public function __construct(SystemConfigService $systemConfigServiceSession $sessionRequestStack $requestStackDataValidator $validator) {
  44.         $this->systemConfigService $systemConfigService;
  45.         $this->session $session;
  46.         $this->requestStack $requestStack;
  47.         $this->validator $validator;
  48.     }
  49.     public static function getSubscribedEvents(): array {
  50.         return [
  51.             CheckoutConfirmPageLoadedEvent::class => 'onConfirmPageLoaded',
  52.             ProductPageLoadedEvent::class => 'onConfirmPageLoaded',
  53.             'framework.validation.order.create' => 'onValidate'
  54.         ];
  55.     }
  56.     /**
  57.      * Event für Confirm Seite
  58.      *
  59.      * @param CheckoutConfirmPageLoadedEvent|ProductPageLoadedEvent $event
  60.      * @throws Exception
  61.      */
  62.     public function onConfirmPageLoaded($event) {
  63.         /** @var CheckoutConfirmPageLoadedEvent|ProductPageLoadedEvent $page */
  64.         $page $event->getPage();
  65.         $config $this->systemConfigService->get('CogiAdvancedDeliveryDate.config'$event->getSalesChannelContext()->getSalesChannel()->getId());
  66.         $output['salesChannelUrl'] = $event->getSalesChannelContext()->getSalesChannel()->getDomains()->first()->getUrl();
  67.         $output['savedDate'] = $this->session->get('cogiAdvancedDeliveryDate'null);
  68.         $output['showCalendarWeeks'] = $config['showCalendarWeeks'] ? 'true' 'false';
  69.         $output['daysOfWeekDisabled'] = $config['daysOfWeekDisabled'] ?? [];
  70.         $startTime time() + ($config['minDays'] * 86400);
  71.         // skip to next day if hour is exceeded
  72.         if (isset($config['timeExceeded']) && strtotime(date('H:i')) > strtotime(date($config['timeExceeded']))) {
  73.             $startTime += 86400;
  74.         }
  75.         // check if the start day collisions with any disabled day of the week
  76.         $currentStartDay date("w"$startTime);
  77.         $modifiedDate false;
  78.         while (in_array($currentStartDay$output['daysOfWeekDisabled'])) {
  79.             $startTime += 86400;
  80.             $currentStartDay date("w"$startTime);
  81.             $modifiedDate true;
  82.         }
  83.         // skip to next day if hour is exceeded
  84.         if ($modifiedDate && isset($config['timeExceeded']) && strtotime(date('H:i')) > strtotime(date($config['timeExceeded']))) {
  85.             $startTime += 86400;
  86.         }
  87.         // if pickup is enabled, set different settings
  88.         if (method_exists($page"getCart") && $this->isPickupActive($config$page->getCart()->getDeliveries()->getElements()[0]->getShippingMethod()->getId())) {
  89.             // pickup datepicker
  90.             $output['endDate'] = date('d.m.Y'time() + ($config['pickupMaxDays'] * 86400));
  91.             $output['startDate'] = date('d.m.Y'time());
  92.             $output['daysOfWeekDisabled'] = $config['pickupDaysOfWeekDisabled'] ?? [];
  93.             $output['savedHour'] = $this->session->get('cogiAdvancedDeliveryPickupHour'null);
  94.             // check already saved hour (in session) if it fits current settings
  95.             if ($output['savedHour']) {
  96.                 if (date("H:i"time() + $config['pickupPreparationTime'] * 60) > $output['savedHour']) {
  97.                     $output['savedHour'] = null;
  98.                     $this->session->set('cogiAdvancedDeliveryPickupHour'null);
  99.                 }
  100.             }
  101.             $output['pickupEnabled'] = true;
  102.             $output['pickupHourMin'] = date("H:i"strtotime($config['pickupHourMin']));
  103.             $output['pickupHourMax'] = date("H:i"strtotime($config['pickupHourMax']));
  104.             $output['pickupHours'] = array();
  105.             $output['disabledDates'] = $this->getDisabledDays($configtrue);
  106.             $pickupIsToday false;
  107.             // check if pickup date is today
  108.             if ($output['savedDate'] === date("d.m.Y"))
  109.                 $pickupIsToday true;
  110.             // iterate hours for the pickup hourpicker
  111.             for ($hour = (int)date("H"strtotime($config['pickupHourMin'])); $hour < (int)date("H"strtotime($config['pickupHourMax'])); $hour++) {
  112.                 if ($hour 10) {
  113.                     $hour "0{$hour}";
  114.                 }
  115.                 // iterate minutes
  116.                 for ($minute 0$minute 59$minute++) {
  117.                     // continue current number if item isnt a step
  118.                     if ($minute $config['pickupHourStep'] !== 0) {
  119.                         continue;
  120.                     }
  121.                     // add prepending zero
  122.                     if ($minute 10) {
  123.                         $minute "0{$minute}";
  124.                     }
  125.                     if ($pickupIsToday && date("H:i"time() + $config['pickupPreparationTime'] * 60) > "{$hour}:{$minute}") {
  126.                         continue;
  127.                     }
  128.                     $output['pickupHours'][] = "{$hour}:{$minute}";
  129.                 }
  130.             }
  131.         } else {
  132.             // normal datepicker
  133.             $output['pickupEnabled'] = false;
  134.             $output['endDate'] = date('d.m.Y'time() + ($config['maxDays'] * 86400));
  135.             $output['startDate'] = date('d.m.Y'$startTime);
  136.             $output['disabledDates'] = $this->getDisabledDays($config);
  137.         }
  138.         $page->addExtension('CogiAdvancedDelivery', new ArrayEntity($output));
  139.     }
  140.     /**
  141.      * @param array $config
  142.      * @param $currentShippingMethodId
  143.      * @return bool
  144.      */
  145.     private function isPickupActive(array $config$currentShippingMethodId) {
  146.         return $config['pickupActive'] === true && $currentShippingMethodId === $config['pickupShippingMethod'];
  147.     }
  148.     private function getDisabledDays(array $configbool $pickup false) {
  149.         $disabledHolidayDates = [];
  150.         $haystack $config['holidayDatesDisabled'] ?? [];
  151.         if ($pickup) {
  152.             $haystack $config['pickupHolidayDatesDisabled'] ?? [];
  153.         }
  154.         foreach (json_decode(file_get_contents(__DIR__ '/../Resources/holidays.json')) as $key => $item) {
  155.             if (in_array($item$haystack)) {
  156.                 $disabledHolidayDates[] = date('d.m.Y'strtotime($key));
  157.             }
  158.         }
  159.         $datesDisabled explode("\n"$config['datesDisabled'] ?? "");
  160.         if ($pickup)
  161.             $datesDisabled explode("\n"$config['pickupDatesDisabled'] ?? "");
  162.         return array_merge($disabledHolidayDates$datesDisabled);
  163.     }
  164.     public function onValidate(BuildValidationEvent $event) {
  165.         $salesChannelId $this->requestStack->getCurrentRequest()->attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_ID);
  166.         $config $this->systemConfigService->get('CogiAdvancedDeliveryDate.config'$salesChannelId);
  167.         $currentShippingMethodId $this->requestStack->getCurrentRequest()->attributes->get('sw-sales-channel-context')->getShippingMethod()->get('id');
  168.         // return if config option is not existant or false
  169.         if (!isset($config['isRequired']) || $config['isRequired'] === false) return;
  170.         // return if the current shipping method is a disabled one
  171.         if (in_array($currentShippingMethodId$config['disabledShippingMethods'] ?? [])) return;
  172.         $data['cogiAdvancedDeliveryDate'] = $this->session->get('cogiAdvancedDeliveryDate'null);
  173.         $data['cogiAdvancedDeliveryPickupHour'] = $this->session->get('cogiAdvancedDeliveryPickupHour'null);
  174.         // validate
  175.         $definition = new DataValidationDefinition('checkout.cogiAdvancedDeliveryDate');
  176.         $definition->add('cogiAdvancedDeliveryDate', new NotBlank());
  177.         // pickup is active, add another validation rule
  178.         if ($this->isPickupActive($config$currentShippingMethodId)) {
  179.             $definition->add('cogiAdvancedDeliveryPickupHour', new NotBlank());
  180.         }
  181.         $violations $this->validator->getViolations($data$definition);
  182.         if (!$violations->count()) return;
  183.         $violations = new ConstraintViolationList();
  184.         $violations->add(new ConstraintViolation(
  185.             'Delivery Date is missing',
  186.             'Delivery Date is missing',
  187.             [],
  188.             '',
  189.             'cogiAdvancedDeliveryDate',
  190.             $data['cogiAdvancedDeliveryDate'],
  191.             null,
  192.             'cogiAdvancedDeliveryDate-missing'
  193.         ));
  194.         throw new ConstraintViolationException($violations$data);
  195.     }
  196. }