mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 09:02:12 +00:00
Merge pull request #7376 from lchrusciel/api-locale-fix
[API] Fix normalization of locale codes
This commit is contained in:
commit
4ce2bc8091
14 changed files with 214 additions and 53 deletions
|
|
@ -0,0 +1,43 @@
|
|||
<?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\Bundle\ApiBundle\Normalizer;
|
||||
|
||||
use FOS\RestBundle\Normalizer\CamelKeysNormalizer;
|
||||
|
||||
/**
|
||||
* Normalizes the array by changing its keys from underscore to camel case, but does not perform this change if the key is an locale code.
|
||||
*
|
||||
* @author Łukasz Chruściel <lukasz.chrusciel@lakion.com>
|
||||
*/
|
||||
final class LocaleAwareCamelKeysNormalizer extends CamelKeysNormalizer
|
||||
{
|
||||
/**
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function normalizeString($string)
|
||||
{
|
||||
if (false === strpos($string, '_')) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
// Custom logic to skip locale codes (e.g. nl_NL)
|
||||
if (1 === preg_match('/^[a-z]{2}_[A-Z]{2}$/', $string)) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
return preg_replace_callback('/_([a-zA-Z0-9])/', function ($matches) {
|
||||
return strtoupper($matches[1]);
|
||||
}, $string);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,5 +22,6 @@
|
|||
<argument type="service" id="fos_oauth_server.entity_manager" />
|
||||
<argument>%fos_oauth_server.model.client.class%</argument>
|
||||
</service>
|
||||
<service id="sylius.normalizer.camel_keys" class="Sylius\Bundle\ApiBundle\Normalizer\LocaleAwareCamelKeysNormalizer" />
|
||||
</services>
|
||||
</container>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,114 @@
|
|||
<?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\Bundle\ApiBundle\Tests\Normalizer;
|
||||
|
||||
use Sylius\Bundle\ApiBundle\Normalizer\LocaleAwareCamelKeysNormalizer;
|
||||
|
||||
/**
|
||||
* @see \FOS\RestBundle\Tests\Normalizer\CamelKeysNormalizerTest
|
||||
*
|
||||
* @author Łukasz Chruściel <lukasz.chrusciel@lakion.com>
|
||||
*/
|
||||
final class LocaleAwareCamelKeysNormalizerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @expectedException \FOS\RestBundle\Normalizer\Exception\NormalizationException
|
||||
*/
|
||||
public function it_does_not_override_existing_keys()
|
||||
{
|
||||
$normalizer = new LocaleAwareCamelKeysNormalizer();
|
||||
$normalizer->normalize([
|
||||
'foo' => [
|
||||
'foo_bar' => 'foo',
|
||||
'foo_Bar' => 'foo',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @dataProvider normalizeProvider
|
||||
*/
|
||||
public function it_normalizes_snake_cased_keys_to_camel_case(array $array, array $expected)
|
||||
{
|
||||
$normalizer = new LocaleAwareCamelKeysNormalizer();
|
||||
$this->assertEquals($expected, $normalizer->normalize($array));
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*
|
||||
* @dataProvider localeAwareNormalizeProvider
|
||||
*/
|
||||
public function it_does_not_normalize_locales_codes(array $array, array $expected)
|
||||
{
|
||||
$normalizer = new LocaleAwareCamelKeysNormalizer();
|
||||
$this->assertEquals($expected, $normalizer->normalize($array));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function normalizeProvider()
|
||||
{
|
||||
$array = $this->normalizeProviderCommon();
|
||||
$array[] = [[
|
||||
'__username' => 'foo',
|
||||
'_password' => 'bar',
|
||||
'_foo_bar' => 'foobar',
|
||||
], [
|
||||
'_Username' => 'foo',
|
||||
'Password' => 'bar',
|
||||
'FooBar' => 'foobar',
|
||||
]];
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function localeAwareNormalizeProvider()
|
||||
{
|
||||
$array = $this->normalizeProviderCommon();
|
||||
$array[] = [['translations' => [
|
||||
'en_US' => ['foo_bar' => 'mops'],
|
||||
'nl_NL' => ['bar' => 'narwhale_io']],
|
||||
], ['translations' => [
|
||||
'en_US' => ['fooBar' => 'mops'],
|
||||
'nl_NL' => ['bar' => 'narwhale_io']],
|
||||
]];
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function normalizeProviderCommon()
|
||||
{
|
||||
return [
|
||||
[[], []],
|
||||
[
|
||||
['foo' => ['Foo_bar_baz' => ['foo_Bar' => ['foo_bar' => 'foo_bar']]],
|
||||
'foo_1ar' => ['foo_bar'],
|
||||
],
|
||||
['foo' => ['FooBarBaz' => ['fooBar' => ['fooBar' => 'foo_bar']]],
|
||||
'foo1ar' => ['foo_bar'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -111,4 +111,4 @@ twig:
|
|||
|
||||
fos_rest:
|
||||
body_listener:
|
||||
array_normalizer: fos_rest.normalizer.camel_keys
|
||||
array_normalizer: sylius.normalizer.camel_keys
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class LocaleApiTest extends JsonApiTestCase
|
|||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$locales = $this->loadFixturesFromFile('resources/locales.yml');
|
||||
|
||||
$this->client->request('GET', '/api/v1/locales/'.$locales['locale_en']->getCode(), [], [], static::$authorizedHeaderWithAccept);
|
||||
$this->client->request('GET', '/api/v1/locales/'.$locales['locale_en_US']->getCode(), [], [], static::$authorizedHeaderWithAccept);
|
||||
|
||||
$response = $this->client->getResponse();
|
||||
$this->assertResponse($response, 'locale/show_response', Response::HTTP_OK);
|
||||
|
|
@ -100,7 +100,7 @@ class LocaleApiTest extends JsonApiTestCase
|
|||
$data =
|
||||
<<<EOT
|
||||
{
|
||||
"code": "es"
|
||||
"code": "es_ES"
|
||||
}
|
||||
EOT;
|
||||
|
||||
|
|
@ -156,12 +156,12 @@ EOT;
|
|||
$this->loadFixturesFromFile('authentication/api_administrator.yml');
|
||||
$locales = $this->loadFixturesFromFile('resources/locales.yml');
|
||||
|
||||
$this->client->request('DELETE', '/api/v1/locales/'.$locales['locale_en']->getCode(), [], [], static::$authorizedHeaderWithContentType, []);
|
||||
$this->client->request('DELETE', '/api/v1/locales/'.$locales['locale_en_US']->getCode(), [], [], static::$authorizedHeaderWithContentType, []);
|
||||
|
||||
$response = $this->client->getResponse();
|
||||
$this->assertResponseCode($response, Response::HTTP_NO_CONTENT);
|
||||
|
||||
$this->client->request('GET', '/api/v1/locales/'.$locales['locale_en']->getId(), [], [], static::$authorizedHeaderWithAccept);
|
||||
$this->client->request('GET', '/api/v1/locales/'.$locales['locale_en_US']->getId(), [], [], static::$authorizedHeaderWithAccept);
|
||||
|
||||
$response = $this->client->getResponse();
|
||||
$this->assertResponse($response, 'error/not_found_response', Response::HTTP_NOT_FOUND);
|
||||
|
|
|
|||
|
|
@ -135,11 +135,11 @@ final class ProductApiTest extends JsonApiTestCase
|
|||
{
|
||||
"code": "MUG_TH",
|
||||
"translations": {
|
||||
"nl": {
|
||||
"name": "Theme Mug",
|
||||
"slug": "theme-mug2"
|
||||
"nl_NL": {
|
||||
"name": "Mok van het thema",
|
||||
"slug": "mok-van-het-thema"
|
||||
},
|
||||
"en": {
|
||||
"en_US": {
|
||||
"name": "Theme Mug",
|
||||
"slug": "theme-mug"
|
||||
}
|
||||
|
|
@ -179,7 +179,7 @@ EOT;
|
|||
<<<EOT
|
||||
{
|
||||
"translations": {
|
||||
"en__US": {
|
||||
"en_US": {
|
||||
"name": "Star Wars",
|
||||
"slug": "star-wars"
|
||||
}
|
||||
|
|
@ -204,7 +204,7 @@ EOT;
|
|||
<<<EOT
|
||||
{
|
||||
"translations": {
|
||||
"en": {
|
||||
"en_US": {
|
||||
"name": "Mug Star Wars Episode V"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
Sylius\Component\Locale\Model\Locale:
|
||||
locale_{en, nl, fr}:
|
||||
locale_{en_US, nl_NL, fr_FR, de_CH}:
|
||||
code: <current()>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
Sylius\Component\Core\Model\ProductTranslation:
|
||||
productTranslation1:
|
||||
slug: mug-star-wars
|
||||
locale: en
|
||||
name: 'Star wars mug'
|
||||
locale: 'en_US'
|
||||
name: 'Star Wars mug'
|
||||
slug: 'star-wars-mug'
|
||||
description: <paragraph(2)>
|
||||
translatable: "@product1"
|
||||
productTranslation2:
|
||||
slug: star-wars-mug
|
||||
locale: en_US
|
||||
name: 'Star Wars mug'
|
||||
locale: 'nl_NL'
|
||||
name: 'Mok van het thema'
|
||||
slug: 'mok-van-het-thema'
|
||||
description: <paragraph(2)>
|
||||
translatable: "@product1"
|
||||
|
||||
|
|
@ -20,27 +20,27 @@ Sylius\Component\Core\Model\ProductVariant:
|
|||
Sylius\Component\Core\Model\Product:
|
||||
product1:
|
||||
updatedAt: 2015-10-10
|
||||
fallbackLocale: en_US
|
||||
currentLocale: en
|
||||
code: MUG_SW
|
||||
currentLocale: 'en_US'
|
||||
fallbackLocale: 'en_US'
|
||||
code: 'MUG_SW'
|
||||
translations:
|
||||
- "@productTranslation1"
|
||||
- "@productTranslation2"
|
||||
product2:
|
||||
updatedAt: 2015-10-04
|
||||
currentLocale: en_US
|
||||
fallbackLocale: en_US
|
||||
code: MUG_LOTR
|
||||
slug: mug-lotr
|
||||
currentLocale: 'en_US'
|
||||
fallbackLocale: 'en_US'
|
||||
code: 'MUG_LOTR'
|
||||
slug: 'mug-lotr'
|
||||
name: 'Lotr mug'
|
||||
description: <paragraph(2)>
|
||||
variants:
|
||||
- "@productVariant"
|
||||
product3:
|
||||
updatedAt: 2015-10-05
|
||||
currentLocale: en_US
|
||||
fallbackLocale: en_US
|
||||
code: MUG_BB
|
||||
slug: mug-breaking-bad
|
||||
currentLocale: 'en_US'
|
||||
fallbackLocale: 'en_US'
|
||||
code: 'MUG_BB'
|
||||
slug: 'mug-breaking-bad'
|
||||
name: 'Breaking bad mug'
|
||||
description: <paragraph(2)>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"id": @integer@,
|
||||
"code": "es",
|
||||
"code": "es_ES",
|
||||
"created_at": "@string@.isDateTime()",
|
||||
"updated_at": "@string@.isDateTime()"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"page": 1,
|
||||
"limit": 10,
|
||||
"pages": 1,
|
||||
"total": 3,
|
||||
"total": 4,
|
||||
"_links": {
|
||||
"self": {
|
||||
"href": "\/api\/v1\/locales\/?page=1&limit=10"
|
||||
|
|
@ -18,17 +18,22 @@
|
|||
"items": [
|
||||
{
|
||||
"id": @integer@,
|
||||
"code": "en"
|
||||
"code": "en_US"
|
||||
},
|
||||
{
|
||||
|
||||
"id": @integer@,
|
||||
"code": "nl"
|
||||
"code": "nl_NL"
|
||||
},
|
||||
{
|
||||
|
||||
"id": @integer@,
|
||||
"code": "fr"
|
||||
"code": "fr_FR"
|
||||
},
|
||||
{
|
||||
|
||||
"id": @integer@,
|
||||
"code": "de_CH"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"id": @integer@,
|
||||
"code": "en",
|
||||
"code": "en_US",
|
||||
"created_at": "@string@.isDateTime()",
|
||||
"updated_at": "@string@.isDateTime()"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"id": @integer@,
|
||||
"code": "en",
|
||||
"code": "en_US",
|
||||
"created_at": "@string@.isDateTime()",
|
||||
"updated_at": "@string@.isDateTime()"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"id": @integer@,
|
||||
"name": "Theme Mug",
|
||||
"code": "MUG_TH",
|
||||
"available_on": "@string@.isDateTime()",
|
||||
"attributes": [],
|
||||
|
|
@ -7,20 +8,17 @@
|
|||
"options": [],
|
||||
"associations": [],
|
||||
"translations": {
|
||||
"en": {
|
||||
"en_US": {
|
||||
"id": @integer@,
|
||||
"locale": "en",
|
||||
"locale": "en_US",
|
||||
"name": "Theme Mug",
|
||||
"slug": "theme-mug"
|
||||
},
|
||||
"nl": {
|
||||
"nl_NL": {
|
||||
"id": @integer@,
|
||||
"locale": "nl",
|
||||
"name": "Theme Mug",
|
||||
"slug": "theme-mug2"
|
||||
},
|
||||
"en_US": {
|
||||
"locale": "en_US"
|
||||
"locale": "nl_NL",
|
||||
"name": "Mok van het thema",
|
||||
"slug": "mok-van-het-thema"
|
||||
}
|
||||
},
|
||||
"product_taxons": [],
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"id": @integer@,
|
||||
"name": "Star wars mug",
|
||||
"name": "Star Wars mug",
|
||||
"code": "MUG_SW",
|
||||
"available_on": "@string@.isDateTime()",
|
||||
"attributes": [],
|
||||
|
|
@ -8,19 +8,19 @@
|
|||
"options": [],
|
||||
"associations": [],
|
||||
"translations": {
|
||||
"en": {
|
||||
"id": @integer@,
|
||||
"locale": "en",
|
||||
"name": "Star wars mug",
|
||||
"slug": "mug-star-wars",
|
||||
"description": "@string@"
|
||||
},
|
||||
"en_US": {
|
||||
"id": @integer@,
|
||||
"locale": "en_US",
|
||||
"name": "Star Wars mug",
|
||||
"slug": "star-wars-mug",
|
||||
"description": "@string@"
|
||||
},
|
||||
"nl_NL": {
|
||||
"id": @integer@,
|
||||
"locale": "nl_NL",
|
||||
"name": "Mok van het thema",
|
||||
"slug": "mok-van-het-thema",
|
||||
"description": "@string@"
|
||||
}
|
||||
},
|
||||
"product_taxons": [],
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue