[Addressing] Country name to code converter

This commit is contained in:
Łukasz Chruściel 2016-02-22 13:32:42 +01:00
parent 2faa1a3cfb
commit 476189b532
7 changed files with 142 additions and 28 deletions

View file

@ -46,6 +46,7 @@
<service id="sylius.behat.context.setup.geographical" class="%sylius.behat.context.setup.geographical.class%" scope="scenario">
<argument type="service" id="sylius.factory.country" container="symfony" />
<argument type="service" id="sylius.repository.country" container="symfony" />
<argument type="service" id="sylius.converter.country_name" container="symfony" />
<tag name="sylius.behat.context" />
</service>

View file

@ -12,10 +12,10 @@
namespace Sylius\Behat\Context\Setup;
use Behat\Behat\Context\Context;
use Sylius\Component\Addressing\Converter\CountryNameConverterInterface;
use Sylius\Component\Addressing\Model\CountryInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Symfony\Component\Intl\Intl;
/**
* @author Kamil Kokot <kamil.kokot@lakion.com>
@ -32,16 +32,24 @@ final class GeographicalContext implements Context
*/
private $countryRepository;
/**
* @var CountryNameConverterInterface
*/
private $countryNameConverter;
/**
* @param FactoryInterface $countryFactory
* @param RepositoryInterface $countryRepository
* @param CountryNameConverterInterface $countryNameConverter
*/
public function __construct(
FactoryInterface $countryFactory,
RepositoryInterface $countryRepository
RepositoryInterface $countryRepository,
CountryNameConverterInterface $countryNameConverter
) {
$this->countryFactory = $countryFactory;
$this->countryRepository = $countryRepository;
$this->countryNameConverter = $countryNameConverter;
}
/**
@ -67,29 +75,8 @@ final class GeographicalContext implements Context
{
/** @var CountryInterface $country */
$country = $this->countryFactory->createNew();
$country->setCode($this->getCountryCodeByEnglishCountryName($name));
$country->setCode($this->countryNameConverter->convertToCode($name));
$this->countryRepository->add($country);
}
/**
* @param string $name
*
* @return string
*
* @throws \InvalidArgumentException If name is not found in country code registry.
*/
private function getCountryCodeByEnglishCountryName($name)
{
$names = Intl::getRegionBundle()->getCountryNames('en');
$countryCode = array_search($name, $names, true);
if (null === $countryCode) {
throw new \InvalidArgumentException(sprintf(
'Country "%s" not found! Available names: %s.', $name, implode(', ', $names)
));
}
return $countryCode;
}
}

View file

@ -13,6 +13,7 @@ namespace spec\Sylius\Behat\Context\Setup;
use Behat\Behat\Context\Context;
use PhpSpec\ObjectBehavior;
use Sylius\Component\Addressing\Converter\CountryNameConverterInterface;
use Sylius\Component\Addressing\Model\CountryInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
@ -22,9 +23,12 @@ use Sylius\Component\Resource\Repository\RepositoryInterface;
*/
class GeographicalContextSpec extends ObjectBehavior
{
function let(FactoryInterface $countryFactory, RepositoryInterface $countryRepository)
{
$this->beConstructedWith($countryFactory, $countryRepository);
function let(
FactoryInterface $countryFactory,
RepositoryInterface $countryRepository,
CountryNameConverterInterface $nameToCodeConverter
) {
$this->beConstructedWith($countryFactory, $countryRepository, $nameToCodeConverter);
}
function it_is_initializable()
@ -42,7 +46,8 @@ class GeographicalContextSpec extends ObjectBehavior
RepositoryInterface $countryRepository,
CountryInterface $australia,
CountryInterface $china,
CountryInterface $france
CountryInterface $france,
CountryNameConverterInterface $nameToCodeConverter
) {
$countryFactory->createNew()->willReturn($australia, $china, $france);
@ -54,6 +59,10 @@ class GeographicalContextSpec extends ObjectBehavior
$countryRepository->add($china)->shouldBeCalled();
$countryRepository->add($france)->shouldBeCalled();
$nameToCodeConverter->convertToCode('Australia')->willReturn('AU');
$nameToCodeConverter->convertToCode('China')->willReturn('CN');
$nameToCodeConverter->convertToCode('France')->willReturn('FR');
$this->storeShipsTo('Australia', 'China', 'France');
}
}

View file

@ -26,6 +26,7 @@
<parameter key="sylius.province_naming_provider.class">Sylius\Component\Addressing\Provider\ProvinceNamingProvider</parameter>
<parameter key="sylius.zone_matcher.class">Sylius\Component\Addressing\Matcher\ZoneMatcher</parameter>
<parameter key="sylius.converter.country_name.class">Sylius\Component\Addressing\Converter\CountryNameConverter</parameter>
<parameter key="sylius.validator.shippable_address.class">Sylius\Bundle\AddressingBundle\Validator\Constraints\ShippableAddressConstraintValidator</parameter>
<parameter key="sylius.validator.valid_province_address.class">Sylius\Bundle\AddressingBundle\Validator\Constraints\ProvinceAddressConstraintValidator</parameter>
@ -59,6 +60,7 @@
<service id="sylius.zone_matcher" class="%sylius.zone_matcher.class%">
<argument type="service" id="sylius.repository.zone" />
</service>
<service id="sylius.converter.country_name" class="%sylius.converter.country_name.class%" />
<service id="sylius.validator.shippable_address" class="%sylius.validator.shippable_address.class%">
<tag name="validator.constraint_validator" alias="sylius_shippable_address_validator" />

View file

@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Component\Addressing\Converter;
use Symfony\Component\Intl\Intl;
/**
* @author Łukasz Chruściel <lukasz.chrusciel@lakion.com>
*/
final class CountryNameConverter implements CountryNameConverterInterface
{
/**
* {@inheritdoc}
*/
public function convertToCode($name, $locale = 'en')
{
$names = Intl::getRegionBundle()->getCountryNames($locale);
$countryCode = array_search($name, $names, true);
if (false === $countryCode) {
throw new \InvalidArgumentException(sprintf(
'Country "%s" not found! Available names: %s.', $name, implode(', ', $names)
));
}
return $countryCode;
}
}

View file

@ -0,0 +1,28 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Component\Addressing\Converter;
/**
* @author Łukasz Chruściel <lukasz.chrusciel@lakion.com>
*/
interface CountryNameConverterInterface
{
/**
* @param string $name
* @param string $locale
*
* @return string
*
* @throws \InvalidArgumentException If name is not found in country code registry.
*/
public function convertToCode($name, $locale = 'en');
}

View file

@ -0,0 +1,50 @@
<?php
/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace spec\Sylius\Component\Addressing\Converter;
use PhpSpec\ObjectBehavior;
use Sylius\Component\Addressing\Converter\CountryNameConverterInterface;
/**
* @author Łukasz Chruściel <lukasz.chrusciel@lakion.com>
*/
class CountryNameConverterSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('Sylius\Component\Addressing\Converter\CountryNameConverter');
}
function it_implements_country_name_to_code_converter_interface()
{
$this->shouldImplement(CountryNameConverterInterface::class);
}
function it_converts_english_country_name_to_codes_by_default()
{
$this->convertToCode('Australia')->shouldReturn('AU');
$this->convertToCode('China')->shouldReturn('CN');
$this->convertToCode('France')->shouldReturn('FR');
}
function it_converts_country_name_to_codes_for_given_locale()
{
$this->convertToCode('Niemcy', 'pl')->shouldReturn('DE');
$this->convertToCode('Chine', 'fr')->shouldReturn('CN');
$this->convertToCode('Francia', 'es')->shouldReturn('FR');
}
function it_throws_an_exception_if_cauntry_name_cannot_be_converted_to_code()
{
$this->shouldThrow(\InvalidArgumentException::class)->during('convertToCode', ['Atlantis']);
}
}