<?php
declare(strict_types=1);
namespace VioB2BLogin\Storefront\Subscriber;
use Exception;
use NetInventors\NetiNextAddressTools\Events\CustomerAddressCriteriaEvent;
use Shopware\Core\Checkout\Customer\Aggregate\CustomerAddress\CustomerAddressEntity;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
use Shopware\Core\PlatformRequest;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Page\Address\Listing\AddressListingCriteriaEvent;
use Shopware\Storefront\Page\Address\Listing\AddressListingPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use VioB2BLogin\Core\Services\EmployeeService;
use VioB2BLogin\Entity\Employee\EmployeeEntity;
use VioB2BLogin\Entity\EmployeeAddress\EmployeeAddressEntity;
class AddressSubscriber implements EventSubscriberInterface
{
private EmployeeService $employeeService;
public function __construct(EmployeeService $employeeService)
{
$this->employeeService = $employeeService;
}
public static function getSubscribedEvents(): array
{
return [
AddressListingCriteriaEvent::class => 'onAddressCriteria',
CustomerAddressCriteriaEvent::class => 'onCustomerAddressCriteria',
AddressListingPageLoadedEvent::class => 'onPageLoaded',
KernelEvents::RESPONSE => 'onKernelResponse'
];
}
public function onAddressCriteria(AddressListingCriteriaEvent $event): void
{
try {
$this->modifyCriteria($event->getCriteria(), $event->getSalesChannelContext());
} catch (Exception $ex) {
}
}
public function onCustomerAddressCriteria(CustomerAddressCriteriaEvent $event): void
{
try {
// check if the criteria has an NotFilter for the default shipping address id or the default billing address id
$filters = $event->getCriteria()->getFilters();
$defaultShippingAddressId = $event->getSalesChannelContext()->getCustomer()->getDefaultShippingAddressId();
$defaultBillingAddressId = $event->getSalesChannelContext()->getCustomer()->getDefaultBillingAddressId();
$onlyAsShippingAddress = false;
$onlyAsBillingAddress = false;
foreach ($filters as $filter) {
if ($filter instanceof NotFilter) {
$queries = $filter->getQueries();
foreach ($queries as $query) {
if ($query instanceof EqualsFilter ) {
$value = $query->getValue();
if ($value === $defaultShippingAddressId ) {
$onlyAsShippingAddress = true;
}
if ($value === $defaultBillingAddressId ) {
$onlyAsBillingAddress = true;
}
}
}
}
}
$this->modifyCriteria($event->getCriteria(), $event->getSalesChannelContext(), $onlyAsShippingAddress, $onlyAsBillingAddress);
} catch (Exception $ex) {
}
}
public function onKernelResponse(ResponseEvent $event)
{
if ($event->getRequest()->get('_route') !== 'frontend.neti_next_address_tools.get_addresses') {
return;
}
$response = $event->getResponse();
if ( ! $response instanceof JsonResponse) {
return;
}
$data = $response->getContent();
/** @noinspection PhpComposerExtensionStubsInspection */
$data = json_decode($data, true);
if ( ! is_array($data) || ! isset($data['data']) || ! isset($data['data']['rows'])) {
return;
}
try {
/** @var SalesChannelContext $salesChannelContext */
$salesChannelContext = $event->getRequest()->attributes->get(PlatformRequest::ATTRIBUTE_SALES_CHANNEL_CONTEXT_OBJECT);
$customer = $salesChannelContext->getCustomer();
$employee = $this->employeeService->getEmployeeByContext($salesChannelContext);
if ($employee instanceof EmployeeEntity && $employee->getAddresses() && $employee->getAddresses()->count() > 0) {
/** @var array $address */
foreach ($data['data']['rows'] as &$address) {
$employeeAddress = $employee->getAddresses()->get($address['id']);
if ($employeeAddress instanceof CustomerAddressEntity) {
$relation = $employeeAddress->getExtensionOfType('relationData', EmployeeAddressEntity::class);
if ($relation instanceof EmployeeAddressEntity) {
$address['relationData'] = $relation->getVars();
}
$address['isDefaultBilling'] = $customer->getDefaultBillingAddressId() === $address['id'];
$address['isDefaultShipping'] = $customer->getDefaultShippingAddressId() === $address['id'];
}
else {
unset($address);
}
}
}
} catch (Exception $ex) {
}
$response->setData($data);
}
public function onPageLoaded(AddressListingPageLoadedEvent $event): void
{
try {
$employee = $this->employeeService->getEmployeeByContext($event->getSalesChannelContext());
if ($employee instanceof EmployeeEntity && $employee->getAddresses() && $employee->getAddresses()->count() > 0) {
foreach ($event->getPage()->getAddresses() as $address) {
$employeeAddress = $employee->getAddresses()->get($address->getId());
if ($employeeAddress instanceof CustomerAddressEntity) {
$relation = $employeeAddress->getExtensionOfType('relationData', EmployeeAddressEntity::class);
if ($relation instanceof EmployeeAddressEntity) {
$address->addExtension('relationData', $relation);
}
}
}
}
} catch (Exception $ex) {
}
}
private function modifyCriteria(
Criteria $criteria,
SalesChannelContext $context,
bool $onlyAsShippingAddess = false,
bool $onlyAsBillingAddess = false
): void
{
$employee = $this->employeeService->getEmployeeByContext($context);
if ($employee instanceof EmployeeEntity && $employee->getAddresses() && $employee->getAddresses()->count() > 0) {
$ids = $employee->getAddresses()->getIds();
if( $onlyAsShippingAddess ){
$ids = $employee->getAddresses()->filter(function (CustomerAddressEntity $address) {
/** @var EmployeeAddressEntity $relation */
$relation = $address->getExtensionOfType('relationData', EmployeeAddressEntity::class);
return $relation->isAsShippingAddress();
})->getIds();
}
if ($onlyAsBillingAddess){
$ids = $employee->getAddresses()->filter(function (CustomerAddressEntity $address) {
/** @var EmployeeAddressEntity $relation */
$relation = $address->getExtensionOfType('relationData', EmployeeAddressEntity::class);
return $relation->isAsBillingAddress();
})->getIds();
}
$criteria->setIds($ids);
}
}
}