<?php declare(strict_types=1);
namespace SmartDato\DatoElectronicInvoicing\Storefront\Controller;
use Shopware\Core\Checkout\Cart\Exception\CustomerNotLoggedInException;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Framework\Routing\Annotation\RouteScope;
use Shopware\Core\Framework\Uuid\Exception\InvalidUuidException;
use Shopware\Core\Framework\Validation\DataBag\DataBag;
use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Controller\AddressController as AddressControllerInner;
use Shopware\Storefront\Framework\Routing\StorefrontResponse;
use SmartDato\DatoElectronicInvoicing\Service\PluginConfig\PluginConfigService;
use SmartDato\DatoElectronicInvoicing\Validation\Constraint\FiscalCodeValidator;
use SmartDato\DatoElectronicInvoicing\Validation\Constraint\MainValidator;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Shopware\Core\Framework\Routing\Annotation\LoginRequired;
use Shopware\Core\Framework\Routing\Annotation\Since;
use Symfony\Component\Routing\Annotation\Route;
/**
* @RouteScope(scopes={"storefront"})
*/
class AddressController extends StorefrontBaseController
{
/** @var AddressControllerInner */
private $addressControllerInner;
/** @var PluginConfigService */
private $pluginConfigService;
/**
* AddressController constructor.
*
* @param AddressControllerInner $addressControllerInner
* @param PluginConfigService $pluginConfigService
*/
public function __construct(
$addressControllerInner,
PluginConfigService $pluginConfigService
)
{
$this->addressControllerInner = $addressControllerInner;
$this->pluginConfigService = $pluginConfigService;
}
/**
* @Since("6.0.0.0")
* @LoginRequired()
* @Route("/account/address", name="frontend.account.address.page", options={"seo"="false"}, methods={"GET"})
*
* @throws CustomerNotLoggedInException
*/
public function accountAddressOverview(Request $request, SalesChannelContext $context, CustomerEntity $customer): Response
{
return $this->addressControllerInner->accountAddressOverview($request, $context, $customer);
}
/**
* @Since("6.0.0.0")
* @LoginRequired()
* @Route("/account/address/create", name="frontend.account.address.create.page", options={"seo"="false"}, methods={"GET"})
*
* @throws CustomerNotLoggedInException
*/
public function accountCreateAddress(Request $request, RequestDataBag $data, SalesChannelContext $context, CustomerEntity $customer): Response
{
return $this->addressControllerInner->accountCreateAddress($request, $data, $context, $customer);
}
/**
* @Since("6.0.0.0")
* @LoginRequired()
* @Route("/account/address/{addressId}", name="frontend.account.address.edit.page", options={"seo"="false"}, methods={"GET"})
*
* @throws CustomerNotLoggedInException
*/
public function accountEditAddress(Request $request, SalesChannelContext $context, CustomerEntity $customer): Response
{
return $this->addressControllerInner->accountEditAddress($request, $context, $customer);
}
/**
* @Since("6.0.0.0")
* @LoginRequired()
* @Route("/account/address/default-{type}/{addressId}", name="frontend.account.address.set-default-address", methods={"POST"})
*
* @throws CustomerNotLoggedInException
* @throws InvalidUuidException
*/
public function switchDefaultAddress(string $type, string $addressId, SalesChannelContext $context, CustomerEntity $customer): RedirectResponse
{
return $this->addressControllerInner->switchDefaultAddress($type, $addressId, $context, $customer);
}
/**
* @Since("6.0.0.0")
* @LoginRequired()
* @Route("/account/address/delete/{addressId}", name="frontend.account.address.delete", options={"seo"="false"}, methods={"POST"})
*
* @throws CustomerNotLoggedInException
*/
public function deleteAddress(string $addressId, SalesChannelContext $context, CustomerEntity $customer): Response
{
return $this->addressControllerInner->deleteAddress($addressId, $context, $customer);
}
/**
* @Since("6.0.0.0")
* @LoginRequired()
* @Route("/account/address/create", name="frontend.account.address.create", options={"seo"="false"}, methods={"POST"})
* @Route("/account/address/{addressId}", name="frontend.account.address.edit.save", options={"seo"="false"}, methods={"POST"})
*
* @throws CustomerNotLoggedInException
*/
public function saveAddress(RequestDataBag $data, SalesChannelContext $context, CustomerEntity $customer): Response
{
$this->handleSaveAddress($data, $context);
return $this->addressControllerInner->saveAddress($data, $context, $customer);
}
/**
* @Since("6.0.0.0")
* @LoginRequired(allowGuest=true)
* @Route("/widgets/account/address-book", name="frontend.account.addressbook", options={"seo"=true}, methods={"POST"}, defaults={"XmlHttpRequest"=true})
*/
public function addressBook(Request $request, RequestDataBag $dataBag, SalesChannelContext $context, CustomerEntity $customer): Response
{
$this->handleAddressBook($dataBag, $context);
/** @var StorefrontResponse $response */
$response = $this->addressControllerInner->addressBook($request, $dataBag, $context, $customer);
$responseData = $response->getData();
if (empty($responseData['messages'])) {
return $response;
}
if (empty($responseData['messages']['type'])) {
return $response;
}
if (empty($responseData['messages']['text'])) {
return $response;
}
$this->addFlash($responseData['messages']['type'], $responseData['messages']['text']);
return $response;
}
/**
* Handle save address
*
* @param RequestDataBag $data
* @param SalesChannelContext $context
*/
private function handleSaveAddress(RequestDataBag $data, SalesChannelContext $context): void
{
if (($address = $data->get('address')) instanceof DataBag) {
$this->addFiscalCodeAndInvoicingFieldsValidationDefinitions($address, $context);
}
}
/**
* Handle address book
*
* @param RequestDataBag $dataBag
* @param SalesChannelContext $context
*/
private function handleAddressBook(RequestDataBag $dataBag, SalesChannelContext $context): void
{
$changeableAddresses = $dataBag->get('changeableAddresses');
if ($changeableAddresses instanceof DataBag && $changeableAddresses->get('changeBilling')) {
$address = $dataBag->get('address');
if ($address instanceof DataBag) {
$this->addFiscalCodeAndInvoicingFieldsValidationDefinitions($address, $context);
}
}
}
/**
* Add fiscal code and invoicing fields validation definitions to validate address before save
*
* @param DataBag $address
* @param SalesChannelContext $context
*/
private function addFiscalCodeAndInvoicingFieldsValidationDefinitions(DataBag $address, SalesChannelContext $context): void
{
if ($context->getCustomer() === null) {
return;
}
if (!$this->isEditedAddressIsBilling($address, $context->getCustomer()->getDefaultBillingAddressId())) {
return;
}
$validationConfig = $this->pluginConfigService->getValidationConfig($context->getSalesChannel()->getId());
if (!$validationConfig->active) {
return;
}
MainValidator::createConstraintsAndAddToContext(
$context->getContext(),
FiscalCodeValidator::getCorrectCustomerType((string)$address->getAlpha('accountType')),
(string)$address->getAlnum('countryId'),
$validationConfig
);
}
/**
* Check that the edited address is the billing address
* If address id not found mean that address is created and not edited
*
* @param DataBag $address
* @param string $defaultBillingAddressId
*
* @return bool
*/
private function isEditedAddressIsBilling(DataBag $address, string $defaultBillingAddressId): bool
{
return ($addressId = $address->get('id')) && $addressId === $defaultBillingAddressId;
}
}