<?php
declare(strict_types=1);
namespace fourtwosix\PreOrder\Subscriber;
use Shopware\Core\Content\Product\ProductEvents;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
use Shopware\Core\Framework\Api\Context\SalesChannelApiSource;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Storefront\Page\PageLoadedEvent;
class ProductDetails implements EventSubscriberInterface
{
/**
* @var SystemConfigService
*/
private $systemConfigService;
private const DATETIME_FORMAT = 'Y-m-d H:i:s';
public function __construct(SystemConfigService $systemConfigService)
{
$this->systemConfigService = $systemConfigService;
}
public static function getSubscribedEvents(): array
{
return [
ProductEvents::PRODUCT_LOADED_EVENT => 'onProductDetails',
CheckoutCartPageLoadedEvent::class => 'onCartPage',
CheckoutConfirmPageLoadedEvent::class => 'onConfirmPage'
];
}
public function onProductDetails(EntityLoadedEvent $event)
{
$salesChannelId = null;
if ($event->getContext()->getSource() instanceof SalesChannelApiSource) {
$salesChannelId = $event->getContext()->getSource()->getSalesChannelId();
}
$buttonColor = $this->systemConfigService->get(
'fourtwosixPreOrderProduct.config.preOrderButtonColor',
$salesChannelId
);
if ($buttonColor == null) {
$buttonColor = '';
}
$matches = array();
preg_match('/#([a-f0-9]{3}){1,2}\b/i', $buttonColor, $matches);
if (empty($matches)) {
return;
}
$buttonColor = $matches[0];
$entities = $event->getEntities();
foreach ($entities as $entity) {
$extensions = new ArrayEntity();
$extensions['preorder_button_color'] = $buttonColor;
$entity->addExtension("productDetailStruct", $extensions);
}
}
public function onCartPage(CheckoutCartPageLoadedEvent $event)
{
$this->addReleaseDateToLineItems($event);
}
public function onConfirmPage(CheckoutConfirmPageLoadedEvent $event)
{
$this->addReleaseDateToLineItems($event);
}
private function addReleaseDateToLineItems(PageLoadedEvent $event): void
{
/* add to lineItems extensions the release date indicator */
$cartReleaseDates = [];
$maxDeliveryDate = [];
$lineItems = $event->getPage()->getCart()->getLineItems();
foreach ($lineItems as $lineItem) {
foreach ($event->getPage()->getCart()->getData() as $originalProduct) {
if (
is_array($originalProduct) ||
!is_object($originalProduct) ||
get_class($originalProduct) != 'Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity' ||
$lineItem->getId() != $originalProduct->getId()
) {
continue;
}
if (
!isset($originalProduct->getCustomFields()["preorder_enabled"]) ||
!$originalProduct->getCustomFields()["preorder_enabled"] ||
!$originalProduct->getReleaseDate()
) {
break;
}
$cartReleaseDates[$lineItem->getId()] = $originalProduct->getReleaseDate()->format(self::DATETIME_FORMAT);
if (!$lineItem->getDeliveryInformation()->getDeliveryTime()) {
$maxDeliveryDate[$lineItem->getId()] = $originalProduct->getReleaseDate()->format(self::DATETIME_FORMAT);
break;
}
$maxDeliveryDate[$lineItem->getId()] = $this->addDate(
$originalProduct->getReleaseDate()->format(self::DATETIME_FORMAT),
$lineItem->getDeliveryInformation()->getDeliveryTime()->getUnit(),
$lineItem->getDeliveryInformation()->getDeliveryTime()->getMax()
);
break;
}
}
$extensions = $event->getPage()->getExtensions();
$extensions["fourtwosixPreorderCartReleaseDates"] = $cartReleaseDates;
$extensions["fourtwosixPreorderCartDeliveryMax"] = $maxDeliveryDate;
$event->getPage()->setExtensions($extensions);
}
public function addDate(string $date, string $unit, int $max)
{
$date = strtotime($date);
switch ($unit) {
case 'hour':
return date(self::DATETIME_FORMAT, strtotime("+{$max} hour", $date));
case 'day':
return date(self::DATETIME_FORMAT, strtotime("+{$max} day", $date));
case 'week':
return date(self::DATETIME_FORMAT, strtotime("+{$max} week", $date));
case 'month':
return date(self::DATETIME_FORMAT, strtotime("+{$max} month", $date));
case 'year':
return date(self::DATETIME_FORMAT, strtotime("+{$max} year", $date));
default:
return $date;
}
}
}