1

I have the requirement where upon importing I need to be able to change to products' product model. I tried to do this by changing the parent in the CSV file I'm importing, but this will show the following message:

WARNING parent: Property "parent" cannot be modified, "new_parent_code" given.

What is the proper way to make this work? I tried 'hacking' the database by manually assigning a different parent to the product by editing the parent directly in the pim_catalog_product-table, and this seemed to work, but when editing the product unexpected results occur.

Could anyone point me in the right direction how I can change a product parent upon importing?

update:

I now came up with the following solution:

In my own bundle, I added Resources/config/updaters.yml (using DependencyInjecten Extension) with the following:

parameters:
    # Rewrite parent field setter so we can allow the importer to update the parent:
    pim_catalog.updater.setter.parent_field.class:            Vendor\Bundle\InstallerBundle\Updater\Setter\ParentFieldSetter

And my custom ParentFieldSetter.php:

namespace Vendor\Bundle\InstallerBundle\Updater\Setter;

use Akeneo\Component\StorageUtils\Exception\ImmutablePropertyException;
use Akeneo\Component\StorageUtils\Repository\IdentifiableObjectRepositoryInterface;

/**
 * Class ParentFieldSetter
 */
class ParentFieldSetter extends \Pim\Component\Catalog\Updater\Setter\ParentFieldSetter
{
    /**
     * @var IdentifiableObjectRepositoryInterface
     */
    private $productModelRepository;

    /**
     * ParentFieldSetter constructor.
     * @param IdentifiableObjectRepositoryInterface $productModelRepository
     * @param array $supportedFields
     */
    public function __construct(
        IdentifiableObjectRepositoryInterface $productModelRepository,
        array $supportedFields
    ) {
        $this->productModelRepository = $productModelRepository;
        parent::__construct($productModelRepository, $supportedFields);
    }

    /**
     * @param \Pim\Component\Catalog\Model\ProductInterface|\Pim\Component\Catalog\Model\ProductModelInterface $product
     * @param string $field
     * @param mixed $data
     * @param array $options
     */
    public function setFieldData($product, $field, $data, array $options = []): void
    {
        try {
            parent::setFieldData($product, $field, $data, $options);
        } catch (ImmutablePropertyException $exception) {
            if ($exception->getPropertyName() === 'parent') {
                // Allow us to change the product parent:
                if ($parent = $this->productModelRepository->findOneByIdentifier($data)) {
                    $familyVariant = $parent->getFamilyVariant();
                    $product->setParent($parent);
                    $product->setFamilyVariant($familyVariant);
                    if (null === $product->getFamily()) {
                        $product->setFamily($familyVariant->getFamily());
                    }
                }
            } else {
                throw $exception;
            }
        }
    }
}

This works. Now, upon importing the parent gets saved properly. I'm only wondering if:

  • a). This implementation is correct.
  • b). I'm not causing some other major issues by changing the parent.

I also noted the following TODO-statement in the original Akeneo-code above the code that throws the error when attempting to change the parent:

// TODO: This is to be removed in PIM-6350.

Anyone from Akeneo care to shed some light on this?

Giel Berkers
  • 2,852
  • 3
  • 39
  • 58

0 Answers0