diff --git a/mapping-experiment.php b/mapping-experiment.php
new file mode 100644
index 000000000..c3ca56eb6
--- /dev/null
+++ b/mapping-experiment.php
@@ -0,0 +1,170 @@
+
+ */
+ private array $pendingTasks = [];
+
+ /**
+ * Important: this method returns a reference to a string which is also internally stored.
+ * It must be called like this:
+ *
+ * $data['someId'] = &$mappingService->getMapping('sourceId');
+ *
+ * The use of '&' is very important, otherwise it will only copy the placeholder string.
+ * More info on this can be found in the PHP docs:
+ * https://www.php.net/manual/en/language.references.return.php
+ */
+ public function &getMapping(string $sourceId): string
+ {
+ // previously we would fetch the mapping from the DB here,
+ // but reaching out to the DB every time is expensive
+
+ // so instead we just return a placeholder string
+ // and update it later, when we know all mappings that are needed
+
+ // and then use the string reference to update the placeholders
+
+ $pointer = self::PLACEHOLDER;
+
+ $task = new MappingTask($pointer, $sourceId);
+ $this->pendingTasks[] = $task;
+
+ return $pointer;
+ }
+
+ public function resolvePendingMappings(): void
+ {
+ // in here we can fetch all requested mappings from the DB
+ // in a single query and update all corresponding strings
+ foreach ($this->pendingTasks as $task) {
+ $task->reference = 'changed-' . $task->sourceId;
+ unset($task->reference);
+ }
+ }
+}
+
+// a stripped-down example of a converter
+function convertData(MappingService $mappingService): array
+{
+ $data['name'] = 'John Doe';
+ $data['manufacturerId'] = &$mappingService->getMapping('manufacturer01');
+ $data['price'] = [];
+ for ($i = 0; $i < 3; ++$i) {
+ $data['price'][] = convertCurrency($i, $mappingService);
+ }
+
+ return $data;
+}
+
+// a stripped-down example of internal logic in a converter
+function convertCurrency(int $i, MappingService $mappingService): array
+{
+ $price = [
+ 'id' => $i,
+ // unfortunately, this does not work, but there is an easy workaround below
+ // 'currencyId' => &$mappingService->getMapping('currency0' . $i),
+ ];
+
+ // this works fine
+ $price['currencyId'] = &$mappingService->getMapping('currency0' . $i);
+
+ return $price;
+}
+
+// === Main logic below ===
+
+$mappingService = new MappingService();
+$convertedData = convertData($mappingService);
+echo '============== Initial data after converter run ==============' . \PHP_EOL;
+var_dump($convertedData);
+
+echo '============== data after mapping tasks got resolved ==============' . \PHP_EOL;
+$mappingService->resolvePendingMappings();
+var_dump($convertedData);
+
+// === Output looks like this ===
+/*
+============== Initial data after converter run ==============
+array(3) {
+ ["name"]=>
+ string(8) "John Doe"
+ ["manufacturerId"]=>
+ &string(24) "placeholder-mapping-uuid"
+ ["price"]=>
+ array(3) {
+ [0]=>
+ array(2) {
+ ["id"]=>
+ int(0)
+ ["currencyId"]=>
+ &string(24) "placeholder-mapping-uuid"
+ }
+ [1]=>
+ array(2) {
+ ["id"]=>
+ int(1)
+ ["currencyId"]=>
+ &string(24) "placeholder-mapping-uuid"
+ }
+ [2]=>
+ array(2) {
+ ["id"]=>
+ int(2)
+ ["currencyId"]=>
+ &string(24) "placeholder-mapping-uuid"
+ }
+ }
+}
+============== data after mapping tasks got resolved ==============
+array(3) {
+ ["name"]=>
+ string(8) "John Doe"
+ ["manufacturerId"]=>
+ string(22) "changed-manufacturer01"
+ ["price"]=>
+ array(3) {
+ [0]=>
+ array(2) {
+ ["id"]=>
+ int(0)
+ ["currencyId"]=>
+ string(18) "changed-currency00"
+ }
+ [1]=>
+ array(2) {
+ ["id"]=>
+ int(1)
+ ["currencyId"]=>
+ string(18) "changed-currency01"
+ }
+ [2]=>
+ array(2) {
+ ["id"]=>
+ int(2)
+ ["currencyId"]=>
+ string(18) "changed-currency02"
+ }
+ }
+}
+ */
diff --git a/src/DependencyInjection/migration.xml b/src/DependencyInjection/migration.xml
index a4235fa4f..9d4310b56 100644
--- a/src/DependencyInjection/migration.xml
+++ b/src/DependencyInjection/migration.xml
@@ -48,6 +48,13 @@
+
+
+
+
+
+
+
@@ -226,6 +233,7 @@
+
diff --git a/src/DependencyInjection/shopware.xml b/src/DependencyInjection/shopware.xml
index bc5201298..aea5462de 100644
--- a/src/DependencyInjection/shopware.xml
+++ b/src/DependencyInjection/shopware.xml
@@ -115,6 +115,7 @@
+
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace SwagMigrationAssistant\Migration\Mapping;
+
+/**
+ * A promise that holds a reference to a string and the data for looking up a mapping.
+ * It makes it possible to update the referenced string at a later point and fulfill the promise to
+ * replace it with an actual UUID.
+ *
+ * If you are familiar with the JS world, this is a bit similar to a JS Promise, but
+ * there is no automatic executor in the background and these need to be manually fulfilled.
+ *
+ * @see MappingServiceV2
+ *
+ * @internal
+ */
+#[Package('fundamentals@after-sales')]
+class MappingPromise
+{
+ public function __construct(
+ /**
+ * points to the placeholder string that needs to be replaced with an actual UUID
+ */
+ public string &$reference,
+ /**
+ * entity used for mapping lookup
+ */
+ public string $entity,
+ /**
+ * source id used for mapping lookup
+ */
+ public string $sourceId,
+ /**
+ * if true, the mapping will be created in DB if it does not exist
+ */
+ public bool $shouldCreate = false,
+ /**
+ * if creating, use this Uuid to map to
+ */
+ public ?string $createWith = null,
+ ) {
+ }
+
+ public function resolve(string $uuid): void
+ {
+ $this->reference = $uuid;
+ unset($this->reference);
+ }
+}
diff --git a/src/Migration/Mapping/MappingService.php b/src/Migration/Mapping/MappingService.php
index 54c8f05ab..36b8a2da8 100644
--- a/src/Migration/Mapping/MappingService.php
+++ b/src/Migration/Mapping/MappingService.php
@@ -114,6 +114,10 @@ public function getMapping(
return $this->mappings[$cacheKey];
}
+ // simulate network latency
+ // todo: remove me
+ // \usleep(1000); // 1ms
+
$sql = 'SELECT id,
connection_id AS connectionId,
entity,
diff --git a/src/Migration/Mapping/MappingServiceV2.php b/src/Migration/Mapping/MappingServiceV2.php
new file mode 100644
index 000000000..2a99eca30
--- /dev/null
+++ b/src/Migration/Mapping/MappingServiceV2.php
@@ -0,0 +1,320 @@
+
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace SwagMigrationAssistant\Migration\Mapping;
+
+use Doctrine\DBAL\Connection;
+use Psr\Log\LoggerInterface;
+use Shopware\Core\Defaults;
+use Shopware\Core\Framework\Uuid\Uuid;
+use Symfony\Contracts\Service\ResetInterface;
+
+/**
+ * @internal
+ */
+#[Package('fundamentals@after-sales')]
+class MappingServiceV2 implements ResetInterface
+{
+ public const PLACEHOLDER = 'uuid-mapping-promise';
+
+ /**
+ * indexed by entityName + oldIdentifier
+ * the value is always a list with at least one promise
+ *
+ * @var array>
+ */
+ private array $unfulfilledPromises = [];
+
+ public function __construct(
+ protected readonly Connection $connection,
+ protected readonly LoggerInterface $logger,
+ ) {
+ }
+
+ /**
+ * Lookup of a mapping with optional creation parameters if it doesn't exist yet.
+ *
+ * Important: this method returns a reference to a string which is also internally stored.
+ * It must be called like this:
+ *
+ * $data['newId'] = &$mappingService->getMapping('entity', 'oldId');
+ *
+ * The use of '&' is very important, otherwise it will only copy the placeholder string.
+ * More info on this can be found in the PHP docs:
+ * https://www.php.net/manual/en/language.references.return.php
+ *
+ * @param bool $shouldCreate if the mapping should be created if it doesn't exist yet
+ * @param string|null $createWith if creating, use this Uuid to map to. All the same lookups will resolve to this
+ *
+ * @return string placeholder string which will be resolved later by calling @see MappingServiceV2->resolvePromises()
+ */
+ public function &getMapping(
+ string $entityName,
+ string $oldIdentifier,
+ bool $shouldCreate = false,
+ ?string $createWith = null,
+ ): string {
+ // todo: figure out a nice dev experience for debugging
+ // todo: this is already a good start?
+ $trace = debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1);
+ $caller = $trace[0] ?? [];
+ $callerString = ($caller['file'] ?? '') . '::' . ($caller['line'] ?? '');
+
+ $ref = self::PLACEHOLDER . '(\'' . $entityName . '\', \'' . $oldIdentifier . '\') +++ ' . $callerString;
+
+ $promise = new MappingPromise($ref, $entityName, $oldIdentifier, $shouldCreate, $createWith);
+
+ $key = $entityName . $oldIdentifier;
+ if (!isset($this->unfulfilledPromises[$key])) {
+ $this->unfulfilledPromises[$key] = [];
+ }
+ $this->unfulfilledPromises[$key][] = $promise;
+
+ return $ref;
+ }
+
+ public function resolvePromises(
+ string $connectionId,
+ ): void {
+ if ($this->unfulfilledPromises === []) {
+ return;
+ }
+
+ $mappingLookups = array_map(
+ fn ($mappingPromises) => [
+ 'entity' => $mappingPromises[0]->entity,
+ 'oldIdentifier' => $mappingPromises[0]->sourceId,
+ ],
+ $this->unfulfilledPromises,
+ );
+ $dbMappings = $this->fetchDbMappings($connectionId, $mappingLookups);
+
+ foreach ($dbMappings as $dbMapping) {
+ $key = $dbMapping->getEntity() . $dbMapping->getOldIdentifier();
+ $promises = $this->unfulfilledPromises[$key];
+ foreach ($promises as $promise) {
+ $promise->resolve($dbMapping->getEntityId());
+ }
+ unset($this->unfulfilledPromises[$key]);
+ }
+
+ // the remaining unfulfilled promises don't have a DB mapping yet
+ $createDbMappings = [];
+ foreach ($this->unfulfilledPromises as $promises) {
+ // search if this particular lookup is allowed to create a mapping
+ // and if exactly one createWith value was provided
+ $shouldCreate = false;
+ $createWith = null;
+ foreach ($promises as $promise) {
+ if ($promise->shouldCreate) {
+ $shouldCreate = true;
+ }
+ if ($promise->createWith) {
+ if ($createWith) {
+ // todo: proper error handling
+ throw new \RuntimeException('resolving mapping promise failed with multiple createWith values for ' . $promises[0]->sourceId . ' for ' . $promises[0]->entity);
+ }
+
+ $createWith = $promise->createWith;
+ }
+ }
+
+ if (!$shouldCreate) {
+ // todo: proper error handling
+ throw new \RuntimeException('Could not resolve mapping promise ' . $promises[0]->sourceId . ' for ' . $promises[0]->entity);
+ }
+
+ // it's fine to create the corresponding mapping and resolve all promises with its value
+ $newEntityId = $createWith ?? Uuid::randomHex();
+
+ $dbMapping = new SwagMigrationMappingEntity();
+ $dbMapping->setId(Uuid::randomHex());
+ $dbMapping->setConnectionId($connectionId);
+ $dbMapping->setEntity($promises[0]->entity);
+ $dbMapping->setOldIdentifier($promises[0]->sourceId);
+ $dbMapping->setEntityId($newEntityId);
+ $dbMapping->setCreatedAt(new \DateTime());
+
+ $createDbMappings[] = $dbMapping;
+
+ // resolve promises
+ // todo: should this only execute after successful DB insert?
+ foreach ($promises as $promise) {
+ $promise->resolve($newEntityId);
+ }
+ }
+
+ unset($this->unfulfilledPromises);
+ $this->unfulfilledPromises = [];
+
+ $this->bulkCreateDbMappings($createDbMappings);
+ }
+
+ public function reset(): void
+ {
+ if ($this->unfulfilledPromises !== []) {
+ $this->logger->error('Resetting MappingServiceV2 without resolving all promises');
+ }
+
+ unset($this->unfulfilledPromises);
+ $this->unfulfilledPromises = [];
+ }
+
+ // todo: move SQL methods below into own class and try to clean them up further
+ /**
+ * @param list $lookups
+ *
+ * @return list
+ */
+ private function fetchDbMappings(string $connectionId, array $lookups): array
+ {
+ if ($lookups === []) {
+ return [];
+ }
+
+ $placeholders = [];
+ $params = [];
+
+ foreach ($lookups as $pair) {
+ $placeholders[] = '(?, ?)';
+ $params[] = $pair['entity'];
+ $params[] = $pair['oldIdentifier'];
+ }
+
+ $sql = \sprintf(
+ 'SELECT id,
+ connection_id AS connectionId,
+ entity,
+ old_identifier AS oldIdentifier,
+ entity_id AS entityId,
+ entity_value AS entityValue,
+ checksum,
+ additional_data AS additionalData
+ FROM swag_migration_mapping
+ WHERE connection_id = :connectionId AND (entity, old_identifier) IN (%s)',
+ implode(', ', $placeholders)
+ );
+
+ $mappings = $this->connection->fetchAllAssociative(
+ $sql,
+ [
+ 'connectionId' => Uuid::fromHexToBytes($connectionId),
+ ...$params,
+ ],
+ [
+ 'connectionId' => 'binary',
+ ]
+ );
+
+ return array_map(
+ function (array $mapping): SwagMigrationMappingEntity {
+ $mapping['id'] = Uuid::fromBytesToHex($mapping['id']);
+ $mapping['connectionId'] = Uuid::fromBytesToHex($mapping['connectionId']);
+ $mapping['entityId'] = isset($mapping['entityId']) ? Uuid::fromBytesToHex($mapping['entityId']) : null;
+
+ $entity = new SwagMigrationMappingEntity();
+ $entity->assign($mapping);
+
+ return $entity;
+ },
+ $mappings,
+ );
+ }
+
+ /**
+ * @param list $mappings
+ */
+ private function bulkCreateDbMappings(array $mappings): void
+ {
+ if ($mappings === []) {
+ return;
+ }
+
+ try {
+ $isFirstInsert = true;
+ $insertSql = 'INSERT INTO swag_migration_mapping (id, connection_id, entity, old_identifier, entity_id, entity_value, checksum, additional_data, created_at) VALUES ';
+ $insertParams = [];
+ $updateSql = ' ON DUPLICATE KEY
+ UPDATE entity = VALUES(entity),
+ old_identifier = VALUES(old_identifier),
+ entity_id = VALUES(entity_id),
+ entity_value = VALUES(entity_value),
+ checksum = VALUES(checksum),
+ additional_data = VALUES(additional_data),
+ updated_at = VALUES(created_at);';
+ foreach ($mappings as $index => $writeMapping) {
+ if ($isFirstInsert) {
+ $isFirstInsert = false;
+ } else {
+ $insertSql .= ', ';
+ }
+
+ $insertSql .= \sprintf('(:id%d, :connectionId%d, :entity%d, :oldIdentifier%d, :entityId%d, :entityValue%d, :checksum%d, :additionalData%d, :createdAt%d)', $index, $index, $index, $index, $index, $index, $index, $index, $index);
+
+ $insertParams['id' . $index] = Uuid::fromHexToBytes($writeMapping->getId());
+ $insertParams['connectionId' . $index] = Uuid::fromHexToBytes($writeMapping->getConnectionId());
+ $insertParams['entity' . $index] = $writeMapping->getEntity();
+ $insertParams['oldIdentifier' . $index] = $writeMapping->getOldIdentifier();
+ $insertParams['entityId' . $index] = $writeMapping->getEntityId() === null ? null : Uuid::fromHexToBytes($writeMapping->getEntityId());
+ $insertParams['entityValue' . $index] = $writeMapping->getEntityValue();
+ $insertParams['checksum' . $index] = $writeMapping->getChecksum();
+ $insertParams['additionalData' . $index] = \json_encode($writeMapping->getAdditionalData());
+ $insertParams['createdAt' . $index] = $writeMapping->getCreatedAt()->format(Defaults::STORAGE_DATE_TIME_FORMAT);
+ }
+
+ $this->connection->executeStatement($insertSql . $updateSql, $insertParams);
+ } catch (\Exception) {
+ $this->createDbMappingsIndividually($mappings);
+ }
+ }
+
+ /**
+ * @param list $mappings
+ */
+ private function createDbMappingsIndividually(array $mappings): void
+ {
+ if ($mappings === []) {
+ return;
+ }
+
+ foreach ($mappings as $writeMapping) {
+ try {
+ $insertSql = 'INSERT INTO swag_migration_mapping (id, connection_id, entity, old_identifier, entity_id, entity_value, checksum, additional_data, created_at)
+ VALUES (:id, :connectionId, :entity, :oldIdentifier, :entityId, :entityValue, :checksum, :additionalData, :createdAt)
+ ON DUPLICATE KEY
+ UPDATE entity = VALUES(entity),
+ old_identifier = VALUES(old_identifier),
+ entity_id = VALUES(entity_id),
+ entity_value = VALUES(entity_value),
+ checksum = VALUES(checksum),
+ additional_data = VALUES(additional_data),
+ updated_at = VALUES(created_at);';
+
+ $insertParams = [];
+ $insertParams['id'] = Uuid::fromHexToBytes($writeMapping->getId());
+ $insertParams['connectionId'] = Uuid::fromHexToBytes($writeMapping->getConnectionId());
+ $insertParams['entity'] = $writeMapping->getEntity();
+ $insertParams['oldIdentifier'] = $writeMapping->getOldIdentifier();
+ $insertParams['entityId'] = $writeMapping->getEntityId() === null ? null : Uuid::fromHexToBytes($writeMapping->getEntityId());
+ $insertParams['entityValue'] = $writeMapping->getEntityValue();
+ $insertParams['checksum'] = $writeMapping->getChecksum();
+ $insertParams['additionalData'] = \json_encode($writeMapping->getAdditionalData());
+ $insertParams['createdAt'] = $writeMapping->getCreatedAt()->format(Defaults::STORAGE_DATE_TIME_FORMAT);
+
+ $this->connection->executeStatement($insertSql, $insertParams);
+ } catch (\Exception $e) {
+ $this->logger->error(
+ 'SwagMigrationAssistant: Error while writing migration mapping',
+ [
+ 'error' => $e->getMessage(),
+ 'mapping' => $writeMapping,
+ ]
+ );
+ }
+ }
+ }
+}
diff --git a/src/Migration/Mapping/SwagMigrationMappingEntity.php b/src/Migration/Mapping/SwagMigrationMappingEntity.php
index 284487165..20a06a0d3 100644
--- a/src/Migration/Mapping/SwagMigrationMappingEntity.php
+++ b/src/Migration/Mapping/SwagMigrationMappingEntity.php
@@ -21,20 +21,20 @@ class SwagMigrationMappingEntity extends Entity
protected ?SwagMigrationConnectionEntity $connection = null;
- protected ?string $entity;
+ protected ?string $entity = null;
- protected ?string $oldIdentifier;
+ protected ?string $oldIdentifier = null;
- protected ?string $entityId;
+ protected ?string $entityId = null;
- protected ?string $entityValue;
+ protected ?string $entityValue = null;
- protected ?string $checksum;
+ protected ?string $checksum = null;
/**
* @var array|null
*/
- protected ?array $additionalData;
+ protected ?array $additionalData = null;
public function getConnectionId(): string
{
diff --git a/src/Migration/Media/MediaFileService.php b/src/Migration/Media/MediaFileService.php
index a3bce2867..f9ec762c2 100644
--- a/src/Migration/Media/MediaFileService.php
+++ b/src/Migration/Media/MediaFileService.php
@@ -75,6 +75,7 @@ public function writeMediaFile(Context $context): void
public function saveMediaFile(array $mediaFile): void
{
+ // todo: this is likely broken with MappingServiceV2 and needs to be checked, maybe refactored
$mediaId = $mediaFile['mediaId'];
if (isset($this->uuids[$mediaId])) {
return;
diff --git a/src/Migration/MessageQueue/Handler/Processor/FetchingProcessor.php b/src/Migration/MessageQueue/Handler/Processor/FetchingProcessor.php
index 2dfaa742b..d255bf9d9 100644
--- a/src/Migration/MessageQueue/Handler/Processor/FetchingProcessor.php
+++ b/src/Migration/MessageQueue/Handler/Processor/FetchingProcessor.php
@@ -61,6 +61,20 @@ public function process(
): void {
$runId = $migrationContext->getRunUuid();
$totalCountOfCurrentEntity = $progress->getDataSets()->getTotalByEntityName($progress->getCurrentEntity());
+
+ // todo: remove benchmarking code
+ if ($progress->getCurrentEntity() === 'product' && $progress->getCurrentEntityProgress() === 0) {
+ $blackfire = new \Blackfire\Client();
+ $config = new \Blackfire\Profile\Configuration();
+ $config->setTitle('Fetching ' . $progress->getCurrentEntity() . ' ' . $progress->getCurrentEntityProgress() . ' / ' . $totalCountOfCurrentEntity . ' limit ' . $migrationContext->getLimit());
+ $config->setMetadata('entity', $progress->getCurrentEntity());
+ $config->setMetadata('progress', (string) $progress->getCurrentEntityProgress());
+ $config->setMetadata('total', (string) $totalCountOfCurrentEntity);
+ $config->setMetadata('limit', (string) $migrationContext->getLimit());
+ $probe = $blackfire->createProbe($config);
+ // code being profiled...
+ }
+
$data = $this->migrationDataFetcher->fetchData($migrationContext, $context);
if ($progress->getCurrentEntityProgress() >= $totalCountOfCurrentEntity) {
@@ -81,6 +95,13 @@ public function process(
$progress->setProgress($progress->getProgress() + \count($data));
$this->updateProgress($runId, $progress, $context);
+
+ // todo: remove benchmarking code
+ if ($progress->getCurrentEntity() === 'product' && $progress->getCurrentEntityProgress() === 0) {
+ // end profiling
+ $profile = $blackfire->endProbe($probe);
+ }
+
$this->bus->dispatch(new MigrationProcessMessage($context, $migrationContext->getRunUuid()));
}
}
diff --git a/src/Migration/Service/MigrationDataConverter.php b/src/Migration/Service/MigrationDataConverter.php
index 92a56366e..fc9f13015 100644
--- a/src/Migration/Service/MigrationDataConverter.php
+++ b/src/Migration/Service/MigrationDataConverter.php
@@ -23,6 +23,7 @@
use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface;
use SwagMigrationAssistant\Migration\Mapping\MappingDeltaResult;
use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface;
+use SwagMigrationAssistant\Migration\Mapping\MappingServiceV2;
use SwagMigrationAssistant\Migration\Media\MediaFileServiceInterface;
use SwagMigrationAssistant\Migration\MigrationContextInterface;
use SwagMigrationAssistant\Migration\Validation\MigrationEntityValidationService;
@@ -38,6 +39,7 @@ public function __construct(
private readonly EntityDefinition $dataDefinition,
private readonly MappingServiceInterface $mappingService,
private readonly MigrationEntityValidationService $validationService,
+ private readonly MappingServiceV2 $mappingServiceV2,
) {
}
@@ -91,6 +93,7 @@ private function convertData(
): array {
$runUuid = $migrationContext->getRunUuid();
+ $convertData = [];
$createData = [];
foreach ($data as $item) {
try {
@@ -106,8 +109,43 @@ private function convertData(
continue;
}
- $convertFailureFlag = empty($convertStruct->getConverted());
+ $convertData[] = [
+ 'convertStruct' => $convertStruct,
+ 'item' => $item,
+ ];
+ } catch (\Throwable $exception) {
+ $this->loggingService->log(
+ MigrationLogBuilder::fromMigrationContext($migrationContext)
+ ->withExceptionMessage($exception->getMessage())
+ ->withExceptionTrace($exception->getTrace())
+ ->withEntityName($dataSet::getEntity())
+ ->withSourceData($item)
+ ->build(RunExceptionLog::class)
+ );
+ $createData[] = [
+ 'entity' => $dataSet::getEntity(),
+ 'runId' => $runUuid,
+ 'raw' => $item,
+ 'converted' => null,
+ 'unmapped' => $item,
+ 'mappingUuid' => null,
+ 'convertFailure' => true,
+ ];
+ }
+ }
+
+ // todo: this can throw as well
+ $this->mappingServiceV2->resolvePromises($migrationContext->getConnection()->getId());
+
+ // todo: validation needs to be called after the whole batch was converted + mappings resolved
+ // todo: should be refactored to work with batches and be outsourced like MigrationDataFetcher + MigrationDataConverter
+ // todo: for now this is a temporary ugly workaround
+ foreach ($convertData as $convertItem) {
+ $convertStruct = $convertItem['convertStruct'];
+ $item = $convertItem['item'];
+
+ try {
$this->validationService->validate(
$migrationContext,
$context,
@@ -116,6 +154,8 @@ private function convertData(
$item
);
+ $convertFailureFlag = empty($convertStruct->getConverted());
+
$createData[] = [
'entity' => $dataSet::getEntity(),
'runId' => $runUuid,
@@ -144,8 +184,6 @@ private function convertData(
'mappingUuid' => null,
'convertFailure' => true,
];
-
- continue;
}
}
diff --git a/src/Profile/Shopware/Converter/ProductConverter.php b/src/Profile/Shopware/Converter/ProductConverter.php
index e9d534751..c5effb900 100644
--- a/src/Profile/Shopware/Converter/ProductConverter.php
+++ b/src/Profile/Shopware/Converter/ProductConverter.php
@@ -32,6 +32,7 @@
use SwagMigrationAssistant\Migration\Mapping\Lookup\MediaDefaultFolderLookup;
use SwagMigrationAssistant\Migration\Mapping\Lookup\TaxLookup;
use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface;
+use SwagMigrationAssistant\Migration\Mapping\MappingServiceV2;
use SwagMigrationAssistant\Migration\Media\MediaFileServiceInterface;
use SwagMigrationAssistant\Migration\MigrationContextInterface;
use SwagMigrationAssistant\Migration\Validation\Log\MigrationValidationRequiredFieldMissingLog;
@@ -80,6 +81,7 @@ public function __construct(
protected readonly MediaDefaultFolderLookup $mediaFolderLookup,
protected readonly LanguageLookup $languageLookup,
protected readonly DeliveryTimeLookup $deliveryTimeLookup,
+ protected readonly MappingServiceV2 $mappingServiceV2,
) {
parent::__construct($mappingService, $loggingService);
}
@@ -187,11 +189,8 @@ public function convert(
if (empty($returnData)) {
$returnData = null;
}
- $this->updateMainMapping($migrationContext, $context);
- $mainMapping = $this->mainMapping['id'] ?? null;
-
- return new ConvertStruct($converted, $returnData, $mainMapping);
+ return new ConvertStruct($converted, $returnData, null);
}
/**
@@ -199,17 +198,14 @@ public function convert(
*/
protected function convertMainProduct(array $data): ConvertStruct
{
- $containerMapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $containerUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::PRODUCT_CONTAINER,
$data['id'],
- $this->context
+ true,
);
- $containerUuid = $containerMapping['entityId'];
$converted = [];
- $converted['id'] = $containerUuid;
- $this->mappingIds[] = $containerMapping['id'];
+ $converted['id'] = &$containerUuid;
unset($data['detail']['articleID']);
$converted = $this->getProductData($data, $converted);
@@ -218,37 +214,27 @@ protected function convertMainProduct(array $data): ConvertStruct
$converted['productNumber'] .= 'M';
// Remove options from product container as in core
unset($converted['options']);
- $this->mainMapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
- DefaultEntities::PRODUCT,
- $this->oldProductId,
- $this->context,
- $this->checksum
- );
- $converted['children'][0]['id'] = $this->mainMapping['entityId'];
+ $productUuid = &$this->mappingServiceV2->getMapping(DefaultEntities::PRODUCT, $this->oldProductId, true);
+ $converted['children'][0]['id'] = &$productUuid;
if (isset($converted['children'][0]['media'])) {
if (isset($converted['children'][0]['cover'])) {
$coverMediaUuid = $converted['children'][0]['cover']['media']['id'];
}
foreach ($converted['children'][0]['media'] as &$media) {
- $productMediaRelationMapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $media['productId'] = &$productUuid;
+ $media['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::PRODUCT_MEDIA,
$media['id'],
- $this->context
+ true,
);
- $productMediaRelationUuid = $productMediaRelationMapping['entityId'];
- $this->mappingIds[] = $productMediaRelationMapping['id'];
- $media['productId'] = $this->mainMapping['entityId'];
- $media['id'] = $productMediaRelationUuid;
if (isset($coverMediaUuid) && $media['media']['id'] === $coverMediaUuid) {
$converted['children'][0]['cover'] = $media;
}
}
}
- $converted['children'][0]['parentId'] = $containerUuid;
+ $converted['children'][0]['parentId'] = &$containerUuid;
unset($data['detail']['id'], $converted['children'][0]['translations'], $converted['children'][0]['customFields']);
if (isset($data['categories'])) {
@@ -271,7 +257,7 @@ protected function convertMainProduct(array $data): ConvertStruct
}
$this->updateMainMapping($this->migrationContext, $this->context);
- return new ConvertStruct($converted, $returnData, $this->mainMapping['id'] ?? null);
+ return new ConvertStruct($converted, $returnData, null);
}
/**
@@ -281,29 +267,16 @@ protected function convertMainProduct(array $data): ConvertStruct
*/
protected function convertVariantProduct(array $data): ConvertStruct
{
- $parentMapping = $this->mappingService->getMapping(
- $this->connectionId,
- DefaultEntities::PRODUCT_CONTAINER,
- $data['detail']['articleID'],
- $this->context
- );
-
- if ($parentMapping === null) {
- throw MigrationException::parentEntityForChildNotFound(DefaultEntities::PRODUCT, $this->oldProductId);
- }
-
- $this->mainMapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $converted = [];
+ $converted['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::PRODUCT,
$this->oldProductId,
- $this->context,
- $this->checksum
+ true
+ );
+ $converted['parentId'] = &$this->mappingServiceV2->getMapping(
+ DefaultEntities::PRODUCT_CONTAINER,
+ $data['detail']['articleID']
);
-
- $converted = [];
- $converted['id'] = $this->mainMapping['entityId'];
- $converted['parentId'] = $parentMapping['entityId'];
- $this->mappingIds[] = $parentMapping['id'];
$converted = $this->getProductData($data, $converted);
unset($data['detail']['id'], $data['detail']['articleID'], $data['categories']);
@@ -315,11 +288,8 @@ protected function convertVariantProduct(array $data): ConvertStruct
if (empty($returnData)) {
$returnData = null;
}
- $this->updateMainMapping($this->migrationContext, $this->context);
- $mainMapping = $this->mainMapping['id'] ?? null;
-
- return new ConvertStruct($converted, $returnData, $mainMapping);
+ return new ConvertStruct($converted, $returnData, null);
}
/**
@@ -329,27 +299,23 @@ protected function convertVariantProduct(array $data): ConvertStruct
*/
private function getUuidForProduct(array &$data): array
{
- $this->mainMapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $converted = [];
+ $newUuid = Uuid::randomHex();
+ $converted['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::PRODUCT,
$this->oldProductId,
- $this->context,
- $this->checksum
+ true,
+ $newUuid,
);
- $converted = [];
- $converted['id'] = $this->mainMapping['entityId'];
-
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ // create another mapping that resolves to the same UUID as the mapping above
+ // but uses a different lookup pair
+ $this->mappingServiceV2->getMapping(
DefaultEntities::PRODUCT_MAIN,
$data['detail']['articleID'],
- $this->context,
- null,
- null,
- $converted['id']
+ true,
+ $newUuid
);
- $this->mappingIds[] = $mapping['id'];
return $converted;
}
@@ -524,10 +490,6 @@ private function getProductData(array &$data, array $converted): array
*/
private function setPurchasePrices(array &$data, array &$converted): void
{
- if ($this->currencyUuid === null) {
- return;
- }
-
$purchasePrice = 0.0;
$purchasePriceGross = 0.0;
if (isset($data['detail']['purchaseprice'])) {
@@ -537,6 +499,8 @@ private function setPurchasePrices(array &$data, array &$converted): void
unset($data['detail']['purchaseprice']);
$price = [];
+ // todo: validate this is fine
+ /*
if ($this->currencyUuid !== Defaults::CURRENCY) {
$price[] = [
'currencyId' => Defaults::CURRENCY,
@@ -545,9 +509,10 @@ private function setPurchasePrices(array &$data, array &$converted): void
'linked' => true,
];
}
+ */
$price[] = [
- 'currencyId' => $this->currencyUuid,
+ 'currencyId' => &$this->currencyUuid,
'gross' => $purchasePriceGross,
'net' => $purchasePrice,
'linked' => true,
@@ -596,19 +561,6 @@ private function getDeliveryTime(string $shippingTime): ?array
}
}
- $mapping = $this->mappingService->getMapping(
- $this->connectionId,
- DefaultEntities::DELIVERY_TIME,
- $shippingTime,
- $this->context
- );
-
- if ($mapping !== null) {
- $convertedDeliveryTime['id'] = $mapping['entityId'];
-
- return $convertedDeliveryTime;
- }
-
$convertedDeliveryTime['id'] = $this->deliveryTimeLookup->get(
$convertedDeliveryTime['min'],
$convertedDeliveryTime['max'],
@@ -617,18 +569,13 @@ private function getDeliveryTime(string $shippingTime): ?array
);
if ($convertedDeliveryTime['id'] === null) {
- $convertedDeliveryTime['id'] = Uuid::randomHex();
+ $convertedDeliveryTime['id'] = &$this->mappingServiceV2->getMapping(
+ DefaultEntities::DELIVERY_TIME,
+ $shippingTime,
+ true,
+ );
}
- $this->mappingService->createMapping(
- $this->connectionId,
- DefaultEntities::DELIVERY_TIME,
- $shippingTime,
- null,
- null,
- $convertedDeliveryTime['id'],
- );
-
return $convertedDeliveryTime;
}
@@ -662,24 +609,20 @@ private function applyOptions(array &$converted, array &$data): void
}
foreach ($data['configuratorOptions'] as $option) {
- $optionMapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $optionUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::PROPERTY_GROUP_OPTION,
Hasher::hash(\mb_strtolower($option['name'] . '_' . $option['group']['name']), 'md5'),
- $this->context
+ true,
);
- $this->mappingIds[] = $optionMapping['id'];
- $optionGroupMapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $optionGroupUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::PROPERTY_GROUP,
Hasher::hash(\mb_strtolower($option['group']['name']), 'md5'),
- $this->context
+ true,
);
- $this->mappingIds[] = $optionGroupMapping['id'];
$optionElement = [
- 'id' => $optionMapping['entityId'],
+ 'id' => &$optionUuid,
'group' => [
- 'id' => $optionGroupMapping['entityId'],
+ 'id' => &$optionGroupUuid,
],
];
@@ -707,15 +650,12 @@ private function applyOptions(array &$converted, array &$data): void
*/
private function getManufacturer(array $data): array
{
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $manufacturer = [];
+ $manufacturer['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::PRODUCT_MANUFACTURER,
$data['id'],
- $this->context
+ true,
);
- $manufacturer = [];
- $manufacturer['id'] = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
$this->applyManufacturerTranslation($manufacturer, $data);
$this->convertValue($manufacturer, 'link', $data, 'link');
@@ -750,19 +690,16 @@ private function applyManufacturerTranslation(array &$manufacturer, array $data)
}
$localeTranslation = [];
- $localeTranslation['productManufacturerId'] = $manufacturer['id'];
+ $localeTranslation['productManufacturerId'] = &$manufacturer['id'];
$this->convertValue($localeTranslation, 'name', $data, 'name');
$this->convertValue($localeTranslation, 'description', $data, 'description');
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $localeTranslation['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::PRODUCT_MANUFACTURER_TRANSLATION,
$data['id'] . ':' . $this->locale,
- $this->context
+ true,
);
- $localeTranslation['id'] = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
$languageUuid = $this->languageLookup->get($this->locale, $this->context);
if ($languageUuid !== null) {
@@ -781,21 +718,19 @@ private function getTax(array $taxData): array
$taxRate = (float) $taxData['tax'];
$taxUuid = $this->taxLookup->get($taxRate, $this->context);
if (empty($taxUuid)) {
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $taxUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::TAX,
$taxData['id'],
- $this->context
+ true,
);
- $taxUuid = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
}
- return [
- 'id' => $taxUuid,
- 'taxRate' => $taxRate,
- 'name' => $taxData['description'],
- ];
+ $tax = [];
+ $tax['id'] = &$taxUuid;
+ $tax['taxRate'] = $taxRate;
+ $tax['name'] = $taxData['description'];
+
+ return $tax;
}
/**
@@ -806,14 +741,11 @@ private function getTax(array $taxData): array
private function getUnit(array $data): array
{
$unit = [];
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $unit['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::UNIT,
$data['id'],
- $this->context
+ true,
);
- $unit['id'] = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
$this->applyUnitTranslation($unit, $data);
$this->convertValue($unit, 'shortCode', $data, 'unit');
@@ -843,14 +775,11 @@ private function applyUnitTranslation(array &$unit, array $data): void
$this->convertValue($localeTranslation, 'shortCode', $data, 'unit');
$this->convertValue($localeTranslation, 'name', $data, 'description');
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $localeTranslation['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::UNIT_TRANSLATION,
$data['id'] . ':' . $this->locale,
- $this->context
+ true,
);
- $localeTranslation['id'] = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
$languageUuid = $this->languageLookup->get($this->locale, $this->context);
if ($languageUuid !== null) {
@@ -870,28 +799,21 @@ private function getEsdFiles(array $esdFiles, string $oldVariantId, array $conve
$mediaObjects = [];
foreach ($esdFiles as $esdFile) {
$newProductMedia = [];
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $newProductMedia['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::PRODUCT_DOWNLOAD,
$oldVariantId . '_' . $esdFile['id'],
- $this->context
+ true,
);
- $newProductMedia['id'] = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
- $newProductMedia['productId'] = $converted['id'];
+ $newProductMedia['productId'] = &$converted['id'];
/** @var array $newMedia */
$newMedia = [];
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $newMedia['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::MEDIA,
'esd_' . $esdFile['id'],
- $this->context
+ true,
);
- $newMedia['id'] = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
-
if (empty($esdFile['name'])) {
$this->loggingService->log(
MigrationLogBuilder::fromMigrationContext($this->migrationContext)
@@ -931,7 +853,7 @@ private function getEsdFiles(array $esdFiles, string $oldVariantId, array $conve
'uri' => $path . '/' . $esdFile['name'],
'fileName' => $esdFile['name'],
'fileSize' => 0,
- 'mediaId' => $newMedia['id'],
+ 'mediaId' => &$newMedia['id'],
]
);
@@ -999,26 +921,20 @@ private function getMedia(array $media, string $oldVariantId, array $converted):
}
$newProductMedia = [];
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $newProductMedia['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::PRODUCT_MEDIA,
$oldVariantId . $mediaData['id'],
- $this->context
+ true,
);
- $newProductMedia['id'] = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
- $newProductMedia['productId'] = $converted['id'];
+ $newProductMedia['productId'] = &$converted['id'];
$this->convertValue($newProductMedia, 'position', $mediaData, 'position', self::TYPE_INTEGER);
$newMedia = [];
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $newMedia['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::MEDIA,
$mediaData['media']['id'],
- $this->context
+ true,
);
- $newMedia['id'] = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
if (empty($mediaData['media']['name'])) {
$mediaData['media']['name'] = $newMedia['id'];
@@ -1031,7 +947,7 @@ private function getMedia(array $media, string $oldVariantId, array $converted):
'uri' => $mediaData['media']['uri'] ?? $mediaData['media']['path'],
'fileName' => $mediaData['media']['name'],
'fileSize' => (int) $mediaData['media']['file_size'],
- 'mediaId' => $newMedia['id'],
+ 'mediaId' => &$newMedia['id'],
]
);
@@ -1039,16 +955,11 @@ private function getMedia(array $media, string $oldVariantId, array $converted):
$this->convertValue($newMedia, 'title', $mediaData['media'], 'name');
$this->convertValue($newMedia, 'alt', $mediaData, 'description');
- $albumMapping = $this->mappingService->getMapping(
- $this->connectionId,
- DefaultEntities::MEDIA_FOLDER,
- $mediaData['media']['albumID'],
- $this->context
- );
-
- if ($albumMapping !== null) {
- $newMedia['mediaFolderId'] = $albumMapping['entityId'];
- $this->mappingIds[] = $albumMapping['id'];
+ if (!empty($mediaData['media']['albumID'])) {
+ $newMedia['mediaFolderId'] = &$this->mappingServiceV2->getMapping(
+ DefaultEntities::MEDIA_FOLDER,
+ $mediaData['media']['albumID'],
+ );
}
$newProductMedia['media'] = $newMedia;
@@ -1143,14 +1054,11 @@ private function applyMediaTranslation(array &$media, array $data): void
$this->convertValue($localeTranslation, 'title', $data['media'], 'name');
$this->convertValue($localeTranslation, 'alt', $data, 'description');
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $localeTranslation['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::MEDIA_TRANSLATION,
$data['media']['id'] . ':' . $this->locale,
- $this->context
+ true,
);
- $localeTranslation['id'] = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
$languageUuid = $this->languageLookup->get($this->locale, $this->context);
if ($languageUuid !== null) {
@@ -1166,15 +1074,12 @@ private function applyMediaTranslation(array &$media, array $data): void
*/
private function getManufacturerMedia(array $media): array
{
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $manufacturerMedia = [];
+ $manufacturerMedia['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::MEDIA,
$media['id'],
- $this->context
+ true,
);
- $manufacturerMedia = [];
- $manufacturerMedia['id'] = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
if (empty($media['name'])) {
$media['name'] = $manufacturerMedia['id'];
@@ -1182,16 +1087,11 @@ private function getManufacturerMedia(array $media): array
$this->applyMediaTranslation($manufacturerMedia, ['media' => $media]);
- $albumMapping = $this->mappingService->getMapping(
- $this->connectionId,
- DefaultEntities::MEDIA_FOLDER,
- $media['albumID'],
- $this->context
- );
-
- if ($albumMapping !== null) {
- $manufacturerMedia['mediaFolderId'] = $albumMapping['entityId'];
- $this->mappingIds[] = $albumMapping['id'];
+ if (!empty($media['albumID'])) {
+ $manufacturerMedia['mediaFolderId'] = &$this->mappingServiceV2->getMapping(
+ DefaultEntities::MEDIA_FOLDER,
+ $media['albumID'],
+ );
}
$this->mediaFileService->saveMediaFile(
@@ -1201,7 +1101,7 @@ private function getManufacturerMedia(array $media): array
'uri' => $media['uri'] ?? $media['path'],
'fileName' => $media['name'],
'fileSize' => (int) $media['file_size'],
- 'mediaId' => $manufacturerMedia['id'],
+ 'mediaId' => &$manufacturerMedia['id'],
]
);
@@ -1219,26 +1119,20 @@ private function applyOptionTranslation(array &$option, array $data): void
$localeOptionTranslation['languageId'] = $languageUuid;
$localeGroupTranslation = $localeOptionTranslation;
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $localeOptionTranslation['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::PROPERTY_GROUP_OPTION_TRANSLATION,
Hasher::hash(\mb_strtolower($data['name'] . '_' . $data['group']['name']), 'md5') . ':' . $this->locale,
- $this->context
+ true,
);
- $localeOptionTranslation['id'] = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
$this->convertValue($localeOptionTranslation, 'name', $data, 'name');
$this->convertValue($localeOptionTranslation, 'position', $data, 'position', self::TYPE_INTEGER);
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $localeGroupTranslation['id'] = &$this->mappingServiceV2->getMapping(
DefaultEntities::PROPERTY_GROUP_TRANSLATION,
Hasher::hash(\mb_strtolower($data['group']['name']), 'md5') . ':' . $this->locale,
- $this->context
+ true,
);
- $localeGroupTranslation['id'] = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
$this->convertValue($localeGroupTranslation, 'name', $data['group'], 'name');
$this->convertValue($localeGroupTranslation, 'description', $data['group'], 'description');
@@ -1259,20 +1153,15 @@ private function getPrice(array $priceData, float $taxRate): array
$gross = \round((float) $priceData['price'] * (1 + $taxRate / 100), $this->context->getRounding()->getDecimals());
if (isset($priceData['currencyShortName'])) {
- $currencyMapping = $this->mappingService->getMapping(
- $this->connectionId,
+ $this->currencyUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::CURRENCY,
$priceData['currencyShortName'],
- $this->context
);
}
- if (!isset($currencyMapping)) {
- return [];
- }
- $this->currencyUuid = $currencyMapping['entityId'];
- $this->mappingIds[] = $currencyMapping['id'];
$price = [];
+ // todo: validate that removing this is fine
+ /*
if ($this->currencyUuid !== Defaults::CURRENCY) {
$price[] = [
'currencyId' => Defaults::CURRENCY,
@@ -1281,9 +1170,10 @@ private function getPrice(array $priceData, float $taxRate): array
'linked' => true,
];
}
+ */
$price[] = [
- 'currencyId' => $this->currencyUuid,
+ 'currencyId' => &$this->currencyUuid,
'gross' => $gross,
'net' => (float) $priceData['price'],
'linked' => true,
@@ -1293,7 +1183,7 @@ private function getPrice(array $priceData, float $taxRate): array
if ($listPrice > 0) {
$listPriceGross = \round((float) $priceData['pseudoprice'] * (1 + $taxRate / 100), $this->context->getRounding()->getDecimals());
$price[0]['listPrice'] = [
- 'currencyId' => $this->currencyUuid,
+ 'currencyId' => &$this->currencyUuid,
'gross' => $listPriceGross,
'net' => $listPrice,
'linked' => true,
@@ -1317,63 +1207,40 @@ private function getPrices(array $priceData, array $converted): array
continue;
}
- $customerGroupMapping = $this->mappingService->getMapping(
- $this->connectionId,
+ $customerGroupUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::CUSTOMER_GROUP,
$price['customergroup']['id'],
- $this->context
);
- if ($customerGroupMapping === null) {
- continue;
- }
- $customerGroupUuid = $customerGroupMapping['entityId'];
- $this->mappingIds[] = $customerGroupMapping['id'];
-
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $productPriceRuleUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::RULE,
'customerGroupRule_productPriceRule_' . $price['id'] . '_' . $price['customergroup']['id'],
- $this->context
+ true,
);
- $productPriceRuleUuid = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $priceRuleUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::RULE,
'customerGroupRule_' . $price['customergroup']['id'],
- $this->context
+ true,
);
- $priceRuleUuid = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $orContainerUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::RULE,
'customerGroupRule_orContainer_' . $price['customergroup']['id'],
- $this->context
+ true,
);
- $orContainerUuid = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $andContainerUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::RULE,
'customerGroupRule_andContainer_' . $price['customergroup']['id'],
- $this->context
+ true,
);
- $andContainerUuid = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $conditionUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::RULE,
'customerGroupRule_condition_' . $price['customergroup']['id'],
- $this->context
+ true,
);
- $conditionUuid = $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
$priceArray = $this->getPrice($price, $converted['tax']['taxRate']);
@@ -1392,10 +1259,10 @@ private function getPrices(array $priceData, array $converted): array
}
$data = [
- 'id' => $productPriceRuleUuid,
- 'productId' => $converted['id'],
+ 'id' => &$productPriceRuleUuid,
+ 'productId' => &$converted['id'],
'rule' => [
- 'id' => $priceRuleUuid,
+ 'id' => &$priceRuleUuid,
'name' => $price['customergroup']['description'],
'priority' => 0,
'moduleTypes' => [
@@ -1405,26 +1272,26 @@ private function getPrices(array $priceData, array $converted): array
],
'conditions' => [
[
- 'id' => $orContainerUuid,
+ 'id' => &$orContainerUuid,
'type' => (new OrRule())->getName(),
'value' => [],
],
[
- 'id' => $andContainerUuid,
+ 'id' => &$andContainerUuid,
'type' => (new AndRule())->getName(),
- 'parentId' => $orContainerUuid,
+ 'parentId' => &$orContainerUuid,
'value' => [],
],
[
- 'id' => $conditionUuid,
+ 'id' => &$conditionUuid,
'type' => 'customerCustomerGroup',
- 'parentId' => $andContainerUuid,
+ 'parentId' => &$andContainerUuid,
'position' => 1,
'value' => [
'customerGroupIds' => [
- $customerGroupUuid,
+ &$customerGroupUuid,
],
'operator' => '=',
],
@@ -1476,20 +1343,19 @@ private function setGivenProductTranslation(array &$data, array &$converted): vo
$localeTranslation = [];
- $localeTranslation['productId'] = $converted['id'];
+ $localeTranslation['productId'] = &$converted['id'];
$this->convertValue($localeTranslation, 'name', $originalData, 'name');
$this->convertValue($localeTranslation, 'keywords', $originalData, 'keywords');
$this->convertValue($localeTranslation, 'description', $originalData, 'description_long');
$this->convertValue($localeTranslation, 'metaTitle', $originalData, 'metaTitle');
$this->convertValue($localeTranslation, 'packUnit', $originalData['detail'], 'packunit');
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ // only create and persist this mapping, no use in this converter
+ $this->mappingServiceV2->getMapping(
DefaultEntities::PRODUCT_TRANSLATION,
$this->oldProductId . ':' . $this->locale,
- $this->context
+ true,
);
- $this->mappingIds[] = $mapping['id'];
$languageUuid = $this->languageLookup->get($this->locale, $this->context);
$localeTranslation['languageId'] = $languageUuid;
@@ -1512,35 +1378,32 @@ private function createMainCategoriesMapping(array $categories): array
{
$mainCategories = [];
foreach ($categories as $category) {
- $id = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $id = &$this->mappingServiceV2->getMapping(
DefaultEntities::PRODUCT_MAIN_CATEGORY,
$category['id'],
- $this->context
- )['entityId'];
+ true,
+ );
- $categoryId = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $categoryId = &$this->mappingServiceV2->getMapping(
DefaultEntities::CATEGORY,
$category['categoryId'],
- $this->context
- )['entityId'];
+ true,
+ );
- $salesChannelId = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
+ $salesChannelId = &$this->mappingServiceV2->getMapping(
DefaultEntities::SALES_CHANNEL,
$category['shopId'],
- $this->context
- )['entityId'];
+ true,
+ );
if (!$id || !$categoryId || !$salesChannelId) {
continue;
}
$mainCategories[] = [
- 'id' => $id,
- 'categoryId' => $categoryId,
- 'salesChannelId' => $salesChannelId,
+ 'id' => &$id,
+ 'categoryId' => &$categoryId,
+ 'salesChannelId' => &$salesChannelId,
];
}
@@ -1557,18 +1420,14 @@ private function getCategoryMapping(array $categories): array
$categoryMapping = [];
foreach ($categories as $category) {
- $mapping = $this->mappingService->getMapping(
- $this->connectionId,
+ $mappingUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::CATEGORY,
$category['id'],
- $this->context
);
- if ($mapping === null) {
- continue;
- }
- $categoryMapping[] = ['id' => (string) $mapping['entityId']];
- $this->mappingIds[] = $mapping['id'];
+ $categoryMapping[] = [
+ 'id' => &$mappingUuid,
+ ];
}
return $categoryMapping;
@@ -1585,30 +1444,23 @@ private function getVisibilities(array $converted, array $shops): array
$visibilities = [];
foreach ($shops as $shop) {
- $mapping = $this->mappingService->getMapping(
- $this->connectionId,
+ $salesChannelUuid = &$this->mappingServiceV2->getMapping(
DefaultEntities::SALES_CHANNEL,
$shop,
- $this->context
);
- if ($mapping !== null) {
- $salesChannelUuid = (string) $mapping['entityId'];
- $this->mappingIds[] = $mapping['id'];
- $mapping = $this->mappingService->getOrCreateMapping(
- $this->connectionId,
- DefaultEntities::PRODUCT_VISIBILITY,
- $this->oldProductId . '_' . $shop,
- $this->context
- );
- $this->mappingIds[] = $mapping['id'];
- $visibilities[] = [
- 'id' => (string) $mapping['entityId'],
- 'productId' => $converted['id'],
- 'salesChannelId' => $salesChannelUuid,
- 'visibility' => ProductVisibilityDefinition::VISIBILITY_ALL,
- ];
- }
+ $productVisibilityUuid = &$this->mappingServiceV2->getMapping(
+ DefaultEntities::PRODUCT_VISIBILITY,
+ $this->oldProductId . '_' . $shop,
+ true,
+ );
+
+ $visibilities[] = [
+ 'id' => &$productVisibilityUuid,
+ 'productId' => &$converted['id'],
+ 'salesChannelId' => &$salesChannelUuid,
+ 'visibility' => ProductVisibilityDefinition::VISIBILITY_ALL,
+ ];
}
return $visibilities;