diff --git a/src/DependencyInjection/shopware.php b/src/DependencyInjection/shopware.php index e0dc2f43e..3913c1437 100644 --- a/src/DependencyInjection/shopware.php +++ b/src/DependencyInjection/shopware.php @@ -115,6 +115,7 @@ use SwagMigrationAssistant\Profile\Shopware\DataSelection\WishlistDataSelection; use SwagMigrationAssistant\Profile\Shopware\Gateway\Api\Reader\ApiReader; use SwagMigrationAssistant\Profile\Shopware\Gateway\Api\Reader\TableCountReader; +use SwagMigrationAssistant\Profile\Shopware\Gateway\Api\Reader\TimezoneReader as ApiTimezoneReader; use SwagMigrationAssistant\Profile\Shopware\Gateway\Api\ShopwareApiGateway; use SwagMigrationAssistant\Profile\Shopware\Gateway\Connection\ConnectionFactory; use SwagMigrationAssistant\Profile\Shopware\Gateway\Local\Reader\AbstractReader; @@ -169,6 +170,7 @@ use SwagMigrationAssistant\Profile\Shopware\Premapping\OrderStateReader; use SwagMigrationAssistant\Profile\Shopware\Premapping\PaymentMethodReader; use SwagMigrationAssistant\Profile\Shopware\Premapping\SalutationReader; +use SwagMigrationAssistant\Profile\Shopware\Premapping\TimezoneReader; use SwagMigrationAssistant\Profile\Shopware\Premapping\TransactionStateReader; use SwagMigrationAssistant\Profile\Shopware\Writer\ProductOptionRelationWriter; use SwagMigrationAssistant\Profile\Shopware\Writer\ProductPropertyRelationWriter; @@ -965,6 +967,13 @@ $services->set(NewsletterRecipientStatusReader::class) ->tag('shopware.migration.pre_mapping_reader'); + $services->set(ApiTimezoneReader::class) + ->parent(ApiReader::class); + + $services->set(TimezoneReader::class) + ->args([service(ApiTimezoneReader::class)]) + ->tag('shopware.migration.pre_mapping_reader'); + $services->set(ProductOptionRelationWriter::class) ->parent(AbstractWriter::class) ->args([ diff --git a/src/DependencyInjection/shopware54.php b/src/DependencyInjection/shopware54.php index 59104b996..55d33303e 100644 --- a/src/DependencyInjection/shopware54.php +++ b/src/DependencyInjection/shopware54.php @@ -100,19 +100,23 @@ $services->set(Shopware54ProductConverter::class) ->parent(ProductConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54ProductOptionRelationConverter::class) ->parent(ProductOptionRelationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54ProductPropertyRelationConverter::class) ->parent(ProductPropertyRelationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54TranslationConverter::class) ->parent(TranslationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54CategoryAttributeConverter::class) ->parent(CategoryAttributeConverter::class) @@ -120,27 +124,33 @@ $services->set(Shopware54CategoryConverter::class) ->parent(CategoryConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54MediaFolderConverter::class) ->parent(MediaFolderConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54MediaConverter::class) ->parent(MediaConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54CustomerConverter::class) ->parent(CustomerConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54CustomerWishlistConverter::class) ->parent(CustomerWishlistConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54OrderConverter::class) ->parent(OrderConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54OrderDocumentAttributeConverter::class) ->parent(OrderDocumentAttributeConverter::class) @@ -148,7 +158,8 @@ $services->set(Shopware54OrderDocumentConverter::class) ->parent(OrderDocumentConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54CustomerGroupAttributeConverter::class) ->parent(CustomerAttributeConverter::class) @@ -156,53 +167,66 @@ $services->set(Shopware54CustomerGroupConverter::class) ->parent(CustomerGroupConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54PropertyGroupOptionConverter::class) ->parent(PropertyGroupOptionConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54NumberRangeConverter::class) ->parent(NumberRangeConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54CurrencyConverter::class) ->parent(CurrencyConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54LanguageConverter::class) ->parent(LanguageConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54SalesChannelConverter::class) ->parent(SalesChannelConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54NewsletterRecipientConverter::class) ->parent(NewsletterRecipientConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54ShippingMethodConverter::class) ->parent(ShippingMethodConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54ProductReviewConverter::class) ->parent(ProductReviewConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54SeoUrlConverter::class) ->parent(SeoUrlConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54CrossSellingConverter::class) ->parent(CrossSellingConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54MainVariantRelationConverter::class) ->parent(MainVariantRelationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware54PromotionConverter::class) ->parent(PromotionConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); }; diff --git a/src/DependencyInjection/shopware55.php b/src/DependencyInjection/shopware55.php index b1ded36b7..7a3cf24c4 100644 --- a/src/DependencyInjection/shopware55.php +++ b/src/DependencyInjection/shopware55.php @@ -100,19 +100,23 @@ $services->set(Shopware55ProductConverter::class) ->parent(ProductConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55ProductOptionRelationConverter::class) ->parent(ProductOptionRelationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55ProductPropertyRelationConverter::class) ->parent(ProductPropertyRelationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55TranslationConverter::class) ->parent(TranslationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55CategoryAttributeConverter::class) ->parent(CategoryAttributeConverter::class) @@ -120,23 +124,28 @@ $services->set(Shopware55CategoryConverter::class) ->parent(CategoryConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55MediaFolderConverter::class) ->parent(MediaFolderConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55MediaConverter::class) ->parent(MediaConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55CustomerConverter::class) ->parent(CustomerConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55OrderConverter::class) ->parent(OrderConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55OrderDocumentAttributeConverter::class) ->parent(OrderDocumentAttributeConverter::class) @@ -144,7 +153,8 @@ $services->set(Shopware55OrderDocumentConverter::class) ->parent(OrderDocumentConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55CustomerGroupAttributeConverter::class) ->parent(CustomerAttributeConverter::class) @@ -152,57 +162,71 @@ $services->set(Shopware55CustomerGroupConverter::class) ->parent(CustomerGroupConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55CustomerWishlistConverter::class) ->parent(CustomerWishlistConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55PropertyGroupOptionConverter::class) ->parent(PropertyGroupOptionConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55NumberRangeConverter::class) ->parent(NumberRangeConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55CurrencyConverter::class) ->parent(CurrencyConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55LanguageConverter::class) ->parent(LanguageConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55SalesChannelConverter::class) ->parent(SalesChannelConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55NewsletterRecipientConverter::class) ->parent(NewsletterRecipientConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55ShippingMethodConverter::class) ->parent(ShippingMethodConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55ProductReviewConverter::class) ->parent(ProductReviewConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55SeoUrlConverter::class) ->parent(SeoUrlConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55CrossSellingConverter::class) ->parent(CrossSellingConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55MainVariantRelationConverter::class) ->parent(MainVariantRelationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware55PromotionConverter::class) ->parent(PromotionConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); }; diff --git a/src/DependencyInjection/shopware56.php b/src/DependencyInjection/shopware56.php index 5276d1429..8811de4a4 100644 --- a/src/DependencyInjection/shopware56.php +++ b/src/DependencyInjection/shopware56.php @@ -100,19 +100,23 @@ $services->set(Shopware56ProductConverter::class) ->parent(ProductConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56ProductOptionRelationConverter::class) ->parent(ProductOptionRelationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56ProductPropertyRelationConverter::class) ->parent(ProductPropertyRelationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56TranslationConverter::class) ->parent(TranslationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56CategoryAttributeConverter::class) ->parent(CategoryAttributeConverter::class) @@ -120,27 +124,33 @@ $services->set(Shopware56CategoryConverter::class) ->parent(CategoryConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56MediaFolderConverter::class) ->parent(MediaFolderConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56MediaConverter::class) ->parent(MediaConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56CustomerConverter::class) ->parent(CustomerConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56CustomerWishlistConverter::class) ->parent(CustomerWishlistConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56OrderConverter::class) ->parent(OrderConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56OrderDocumentAttributeConverter::class) ->parent(OrderDocumentAttributeConverter::class) @@ -148,7 +158,8 @@ $services->set(Shopware56OrderDocumentConverter::class) ->parent(OrderDocumentConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56CustomerGroupAttributeConverter::class) ->parent(CustomerAttributeConverter::class) @@ -156,53 +167,66 @@ $services->set(Shopware56CustomerGroupConverter::class) ->parent(CustomerGroupConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56PropertyGroupOptionConverter::class) ->parent(PropertyGroupOptionConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56NumberRangeConverter::class) ->parent(NumberRangeConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56CurrencyConverter::class) ->parent(CurrencyConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56LanguageConverter::class) ->parent(LanguageConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56SalesChannelConverter::class) ->parent(SalesChannelConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56NewsletterRecipientConverter::class) ->parent(NewsletterRecipientConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56ShippingMethodConverter::class) ->parent(ShippingMethodConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56ProductReviewConverter::class) ->parent(ProductReviewConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56SeoUrlConverter::class) ->parent(SeoUrlConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56CrossSellingConverter::class) ->parent(CrossSellingConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56MainVariantRelationConverter::class) ->parent(MainVariantRelationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware56PromotionConverter::class) ->parent(PromotionConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); }; diff --git a/src/DependencyInjection/shopware57.php b/src/DependencyInjection/shopware57.php index fcfe55967..8e1b0dbd6 100644 --- a/src/DependencyInjection/shopware57.php +++ b/src/DependencyInjection/shopware57.php @@ -100,19 +100,23 @@ $services->set(Shopware57ProductConverter::class) ->parent(ProductConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57ProductOptionRelationConverter::class) ->parent(ProductOptionRelationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57ProductPropertyRelationConverter::class) ->parent(ProductPropertyRelationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57TranslationConverter::class) ->parent(TranslationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57CategoryAttributeConverter::class) ->parent(CategoryAttributeConverter::class) @@ -120,27 +124,33 @@ $services->set(Shopware57CategoryConverter::class) ->parent(CategoryConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57MediaFolderConverter::class) ->parent(MediaFolderConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57MediaConverter::class) ->parent(MediaConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57CustomerConverter::class) ->parent(CustomerConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57CustomerWishlistConverter::class) ->parent(CustomerWishlistConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57OrderConverter::class) ->parent(OrderConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57OrderDocumentAttributeConverter::class) ->parent(OrderDocumentAttributeConverter::class) @@ -148,7 +158,8 @@ $services->set(Shopware57OrderDocumentConverter::class) ->parent(OrderDocumentConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57CustomerGroupAttributeConverter::class) ->parent(CustomerAttributeConverter::class) @@ -156,53 +167,66 @@ $services->set(Shopware57CustomerGroupConverter::class) ->parent(CustomerGroupConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57PropertyGroupOptionConverter::class) ->parent(PropertyGroupOptionConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57PromotionConverter::class) ->parent(PromotionConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57NumberRangeConverter::class) ->parent(NumberRangeConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57MainVariantRelationConverter::class) ->parent(MainVariantRelationConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57CurrencyConverter::class) ->parent(CurrencyConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57LanguageConverter::class) ->parent(LanguageConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57SalesChannelConverter::class) ->parent(SalesChannelConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57NewsletterRecipientConverter::class) ->parent(NewsletterRecipientConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57ShippingMethodConverter::class) ->parent(ShippingMethodConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57ProductReviewConverter::class) ->parent(ProductReviewConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57SeoUrlConverter::class) ->parent(SeoUrlConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); $services->set(Shopware57CrossSellingConverter::class) ->parent(CrossSellingConverter::class) - ->tag('shopware.migration.converter'); + ->tag('shopware.migration.converter') + ->tag('kernel.reset', ['method' => 'reset']); }; diff --git a/src/Exception/MigrationException.php b/src/Exception/MigrationException.php index 755ab62cb..f2db21293 100644 --- a/src/Exception/MigrationException.php +++ b/src/Exception/MigrationException.php @@ -11,6 +11,7 @@ use Shopware\Core\Framework\DataAbstractionLayer\Field\Field; use Shopware\Core\Framework\HttpException; use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Gateway\Reader\ReaderInterface; use Symfony\Component\HttpFoundation\Response; /** @@ -107,6 +108,8 @@ class MigrationException extends HttpException final public const MAIN_VARIANT_RELATION_MISSING_ID_AND_ORDER_NUMBER = 'SWAG_MIGRATION__MAIN_VARIANT_RELATION_MISSING_ID_AND_ORDER_NUMBER'; + final public const READER_REGISTRY_USAGE_NOT_ALLOWED = 'SWAG_MIGRATION__READER_REGISTRY_USAGE_NOT_ALLOWED'; + public static function associationEntityRequiredMissing(string $entity, string $missingEntity): self { return new self( @@ -567,4 +570,17 @@ public static function mainVariantRelationMissingIdAndOrderNumber(): self 'MainVariantRelation requires ID and order number.', ); } + + /** + * @param class-string $class + */ + public static function readerRegistryUsageNotAllowed(string $class): self + { + return new self( + Response::HTTP_INTERNAL_SERVER_ERROR, + self::READER_REGISTRY_USAGE_NOT_ALLOWED, + 'The reader "{{ reader }}" is an internal helper and must not be resolved through the ReaderRegistry.', + ['reader' => $class] + ); + } } diff --git a/src/Migration/Logging/Log/ConvertDateTimeFailedLog.php b/src/Migration/Logging/Log/ConvertDateTimeFailedLog.php new file mode 100644 index 000000000..2099d930b --- /dev/null +++ b/src/Migration/Logging/Log/ConvertDateTimeFailedLog.php @@ -0,0 +1,30 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Migration\Logging\Log; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\AbstractMigrationLogEntry; + +#[Package('fundamentals@after-sales')] +readonly class ConvertDateTimeFailedLog extends AbstractMigrationLogEntry +{ + public static function getLevel(): string + { + return self::LOG_LEVEL_WARNING; + } + + public static function getCode(): string + { + return 'SWAG_MIGRATION_CONVERT_DATE_TIME'; + } + + public static function isUserFixable(): bool + { + return false; + } +} diff --git a/src/Profile/Shopware/Converter/CustomerConverter.php b/src/Profile/Shopware/Converter/CustomerConverter.php index 979fbe7b7..d595ee092 100644 --- a/src/Profile/Shopware/Converter/CustomerConverter.php +++ b/src/Profile/Shopware/Converter/CustomerConverter.php @@ -153,7 +153,7 @@ public function convert( $this->convertValue($converted, 'firstName', $data, 'firstname'); $this->convertValue($converted, 'lastName', $data, 'lastname'); $this->convertValue($converted, 'customerNumber', $data, 'customernumber'); - $this->convertValue($converted, 'birthday', $data, 'birthday', self::TYPE_DATETIME); + $this->convertValue($converted, 'birthday', $data, 'birthday', self::TYPE_DATE); $this->convertValue($converted, 'lockedUntil', $data, 'lockeduntil', self::TYPE_DATETIME); $this->setAccountType($data, $converted); diff --git a/src/Profile/Shopware/Converter/NewsletterRecipientConverter.php b/src/Profile/Shopware/Converter/NewsletterRecipientConverter.php index 97347cba6..5f9fe2cc9 100644 --- a/src/Profile/Shopware/Converter/NewsletterRecipientConverter.php +++ b/src/Profile/Shopware/Converter/NewsletterRecipientConverter.php @@ -50,6 +50,7 @@ public function convert( Context $context, MigrationContextInterface $migrationContext, ): ConvertStruct { + $this->migrationContext = $migrationContext; $connection = $migrationContext->getConnection(); $this->connectionId = $connection->getId(); $this->runId = $migrationContext->getRunUuid(); @@ -84,8 +85,8 @@ public function convert( $converted['id'] = $this->mainMapping['entityId']; $this->convertValue($converted, 'email', $data, 'email'); - $this->convertValue($converted, 'createdAt', $data, 'added', 'datetime'); - $this->convertValue($converted, 'confirmedAt', $data, 'double_optin_confirmed', 'datetime'); + $this->convertValue($converted, 'createdAt', $data, 'added', self::TYPE_DATETIME); + $this->convertValue($converted, 'confirmedAt', $data, 'double_optin_confirmed', self::TYPE_DATETIME); if (isset($data['address'])) { $address = $data['address']; diff --git a/src/Profile/Shopware/Converter/ProductConverter.php b/src/Profile/Shopware/Converter/ProductConverter.php index 34f7479ed..b10774c3f 100644 --- a/src/Profile/Shopware/Converter/ProductConverter.php +++ b/src/Profile/Shopware/Converter/ProductConverter.php @@ -471,7 +471,7 @@ private function getProductData(array &$data, array $converted): array $this->convertValue($converted, 'minPurchase', $data['detail'], 'minpurchase', self::TYPE_INTEGER); $this->convertValue($converted, 'purchaseUnit', $data['detail'], 'purchaseunit', self::TYPE_FLOAT); $this->convertValue($converted, 'referenceUnit', $data['detail'], 'referenceunit', self::TYPE_FLOAT); - $this->convertValue($converted, 'releaseDate', $data['detail'], 'releasedate', self::TYPE_DATETIME); + $this->convertValue($converted, 'releaseDate', $data['detail'], 'releasedate', self::TYPE_DATE); $this->convertValue($converted, 'shippingFree', $data['detail'], 'shippingfree', self::TYPE_BOOLEAN); $this->setPurchasePrices($data, $converted); diff --git a/src/Profile/Shopware/Converter/PromotionConverter.php b/src/Profile/Shopware/Converter/PromotionConverter.php index 4f046ff4b..3bff7ca4d 100644 --- a/src/Profile/Shopware/Converter/PromotionConverter.php +++ b/src/Profile/Shopware/Converter/PromotionConverter.php @@ -56,6 +56,8 @@ public function getSourceIdentifier(array $data): string public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ConvertStruct { + $this->migrationContext = $migrationContext; + $this->generateChecksum($data); $this->context = $context; diff --git a/src/Profile/Shopware/Converter/ShopwareConverter.php b/src/Profile/Shopware/Converter/ShopwareConverter.php index 587c68526..d081bddf4 100644 --- a/src/Profile/Shopware/Converter/ShopwareConverter.php +++ b/src/Profile/Shopware/Converter/ShopwareConverter.php @@ -7,26 +7,43 @@ namespace SwagMigrationAssistant\Profile\Shopware\Converter; +use Shopware\Core\Defaults; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; use SwagMigrationAssistant\Migration\Connection\Helper\ConnectionNameSanitizer; use SwagMigrationAssistant\Migration\Converter\Converter; +use SwagMigrationAssistant\Migration\DataSelection\DataSet\DataSet; use SwagMigrationAssistant\Migration\DataSelection\DefaultEntities; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogBuilder; +use SwagMigrationAssistant\Migration\Logging\Log\ConvertDateTimeFailedLog; use SwagMigrationAssistant\Migration\Mapping\Lookup\LanguageLookup; use SwagMigrationAssistant\Migration\MigrationContextInterface; +use SwagMigrationAssistant\Profile\Shopware\Premapping\TimezoneReader; +use Symfony\Contracts\Service\ResetInterface; #[Package('fundamentals@after-sales')] -abstract class ShopwareConverter extends Converter +abstract class ShopwareConverter extends Converter implements ResetInterface { protected const TYPE_STRING = 'string'; protected const TYPE_BOOLEAN = 'bool'; protected const TYPE_INVERT_BOOLEAN = 'invert_bool'; protected const TYPE_INTEGER = 'int'; protected const TYPE_FLOAT = 'float'; + protected const TYPE_DATE = 'date'; protected const TYPE_DATETIME = 'datetime'; protected MigrationContextInterface $migrationContext; + /** + * @var array + */ + private array $timezoneCache = []; + + public function reset(): void + { + $this->timezoneCache = []; + } + public function getSourceIdentifier(array $data): string { return $data['id']; @@ -79,12 +96,26 @@ protected function convertValue( $sourceValue = (float) $sourceData[$sourceKey]; break; - case self::TYPE_DATETIME: + case self::TYPE_DATE: $sourceValue = $sourceData[$sourceKey]; if (!$this->validDate($sourceValue)) { return; } + break; + case self::TYPE_DATETIME: + $dataset = $this->migrationContext->getDataSet(); + $entityName = null; + if ($dataset instanceof DataSet) { + $entityName = $dataset::getEntity(); + } + + $sourceValue = $this->convertDateTime((string) $sourceData[$sourceKey], $entityName); + + if ($sourceValue === null) { + return; + } + break; default: $sourceValue = (string) $sourceData[$sourceKey]; @@ -94,17 +125,6 @@ protected function convertValue( unset($sourceData[$sourceKey]); } - protected function validDate(string $value): bool - { - try { - new \DateTime($value); - - return true; - } catch (\Exception) { - return false; - } - } - /** * @param array $attributes * @param list $excludeList @@ -162,6 +182,16 @@ protected function getAttributes( if (isset($mapping['additionalData']['columnType']) && $mapping['additionalData']['columnType'] === 'float') { $value = (float) $value; } + + if (isset($mapping['additionalData']['columnType']) && $mapping['additionalData']['columnType'] === 'datetime') { + $convertedValue = $this->convertDateTime((string) $value, $entityName); + + if ($convertedValue === null) { + continue; + } + + $value = $convertedValue; + } } } @@ -174,4 +204,87 @@ protected function getAttributes( return $result; } + + protected function validDate(string $value): bool + { + try { + new \DateTime($value); + + return true; + } catch (\Exception) { + return false; + } + } + + private function convertDateTime(string $value, ?string $entityName): ?string + { + if ($value === '') { + return null; + } + + try { + $timezone = $this->getTimezoneFromPremapping(); + if ($timezone === null) { + return (new \DateTimeImmutable($value))->format(Defaults::STORAGE_DATE_TIME_FORMAT); + } + + $date = new \DateTimeImmutable($value, new \DateTimeZone($timezone)); + + return $date + ->setTimezone(new \DateTimeZone('UTC')) + ->format(Defaults::STORAGE_DATE_TIME_FORMAT); + } catch (\Throwable $exception) { + $logBuilder = MigrationLogBuilder::fromMigrationContext($this->migrationContext) + ->withSourceData(['dateTime' => $value]) + ->withExceptionMessage($exception->getMessage()) + ->withException($exception); + + if ($entityName !== null) { + $logBuilder->withEntityName($entityName); + } + + $this->loggingService->log($logBuilder->build(ConvertDateTimeFailedLog::class)); + + return null; + } + } + + /** + * We do not want to add an optional context to the + * "ShopwareConverter::convertValue()" method, as this would break the API + * + * That is why: + * the timezone is read from the connection premapping because the converter has + * no Shopware "Context" available. + * + * "MappingServiceInterface::getMapping()" requires a "Context". + * The timezone is a premapping configuration, so reading it from + * "$migrationContext->getConnection()->getPremapping()" keeps it available + * during conversion without DAL. + */ + private function getTimezoneFromPremapping(): ?string + { + $runId = $this->migrationContext->getRunUuid(); + if (\array_key_exists($runId, $this->timezoneCache)) { + return $this->timezoneCache[$runId]; + } + + $timezone = null; + $premapping = $this->migrationContext->getConnection()->getPremapping(); + foreach ($premapping ?? [] as $item) { + if ($item->getEntity() !== TimezoneReader::MAPPING_NAME) { + continue; + } + + foreach ($item->getMapping() as $mapping) { + if ($mapping->getSourceId() === TimezoneReader::SOURCE_ID) { + $timezone = $mapping->getDestinationUuid() === '' ? null : $mapping->getDestinationUuid(); + } + } + } + + $this->timezoneCache[$runId] = $timezone; + + return $timezone; + } } diff --git a/src/Profile/Shopware/Gateway/Api/Reader/TimezoneReader.php b/src/Profile/Shopware/Gateway/Api/Reader/TimezoneReader.php new file mode 100644 index 000000000..3c8c2528b --- /dev/null +++ b/src/Profile/Shopware/Gateway/Api/Reader/TimezoneReader.php @@ -0,0 +1,38 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Profile\Shopware\Gateway\Api\Reader; + +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Exception\MigrationException; +use SwagMigrationAssistant\Migration\MigrationContextInterface; + +/** + * This API helper is used only by the Shopware timezone premapping. + * + * This is intentionally not a regular migration reader and must not be resolved + * through the ReaderRegistry during the migration process. It + * only exists to fetch the source system timezone from the Migration Connector + * API in the premapping. + * + * The class extends ApiReader only to reuse the existing API client/request + * handling for connector endpoints instead of duplicating that logic here. + */ +#[Package('fundamentals@after-sales')] +class TimezoneReader extends ApiReader +{ + public function supports(MigrationContextInterface $migrationContext): bool + { + // TimezoneReader must not be resolved through the ReaderRegistry + throw MigrationException::readerRegistryUsageNotAllowed(self::class); + } + + protected function getApiRoute(): string + { + return 'SwagMigrationTimezone'; + } +} diff --git a/src/Profile/Shopware/Gateway/Local/Reader/EnvironmentReader.php b/src/Profile/Shopware/Gateway/Local/Reader/EnvironmentReader.php index 2bb7fb446..1c1f1b5b8 100644 --- a/src/Profile/Shopware/Gateway/Local/Reader/EnvironmentReader.php +++ b/src/Profile/Shopware/Gateway/Local/Reader/EnvironmentReader.php @@ -13,23 +13,28 @@ use SwagMigrationAssistant\Migration\Gateway\Reader\EnvironmentReaderInterface; use SwagMigrationAssistant\Migration\MigrationContextInterface; +/** + * @phpstan-type EnvironmentInfo array{defaultShopLanguage: string, host: string, additionalData: array, defaultCurrency: string, config: array} + */ #[Package('fundamentals@after-sales')] class EnvironmentReader extends AbstractReader implements EnvironmentReaderInterface { /** - * @return array{defaultShopLanguage: string, host: string, additionalData: array, defaultCurrency: string} + * @return EnvironmentInfo */ public function read(MigrationContextInterface $migrationContext): array { $locale = $this->getDefaultShopLocale($migrationContext); - return [ + $environmentInformation = [ 'defaultShopLanguage' => $locale, 'host' => $this->getHost($migrationContext), 'additionalData' => $this->getAdditionalData($migrationContext), 'defaultCurrency' => $this->getDefaultCurrency($migrationContext), 'config' => $this->getConfig($migrationContext), ]; + + return $environmentInformation; } /** diff --git a/src/Profile/Shopware/Gateway/Local/ShopwareLocalGateway.php b/src/Profile/Shopware/Gateway/Local/ShopwareLocalGateway.php index beb5b777f..f0ee9b22b 100644 --- a/src/Profile/Shopware/Gateway/Local/ShopwareLocalGateway.php +++ b/src/Profile/Shopware/Gateway/Local/ShopwareLocalGateway.php @@ -148,7 +148,7 @@ public function readEnvironmentInformation( $environmentData['defaultCurrency'], $environmentData['defaultShopLanguage'], $targetLocaleCode, - $this->generateFingerprint($environmentData) + $this->generateFingerprint($environmentData), ); } diff --git a/src/Profile/Shopware/Premapping/TimezoneReader.php b/src/Profile/Shopware/Premapping/TimezoneReader.php new file mode 100644 index 000000000..4ce794c3a --- /dev/null +++ b/src/Profile/Shopware/Premapping/TimezoneReader.php @@ -0,0 +1,114 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Profile\Shopware\Premapping; + +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\MigrationContextInterface; +use SwagMigrationAssistant\Migration\Premapping\AbstractPremappingReader; +use SwagMigrationAssistant\Migration\Premapping\PremappingChoiceStruct; +use SwagMigrationAssistant\Migration\Premapping\PremappingEntityStruct; +use SwagMigrationAssistant\Migration\Premapping\PremappingStruct; +use SwagMigrationAssistant\Profile\Shopware\Gateway\Api\Reader\TimezoneReader as ApiTimezoneReader; +use SwagMigrationAssistant\Profile\Shopware\Gateway\Api\ShopwareApiGateway; +use SwagMigrationAssistant\Profile\Shopware\Gateway\Local\ShopwareLocalGateway; +use SwagMigrationAssistant\Profile\Shopware\ShopwareProfileInterface; + +#[Package('after-sales')] +class TimezoneReader extends AbstractPremappingReader +{ + public const MAPPING_NAME = 'source_timezone'; + + public const SOURCE_ID = 'timezone'; + + /** + * @var array + */ + private array $validTimezones; + + public function __construct( + private readonly ApiTimezoneReader $timezoneReader, + ) { + $this->validTimezones = \array_flip(\DateTimeZone::listIdentifiers()); + } + + public function supports(MigrationContextInterface $migrationContext, array $entityGroupNames): bool + { + return $migrationContext->getProfile() instanceof ShopwareProfileInterface + && \in_array($migrationContext->getGateway()->getName(), [ + ShopwareApiGateway::GATEWAY_NAME, + ShopwareLocalGateway::GATEWAY_NAME, + ], true); + } + + public static function getMappingName(): string + { + return self::MAPPING_NAME; + } + + public function getPremapping(Context $context, MigrationContextInterface $migrationContext): PremappingStruct + { + $this->fillConnectionPremappingDictionary($migrationContext); + + $choices = $this->getTimeZoneList(); + + $sourceTimezone = $this->readSourceTimezone($migrationContext); + + $destinationTimezone = ''; + + if ($sourceTimezone !== null && isset($this->validTimezones[$sourceTimezone])) { + $destinationTimezone = $sourceTimezone; + } + + if (isset($this->connectionPremappingDictionary[self::SOURCE_ID])) { + $configuredDestination = $this->connectionPremappingDictionary[self::SOURCE_ID]->getDestinationUuid(); + + if (isset($this->validTimezones[$configuredDestination])) { + $destinationTimezone = $configuredDestination; + } + } + + return new PremappingStruct( + self::getMappingName(), + [ + new PremappingEntityStruct( + self::SOURCE_ID, + 'Source system time zone', + $destinationTimezone + ), + ], + $choices + ); + } + + private function readSourceTimezone(MigrationContextInterface $migrationContext): ?string + { + if ($migrationContext->getConnection()->getGatewayName() !== ShopwareApiGateway::GATEWAY_NAME) { + return null; + } + + $timezoneResult = $this->timezoneReader->read($migrationContext); + $timezone = $timezoneResult[0][self::SOURCE_ID] ?? null; + if (!\is_string($timezone) || $timezone === '' || !isset($this->validTimezones[$timezone])) { + return null; + } + + return $timezone; + } + + /** + * @return array + */ + private function getTimeZoneList(): array + { + return array_map( + static fn (string $timezone): PremappingChoiceStruct => new PremappingChoiceStruct($timezone, $timezone), + \DateTimeZone::listIdentifiers() + ); + } +} diff --git a/src/Resources/app/administration/src/module/swag-migration/snippet/de.json b/src/Resources/app/administration/src/module/swag-migration/snippet/de.json index 0e35c33e6..68df9d980 100644 --- a/src/Resources/app/administration/src/module/swag-migration/snippet/de.json +++ b/src/Resources/app/administration/src/module/swag-migration/snippet/de.json @@ -371,7 +371,8 @@ "salesChannel": "Newsletter-Verkaufskanal", "newsletter_status": "Newsletter-Status", "shipping_availability_rule": "Versandartverfügbarkeit", - "user": "Administration Benutzer" + "user": "Administration Benutzer", + "source_timezone": "Zeitzone" } }, "loadingScreenCard": { diff --git a/src/Resources/app/administration/src/module/swag-migration/snippet/en.json b/src/Resources/app/administration/src/module/swag-migration/snippet/en.json index c74c446b1..f9afc9ea2 100644 --- a/src/Resources/app/administration/src/module/swag-migration/snippet/en.json +++ b/src/Resources/app/administration/src/module/swag-migration/snippet/en.json @@ -371,7 +371,8 @@ "salesChannel": "Newsletter Sales Channel", "newsletter_status": "Newsletter status", "shipping_availability_rule": "Shipping method availability", - "user": "Administration user" + "user": "Administration user", + "source_timezone": "Timezone" } }, "loadingScreenCard": { diff --git a/tests/Profile/Shopware/Converter/ShopwareConverterTest.php b/tests/Profile/Shopware/Converter/ShopwareConverterTest.php new file mode 100644 index 000000000..a2714dc4e --- /dev/null +++ b/tests/Profile/Shopware/Converter/ShopwareConverterTest.php @@ -0,0 +1,299 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Test\Profile\Shopware\Converter; + +use PHPUnit\Framework\TestCase; +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Uuid\Uuid; +use SwagMigrationAssistant\Migration\Connection\SwagMigrationConnectionEntity; +use SwagMigrationAssistant\Migration\DataSelection\DataSet\DataSet; +use SwagMigrationAssistant\Migration\Logging\Log\Builder\MigrationLogEntry; +use SwagMigrationAssistant\Migration\Logging\Log\ConvertDateTimeFailedLog; +use SwagMigrationAssistant\Migration\Logging\LoggingServiceInterface; +use SwagMigrationAssistant\Migration\Mapping\MappingServiceInterface; +use SwagMigrationAssistant\Migration\MigrationContext; +use SwagMigrationAssistant\Migration\Premapping\PremappingEntityStruct; +use SwagMigrationAssistant\Migration\Premapping\PremappingStruct; +use SwagMigrationAssistant\Profile\Shopware\DataSelection\DataSet\ProductDataSet; +use SwagMigrationAssistant\Profile\Shopware\Gateway\Local\ShopwareLocalGateway; +use SwagMigrationAssistant\Profile\Shopware\Premapping\TimezoneReader; +use SwagMigrationAssistant\Profile\Shopware55\Shopware55Profile; + +#[Package('after-sales')] +class ShopwareConverterTest extends TestCase +{ + private Context $context; + + private SwagMigrationConnectionEntity $connection; + + protected function setUp(): void + { + $this->context = Context::createDefaultContext(); + $this->connection = new SwagMigrationConnectionEntity(); + $this->connection->setId(Uuid::randomHex()); + $this->connection->setProfileName(Shopware55Profile::PROFILE_NAME); + $this->connection->setGatewayName(ShopwareLocalGateway::GATEWAY_NAME); + $this->connection->setCredentialFields([]); + } + + public function testConvertValueConvertsDateTimeWithMappedSourceTimezoneToUtcStorageFormat(): void + { + $mappingService = $this->createMock(MappingServiceInterface::class); + $mappingService->expects($this->never())->method('getValue'); + $this->setSourceTimezone('Europe/Berlin'); + + $converter = $this->createConverter($mappingService); + + [$converted, $source] = $converter->convertDateTimeValue('2026-05-01 12:30:00'); + + static::assertSame(['createdAt' => '2026-05-01 10:30:00.000'], $converted); + static::assertSame([], $source); + } + + public function testConvertValueCachesSourceTimezonePerRun(): void + { + $mappingService = $this->createMock(MappingServiceInterface::class); + $mappingService->expects($this->never())->method('getValue'); + $this->setSourceTimezone('Europe/Berlin'); + + $converter = $this->createConverter($mappingService); + + [$firstConverted] = $converter->convertDateTimeValue('2026-05-01 12:00:00'); + $this->setSourceTimezone('UTC'); + [$secondConverted] = $converter->convertDateTimeValue('2026-05-01 13:00:00'); + + static::assertSame('2026-05-01 10:00:00.000', $firstConverted['createdAt']); + static::assertSame('2026-05-01 11:00:00.000', $secondConverted['createdAt']); + } + + public function testConvertValueUsesUpdatedSourceTimezoneForNewRun(): void + { + $mappingService = $this->createMock(MappingServiceInterface::class); + $mappingService->expects($this->never())->method('getValue'); + $this->setSourceTimezone('Europe/Berlin'); + + $converter = $this->createConverter($mappingService, null, Uuid::randomHex()); + + [$firstConverted] = $converter->convertDateTimeValue('2026-05-01 12:00:00'); + + $this->setSourceTimezone('UTC'); + $converter->setMigrationContext($this->createMigrationContext(Uuid::randomHex())); + + [$secondConverted] = $converter->convertDateTimeValue('2026-05-01 13:00:00'); + + static::assertSame('2026-05-01 10:00:00.000', $firstConverted['createdAt']); + static::assertSame('2026-05-01 13:00:00.000', $secondConverted['createdAt']); + } + + public function testConvertValueCachesMissingSourceTimezonePerRun(): void + { + $mappingService = $this->createMock(MappingServiceInterface::class); + $mappingService->expects($this->never())->method('getValue'); + $this->setSourceTimezone(null); + + $converter = $this->createConverter($mappingService); + + [$firstConverted] = $converter->convertDateTimeValue('2026-05-01 12:00:00'); + $this->setSourceTimezone('Europe/Berlin'); + [$secondConverted] = $converter->convertDateTimeValue('2026-05-01 13:00:00'); + + static::assertSame('2026-05-01 12:00:00.000', $firstConverted['createdAt']); + static::assertSame('2026-05-01 13:00:00.000', $secondConverted['createdAt']); + } + + public function testConvertValueConvertsDateTimeWithoutContext(): void + { + $mappingService = $this->createMock(MappingServiceInterface::class); + $mappingService->expects($this->never())->method('getValue'); + + $converter = $this->createConverter($mappingService); + + [$converted, $source] = $converter->convertDateTimeValue('2026-05-01 12:30:00'); + + static::assertSame(['createdAt' => '2026-05-01 12:30:00.000'], $converted); + static::assertSame([], $source); + } + + public function testConvertValueDoesNotConvertDateTimeWithInvalidMappedTimezone(): void + { + $mappingService = $this->createMock(MappingServiceInterface::class); + $mappingService->expects($this->never())->method('getValue'); + $loggingService = $this->createMock(LoggingServiceInterface::class); + $loggingService->expects($this->once()) + ->method('log') + ->with(static::callback(static function (MigrationLogEntry $logEntry): bool { + static::assertSame(ConvertDateTimeFailedLog::getCode(), $logEntry->getCode()); + static::assertNull($logEntry->getEntityName()); + + return true; + })) + ->willReturnSelf(); + $this->setSourceTimezone('Not/A_Timezone'); + + $converter = $this->createConverter($mappingService, $loggingService); + + [$converted, $source] = $converter->convertDateTimeValue('2026-05-01 12:30:00'); + + static::assertSame([], $converted); + static::assertSame(['createdAt' => '2026-05-01 12:30:00'], $source); + } + + public function testConvertValueLogsDataSetEntityNameWhenDateTimeCannotBeConverted(): void + { + $mappingService = $this->createMock(MappingServiceInterface::class); + $mappingService->expects($this->never())->method('getValue'); + $loggingService = $this->createMock(LoggingServiceInterface::class); + $loggingService->expects($this->once()) + ->method('log') + ->with(static::callback(static function (MigrationLogEntry $logEntry): bool { + static::assertSame(ConvertDateTimeFailedLog::getCode(), $logEntry->getCode()); + static::assertSame(ProductDataSet::getEntity(), $logEntry->getEntityName()); + + return true; + })) + ->willReturnSelf(); + $this->setSourceTimezone('Not/A_Timezone'); + + $converter = $this->createConverter($mappingService, $loggingService, '', new ProductDataSet()); + + [$converted, $source] = $converter->convertDateTimeValue('2026-05-01 12:30:00'); + + static::assertSame([], $converted); + static::assertSame(['createdAt' => '2026-05-01 12:30:00'], $source); + } + + public function testConvertValueKeepsValidDateValueUnchanged(): void + { + $converter = $this->createConverter($this->createMock(MappingServiceInterface::class)); + + [$converted, $source] = $converter->convertDateValue('2026-05-01'); + + static::assertSame(['birthday' => '2026-05-01'], $converted); + static::assertSame([], $source); + } + + public function testConvertValueDoesNotConvertInvalidDateValue(): void + { + $converter = $this->createConverter($this->createMock(MappingServiceInterface::class)); + + [$converted, $source] = $converter->convertDateValue('not a date'); + + static::assertSame([], $converted); + static::assertSame(['birthday' => 'not a date'], $source); + } + + public function testGetAttributesConvertsDateTimeCustomFieldWithMappedSourceTimezone(): void + { + $mappingService = $this->createMock(MappingServiceInterface::class); + $mappingService->expects($this->once()) + ->method('getMapping') + ->with($this->connection->getId(), 'product_custom_field', 'release_time', $this->context) + ->willReturn([ + 'id' => Uuid::randomHex(), + 'additionalData' => [ + 'columnType' => 'datetime', + ], + ]); + $mappingService->expects($this->never())->method('getValue'); + $this->setSourceTimezone('Europe/Berlin'); + + $converter = $this->createConverter($mappingService); + + $converted = $converter->convertAttributes( + ['release_time' => '2026-05-01 12:30:00'], + 'product', + 'shopware', + $this->context + ); + + static::assertSame([ + 'migration_shopware_product_release_time' => '2026-05-01 10:30:00.000', + ], $converted); + } + + public function testGetAttributesLogsEntityNameWhenDateTimeCustomFieldCannotBeConverted(): void + { + $mappingService = $this->createMock(MappingServiceInterface::class); + $mappingService->expects($this->once()) + ->method('getMapping') + ->with($this->connection->getId(), 'product_custom_field', 'release_time', $this->context) + ->willReturn([ + 'id' => Uuid::randomHex(), + 'additionalData' => [ + 'columnType' => 'datetime', + ], + ]); + $mappingService->expects($this->never())->method('getValue'); + + $loggingService = $this->createMock(LoggingServiceInterface::class); + $loggingService->expects($this->once()) + ->method('log') + ->with(static::callback(static function (MigrationLogEntry $logEntry): bool { + static::assertSame(ConvertDateTimeFailedLog::getCode(), $logEntry->getCode()); + static::assertSame('product', $logEntry->getEntityName()); + + return true; + })) + ->willReturnSelf(); + + $this->setSourceTimezone('Not/A_Timezone'); + + $converter = $this->createConverter($mappingService, $loggingService); + + $converted = $converter->convertAttributes( + ['release_time' => '2026-05-01 12:30:00'], + 'product', + 'shopware', + $this->context + ); + + static::assertNull($converted); + } + + private function createConverter( + MappingServiceInterface $mappingService, + ?LoggingServiceInterface $loggingService = null, + string $runUuid = '', + ?DataSet $dataSet = null, + ): TestShopwareConverter { + $converter = new TestShopwareConverter( + $mappingService, + $loggingService ?? $this->createMock(LoggingServiceInterface::class) + ); + $converter->setMigrationContext($this->createMigrationContext($runUuid, $dataSet)); + + return $converter; + } + + private function createMigrationContext(string $runUuid = '', ?DataSet $dataSet = null): MigrationContext + { + return new MigrationContext( + $this->connection, + new Shopware55Profile(), + null, + $dataSet, + $runUuid + ); + } + + private function setSourceTimezone(?string $timezone): void + { + if ($timezone === null) { + $this->connection->setPremapping([]); + + return; + } + + $this->connection->setPremapping([ + new PremappingStruct(TimezoneReader::getMappingName(), [ + new PremappingEntityStruct(TimezoneReader::SOURCE_ID, $timezone, $timezone), + ]), + ]); + } +} diff --git a/tests/Profile/Shopware/Converter/TestShopwareConverter.php b/tests/Profile/Shopware/Converter/TestShopwareConverter.php new file mode 100644 index 000000000..578f679df --- /dev/null +++ b/tests/Profile/Shopware/Converter/TestShopwareConverter.php @@ -0,0 +1,69 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Test\Profile\Shopware\Converter; + +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\Log\Package; +use SwagMigrationAssistant\Migration\Converter\ConvertStruct; +use SwagMigrationAssistant\Migration\MigrationContextInterface; +use SwagMigrationAssistant\Profile\Shopware\Converter\ShopwareConverter; + +#[Package('fundamentals@after-sales')] +class TestShopwareConverter extends ShopwareConverter +{ + public function supports(MigrationContextInterface $migrationContext): bool + { + return true; + } + + public function convert(array $data, Context $context, MigrationContextInterface $migrationContext): ?ConvertStruct + { + return null; + } + + public function setMigrationContext(MigrationContextInterface $migrationContext): void + { + $this->migrationContext = $migrationContext; + } + + /** + * @return array{0: array, 1: array} + */ + public function convertDateTimeValue(string $value): array + { + $converted = []; + $source = ['createdAt' => $value]; + + $this->convertValue($converted, 'createdAt', $source, 'createdAt', self::TYPE_DATETIME); + + return [$converted, $source]; + } + + /** + * @return array{0: array, 1: array} + */ + public function convertDateValue(string $value): array + { + $converted = []; + $source = ['birthday' => $value]; + + $this->convertValue($converted, 'birthday', $source, 'birthday', self::TYPE_DATE); + + return [$converted, $source]; + } + + /** + * @param array $attributes + * + * @return array|null + */ + public function convertAttributes(array $attributes, string $entityName, string $connectionName, ?Context $context = null): ?array + { + return $this->getAttributes($attributes, $entityName, $connectionName, [], $context); + } +} diff --git a/tests/Profile/Shopware/Gateway/ApiEnvironmentReaderTest.php b/tests/Profile/Shopware/Gateway/ApiEnvironmentReaderTest.php index ab8df2a42..6fdd6e8ca 100644 --- a/tests/Profile/Shopware/Gateway/ApiEnvironmentReaderTest.php +++ b/tests/Profile/Shopware/Gateway/ApiEnvironmentReaderTest.php @@ -18,6 +18,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Uuid\Uuid; use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\Connection\SwagMigrationConnectionEntity; use SwagMigrationAssistant\Migration\Gateway\HttpSimpleClient; @@ -42,10 +43,7 @@ public function testEmptyClientReturnsRequestStatus(): void $environmentReader = new EnvironmentReader($connectionFactory); - $migrationContext = new MigrationContext( - new SwagMigrationConnectionEntity(), - new Shopware55Profile(), - ); + $migrationContext = $this->createMigrationContext(); $response = $environmentReader->read($migrationContext); @@ -82,10 +80,7 @@ public function testResponseExceptions( $client = new HttpSimpleClient($options); - $migrationContext = new MigrationContext( - new SwagMigrationConnectionEntity(), - new Shopware55Profile(), - ); + $migrationContext = $this->createMigrationContext(); $connectionFactory = $this->createMock(ConnectionFactory::class); $connectionFactory @@ -232,10 +227,7 @@ public function testGetsEnvironmentInformation(): void $client = new HttpSimpleClient($options); - $migrationContext = new MigrationContext( - new SwagMigrationConnectionEntity(), - new Shopware55Profile() - ); + $migrationContext = $this->createMigrationContext(); $connectionFactory = $this->createMock(ConnectionFactory::class); $connectionFactory @@ -249,4 +241,20 @@ public function testGetsEnvironmentInformation(): void static::assertEquals(['version' => 'test'], $response['environmentInformation']); static::assertEquals(new RequestStatusStruct(), $response['requestStatus']); } + + private function createMigrationContext(): MigrationContext + { + return $this->createMigrationContextWithConnectionId(Uuid::randomHex()); + } + + private function createMigrationContextWithConnectionId(string $connectionId): MigrationContext + { + $connection = new SwagMigrationConnectionEntity(); + $connection->setId($connectionId); + + return new MigrationContext( + $connection, + new Shopware55Profile() + ); + } } diff --git a/tests/Profile/Shopware/Gateway/ApiReaderTest.php b/tests/Profile/Shopware/Gateway/ApiReaderTest.php index f670eaf77..33122ea88 100644 --- a/tests/Profile/Shopware/Gateway/ApiReaderTest.php +++ b/tests/Profile/Shopware/Gateway/ApiReaderTest.php @@ -18,6 +18,7 @@ use SwagMigrationAssistant\Migration\MigrationContext; use SwagMigrationAssistant\Profile\Shopware\DataSelection\DataSet\ProductDataSet; use SwagMigrationAssistant\Profile\Shopware\Gateway\Api\Reader\ProductReader; +use SwagMigrationAssistant\Profile\Shopware\Gateway\Api\Reader\TimezoneReader; use SwagMigrationAssistant\Profile\Shopware\Gateway\Connection\ConnectionFactory; use SwagMigrationAssistant\Profile\Shopware55\Shopware55Profile; use Symfony\Component\HttpFoundation\Response as SymfonyResponse; @@ -106,4 +107,25 @@ public function testReadGatewayException(): void static::fail('MigrationException not thrown'); } + + public function testTimezoneReaderCannotBeResolvedThroughReaderRegistry(): void + { + $migrationContext = new MigrationContext( + new SwagMigrationConnectionEntity(), + new Shopware55Profile(), + ); + $reader = new TimezoneReader($this->createMock(ConnectionFactory::class)); + + try { + $reader->supports($migrationContext); + } catch (MigrationException $e) { + static::assertSame(SymfonyResponse::HTTP_INTERNAL_SERVER_ERROR, $e->getStatusCode()); + static::assertSame(MigrationException::READER_REGISTRY_USAGE_NOT_ALLOWED, $e->getErrorCode()); + static::assertSame(TimezoneReader::class, $e->getParameters()['reader']); + + return; + } + + static::fail('MigrationException not thrown'); + } } diff --git a/tests/Profile/Shopware/Gateway/Local/EnvironmentReaderTest.php b/tests/Profile/Shopware/Gateway/Local/EnvironmentReaderTest.php index 7aa4a643b..9a480dbdc 100644 --- a/tests/Profile/Shopware/Gateway/Local/EnvironmentReaderTest.php +++ b/tests/Profile/Shopware/Gateway/Local/EnvironmentReaderTest.php @@ -59,5 +59,19 @@ public function testRead(): void static::assertSame('1', $additionalData['children'][0]['main_id']); static::assertSame('en_GB', $additionalData['children'][0]['locale']['locale']); static::assertSame('39', $additionalData['children'][0]['category_id']); + static::assertArrayNotHasKey('timezone', $data); + } + + public function testReadDoesNotReadTimezoneFromInstallationRootConfig(): void + { + $credentialFields = $this->connection->getCredentialFields(); + static::assertIsArray($credentialFields); + + $credentialFields['installationRoot'] = __DIR__ . '/_fixtures/environment_reader/valid'; + $this->connection->setCredentialFields($credentialFields); + + $data = $this->environmentReader->read($this->migrationContext); + + static::assertArrayNotHasKey('timezone', $data); } } diff --git a/tests/Profile/Shopware/Gateway/Local/_fixtures/environment_reader/config_does_not_return_array/config.php b/tests/Profile/Shopware/Gateway/Local/_fixtures/environment_reader/config_does_not_return_array/config.php new file mode 100644 index 000000000..828748973 --- /dev/null +++ b/tests/Profile/Shopware/Gateway/Local/_fixtures/environment_reader/config_does_not_return_array/config.php @@ -0,0 +1,8 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return 'invalid'; diff --git a/tests/Profile/Shopware/Gateway/Local/_fixtures/environment_reader/empty_database_timezone/config.php b/tests/Profile/Shopware/Gateway/Local/_fixtures/environment_reader/empty_database_timezone/config.php new file mode 100644 index 000000000..03c4bc135 --- /dev/null +++ b/tests/Profile/Shopware/Gateway/Local/_fixtures/environment_reader/empty_database_timezone/config.php @@ -0,0 +1,12 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return [ + 'db' => [ + 'timezone' => '', + ], +]; diff --git a/tests/Profile/Shopware/Gateway/Local/_fixtures/environment_reader/missing_database_timezone/config.php b/tests/Profile/Shopware/Gateway/Local/_fixtures/environment_reader/missing_database_timezone/config.php new file mode 100644 index 000000000..97db6e9a5 --- /dev/null +++ b/tests/Profile/Shopware/Gateway/Local/_fixtures/environment_reader/missing_database_timezone/config.php @@ -0,0 +1,10 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return [ + 'db' => [], +]; diff --git a/tests/Profile/Shopware/Gateway/Local/_fixtures/environment_reader/valid/config.php b/tests/Profile/Shopware/Gateway/Local/_fixtures/environment_reader/valid/config.php new file mode 100644 index 000000000..9b4f6e05a --- /dev/null +++ b/tests/Profile/Shopware/Gateway/Local/_fixtures/environment_reader/valid/config.php @@ -0,0 +1,12 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return [ + 'db' => [ + 'timezone' => 'Europe/Berlin', + ], +]; diff --git a/tests/Profile/Shopware/Gateway/ShopwareApiGatewayTest.php b/tests/Profile/Shopware/Gateway/ShopwareApiGatewayTest.php index d71223b64..6ae5a5893 100644 --- a/tests/Profile/Shopware/Gateway/ShopwareApiGatewayTest.php +++ b/tests/Profile/Shopware/Gateway/ShopwareApiGatewayTest.php @@ -11,6 +11,7 @@ use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Log\Package; use Shopware\Core\Framework\Test\TestCaseBase\KernelTestBehaviour; +use Shopware\Core\Framework\Uuid\Uuid; use SwagMigrationAssistant\Exception\MigrationException; use SwagMigrationAssistant\Migration\Connection\SwagMigrationConnectionEntity; use SwagMigrationAssistant\Migration\EnvironmentInformation; @@ -75,6 +76,7 @@ public function testReadFailed(): void public function testReadEnvironmentInformationFailed(): void { $connection = new SwagMigrationConnectionEntity(); + $connection->setId(Uuid::randomHex()); $connection->setCredentialFields([ 'endpoint' => 'testing', 'apiUser' => 'testing', @@ -120,6 +122,7 @@ public function testReadEnvironmentInformation(): void $connectionFactory = new ConnectionFactory(); $apiReader = new ProductReader($connectionFactory); $environmentReader = new EnvironmentDummyReader($connectionFactory); + $environmentReader->setDummyData([]); $tableReader = new TableReader($connectionFactory); $tableCountReader = new TableCountDummyReader($connectionFactory, new DummyLoggingService()); diff --git a/tests/Profile/Shopware/Premapping/TimezoneReaderTest.php b/tests/Profile/Shopware/Premapping/TimezoneReaderTest.php new file mode 100644 index 000000000..461be62e8 --- /dev/null +++ b/tests/Profile/Shopware/Premapping/TimezoneReaderTest.php @@ -0,0 +1,157 @@ + + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace SwagMigrationAssistant\Test\Profile\Shopware\Premapping; + +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\TestCase; +use Shopware\Core\Framework\Context; +use Shopware\Core\Framework\Log\Package; +use Shopware\Core\Framework\Uuid\Uuid; +use SwagMigrationAssistant\Migration\Connection\SwagMigrationConnectionEntity; +use SwagMigrationAssistant\Migration\Gateway\GatewayInterface; +use SwagMigrationAssistant\Migration\MigrationContext; +use SwagMigrationAssistant\Migration\Premapping\PremappingEntityStruct; +use SwagMigrationAssistant\Migration\Premapping\PremappingStruct; +use SwagMigrationAssistant\Profile\Shopware\Gateway\Api\Reader\TimezoneReader as ApiTimezoneReader; +use SwagMigrationAssistant\Profile\Shopware\Gateway\Api\ShopwareApiGateway; +use SwagMigrationAssistant\Profile\Shopware\Gateway\Local\ShopwareLocalGateway; +use SwagMigrationAssistant\Profile\Shopware\Premapping\TimezoneReader; +use SwagMigrationAssistant\Profile\Shopware55\Shopware55Profile; + +#[Package('after-sales')] +class TimezoneReaderTest extends TestCase +{ + private Context $context; + + protected function setUp(): void + { + $this->context = Context::createDefaultContext(); + } + + public function testSupportsShopwareApiAndLocalGateways(): void + { + $reader = $this->createReader(null, 0); + + static::assertTrue($reader->supports($this->createMigrationContext(ShopwareApiGateway::GATEWAY_NAME), [])); + static::assertTrue($reader->supports($this->createMigrationContext(ShopwareLocalGateway::GATEWAY_NAME), [])); + } + + public function testGetPremappingUsesDetectedSourceTimezone(): void + { + $migrationContext = $this->createMigrationContext(ShopwareApiGateway::GATEWAY_NAME); + $reader = $this->createReader([[TimezoneReader::SOURCE_ID => 'Europe/Berlin']]); + $premapping = $reader->getPremapping($this->context, $migrationContext); + + static::assertSame(TimezoneReader::getMappingName(), $premapping->getEntity()); + static::assertNotEmpty($premapping->getChoices()); + static::assertCount(1, $premapping->getMapping()); + static::assertSame(TimezoneReader::SOURCE_ID, $premapping->getMapping()[0]->getSourceId()); + static::assertSame('Source system time zone', $premapping->getMapping()[0]->getDescription()); + static::assertSame('Europe/Berlin', $premapping->getMapping()[0]->getDestinationUuid()); + } + + public function testGetPremappingKeepsConfiguredDestinationTimezone(): void + { + $connection = $this->createConnection(ShopwareLocalGateway::GATEWAY_NAME); + $connection->setPremapping([ + new PremappingStruct(TimezoneReader::getMappingName(), [ + new PremappingEntityStruct(TimezoneReader::SOURCE_ID, 'Europe/Berlin', 'America/New_York'), + ]), + ]); + + $migrationContext = $this->createMigrationContext(ShopwareLocalGateway::GATEWAY_NAME, $connection); + $reader = $this->createReader(null, 0); + $premapping = $reader->getPremapping($this->context, $migrationContext); + + static::assertSame('America/New_York', $premapping->getMapping()[0]->getDestinationUuid()); + } + + #[DataProvider('missingSourceTimezoneProvider')] + public function testGetPremappingReturnsSelectableRowWhenSourceTimezoneCannotBeRead(?string $sourceTimezone): void + { + $migrationContext = $this->createMigrationContext(ShopwareApiGateway::GATEWAY_NAME); + $reader = $this->createReader([[TimezoneReader::SOURCE_ID => $sourceTimezone]]); + $premapping = $reader->getPremapping($this->context, $migrationContext); + + static::assertNotEmpty($premapping->getChoices()); + static::assertCount(1, $premapping->getMapping()); + static::assertSame(TimezoneReader::SOURCE_ID, $premapping->getMapping()[0]->getSourceId()); + static::assertSame('Source system time zone', $premapping->getMapping()[0]->getDescription()); + static::assertSame('', $premapping->getMapping()[0]->getDestinationUuid()); + } + + public function testGetPremappingUsesEnvironmentInformationForApiGateway(): void + { + $migrationContext = $this->createMigrationContext(ShopwareApiGateway::GATEWAY_NAME); + $reader = $this->createReader([[TimezoneReader::SOURCE_ID => 'UTC']]); + $premapping = $reader->getPremapping($this->context, $migrationContext); + + static::assertSame('UTC', $premapping->getMapping()[0]->getDestinationUuid()); + } + + public function testGetPremappingDoesNotReadSourceTimezoneForLocalGateway(): void + { + $migrationContext = $this->createMigrationContext(ShopwareLocalGateway::GATEWAY_NAME); + $reader = $this->createReader(null, 0); + $premapping = $reader->getPremapping($this->context, $migrationContext); + + static::assertSame('Source system time zone', $premapping->getMapping()[0]->getDescription()); + static::assertSame('', $premapping->getMapping()[0]->getDestinationUuid()); + } + + /** + * @return array + */ + public static function missingSourceTimezoneProvider(): array + { + return [ + 'missing source timezone' => ['sourceTimezone' => null], + 'empty source timezone' => ['sourceTimezone' => ''], + 'invalid source timezone' => ['sourceTimezone' => 'Not/A_Timezone'], + ]; + } + + /** + * @param array|null $timezoneResult + */ + private function createReader(?array $timezoneResult, int $readCount = 1): TimezoneReader + { + $timezoneReader = $this->createMock(ApiTimezoneReader::class); + $readExpectation = $timezoneReader->expects($this->exactly($readCount)) + ->method('read'); + + if ($timezoneResult !== null) { + $readExpectation->willReturn($timezoneResult); + } + + return new TimezoneReader($timezoneReader); + } + + private function createMigrationContext(string $gatewayName, ?SwagMigrationConnectionEntity $connection = null): MigrationContext + { + $gateway = $this->createMock(GatewayInterface::class); + $gateway->method('getName')->willReturn($gatewayName); + + return new MigrationContext( + $connection ?? $this->createConnection($gatewayName), + new Shopware55Profile(), + $gateway + ); + } + + private function createConnection(string $gatewayName): SwagMigrationConnectionEntity + { + $connection = new SwagMigrationConnectionEntity(); + $connection->setId(Uuid::randomHex()); + $connection->setProfileName(Shopware55Profile::PROFILE_NAME); + $connection->setGatewayName($gatewayName); + $connection->setCredentialFields([]); + + return $connection; + } +} diff --git a/tests/acceptance/fixtures/MigrationConnection.ts b/tests/acceptance/fixtures/MigrationConnection.ts index 8bb94358f..27c89cc45 100644 --- a/tests/acceptance/fixtures/MigrationConnection.ts +++ b/tests/acceptance/fixtures/MigrationConnection.ts @@ -11,6 +11,7 @@ export interface MigrationConnectionStruct { export const MigrationConnection = base.extend({ MigrationConnection: async ({ AdminApiContext, DatabaseCredentials }, use) => { const connectionName = 'shopware'; + const installationRoot = '/tmp'; const createResponse = await AdminApiContext.post('/api/swag-migration-connection', { data: { @@ -43,7 +44,7 @@ export const MigrationConnection = base.extend({ dbUser: DatabaseCredentials.user, dbPassword: DatabaseCredentials.password, dbName: DatabaseCredentials.database, - installationRoot: '/tmp', + installationRoot, }, }, }); diff --git a/tests/acceptance/snapshots/MigrationTest.spec.ts/linux/data-selection-assigment-with-errors.png b/tests/acceptance/snapshots/MigrationTest.spec.ts/linux/data-selection-assigment-with-errors.png index bfc5d659f..7c8a6c47d 100644 Binary files a/tests/acceptance/snapshots/MigrationTest.spec.ts/linux/data-selection-assigment-with-errors.png and b/tests/acceptance/snapshots/MigrationTest.spec.ts/linux/data-selection-assigment-with-errors.png differ diff --git a/tests/acceptance/snapshots/MigrationTest.spec.ts/linux/migration-log-sw5.txt b/tests/acceptance/snapshots/MigrationTest.spec.ts/linux/migration-log-sw5.txt index 46f35dba1..0c372993d 100644 --- a/tests/acceptance/snapshots/MigrationTest.spec.ts/linux/migration-log-sw5.txt +++ b/tests/acceptance/snapshots/MigrationTest.spec.ts/linux/migration-log-sw5.txt @@ -243,6 +243,19 @@ Environment information (JSON): Pre-mapping (JSON): [ + { + "extensions": [], + "entity": "source_timezone", + "mapping": [ + { + "extensions": [], + "sourceId": "timezone", + "description": "Source system time zone", + "destinationUuid": "Africa\/Abidjan" + } + ], + "choices": [] + }, { "extensions": [], "entity": "order_state",