phpsymfonydependency-injection

Replace argument on a service that inherit of another


I tried to override an argument on a list of services with a compiler pass.

This is working fine for all of my services execpt one. This service use service inheritance :

pim_connector.array_converter.flat_to_standard.product.value_converter.abstract:
        class: '%pim_connector.array_converter.flat_to_standard.product.value_converter.abstract.class%'
        arguments:
            - '@pim_connector.array_converter.flat_to_standard.product.field_splitter'

pim_connector.array_converter.flat_to_standard.product.value_converter.simpleselect:
        class: '%pim_connector.array_converter.flat_to_standard.product.value_converter.simpleselect.class%'
        parent: pim_connector.array_converter.flat_to_standard.product.value_converter.abstract
        arguments:
            - ['pim_catalog_simpleselect', 'pim_reference_data_simpleselect']
        tags:
            - { name: 'pim_connector.array_converter.flat_to_standard.product.value_converter' }

On my compiler pass if I dump my arguments like this :

class MyCompilerPass implements CompilerPassInterface
{
    /**
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        $service = $container->getDefinition('pim_connector.array_converter.flat_to_standard.product.value_converter.simpleselect');
        var_dump($service->getArguments());exit;
    }
}

I have this :

/srv/pim/src/MyNamespace/PimCatalogBundle/DependencyInjection/CompilerPass/MyCompilerPass.php:31:
array (size=1)
  0 => 
    array (size=2)
      0 => string 'pim_catalog_simpleselect' (length=24)
      1 => string 'pim_reference_data_simpleselect' (length=31)

So I tried to replace the argument with the index 0 but I have this error :

request.CRITICAL: Uncaught PHP Exception Symfony\Component\Debug\Exception\FatalThrowableError: "Type error: Argument 1 passed to Pim\Component\Connector\ArrayConverter\FlatToStandard\Product\ValueConverter\SimpleSelectConverter::__construct() must be an instance of Pim\Component\Connector\ArrayConverter\FlatToStandard\Product\FieldSplitter, array given

If I try to use the index 1, I have this one : Uncaught Symfony\Component\DependencyInjection\Exception\OutOfBoundsException: The argument "1" doesn't exist.

Have you an idea of the problem ?

The class of the service pim_connector.array_converter.flat_to_standard.product.value_converter.simpleselect is this one :

namespace Pim\Component\Connector\ArrayConverter\FlatToStandard\Product\ValueConverter;

use Pim\Component\Connector\ArrayConverter\FlatToStandard\Product\FieldSplitter;

class SimpleSelectConverter extends AbstractValueConverter
{
    /**
     * @param FieldSplitter $fieldSplitter
     * @param array         $supportedFieldType
     */
    public function __construct(FieldSplitter $fieldSplitter, array $supportedFieldType)
    {
        parent::__construct($fieldSplitter);

        $this->supportedFieldType = $supportedFieldType;
    }

    /**
     * {@inheritdoc}
     */
    public function convert(array $attributeFieldInfo, $value)
    {
        if ('' === $value) {
            $value = null;
        }

        return [$attributeFieldInfo['attribute']->getCode() => [[
            'locale' => $attributeFieldInfo['locale_code'],
            'scope'  => $attributeFieldInfo['scope_code'],
            'data'   => $value,
        ]]];
    }
}

And my Compiler pass is here :

class MyCompilerPass implements CompilerPassInterface
{
    private const SERVICES = [
        'pim_catalog.validator.constraint.attribute_type_for_option' => 0,
        'pim_catalog.comparator.attribute.option' => 0,
        'pim_api.controller.attribute_option' => 12,
        'pim_catalog.query.elasticsearch.filter.option' => 2,
        'pim_catalog.query.elasticsearch.sorter.option' => 1,
        'pim_connector.array_converter.flat_to_standard.product.value_converter.simpleselect' => 1,
        'pim_connector.array_converter.standard_to_flat.product.value_converter.simpleselect' => 1
    ];

    /**
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
       foreach (self::SERVICES as $id => $index) {
            $service = $container->getDefinition($id);

            $service->replaceArgument($index, array_merge(
                $service->getArgument($index),
                ['my_new_type']
            ));
        }
    }
}

Solution

  • I create an issue on github : [DI] Compiler pass : can't replace a parameter with inheritance of services

    Edit : So the solution was just to add priority on my compiler pass :

    $container->addCompilerPass(new TryToOverrideSubServiceParameterPass(), PassConfig::TYPE_OPTIMIZE, -1);