<?php declare(strict_types=1);
namespace Acris\ShopSwitch\Components;
use Acris\ShopSwitch\Components\Struct\PossibleCountryCollection;
use Acris\ShopSwitch\Components\Struct\PossibleCountryStruct;
use Acris\ShopSwitch\Components\Struct\PossibleLanguageCollection;
use Acris\ShopSwitch\Components\Struct\PossibleLanguageStruct;
use Acris\ShopSwitch\Custom\ShopSwitchRuleDefinition;
use Acris\ShopSwitch\Custom\ShopSwitchRuleDomainEntity;
use Acris\ShopSwitch\Custom\ShopSwitchRuleEntity;
use Shopware\Core\Framework\Context;
use Shopware\Core\System\Locale\LocaleEntity;
use Shopware\Core\System\SalesChannel\Aggregate\SalesChannelDomain\SalesChannelDomainEntity;
use Symfony\Component\HttpFoundation\Request;
class ShopSwitchRuleService
{
/**
* @var ShopSwitchRedirectUrlService
*/
private $redirectUrlService;
/**
* @var SalesChannelCountryLanguageService
*/
private $salesChannelCountryLanguageService;
public function __construct(
ShopSwitchRedirectUrlService $redirectUrlService,
SalesChannelCountryLanguageService $salesChannelCountryLanguageService
)
{
$this->redirectUrlService = $redirectUrlService;
$this->salesChannelCountryLanguageService = $salesChannelCountryLanguageService;
}
public function getPossibleCountriesOfRule(ShopSwitchRuleEntity $ruleEntity, string $activeDomainUrl, Context $context, Request $request): PossibleCountryCollection
{
$possibleCountryCollection = new PossibleCountryCollection();
if($ruleEntity->getRuleDefinitionType() !== ShopSwitchRuleDefinition::RULE_DEFINITION_TYPE_COUNTRY_LANGUAGE && $ruleEntity->getRuleDefinitionType() !== ShopSwitchRuleDefinition::RULE_DEFINITION_TYPE_COUNTRY) {
return $possibleCountryCollection;
}
$salesChannelIds = $this->getSalesChannelIdsFromRuleEntity($ruleEntity);
$this->sortRuleEntityDomains($ruleEntity);
foreach ($ruleEntity->getDomains()->getElements() as $domainEntity) {
if($domainEntity->isActive() === false) {
continue;
}
$domainUrl = (!empty($domainEntity->getRedirectTo()) && $domainEntity->getRedirectTo() === 'external') ? $domainEntity->getExternalUrl() : $this->redirectUrlService->getUrlByRequestAndDomainUrl($domainEntity->getDomain(), $activeDomainUrl, $ruleEntity, $request);
if(empty($domainUrl) === false) $domainEntity->setFoundUrl($domainUrl);
$prioritizeDomainUrl = $domainEntity->getDomain() instanceof SalesChannelDomainEntity && $context->getLanguageId() === $domainEntity->getDomain()->getLanguageId();
// Do blacklist first, because whitelist should override
if($domainEntity->getCountryBlacklist() && $domainEntity->getCountryBlacklist()->count() !== 0) {
foreach ($this->salesChannelCountryLanguageService->getCountriesFromSalesChannelIds($salesChannelIds, $context)->getElements() as $countryEntityFromSalesChannel) {
foreach ($domainEntity->getCountryBlacklist()->getElements() as $countryEntity) {
if($countryEntityFromSalesChannel->getId() === $countryEntity->getId()) {
continue 2;
}
}
if($possibleCountryCollection->has($countryEntityFromSalesChannel->getId()) === true) {
$domainUrls = $this->mergeDomainUrls($domainUrl, $possibleCountryCollection->get($countryEntityFromSalesChannel->getId())->getDomainUrls(), $prioritizeDomainUrl);
} else {
$domainUrls = [$domainUrl];
}
$possibleCountryCollection->set($countryEntityFromSalesChannel->getId(), new PossibleCountryStruct(
$countryEntityFromSalesChannel->getTranslation('name'),
$countryEntityFromSalesChannel->getIso(),
$domainUrl,
$domainUrls,
$countryEntityFromSalesChannel->getId(),
$countryEntityFromSalesChannel->getPosition(),
$domainEntity
));
}
}
if($domainEntity->getCountryWhitelist()) {
foreach ($domainEntity->getCountryWhitelist()->getElements() as $countryEntity) {
if($possibleCountryCollection->has($countryEntity->getId()) === true) {
$domainUrls = $this->mergeDomainUrls($domainUrl, $possibleCountryCollection->get($countryEntity->getId())->getDomainUrls(), $prioritizeDomainUrl);
} else {
$domainUrls = [$domainUrl];
}
$possibleCountryCollection->set($countryEntity->getId(), new PossibleCountryStruct(
$countryEntity->getTranslation('name'),
$countryEntity->getIso(),
$domainUrl,
$domainUrls,
$countryEntity->getId(),
$countryEntity->getPosition(),
$domainEntity
));
}
}
}
return $this->sortCountriesByNameAndPosition($possibleCountryCollection);
}
public function getPossibleCountriesOfSalesChannel(ShopSwitchRuleEntity $ruleEntity, Context $context): PossibleCountryCollection
{
$possibleCountryCollection = new PossibleCountryCollection();
foreach ($ruleEntity->getDomains()->getElements() as $domainEntity) {
if($domainEntity->isActive() === false) {
continue;
}
foreach ($this->salesChannelCountryLanguageService->getCountriesFromSalesChannel($domainEntity->getDomain()->getSalesChannelId(), $context)->getElements() as $countryEntityFromSalesChannel) {
$possibleCountryCollection->set($countryEntityFromSalesChannel->getId(), new PossibleCountryStruct(
$countryEntityFromSalesChannel->getTranslated()['name'],
$countryEntityFromSalesChannel->getIso(),
'',
[],
$countryEntityFromSalesChannel->getId(),
$countryEntityFromSalesChannel->getPosition(),
$domainEntity
));
}
}
return $this->sortCountriesByNameAndPosition($possibleCountryCollection);
}
public function getPossibleLanguagesOfRule(ShopSwitchRuleEntity $ruleEntity, string $activeDomainUrl, Context $context, Request $request): PossibleLanguageCollection
{
$possibleLanguageCollection = new PossibleLanguageCollection();
if($ruleEntity->getRuleDefinitionType() !== ShopSwitchRuleDefinition::RULE_DEFINITION_TYPE_COUNTRY_LANGUAGE && $ruleEntity->getRuleDefinitionType() !== ShopSwitchRuleDefinition::RULE_DEFINITION_TYPE_LANGUAGE) {
return $possibleLanguageCollection;
}
$salesChannelIds = $this->getSalesChannelIdsFromRuleEntity($ruleEntity);
foreach ($ruleEntity->getDomains()->getElements() as $domainEntity) {
if($domainEntity->isActive() === false) {
continue;
}
$domainUrl = (!empty($domainEntity->getRedirectTo()) && $domainEntity->getRedirectTo() === 'external') ? $domainEntity->getExternalUrl() : $this->redirectUrlService->getUrlByRequestAndDomainUrl($domainEntity->getDomain(), $activeDomainUrl, $ruleEntity, $request);
$prioritizeDomainUrl = $domainEntity->getDomain() instanceof SalesChannelDomainEntity && $context->getLanguageId() === $domainEntity->getDomain()->getLanguageId();
// Do blacklist first, because whitelist should override
if($domainEntity->getLanguageBlacklist() && $domainEntity->getLanguageBlacklist()->count() !== 0) {
foreach ($this->salesChannelCountryLanguageService->getLanguagesFromSalesChannelIds($salesChannelIds, $context)->getElements() as $languageEntityFromSalesChannel) {
$localeEntityFromSalesChannel = $languageEntityFromSalesChannel->getLocale();
if(empty($localeEntityFromSalesChannel)) {
continue;
}
foreach ($domainEntity->getLanguageBlacklist()->getElements() as $languageEntity) {
if($languageEntityFromSalesChannel->getId() === $languageEntity->getId()) {
continue 2;
}
}
if($possibleLanguageCollection->has($languageEntityFromSalesChannel->getId()) === true) {
$domainUrls = $this->mergeDomainUrls($domainUrl, $possibleLanguageCollection->get($languageEntityFromSalesChannel->getId())->getDomainUrls(), $prioritizeDomainUrl);
} else {
$domainUrls = [$domainUrl];
}
$possibleLanguageCollection->set($languageEntityFromSalesChannel->getId(), new PossibleLanguageStruct(
$this->getNameOfLanguageAndLocale($localeEntityFromSalesChannel),
$localeEntityFromSalesChannel->getCode(),
$domainUrl,
$domainUrls,
$localeEntityFromSalesChannel->getId(),
$languageEntityFromSalesChannel->getId(),
$domainEntity
));
}
}
if($domainEntity->getLanguageWhitelist()) {
foreach ($domainEntity->getLanguageWhitelist()->getElements() as $languageEntity) {
$localeEntity = $languageEntity->getLocale();
if(empty($localeEntity)) {
continue;
}
if($possibleLanguageCollection->has($languageEntity->getId()) === true) {
$domainUrls = $this->mergeDomainUrls($domainUrl, $possibleLanguageCollection->get($languageEntity->getId())->getDomainUrls(), $prioritizeDomainUrl);
} else {
$domainUrls = [$domainUrl];
}
$possibleLanguageCollection->set($languageEntity->getId(), new PossibleLanguageStruct(
$this->getNameOfLanguageAndLocale($localeEntity),
$localeEntity->getCode(),
$domainUrl,
$domainUrls,
$localeEntity->getId(),
$languageEntity->getId(),
$domainEntity
));
}
}
}
return $this->sortLanguagesByName($possibleLanguageCollection);
}
public function getActiveRuleDomain(string $activeDomainId, ShopSwitchRuleEntity $activeRule): ?ShopSwitchRuleDomainEntity
{
foreach ($activeRule->getDomains()->getElements() as $ruleDomainEntity) {
if((!empty($ruleDomainEntity->getDomain()) && $ruleDomainEntity->getDomain()->getId() === $activeDomainId) || $ruleDomainEntity->getRedirectTo() === 'external') {
return $ruleDomainEntity;
}
}
return null;
}
private function mergeDomainUrls($domainId, $domainUrls = [], $insertBefore = false): array
{
if(in_array($domainId, $domainUrls) === false) {
if($insertBefore === true) {
array_unshift($domainUrls, $domainId);
} else {
array_push($domainUrls, $domainId);
}
}
return $domainUrls;
}
private function sortCountriesByNameAndPosition(PossibleCountryCollection $possibleCountryCollection): PossibleCountryCollection
{
$possibleCountryCollection->sort(function (PossibleCountryStruct $a, PossibleCountryStruct $b) {
if($a->getPosition() !== $b->getPosition()) {
return $a->getPosition() > $b->getPosition();
}
return $a->getName() > $b->getName();
});
return $possibleCountryCollection;
}
private function sortLanguagesByName(PossibleLanguageCollection $possibleLanguageCollection): PossibleLanguageCollection
{
$possibleLanguageCollection->sort(function (PossibleLanguageStruct $a, PossibleLanguageStruct $b) {
return $a->getName() > $b->getName();
});
return $possibleLanguageCollection;
}
private function getNameOfLanguageAndLocale(LocaleEntity $localeEntityFromSalesChannel): string
{
if(!empty($localeEntityFromSalesChannel->getTranslation('name'))) {
return $localeEntityFromSalesChannel->getTranslation('name');
}
return $localeEntityFromSalesChannel->getName();
}
private function getSalesChannelIdsFromRuleEntity(ShopSwitchRuleEntity $ruleEntity): array
{
$salesChannelIds = [];
foreach ($ruleEntity->getDomains() as $domain) {
if($domain->getDomain() instanceof SalesChannelDomainEntity) {
$salesChannelIds[] = $domain->getDomain()->getSalesChannelId();
}
}
return $salesChannelIds;
}
private function sortRuleEntityDomains(ShopSwitchRuleEntity $ruleEntity): void
{
if(empty($ruleEntity->getDomains())) return;
$ruleEntity->getDomains()->sort(function (ShopSwitchRuleDomainEntity $a, ShopSwitchRuleDomainEntity $b) {
$aHasCountryBlacklist = !empty($a->getCountryBlacklist()) && $a->getCountryBlacklist()->count() > 0;
$aHasLanguageBlacklist = !empty($a->getLanguageBlacklist()) && $a->getLanguageBlacklist()->count() > 0;
$bHasCountryBlacklist = !empty($b->getCountryBlacklist()) && $b->getCountryBlacklist()->count() > 0;
$bHasLanguageBlacklist = !empty($b->getLanguageBlacklist()) && $b->getLanguageBlacklist()->count() > 0;
// first check if both exists
if($aHasCountryBlacklist && $aHasLanguageBlacklist) return -1;
if($bHasCountryBlacklist && $bHasLanguageBlacklist) return 1;
if($aHasCountryBlacklist || $aHasLanguageBlacklist) return -1;
if($bHasCountryBlacklist || $bHasLanguageBlacklist) return 1;
return 0;
});
}
}