<?php
declare(strict_types=1);
namespace VioB2BLogin\Core\System\SalesChannel\Context;
use Shopware\Core\Checkout\Cart\Delivery\Struct\ShippingLocation;
use Shopware\Core\Checkout\Customer\Aggregate\CustomerAddress\CustomerAddressEntity;
use Shopware\Core\System\SalesChannel\Context\AbstractSalesChannelContextFactory;
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextPersister;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use VioB2BLogin\Core\Services\EmployeeService;
use VioB2BLogin\Entity\Employee\EmployeeEntity;
use VioB2BLogin\Entity\EmployeeAddress\EmployeeAddressEntity;
class SalesChannelContextFactory extends AbstractSalesChannelContextFactory
{
public const EMPLOYEE_ID = 'employeeId';
public const EMPLOYEE_KEY = 'employee';
private AbstractSalesChannelContextFactory $coreFactory;
private SalesChannelContextPersister $contextPersister;
private EmployeeService $employeeService;
public function __construct(
AbstractSalesChannelContextFactory $coreFactory,
EmployeeService $employeeService,
SalesChannelContextPersister $contextPersister
)
{
$this->coreFactory = $coreFactory;
$this->contextPersister = $contextPersister;
$this->employeeService = $employeeService;
}
public function getDecorated(): AbstractSalesChannelContextFactory
{
return $this->coreFactory;
}
public function create(string $token, string $salesChannelId, array $options = []): SalesChannelContext
{
$saleChannelContext = $this->coreFactory->create($token, $salesChannelId, $options);
$session = $this->contextPersister->load($token, $salesChannelId);
$employee = $this->loadEmployee($session, $saleChannelContext);
$saleChannelContext->addExtension(self::EMPLOYEE_KEY, $employee);
if ($employee instanceof EmployeeEntity
) {
$newDefaultBillingAddressId = null;
$newDefaultShippingAddressId = null;
$possibleBillingIds = [];
// reset default billing address in Context
if ($employee->getAddresses()
&& $employee->getAddresses()->count() > 0
) {
$possibleBillingIds = $employee->getAddresses()->filter(
function (CustomerAddressEntity $address) {
/** @var EmployeeAddressEntity $relation */
$relation = $address->getExtensionOfType('relationData', EmployeeAddressEntity::class);
return $relation->isAsBillingAddress();
})->getIds();
$newDefaultBillingAddressId = array_shift($possibleBillingIds);
if (!empty($newDefaultBillingAddressId)
) {
if (!in_array($saleChannelContext->getCustomer()->getDefaultBillingAddressId(), $possibleBillingIds, true)) {
$saleChannelContext->getCustomer()->setDefaultBillingAddressId($newDefaultBillingAddressId);
$saleChannelContext->getCustomer()->setDefaultBillingAddress($employee->getAddresses()->get($newDefaultBillingAddressId));
}
if ($saleChannelContext->getCustomer()->getActiveBillingAddress() === null
|| !in_array($saleChannelContext->getCustomer()->getActiveBillingAddress()->getId(), $possibleBillingIds, true)) {
$saleChannelContext->getCustomer()->setActiveBillingAddress($employee->getAddresses()->get($newDefaultBillingAddressId));
}
}
}
// reset default billing address in Context
if ($employee->getAddresses()
&& $employee->getAddresses()->count() > 0
) {
$possibleShippingIds = $employee->getAddresses()->filter(
function (CustomerAddressEntity $address) {
/** @var EmployeeAddressEntity $relation */
$relation = $address->getExtensionOfType('relationData', EmployeeAddressEntity::class);
return $relation->isAsShippingAddress();
})->getIds();
if (!empty($possibleShippingIds)) {
$newDefaultShippingAddressId = array_shift($possibleShippingIds);
} elseif (!empty($newDefaultBillingAddressId)) {
$newDefaultShippingAddressId = $newDefaultBillingAddressId;
}
if (!empty($newDefaultShippingAddressId)) {
if (!in_array($saleChannelContext->getCustomer()->getDefaultShippingAddressId(), $possibleShippingIds, true)) {
$saleChannelContext->getCustomer()->setDefaultShippingAddressId($newDefaultShippingAddressId);
$saleChannelContext->getCustomer()->setDefaultShippingAddress($employee->getAddresses()->get($newDefaultShippingAddressId));
}
if ($saleChannelContext->getCustomer()->getActiveShippingAddress() === null
|| !in_array($saleChannelContext->getCustomer()->getActiveShippingAddress()->getId(), $possibleShippingIds, true)) {
$saleChannelContext->getCustomer()->setActiveShippingAddress($employee->getAddresses()->get($newDefaultShippingAddressId));
}
// validate shipping Location
$shippingLocation = $saleChannelContext->getShippingLocation();
if (!in_array($shippingLocation->getAddress()->getId(), $possibleShippingIds, true)
) {
$newShippingLocation = ShippingLocation::createFromAddress($employee->getAddresses()->get($newDefaultShippingAddressId));
// create new SalesChannelContext with new shipping location
$newSaleChannelContext = new SalesChannelContext(
$saleChannelContext->getContext(),
$saleChannelContext->getToken(),
$saleChannelContext->getDomainId(),
$saleChannelContext->getSalesChannel(),
$saleChannelContext->getCurrency(),
$saleChannelContext->getCurrentCustomerGroup(),
$saleChannelContext->getFallbackCustomerGroup(),
$saleChannelContext->getTaxRules(),
$saleChannelContext->getPaymentMethod(),
$saleChannelContext->getShippingMethod(),
$newShippingLocation,
$saleChannelContext->getCustomer(),
$saleChannelContext->getItemRounding(),
$saleChannelContext->getTotalRounding(),
$saleChannelContext->getRuleIds()
);
$newSaleChannelContext->addExtensions($saleChannelContext->getExtensions());
$saleChannelContext = $newSaleChannelContext;
}
}
}
}
return $saleChannelContext;
}
/**
* @param array $options
* @param SalesChannelContext $context
* @return EmployeeEntity|null
*/
protected function loadEmployee(array $options, SalesChannelContext $context): ?EmployeeEntity
{
if (!array_key_exists(self::EMPLOYEE_ID, $options)) {
return null;
}
$employeeId = $options[self::EMPLOYEE_ID];
return $this->employeeService->getById($employeeId, $context);
}
}