Skip to content

Commit

Permalink
Merge pull request #1261 from dpfaffenbauer/issue/1260
Browse files Browse the repository at this point in the history
[Country] don't call the request based resolvers every time
  • Loading branch information
dpfaffenbauer authored Feb 7, 2020
2 parents 4f0c55e + 4933f64 commit b30c9a3
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,17 @@ services:
public: false
arguments:
- '@coreshop.repository.country'
- '@pimcore.cache.core.handler'
tags:
- { name: coreshop.context.country.request_based.resolver, priority: 10 }

coreshop.context.country.cached: '@CoreShop\Component\Address\Context\RequestBased\CachedCountryContext'
CoreShop\Component\Address\Context\RequestBased\CachedCountryContext:
decorates: coreshop.context.country.request_based.resolver.composite
decoration_priority: 255
arguments:
- '@CoreShop\Component\Address\Context\RequestBased\CachedCountryContext.inner'

coreshop.address.formatter: '@CoreShop\Component\Address\Formatter\AddressFormatter'
CoreShop\Component\Address\Formatter\AddressFormatterInterface: '@CoreShop\Component\Address\Formatter\AddressFormatter'
CoreShop\Component\Address\Formatter\AddressFormatter:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/**
* CoreShop.
*
* This source file is subject to the GNU General Public License version 3 (GPLv3)
* For the full copyright and license information, please view the LICENSE.md and gpl-3.0.txt
* files that are distributed with this source code.
*
* @copyright Copyright (c) 2015-2020 Dominik Pfaffenbauer (https://www.pfaffenbauer.at)
* @license https://www.coreshop.org/license GNU General Public License version 3 (GPLv3)
*/

namespace CoreShop\Component\Address\Context\RequestBased;

use CoreShop\Component\Address\Context\RequestBased\RequestResolverInterface;
use CoreShop\Component\Address\Model\CountryInterface;
use Symfony\Component\HttpFoundation\Request;

final class CachedCountryContext implements RequestResolverInterface
{
/**
* @var RequestResolverInterface
*/
private $inner;

/**
* @var CountryInterface
*/
private $country;

/**
* @param RequestResolverInterface $inner
*/
public function __construct(RequestResolverInterface $inner)
{
$this->inner = $inner;
}

/**
* {@inheritdoc}
*/
public function findCountry(Request $request)
{
if (null === $this->country) {
$this->country = $this->inner->findCountry($request);
}

return $this->country;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use CoreShop\Component\Address\Model\CountryInterface;
use CoreShop\Component\Address\Repository\CountryRepositoryInterface;
use GeoIp2\Database\Reader;
use Pimcore\Cache\Core\CoreHandlerInterface;
use Symfony\Component\HttpFoundation\Request;

final class GeoLiteBasedRequestResolver implements RequestResolverInterface
Expand All @@ -25,43 +26,87 @@ final class GeoLiteBasedRequestResolver implements RequestResolverInterface
*/
private $countryRepository;

/**
* @var CoreHandlerInterface
*/
private $cache;

/**
* @var string
*/
private $geoDbFile;

/**
* @param CountryRepositoryInterface $countryRepository
* @param CoreHandlerInterface $cache
*/
public function __construct(CountryRepositoryInterface $countryRepository)
public function __construct(CountryRepositoryInterface $countryRepository, CoreHandlerInterface $cache)
{
$this->countryRepository = $countryRepository;
$this->cache = $cache;
$this->geoDbFile = PIMCORE_CONFIGURATION_DIRECTORY . '/GeoLite2-City.mmdb';
}

/**
* {@inheritdoc}
*/
public function findCountry(Request $request)
{
$geoDbFile = PIMCORE_CONFIGURATION_DIRECTORY . '/GeoLite2-City.mmdb';
$record = null;
if (!file_exists($this->geoDbFile)) {
throw new CountryNotFoundException();
}

if (file_exists($geoDbFile)) {
try {
$reader = new Reader($geoDbFile);
$record = null;
$isoCode = null;
$clientIp = $request->getClientIp();

$clientIp = $request->getClientIp();
if ($this->checkIfIpIsPrivate($clientIp)) {
throw new CountryNotFoundException();
}

if (!$this->checkIfIpIsPrivate($clientIp)) {
$record = $reader->city($clientIp);
$cacheKey = sprintf('geo_lite_ip_%s', md5($clientIp));

$country = $this->countryRepository->findByCode($record->country->isoCode);
if ($countryIsoCode = $this->cache->getItem($cacheKey)) {
$country = $this->countryRepository->findByCode($countryIsoCode);

if ($country instanceof CountryInterface) {
return $country;
}
}
} catch (\Exception $e) {
//If something goes wrong, ignore the exception and throw a CountryNotFoundException
if ($country instanceof CountryInterface) {
return $country;
}
}

throw new CountryNotFoundException();
$countryIsoCode = $this->guessCountryByGeoLite($clientIp);

if ($countryIsoCode === null) {
throw new CountryNotFoundException();
}

$country = $this->countryRepository->findByCode($countryIsoCode);

if (!$country instanceof CountryInterface) {
throw new CountryNotFoundException();
}

$this->cache->save($cacheKey, $countryIsoCode, [], 24*60*60);

return $country;
}

/**
* @param string $clientIp
*
* @return string|null
*/
private function guessCountryByGeoLite($clientIp)
{
try {
$reader = new Reader($this->geoDbFile);
$record = $reader->city($clientIp);
return $record->country->isoCode;
} catch (\Exception $e) {
//If something goes wrong, ignore the exception and throw a CountryNotFoundException
}

return null;
}

/**
Expand All @@ -73,7 +118,7 @@ public function findCountry(Request $request)
*/
private function checkIfIpIsPrivate($clientIp)
{
$priAddrs = [
$privateAddresses = [
'10.0.0.0|10.255.255.255', // single class A network
'172.16.0.0|172.31.255.255', // 16 contiguous class B network
'192.168.0.0|192.168.255.255', // 256 contiguous class C network
Expand All @@ -82,8 +127,8 @@ private function checkIfIpIsPrivate($clientIp)
];

$longIp = ip2long($clientIp);
if ($longIp != -1) {
foreach ($priAddrs as $priAddr) {
if ($longIp !== -1) {
foreach ($privateAddresses as $priAddr) {
list($start, $end) = explode('|', $priAddr);

// IF IS PRIVATE
Expand Down

0 comments on commit b30c9a3

Please sign in to comment.