Skip to content

Commit

Permalink
Merge pull request #533 from BitBagCommerce/feature/OP-525
Browse files Browse the repository at this point in the history
OP-525: Content migration script
  • Loading branch information
jkindly authored Sep 24, 2024
2 parents 3740621 + c8dc43a commit 4b028d9
Show file tree
Hide file tree
Showing 30 changed files with 493 additions and 139 deletions.
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

0 comments on commit 4b028d9

Please sign in to comment.