4

We are using Shopware 6.3.5 and want to replace properties during import (update) of products.

We specifiy to product ID and the list or property UUIDs (in the column properties)

Currently, those get added to the existing properties in the database.

This seems to be due to the behavior of the upsert call during the import.

How can this be changed?

We tried this:

DI:

<argument type="service" id="product.repository"/>

Method:

class ImportSubscriber implements EventSubscriberInterface
{
    private EntityRepositoryInterface $productRepository;

    public function __construct(EntityRepositoryInterface $productRepository)
    {
        $this->productRepository = $productRepository;
    }

    public static function getSubscribedEvents(): array
    {
        return [
            ImportExportBeforeImportRecordEvent::class => 'onImportExportBeforeImportRecord'
        ];
    }

    public function onImportExportBeforeImportRecord(ImportExportBeforeImportRecordEvent $event)
    {
        $this->productRepository->update([
            [
                'id' => $event->getRecord()['id'],
                'property_ids' => null,
            ]
        ], $event->getContext());
    }
}

But this update statement causes a \Shopware\Core\Framework\DataAbstractionLayer\Write\Command\WriteTypeIntendException in \Shopware\Core\Framework\DataAbstractionLayer\Write\Command\WriteCommandQueue::ensureIs

I am also wondering what this WriteCommandQueue does and if it is too lower level what I am trying to do?

Additionally I am wondering if property_ids is the right field to change or actually I have to clear up the product_property table for that import row?

EDIT

Next I tried this

DI:

<argument type="service" id="product_property.repository"/>

Method:

    public function onImportExportBeforeImportRecord(ImportExportBeforeImportRecordEvent $event)
    {
        $existing = $this->productPropertryRepository->search(
            (new Criteria())->addFilter(new EqualsFilter('productId', $event->getRecord()['id'])),
            $event->getContext()
        );
        $entities = $existing->getEntities();
        foreach($entities as $entity) {
            $this->productPropertryRepository->delete([
                [
                    'productId' => $event->getRecord()['id'],
                    'optionId' => $entity->get('optionId')
                ]
            ], $event->getContext());
        }
    }

But I get a

Shopware\Core\Framework\DataAbstractionLayer\Exception\MappingEntityClassesException with

Mapping definition neither have entities nor collection.

Alex
  • 32,506
  • 16
  • 106
  • 171

2 Answers2

3

The search method does not work on Mapping Definitions. You can use searchIds to get the ids and call the delete like you have.

Shyim
  • 761
  • 3
  • 2
1

Based on @Shyim's answer, this works:

    public function onImportExportBeforeImportRecord(ImportExportBeforeImportRecordEvent $event)
    {
        $existing = $this->productPropertyRepository->searchIds(
            (new Criteria())->addFilter(new EqualsFilter('productId', $event->getRecord()['id'])),
            $event->getContext()
        );

        foreach($existing->getIds() as $id) {
            if (in_array($id['property_group_option_id'], ($event->getRecord()['properties'] ?? [] ))) {
                continue;
            }

            $this->productPropertyRepository->delete([
                [
                    'productId' => $event->getRecord()['id'],
                    'optionId' => $id['property_group_option_id']
                ]
            ], $event->getContext());
        }
    }

Note: This deletes all current properties, a more sophistic solution might be to only specific properties (for example by supplying a list of names in the import) or have a positive/negative list with properties that should be cleared or kept.

Alex
  • 32,506
  • 16
  • 106
  • 171