Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OP-525: Content migration script #533

Merged
merged 4 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/block_legacy.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
code,type,name_en_US,content_en_US,sections,channels,products,image_en_US,slug_en_US
test4,image,Test,test,"blog, general",US_WEB,"010ba66b-adee-3d6e-9d63-67c44d686db1, 01d35db9-247d-3834-b300-20483d5e34e8",https://bitbag.shop/assets/web/images/header-logo.png,https://bitbag.shop/assets/web/images/header-logo.png
49 changes: 49 additions & 0 deletions doc/legacy_data_migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Legacy data migration

## Introduction

You can migrate your blocks & pages from the 4.x version to the 5.x version of the plugin.
To do so, you need to follow the steps below.

## Steps

1. Create new CSV files with blocks & pages data in the 4.x format.
See an example in [block_legacy.csv](block_legacy.csv) or [page_legacy.csv](page_legacy.csv).
2. Install the 5.x version of the plugin.
3. Go to the console and run the following command:
```bash
bin/console cms:import:csv page_legacy {file_path}.csv
bin/console cms:import:csv block_legacy {file_path}.csv
```

## Info about legacy CSV files columns

### Blocks

- **code** - block code.
- **type** - it will be ignored.
- **name_LOCALE** - block name. First occurrence of its column is the default name for the block.
For each locale, there will be created a Heading content element.
- **content_LOCALE** - block content. For each locale, there will be created a Textarea content element.
- **sections** - it will be converted to the block's collections.
- **channels** - block channels.
- **products** - block products. There will be created Products grid content element.
- **image_LOCALE** - block image. For each locale, there will be created a Single media content element.
- **slug_LOCALE** - it will be ignored.

### Pages

- **code** - page code.
- **sections** - it will be converted to the page's collections.
- **channels** - page channels.
- **products** - page products. There will be created Products grid content element.
- **slug_LOCALE** - page slug.
- **name_LOCALE** - page name. First occurrence of its column is the default name for the page.
For each locale, there will be created a Heading content element.
- **image_LOCALE** - page image. For each locale, there will be created a Single media content element.
- **meta_keywords_LOCALE** - page meta keywords.
- **meta_description_LOCALE** - page meta description.
- **content_LOCALE** - page content. For each locale, there will be created a Textarea content element.
- **breadcrumb_LOCALE** - it will be ignored.
- **name_when_linked_LOCALE** - for each locale, there will be created a teaser title.
- **description_when_linked_LOCALE** - for each locale, there will be created a teaser content.
2 changes: 2 additions & 0 deletions doc/page_legacy.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
code,sections,channels,products,slug_en_US,name_en_US,image_en_US,meta_keywords_en_US,meta_description_en_US,content_en_US,breadcrumb_en_US,name_when_linked_en_US,description_when_linked_en_US
aboutUS,,US_WEB,,about_us,About US,,About US,About US,"",,,
4 changes: 0 additions & 4 deletions spec/Importer/BlockImporterSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ public function let(
ResourceResolverInterface $blockResourceResolver,
ImporterCollectionsResolverInterface $importerCollectionsResolver,
ImporterChannelsResolverInterface $importerChannelsResolver,
ImporterLocalesResolverInterface $importerLocalesResolver,
ImporterProductsResolverInterface $importerProductsResolver,
ImporterTaxonsResolverInterface $importerTaxonsResolver,
ImporterProductsInTaxonsResolverInterface $importerProductsInTaxonsResolver,
Expand All @@ -36,7 +35,6 @@ public function let(
$blockResourceResolver,
$importerCollectionsResolver,
$importerChannelsResolver,
$importerLocalesResolver,
$importerProductsResolver,
$importerTaxonsResolver,
$importerProductsInTaxonsResolver,
Expand All @@ -55,7 +53,6 @@ public function it_imports_block(
ResourceResolverInterface $blockResourceResolver,
ImporterCollectionsResolverInterface $importerCollectionsResolver,
ImporterChannelsResolverInterface $importerChannelsResolver,
ImporterLocalesResolverInterface $importerLocalesResolver,
ImporterProductsResolverInterface $importerProductsResolver,
ImporterTaxonsResolverInterface $importerTaxonsResolver,
ImporterProductsInTaxonsResolverInterface $importerProductsInTaxonsResolver,
Expand All @@ -73,7 +70,6 @@ public function it_imports_block(

$importerCollectionsResolver->resolve($block, null)->shouldBeCalled();
$importerChannelsResolver->resolve($block, null)->shouldBeCalled();
$importerLocalesResolver->resolve($block, null)->shouldBeCalled();
$importerProductsResolver->resolve($block, null)->shouldBeCalled();
$importerTaxonsResolver->resolve($block, null)->shouldBeCalled();
$importerProductsInTaxonsResolver->resolve($block, null)->shouldBeCalled();
Expand Down
61 changes: 0 additions & 61 deletions spec/Resolver/BlockResourceResolverSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace spec\Sylius\CmsPlugin\Resolver;

use Doctrine\Common\Collections\ArrayCollection;
use PhpSpec\ObjectBehavior;
use Psr\Log\LoggerInterface;
use Sylius\CmsPlugin\Entity\BlockInterface;
Expand All @@ -14,7 +13,6 @@
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Locale\Context\LocaleContextInterface;
use Sylius\Component\Locale\Model\LocaleInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;

final class BlockResourceResolverSpec extends ObjectBehavior
Expand All @@ -39,74 +37,15 @@ public function it_implements_block_resource_resolver_interface(): void
$this->shouldHaveType(BlockResourceResolverInterface::class);
}

public function it_logs_warning_if_block_was_not_found(
BlockRepositoryInterface $blockRepository,
LoggerInterface $logger,
ChannelContextInterface $channelContext,
ChannelInterface $channel,
) {
$channel->getCode()->willReturn('WEB');
$channelContext->getChannel()->willReturn($channel);
$blockRepository->findEnabledByCode('homepage_banner', 'WEB')->willReturn(null);

$logger
->warning(sprintf(
'Block with "%s" code was not found in the database.',
'homepage_banner',
))
->shouldBeCalled()
;

$this->findOrLog('homepage_banner');
}

public function it_logs_warning_if_block_was_found_but_it_does_not_have_locale(
BlockRepositoryInterface $blockRepository,
LoggerInterface $logger,
ChannelContextInterface $channelContext,
ChannelInterface $channel,
LocaleContextInterface $localeContext,
LocaleInterface $locale,
RepositoryInterface $localeRepository,
BlockInterface $block,
) {
$channel->getCode()->willReturn('WEB');
$channelContext->getChannel()->willReturn($channel);
$blockRepository->findEnabledByCode('homepage_banner', 'WEB')->willReturn($block);
$localeContext->getLocaleCode()->willReturn('en_US');
$locale->getCode()->willReturn('en_US');
$localeRepository->findOneBy(['code' => 'en_US'])->willReturn($locale);
$block->hasLocale($locale)->willReturn(false);
$block->getLocales()->willReturn(new ArrayCollection(['pl_PL']));

$logger
->warning(sprintf(
'Block with "%s" code was found in the database, but it does not have "%s" locale.',
'homepage_banner',
'en_US',
))
->shouldBeCalled()
;

$this->findOrLog('homepage_banner');
}

public function it_returns_block_if_found_in_database(
BlockRepositoryInterface $blockRepository,
BlockInterface $block,
ChannelContextInterface $channelContext,
ChannelInterface $channel,
LocaleContextInterface $localeContext,
LocaleInterface $locale,
RepositoryInterface $localeRepository,
) {
$channel->getCode()->willReturn('WEB');
$channelContext->getChannel()->willReturn($channel);
$blockRepository->findEnabledByCode('homepage_banner', 'WEB')->willReturn($block);
$localeContext->getLocaleCode()->willReturn('en_US');
$locale->getCode()->willReturn('en_US');
$localeRepository->findOneBy(['code' => 'en_US'])->willReturn($locale);
$block->hasLocale($locale)->willReturn(true);

$this->findOrLog('homepage_banner')->shouldReturn($block);
}
Expand Down
3 changes: 0 additions & 3 deletions src/Entity/Block.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Sylius\CmsPlugin\Entity\Trait\ChannelsAwareTrait;
use Sylius\CmsPlugin\Entity\Trait\CollectibleTrait;
use Sylius\CmsPlugin\Entity\Trait\ContentElementsAwareTrait;
use Sylius\CmsPlugin\Entity\Trait\LocaleAwareTrait;
use Sylius\CmsPlugin\Entity\Trait\ProductsAwareTrait;
use Sylius\CmsPlugin\Entity\Trait\ProductsInTaxonsAwareTrait;
use Sylius\CmsPlugin\Entity\Trait\TaxonAwareTrait;
Expand All @@ -19,7 +18,6 @@ class Block implements BlockInterface
use CollectibleTrait;
use ChannelsAwareTrait;
use ContentElementsAwareTrait;
use LocaleAwareTrait;
use ProductsAwareTrait;
use TaxonAwareTrait;
use ProductsInTaxonsAwareTrait;
Expand All @@ -29,7 +27,6 @@ public function __construct()
$this->initializeCollectionsCollection();
$this->initializeChannelsCollection();
$this->initializeContentElementsCollection();
$this->initializeLocalesCollection();
$this->initializeProductsCollection();
$this->initializeTaxonCollection();
$this->initializeProductsInTaxonsCollection();
Expand Down
1 change: 0 additions & 1 deletion src/Entity/BlockInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ interface BlockInterface extends
CollectibleInterface,
ChannelsAwareInterface,
ContentElementsAwareInterface,
LocaleAwareInterface,
ProductsAwareInterface,
TaxonAwareInterface,
ProductsInTaxonsAwareInterface,
Expand Down
85 changes: 85 additions & 0 deletions src/Factory/ContentElementFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

declare(strict_types=1);

namespace Sylius\CmsPlugin\Factory;

use Sylius\CmsPlugin\Entity\ContentConfiguration;

final class ContentElementFactory
{
public static function createHeadingContentElement(
?string $locale,
?string $headingType,
?string $headingContent,
): ?ContentConfiguration {
if (null === $headingContent) {
return null;
}

$contentConfiguration = new ContentConfiguration();
$contentConfiguration->setLocale($locale ?? 'en_US');
$contentConfiguration->setType('heading');
$contentConfiguration->setConfiguration([
'heading_type' => $headingType ?? 'h1',
'heading' => $headingContent,
]);

return $contentConfiguration;
}

public static function createTextareaContentElement(?string $locale, ?string $content): ?ContentConfiguration
{
if (null === $content) {
return null;
}

$contentConfiguration = new ContentConfiguration();
$contentConfiguration->setLocale($locale ?? 'en_US');
$contentConfiguration->setType('textarea');
$contentConfiguration->setConfiguration([
'textarea' => $content,
]);

return $contentConfiguration;
}

public static function createProductsGridContentElement(?string $locale, ?string $codes): ?ContentConfiguration
{
if (null === $codes) {
return null;
}

$productsCodes = explode(',', $codes);
$productsCodes = array_map(static function (string $element): string {
return trim($element);
}, $productsCodes);

$contentConfiguration = new ContentConfiguration();
$contentConfiguration->setLocale($locale ?? 'en_US');
$contentConfiguration->setType('products_grid');
$contentConfiguration->setConfiguration([
'products_grid' => [
'products' => $productsCodes,
],
]);

return $contentConfiguration;
}

public static function createSingleMediaContentElement(?string $locale, ?string $code): ?ContentConfiguration
{
if (null === $code) {
return null;
}

$contentConfiguration = new ContentConfiguration();
$contentConfiguration->setLocale($locale ?? 'en_US');
$contentConfiguration->setType('single_media');
$contentConfiguration->setConfiguration([
'single_media' => $code,
]);

return $contentConfiguration;
}
}
1 change: 0 additions & 1 deletion src/Fixture/BlockFixture.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ protected function configureOptionsNode(ArrayNodeDefinition $optionsNode): void
->booleanNode('enabled')->defaultTrue()->end()
->arrayNode('collections')->scalarPrototype()->end()->end()
->arrayNode('channels')->scalarPrototype()->end()->end()
->arrayNode('locales')->scalarPrototype()->end()->end()
->arrayNode('products')->scalarPrototype()->end()->end()
->arrayNode('taxons')->scalarPrototype()->end()->end()
->arrayNode('products_in_taxons')->scalarPrototype()->end()->end()
Expand Down
3 changes: 0 additions & 3 deletions src/Fixture/Factory/BlockFixtureFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use Sylius\CmsPlugin\Assigner\ChannelsAssignerInterface;
use Sylius\CmsPlugin\Assigner\CollectionsAssignerInterface;
use Sylius\CmsPlugin\Assigner\LocalesAssignerInterface;
use Sylius\CmsPlugin\Assigner\ProductsAssignerInterface;
use Sylius\CmsPlugin\Assigner\ProductsInTaxonsAssignerInterface;
use Sylius\CmsPlugin\Assigner\TaxonsAssignerInterface;
Expand All @@ -22,7 +21,6 @@ public function __construct(
private BlockRepositoryInterface $blockRepository,
private CollectionsAssignerInterface $collectionsAssigner,
private ChannelsAssignerInterface $channelAssigner,
private LocalesAssignerInterface $localesAssigner,
private ProductsAssignerInterface $productsAssigner,
private TaxonsAssignerInterface $taxonsAssigner,
private ProductsInTaxonsAssignerInterface $productsInTaxonsAssigner,
Expand Down Expand Up @@ -56,7 +54,6 @@ private function createBlock(string $code, array $blockData): void

$this->collectionsAssigner->assign($block, $blockData['collections']);
$this->channelAssigner->assign($block, $blockData['channels']);
$this->localesAssigner->assign($block, $blockData['locales']);
$this->productsAssigner->assign($block, $blockData['products']);
$this->taxonsAssigner->assign($block, $blockData['taxons']);
$this->productsInTaxonsAssigner->assign($block, $blockData['products_in_taxons']);
Expand Down
1 change: 0 additions & 1 deletion src/Form/Type/BlockType.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'multiple' => true,
'expanded' => true,
])
->add('locales')
->add('contentElements', CollectionType::class, [
'label' => false,
'entry_type' => ContentConfigurationType::class,
Expand Down
8 changes: 5 additions & 3 deletions src/Importer/AbstractImporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,15 @@ protected function getTranslatableColumnValue(
protected function getAvailableLocales(array $translatableColumns, array $columns): array
{
$locales = [];

foreach ($translatableColumns as $translatableColumn) {
$translatableColumn = str_replace('__locale__', '_', $translatableColumn);

foreach ($columns as $column) {
if (str_starts_with($column, $translatableColumn)) {
$locales[] = str_replace($translatableColumn, '', $column);
$localePart = substr($column, strlen($translatableColumn));

if (preg_match('/^[a-z]{2}(_[A-Z]{2})?$/', $localePart)) {
$locales[] = $localePart;
}
}
}
}
Expand Down
3 changes: 0 additions & 3 deletions src/Importer/BlockImporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use Sylius\CmsPlugin\Repository\BlockRepositoryInterface;
use Sylius\CmsPlugin\Resolver\Importer\ImporterChannelsResolverInterface;
use Sylius\CmsPlugin\Resolver\Importer\ImporterCollectionsResolverInterface;
use Sylius\CmsPlugin\Resolver\Importer\ImporterLocalesResolverInterface;
use Sylius\CmsPlugin\Resolver\Importer\ImporterProductsInTaxonsResolverInterface;
use Sylius\CmsPlugin\Resolver\Importer\ImporterProductsResolverInterface;
use Sylius\CmsPlugin\Resolver\Importer\ImporterTaxonsResolverInterface;
Expand All @@ -22,7 +21,6 @@ public function __construct(
private ResourceResolverInterface $blockResourceResolver,
private ImporterCollectionsResolverInterface $importerCollectionsResolver,
private ImporterChannelsResolverInterface $importerChannelsResolver,
private ImporterLocalesResolverInterface $importerLocalesResolver,
private ImporterProductsResolverInterface $importerProductsResolver,
private ImporterTaxonsResolverInterface $importerTaxonsResolver,
private ImporterProductsInTaxonsResolverInterface $importerProductsInTaxonsResolver,
Expand All @@ -45,7 +43,6 @@ public function import(array $row): void

$this->importerCollectionsResolver->resolve($block, $this->getColumnValue(self::COLLECTIONS_COLUMN, $row));
$this->importerChannelsResolver->resolve($block, $this->getColumnValue(self::CHANNELS_COLUMN, $row));
$this->importerLocalesResolver->resolve($block, $this->getColumnValue(self::LOCALES_COLUMN, $row));
$this->importerProductsResolver->resolve($block, $this->getColumnValue(self::PRODUCTS_COLUMN, $row));
$this->importerTaxonsResolver->resolve($block, $this->getColumnValue(self::TAXONS_COLUMN, $row));
$this->importerProductsInTaxonsResolver->resolve($block, $this->getColumnValue(self::PRODUCTS_IN_TAXONS_COLUMN, $row));
Expand Down
2 changes: 0 additions & 2 deletions src/Importer/BlockImporterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ interface BlockImporterInterface extends ImporterInterface

public const COLLECTIONS_COLUMN = 'collections';

public const LOCALES_COLUMN = 'locales';

public const CHANNELS_COLUMN = 'channels';

public const PRODUCTS_COLUMN = 'products';
Expand Down
Loading
Loading