Skip to content

Commit

Permalink
Add geoip resolvers & prevent fatal error
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-kl1 committed Oct 1, 2021
1 parent e875be9 commit 8fd2483
Show file tree
Hide file tree
Showing 13 changed files with 383 additions and 21 deletions.
5 changes: 4 additions & 1 deletion Model/CountryRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Opengento\CountryStore\Api\CountryRepositoryInterface;
use Opengento\CountryStore\Api\Data\CountryInterface;
use Opengento\CountryStore\Api\Data\CountryInterfaceFactory;
use function strtoupper;

final class CountryRepository implements CountryRepositoryInterface
{
Expand All @@ -34,7 +35,9 @@ public function __construct(

public function get(string $countryCode): CountryInterface
{
return $this->countries[$countryCode] ?? $this->countries[$countryCode] = $this->readExtensions->execute(
$countryCode = strtoupper($countryCode);

return $this->countries[$countryCode] ??= $this->readExtensions->execute(
$this->countryFactory->create(['data' => ['code' => $countryCode]]),
['code' => $countryCode]
);
Expand Down
6 changes: 3 additions & 3 deletions Model/Mapper/CountryStoreMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public function getStoresByCountry(CountryInterface $country, ?WebsiteInterface
private function loadMapper(): void
{
$this->countriesByStore = [];
$storesByCountry = [[]];
$storesByCountry = [];

foreach ($this->resolveCountryStoreMapper() as $countryStoreMapper) {
if (isset($countryStoreMapper['countries'], $countryStoreMapper['store'])) {
Expand All @@ -96,12 +96,12 @@ private function loadMapper(): void
}
}

$this->storesByCountry = array_merge_recursive(...$storesByCountry);
$this->storesByCountry = array_merge_recursive([], ...$storesByCountry);
}

private function resolveCountryStoreMapper(): array
{
return $this->countryStoreMapper ?? $this->countryStoreMapper = $this->serializer->unserialize(
return $this->countryStoreMapper ??= $this->serializer->unserialize(
$this->scopeConfig->getValue(self::CONFIG_PATH_COUNTRY_STORE_MAP) ?? '{}'
);
}
Expand Down
46 changes: 46 additions & 0 deletions Model/Resolver/CloudFare.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
/**
* Copyright © OpenGento, All rights reserved.
* See LICENSE bundled with this library for license details.
*/
declare(strict_types=1);

namespace Opengento\CountryStore\Model\Resolver;

use Magento\Framework\HTTP\PhpEnvironment\Request;
use Opengento\CountryStore\Api\CountryRepositoryInterface;
use Opengento\CountryStore\Api\CountryResolverInterface;
use Opengento\CountryStore\Api\Data\CountryInterface;
use Opengento\CountryStore\Model\CountryResolver;

final class CloudFare implements CountryResolverInterface
{
public const RESOLVER_CODE = 'cloudFare';

public const CF_HTTP_HEADER_IPCOUNTRY = 'HTTP_CF_IPCOUNTRY';

private Request $request;

private ResolverFactory $resolverFactory;

private CountryRepositoryInterface $countryRepository;

public function __construct(
Request $request,
ResolverFactory $resolverFactory,
CountryRepositoryInterface $countryRepository
) {
$this->request = $request;
$this->resolverFactory = $resolverFactory;
$this->countryRepository = $countryRepository;
}

public function getCountry(): CountryInterface
{
$countryCode = (string) $this->request->getServerValue(self::CF_HTTP_HEADER_IPCOUNTRY);

return $countryCode
? $this->countryRepository->get($countryCode)
: $this->resolverFactory->get(CountryResolver::DEFAULT_COUNTRY_RESOLVER_CODE)->getCountry();
}
}
54 changes: 54 additions & 0 deletions Model/Resolver/HttpHeaderValue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
/**
* Copyright © OpenGento, All rights reserved.
* See LICENSE bundled with this library for license details.
*/
declare(strict_types=1);

namespace Opengento\CountryStore\Model\Resolver;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\HTTP\PhpEnvironment\Request;
use Magento\Store\Model\ScopeInterface;
use Opengento\CountryStore\Api\CountryRepositoryInterface;
use Opengento\CountryStore\Api\CountryResolverInterface;
use Opengento\CountryStore\Api\Data\CountryInterface;
use Opengento\CountryStore\Model\CountryResolver;

final class HttpHeaderValue implements CountryResolverInterface
{
private const CONFIG_PATH_COUNTRY_HTTP_HEADER_NAME = 'country/resolver/http_header_name';

public const RESOLVER_CODE = 'httpHeaderValue';

private Request $request;

private ScopeConfigInterface $scopeConfig;

private ResolverFactory $resolverFactory;

private CountryRepositoryInterface $countryRepository;

public function __construct(
Request $request,
ScopeConfigInterface $scopeConfig,
ResolverFactory $resolverFactory,
CountryRepositoryInterface $countryRepository
) {
$this->request = $request;
$this->scopeConfig = $scopeConfig;
$this->resolverFactory = $resolverFactory;
$this->countryRepository = $countryRepository;
}

public function getCountry(): CountryInterface
{
$countryCode = (string) $this->request->getServerValue(
$this->scopeConfig->getValue(self::CONFIG_PATH_COUNTRY_HTTP_HEADER_NAME, ScopeInterface::SCOPE_WEBSITE)
);

return $countryCode
? $this->countryRepository->get($countryCode)
: $this->resolverFactory->get(CountryResolver::DEFAULT_COUNTRY_RESOLVER_CODE)->getCountry();
}
}
18 changes: 13 additions & 5 deletions Model/ResourceModel/Country/Relation/ReadHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Phrase;
use Opengento\CountryStore\Api\Data\CountryInterface;
use Psr\Log\LoggerInterface;
use function is_array;

final class ReadHandler implements ExtensionInterface
Expand All @@ -24,14 +25,18 @@ final class ReadHandler implements ExtensionInterface

private CollectionFactory $collectionFactory;

private LoggerInterface $logger;

private ?Collection $collection;

public function __construct(
HydratorPool $hydratorPool,
CollectionFactory $collectionFactory
CollectionFactory $collectionFactory,
LoggerInterface $logger
) {
$this->hydratorPool = $hydratorPool;
$this->collectionFactory = $collectionFactory;
$this->logger = $logger;
$this->collection = null;
}

Expand All @@ -40,7 +45,6 @@ public function __construct(
* @param CountryInterface $entity
* @param array|null $arguments
* @return CountryInterface
* @throws NoSuchEntityException
*/
public function execute($entity, $arguments = null): CountryInterface
{
Expand All @@ -52,7 +56,13 @@ public function execute($entity, $arguments = null): CountryInterface
if (!is_array($arguments) && !isset($arguments['code'])) {
throw new InvalidArgumentException('Argument name "arguments" does not have "code" key-value pair.');
}
$country = $this->fetchCountry((string) $arguments['code']);
try {
$country = $this->fetchCountry((string)$arguments['code']);
} catch (NoSuchEntityException $e) {
$this->logger->error($e->getLogMessage(), $e->getTrace());

return $entity;
}

return $this->hydratorPool->getHydrator(CountryInterface::class)->hydrate($entity, [
'code' => $country->getCountryId(),
Expand All @@ -62,8 +72,6 @@ public function execute($entity, $arguments = null): CountryInterface
}

/**
* @param string $countryCode
* @return Country
* @throws NoSuchEntityException
*/
private function fetchCountry(string $countryCode): Country
Expand Down
9 changes: 4 additions & 5 deletions Model/Store/RelatedWebsites.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,12 @@ public function __construct(

public function getListIds(WebsiteInterface $website): array
{
return $this->websites[(int) $website->getId()]
?? $this->websites[(int) $website->getId()] = $this->resolveWebsites($website);
return $this->websites[(int) $website->getId()] ??= $this->resolveWebsites($website);
}

private function resolveWebsites(WebsiteInterface $website): array
{
$websites = [[(int) $website->getId()]];
$websites = [];

foreach ($this->resolveWebsiteGroups() as $group) {
$websitesIds = array_map('\intval', $group['websites'] ?? []);
Expand All @@ -52,12 +51,12 @@ private function resolveWebsites(WebsiteInterface $website): array
}
}

return array_values(array_unique(array_merge(...$websites)));
return array_values(array_unique(array_merge([(int) $website->getId()], ...$websites)));
}

private function resolveWebsiteGroups(): array
{
return $this->websiteGroups ?? $this->websiteGroups = $this->serializer->unserialize(
return $this->websiteGroups ??= $this->serializer->unserialize(
$this->scopeConfig->getValue(self::CONFIG_PATH_COUNTRY_WEBSITE_MAP) ?? '{}'
);
}
Expand Down
37 changes: 34 additions & 3 deletions Test/Unit/CustomerData/CountryStoreDataTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@
namespace Opengento\CountryStore\Test\Unit\CustomerData;

use Magento\Framework\Api\ExtensibleDataObjectConverter;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\Reflection\DataObjectProcessor;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\StoreManagerInterface;
use Opengento\CountryStore\Api\CountryRegistryInterface;
use Opengento\CountryStore\Api\CountryResolverInterface;
use Opengento\CountryStore\Api\CountryStoreResolverInterface;
use Opengento\CountryStore\Api\Data\CountryExtensionInterface;
use Opengento\CountryStore\Api\Data\CountryInterface;
use Opengento\CountryStore\CustomerData\CountryStoreData;
use Opengento\CountryStore\Model\Resolver\DefaultCountryStore;
use Opengento\CountryStore\Model\Resolver\ResolverFactory;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
Expand All @@ -25,11 +29,22 @@
*/
class CountryStoreDataTest extends TestCase
{
private const DEFAULT_RESOLVER_CLASS = 'Vendor\\Module\\Resolver\\Default';

/**
* @var MockObject|CountryRegistryInterface
*/
private $countryRegistry;

/**
* @var ObjectManagerInterface|mixed|MockObject
*/
private $objectManager;

private ResolverFactory $countryResolverFactory;

private CountryResolverInterface $countryResolver;

/**
* @var MockObject|CountryStoreResolverInterface
*/
Expand All @@ -52,13 +67,20 @@ class CountryStoreDataTest extends TestCase
protected function setUp(): void
{
$this->countryRegistry = $this->getMockForAbstractClass(CountryRegistryInterface::class);
$this->objectManager = $this->getMockForAbstractClass(ObjectManagerInterface::class);
$this->countryResolverFactory = new ResolverFactory(
$this->objectManager,
[DefaultCountryStore::RESOLVER_CODE => self::DEFAULT_RESOLVER_CLASS]
);
$this->countryResolver = $this->getMockForAbstractClass(CountryResolverInterface::class);
$this->countryStoreResolver = $this->getMockForAbstractClass(CountryStoreResolverInterface::class);
$this->storeManager = $this->getMockForAbstractClass(StoreManagerInterface::class);
$this->dataObjectProcessor = $this->createMock(DataObjectProcessor::class);
$this->dataObjectConverter = new ExtensibleDataObjectConverter($this->dataObjectProcessor);

$this->countryData = new CountryStoreData(
$this->countryRegistry,
$this->countryResolverFactory,
$this->countryStoreResolver,
$this->storeManager,
$this->dataObjectConverter,
Expand All @@ -79,10 +101,19 @@ public function testGetSectionData(
): void {
$countryInvalidated = $registeredCountry !== $resolvedCountry;

$this->countryRegistry->expects($countryInvalidated ? $this->exactly(2) : $this->once())
$this->objectManager->expects($countryInvalidated ? $this->once() : $this->never())
->method('get')
->with(self::DEFAULT_RESOLVER_CLASS)
->willReturn($this->countryResolver);
$this->countryResolver->expects($countryInvalidated ? $this->once() : $this->never())
->method('getCountry')
->willReturn($resolvedCountry);
$this->countryRegistry->expects($this->once())
->method('get')
->willReturn($registeredCountry, $resolvedCountry);
$this->countryRegistry->expects($countryInvalidated ? $this->once() : $this->never())->method('clear');
->willReturn($registeredCountry);
$this->countryRegistry->expects($countryInvalidated ? $this->once() : $this->never())
->method('set')
->with($resolvedCountry->getCode());

$this->countryStoreResolver->expects($this->once())
->method('getStoreAware')
Expand Down
Loading

0 comments on commit 8fd2483

Please sign in to comment.