Skip to content

Commit 94c3c12

Browse files
Fix supported locales resolving
1 parent 9062908 commit 94c3c12

File tree

8 files changed

+335
-7
lines changed

8 files changed

+335
-7
lines changed

spec/Processor/LocaleProcessorSpec.php

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,22 @@
1414
namespace spec\Sylius\PayPalPlugin\Processor;
1515

1616
use PhpSpec\ObjectBehavior;
17+
use Sylius\PayPalPlugin\Resolver\SupportedLocaleResolverInterface;
1718

1819
final class LocaleProcessorSpec extends ObjectBehavior
1920
{
21+
function let(SupportedLocaleResolverInterface $supportedLocaleResolver): void
22+
{
23+
$supportedLocaleResolver->resolve('et')->willReturn('et_EE');
24+
$supportedLocaleResolver->resolve('pl')->willReturn('pl_PL');
25+
$supportedLocaleResolver->resolve('ja')->willReturn('ja_JP');
26+
$supportedLocaleResolver->resolve('it_IT')->willReturn('it_IT');
27+
$supportedLocaleResolver->resolve('de_DE')->willReturn('de_DE');
28+
$supportedLocaleResolver->resolve('en')->willReturn('en_US');
29+
30+
$this->beConstructedWith($supportedLocaleResolver);
31+
}
32+
2033
function it_always_processes_locale_to_version_with_region(): void
2134
{
2235
$this->process('et')->shouldReturn('et_EE');
@@ -27,12 +40,34 @@ function it_always_processes_locale_to_version_with_region(): void
2740
function it_returns_same_locale_if_it_is_valid(): void
2841
{
2942
$this->process('it_IT')->shouldReturn('it_IT');
43+
$this->process('de_DE')->shouldReturn('de_DE');
44+
}
45+
46+
function it_returns_correct_locale_for_en_locale(): void
47+
{
48+
$this->process('en')->shouldReturn('en_US');
49+
}
50+
51+
function it_always_processes_locale_to_version_with_region_using_legacy_mode(): void
52+
{
53+
$this->beConstructedWith(null);
54+
$this->process('et')->shouldReturn('et_EE');
55+
$this->process('pl')->shouldReturn('pl_PL');
56+
$this->process('ja')->shouldReturn('ja_JP');
57+
}
58+
59+
function it_returns_same_locale_if_it_is_valid_using_legacy_mode(): void
60+
{
61+
$this->beConstructedWith(null);
62+
$this->process('it_IT')->shouldReturn('it_IT');
63+
$this->process('de_DE')->shouldReturn('de_DE');
3064
$this->process('ja_JP_TRADITIONAL')->shouldReturn('ja_JP_TRADITIONAL');
3165
$this->process('sd_Arab_PK')->shouldReturn('sd_Arab_PK');
3266
}
3367

34-
function it_returns_correct_locale_for_en_locale(): void
68+
function it_returns_correct_locale_for_en_locale_using_legacy_mode(): void
3569
{
70+
$this->beConstructedWith(null);
3671
$this->process('en')->shouldReturn('en_US');
3772
}
3873
}

src/DependencyInjection/Configuration.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@
1818

1919
final class Configuration implements ConfigurationInterface
2020
{
21+
private const ALL_PAYPAL_SUPPORTED_LOCALES = [
22+
'ar_EG', 'cs_CZ', 'da_DK', 'de_DE', 'el_GR', 'en_US', 'en_AU', 'en_GB',
23+
'en_IN', 'es_ES', 'es_XC', 'fi_FI', 'fr_FR', 'fr_CA', 'fr_XC', 'he_IL',
24+
'hu_HU', 'id_ID', 'it_IT', 'ja_JP', 'ko_KR', 'nl_NL', 'no_NO', 'pl_PL',
25+
'pt_BR', 'pt_PT', 'ru_RU', 'sk_SK', 'sv_SE', 'th_TH', 'zh_CN', 'zh_HK',
26+
'zh_TW', 'zh_XC',
27+
];
28+
2129
public function getConfigTreeBuilder(): TreeBuilder
2230
{
2331
$treeBuilder = new TreeBuilder('sylius_pay_pal_plugin');
@@ -34,6 +42,11 @@ public function getConfigTreeBuilder(): TreeBuilder
3442
->end()
3543
->end()
3644
->end()
45+
->arrayNode('supported_locales')
46+
->scalarPrototype()->end()
47+
->defaultValue(self::ALL_PAYPAL_SUPPORTED_LOCALES)
48+
->performNoDeepMerging()
49+
->end()
3750
->end()
3851
;
3952

src/DependencyInjection/SyliusPayPalExtension.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public function load(array $configs, ContainerBuilder $container): void
3434

3535
$this->setCommunicationParameters($container, $config);
3636

37+
$container->setParameter('sylius_paypal.supported_locales', $config['supported_locales']);
38+
3739
$loaderResolver = new LoaderResolver([
3840
new PhpFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')),
3941
new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')),

src/Processor/LocaleProcessor.php

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,46 @@
1313

1414
namespace Sylius\PayPalPlugin\Processor;
1515

16+
use Sylius\PayPalPlugin\Resolver\SupportedLocaleResolverInterface;
1617
use Symfony\Component\Intl\Locales;
1718

1819
final class LocaleProcessor implements LocaleProcessorInterface
1920
{
21+
private const ALLOWED_LOCALE_PATTERN = '/^[a-z]{2}(_[A-Z]{2})?$/';
22+
23+
public function __construct(
24+
private readonly ?SupportedLocaleResolverInterface $supportedLocaleResolver = null,
25+
) {
26+
if (null === $this->supportedLocaleResolver) {
27+
trigger_deprecation(
28+
'sylius/paypal-plugin',
29+
'1.7',
30+
sprintf(
31+
'Not passing an instance of "%s" is deprecated and will be prohibited in 3.0',
32+
SupportedLocaleResolverInterface::class,
33+
),
34+
);
35+
}
36+
}
37+
2038
public function process(string $locale): string
2139
{
22-
if ($this->isValidLocale($locale)) {
40+
if (null !== $this->supportedLocaleResolver) {
41+
$locale = trim($locale);
42+
43+
if ($this->isValidLocale($locale)) {
44+
return $this->supportedLocaleResolver->resolve($locale);
45+
}
46+
47+
throw new \UnexpectedValueException(sprintf('Locale "%s" is not valid.', $locale));
48+
}
49+
50+
return $this->legacyProcess($locale);
51+
}
52+
53+
private function legacyProcess(string $locale): string
54+
{
55+
if (str_contains($locale, '_')) {
2356
return $locale;
2457
}
2558

@@ -29,21 +62,24 @@ public function process(string $locale): string
2962

3063
$locales = array_filter(Locales::getLocales(), function (string $targetLocale) use ($locale): bool {
3164
return
32-
strpos($targetLocale, $locale) === 0 &&
33-
strpos($targetLocale, '_') !== false &&
34-
strlen($targetLocale) === 5
65+
str_starts_with($targetLocale, $locale) &&
66+
strlen($targetLocale) === 5 &&
67+
$this->isValidLocale($targetLocale)
3568
;
3669
});
3770

3871
if ([] === $locales) {
3972
throw new \UnexpectedValueException(sprintf('Locale "%s" is not supported by PayPal.', $locale));
4073
}
4174

42-
return $locales[array_key_first($locales)];
75+
return array_shift($locales);
4376
}
4477

4578
private function isValidLocale(string $locale): bool
4679
{
47-
return strpos($locale, '_') !== false;
80+
return
81+
false === str_contains($locale, ' ') &&
82+
1 === preg_match(self::ALLOWED_LOCALE_PATTERN, $locale)
83+
;
4884
}
4985
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\PayPalPlugin\Resolver;
15+
16+
final class SupportedLocaleResolver implements SupportedLocaleResolverInterface
17+
{
18+
private readonly array $supportedLocales;
19+
20+
public function __construct(
21+
array $supportedLocales = [],
22+
) {
23+
$this->supportedLocales = array_unique($supportedLocales);
24+
}
25+
26+
public function resolve(string $locale): string
27+
{
28+
if (empty(trim($locale))) {
29+
throw new \UnexpectedValueException('Locale cannot be empty.');
30+
}
31+
32+
$length = strlen($locale);
33+
if (5 === $length) {
34+
if (in_array($locale, $this->supportedLocales, true)) {
35+
return $locale;
36+
}
37+
38+
throw new \UnexpectedValueException(
39+
sprintf('Locale "%s" is not supported by PayPal.', $locale),
40+
);
41+
}
42+
if (2 === $length) {
43+
return $this->findSupportedLocaleByLanguageCode($locale);
44+
}
45+
46+
throw new \UnexpectedValueException(
47+
sprintf('Locale "%s" is not supported by PayPal.', $locale),
48+
);
49+
}
50+
51+
private function findSupportedLocaleByLanguageCode(string $languageCode): string
52+
{
53+
foreach ($this->supportedLocales as $locale) {
54+
if (str_starts_with($locale, $languageCode)) {
55+
return $locale;
56+
}
57+
}
58+
59+
throw new \UnexpectedValueException(
60+
sprintf('Language "%s" could not be resolved into a locale supported by PayPal.', $languageCode),
61+
);
62+
}
63+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\PayPalPlugin\Resolver;
15+
16+
interface SupportedLocaleResolverInterface
17+
{
18+
/** @throw \UnexpectedValueException */
19+
public function resolve(string $locale): string;
20+
}

src/Resources/config/services.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,5 +356,13 @@
356356
<argument type="service" id="sylius.repository.payment_method" />
357357
</service>
358358
<service id="Sylius\PayPalPlugin\Resolver\PayPalPaymentMethodsResolverInterface" alias="sylius_paypal.resolver.paypal_payment_methods" />
359+
360+
<service
361+
id="sylius_paypal.resolver.supported_locale"
362+
class="Sylius\PayPalPlugin\Resolver\SupportedLocaleResolver"
363+
>
364+
<argument>%sylius_paypal.supported_locales%</argument>
365+
</service>
366+
<service id="Sylius\PayPalPlugin\Resolver\SupportedLocaleResolverInterface" alias="sylius_paypal.resolver.supported_locale" />
359367
</services>
360368
</container>

0 commit comments

Comments
 (0)