Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# NEXT

- Fixed Shopware 5 customer migration with custom locales by resolving `languageId` from existing migration mappings during the same run

# 16.2.0

- #15568 - Switched to PHP Symfony service definitions
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG_de-DE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# NEXT

- Fehler bei der Migration von Shopware-5-Kunden mit benutzerdefinierten Sprachen behoben, indem die `languageId` im selben Lauf aus vorhandenen Migrations-Mappings aufgelöst wird

# 16.2.0

- #15568 - Umstellung auf PHP-Symfony-Service-Definitionen
Expand Down
17 changes: 11 additions & 6 deletions src/Profile/Shopware/Converter/CustomerConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,12 @@ public function convert(
unset($data['attributes']);

if (isset($data['customerlanguage']['locale'])) {
$languageUuid = $this->languageLookup->get($data['customerlanguage']['locale'], $context);
$languageUuid = $this->resolveLanguageId(
$data['customerlanguage']['locale'],
$this->languageLookup,
$context,
);

if ($languageUuid !== null) {
$converted['languageId'] = $languageUuid;
}
Expand Down Expand Up @@ -326,19 +331,19 @@ protected function applyAddresses(array &$originalData, array &$converted): void
$newAddress = [];
$salutationUuid = $this->getSalutation($address['salutation']);

if ($salutationUuid === null) {
continue;
}

$addressMapping = $this->mappingService->getOrCreateMapping(
$this->connectionId,
DefaultEntities::CUSTOMER_ADDRESS,
$address['id'],
$this->context
);

$newAddress['id'] = $addressMapping['entityId'];
$this->mappingIds[] = $addressMapping['id'];
$newAddress['salutationId'] = $salutationUuid;

if ($salutationUuid !== null) {
$newAddress['salutationId'] = $salutationUuid;
}

if (isset($originalData['default_billing_address_id']) && $address['id'] === $originalData['default_billing_address_id']) {
$converted['defaultBillingAddressId'] = $newAddress['id'];
Expand Down
20 changes: 20 additions & 0 deletions src/Profile/Shopware/Converter/ShopwareConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use Shopware\Core\Framework\Log\Package;
use SwagMigrationAssistant\Migration\Connection\Helper\ConnectionNameSanitizer;
use SwagMigrationAssistant\Migration\Converter\Converter;
use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities;
use SwagMigrationAssistant\Migration\Mapping\Lookup\LanguageLookup;
use SwagMigrationAssistant\Migration\MigrationContextInterface;

#[Package('fundamentals@after-sales')]
Expand All @@ -30,6 +32,24 @@ public function getSourceIdentifier(array $data): string
return $data['id'];
}

protected function resolveLanguageId(string $locale, LanguageLookup $languageLookup, Context $context): ?string
{
$mapping = $this->mappingService->getMapping(
$this->migrationContext->getConnection()->getId(),
DefaultEntities::LANGUAGE,
$locale,
$context
);

if (isset($mapping['entityId'])) {
$this->mappingIds[] = $mapping['id'];

return $mapping['entityId'];
}

return $languageLookup->get($locale, $context);
}

/**
* @param array<string, mixed> $newData
* @param array<string, mixed> $sourceData
Expand Down
21 changes: 20 additions & 1 deletion src/Profile/Shopware/Gateway/Local/Reader/LanguageReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ public function supports(MigrationContextInterface $migrationContext): bool

public function read(MigrationContextInterface $migrationContext): array
{
$fetchedShopLocaleIds = \array_unique($this->fetchShopLocaleIds($migrationContext));
$fetchedShopLocaleIds = \array_unique(\array_merge(
$this->fetchShopLocaleIds($migrationContext),
$this->fetchCustomerLocaleIds($migrationContext)
));

$locales = $this->fetchLocales($fetchedShopLocaleIds, $migrationContext);

return $this->appendAssociatedData($locales, $migrationContext);
Expand Down Expand Up @@ -76,6 +80,21 @@ private function fetchShopLocaleIds(MigrationContextInterface $migrationContext)
return $query->fetchFirstColumn();
}

/**
* @return list<string>
*/
private function fetchCustomerLocaleIds(MigrationContextInterface $migrationContext): array
Comment thread
larskemper marked this conversation as resolved.
{
$connection = $this->getConnection($migrationContext);
$query = $connection->createQueryBuilder();
$query->from('s_user', 'customer');
$query->addSelect('customer.language');
$query->distinct();
$query->where('customer.language IS NOT NULL');

return $query->executeQuery()->fetchFirstColumn();
}

private function fetchLocales(array $fetchedShopLocaleIds, MigrationContextInterface $migrationContext): array
{
$connection = $this->getConnection($migrationContext);
Expand Down
63 changes: 62 additions & 1 deletion tests/Profile/Shopware/Gateway/Local/LanguageReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace SwagMigrationAssistant\Test\Profile\Shopware\Gateway\Local;

use Doctrine\DBAL\Connection;
use PHPUnit\Framework\TestCase;
use Shopware\Core\Framework\Log\Package;
use SwagMigrationAssistant\Migration\MigrationContext;
Expand All @@ -25,11 +26,18 @@ class LanguageReaderTest extends TestCase

private MigrationContext $migrationContext;

private Connection $dbConnection;

private int $customerLocaleId = 9999;

private bool $customerLocaleInserted = false;

protected function setUp(): void
{
$this->connectionSetup();

$this->languageReader = new LanguageReader(new ConnectionFactory());
$connectionFactory = new ConnectionFactory();
$this->languageReader = new LanguageReader($connectionFactory);

$this->migrationContext = new MigrationContext(
$this->connection,
Expand All @@ -42,6 +50,25 @@ protected function setUp(): void
);

$this->migrationContext->setGateway(new DummyLocalGateway());

$this->dbConnection = $connectionFactory->createDatabaseConnection($this->migrationContext);
$this->dbConnection->executeStatement('UPDATE s_user SET language = :language WHERE id = :id', [
'language' => 1,
'id' => 1,
]);
}

protected function tearDown(): void
{
// reset customer to the fixture default locale
$this->dbConnection->executeStatement('UPDATE s_user SET language = :language WHERE id = :id', [
'language' => 1,
'id' => 1,
]);

if ($this->customerLocaleInserted) {
$this->dbConnection->executeStatement('DELETE FROM s_core_locales WHERE id = :id', ['id' => $this->customerLocaleId]);
}
}

public function testRead(): void
Expand All @@ -63,4 +90,38 @@ public function testRead(): void
static::assertSame('de_DE', $data[1]['translations'][0]['locale']);
static::assertSame('en_GB', $data[1]['translations'][1]['locale']);
}

public function testReadIncludesCustomerLocalesOutsideShopLocales(): void
{
$existingLocaleId = $this->dbConnection->fetchOne(
'SELECT id FROM s_core_locales WHERE locale = :locale',
['locale' => 'ar_EG']
);

if ($existingLocaleId === false) {
$this->dbConnection->executeStatement(
'INSERT INTO s_core_locales (id, locale, language, territory) VALUES (:id, :locale, :language, :territory)',
[
'id' => $this->customerLocaleId,
'locale' => 'ar_EG',
'language' => 'Arabic',
'territory' => 'Egypt',
]
);

$this->customerLocaleInserted = true;
} else {
$this->customerLocaleId = (int) $existingLocaleId;
}

$this->dbConnection->executeStatement('UPDATE s_user SET language = :language WHERE id = :id', [
'language' => $this->customerLocaleId,
'id' => 1,
]);

$data = $this->languageReader->read($this->migrationContext);

static::assertCount(3, $data);
static::assertContains('ar-EG', \array_column($data, 'locale'));
}
}
70 changes: 70 additions & 0 deletions tests/Profile/Shopware55/Converter/CustomerConverterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -372,4 +372,74 @@ public function testConvertBusinessCustomer(): void
static::assertSame('Shopware AG', $converted['company']);
static::assertSame(CustomerEntity::ACCOUNT_TYPE_BUSINESS, $converted['accountType']);
}

public function testConvertKeepsDefaultAddressesWhenAddressSalutationIsUnknown(): void
{
$customerData = require __DIR__ . '/../../../_fixtures/customer_data.php';
$customerData = $customerData[0];
$customerData['addresses'][0]['salutation'] = 'unknown-salutation';

$context = Context::createDefaultContext();
$convertResult = $this->customerConverter->convert(
$customerData,
$context,
$this->migrationContext
);

$converted = $convertResult->getConverted();
static::assertNotNull($converted);
static::assertCount(3, $converted['addresses']);
static::assertArrayNotHasKey('salutationId', $converted['addresses'][0]);
static::assertSame($converted['addresses'][0]['id'], $converted['defaultBillingAddressId']);
static::assertSame($converted['addresses'][1]['id'], $converted['defaultShippingAddressId']);

$logs = $this->loggingService->getLoggingArray();
static::assertCount(1, $logs);
static::assertSame(ConvertEntityUnknownLog::getCode(), $logs[0]['code']);
}

public function testConvertUsesLanguageMappingWhenLanguageDoesNotExistYet(): void
{
$customerData = require __DIR__ . '/../../../_fixtures/customer_data.php';
$customerData = $customerData[0];
$customerData['customerlanguage']['locale'] = 'ar-EG';

$languageId = Uuid::randomHex();
$context = Context::createDefaultContext();
$this->mappingService->getOrCreateMapping(
$this->connectionId,
DefaultEntities::LANGUAGE,
'ar-EG',
$context,
null,
[],
$languageId
);

$languageLookup = $this->createMock(LanguageLookup::class);
$languageLookup->expects($this->never())->method('get');

$validator = static::getContainer()->get('validator');
$salesChannelRepo = static::getContainer()->get('sales_channel.repository');

$customerConverter = new Shopware55CustomerConverter(
$this->mappingService,
$this->loggingService,
$validator,
$salesChannelRepo,
static::getContainer()->get(CountryLookup::class),
$languageLookup,
static::getContainer()->get(CountryStateLookup::class),
);

$convertResult = $customerConverter->convert(
$customerData,
$context,
$this->migrationContext
);

$converted = $convertResult->getConverted();
static::assertNotNull($converted);
static::assertSame($languageId, $converted['languageId']);
}
}
Loading