How to initialize $workflowRegistry for Workflow PHP API


#1

As suggested in the documentation:
https://pimcore.com/docs/5.x/Development_Documentation/Workflow_Management/Working_with_PHP_API.html
We can get Workflow object by using the following statement:
$workflow = $workflowRegistry->get($object, ‘workflow’);

But it has asked to fetch $workflowRegistry from Symfony\Component\Workflow\Registry from Symfony container… which I am unable to figure out… How to initiate the $workflowRegistry?

Thanks in advance.
Best Regards,
Akansh


#2

Dependency Injection


#3

Hi Dominik,

Thanks for the lead.
I have tried various different ways to inject dependencies (while I am trying to access workflow object in pimcore.dataobject.postAdd event):

  1. I have no scope of passing Registry object in parameter.

  2. $workflowRegistry = $containerBuilder->get(Registry::class);

  3. $workflowRegistry = $containerBuilder->get(‘workflow.product_cycle’);

  4. $workflowRegistry= new YamlFileLoader($containerBuilder, new FileLocator(DIR));
    $workflow->load(‘config.yml’);

I have followed https://symfony.com/doc/current/components/dependency_injection.html of Symfony 3.4 docs for the above.

Could anyone guide me from here?

Thanks in advance.
Regards,
Akansh


#4

can you show me your code?


#5

I am trying to import Post-save method of Data Object:

class ObjectListener extends Controller
{

public function onPostAdd(ElementEventInterface $e)
{

    if ($e instanceof DataObjectEvent) {
        $object = $e->getObject();

        if ($object instanceof Product) {

            if ($object->getTypes() != null) {
               // $workflowRegistry = ???
                $workflow = $workflowRegistry->get($object, 'workflow');
                if ($workflow->can($object, 'mark_1')) {
                    $workflow->apply($object, 'mark_1');
                    $object->save();
                }
            }

        }
    }
}

}


#6

Hi,
You should solve it injecting the workflow registry in the constructor:

use Symfony\Component\Workflow\Registry;

private $workflowRegistry;

public function __construct(Registry $workflowRegistry) {
    $this->workflowRegistry = $workflowRegistry;
}

And then use it in your method with $this->workflowRegistry.

I didn’t test the code but it should work.
Hope it helps you!


#7

Hi,
Thanks Alessandro for the solution.
I have implemented the same for my ObjectListener class as defined above, but it is giving me the following error:

Error: Type error: Too few arguments to function AppBundle\EventListener\ObjectListener::__construct(), 0 passed in /var/www/html/primepim/var/cache/prod/Container1tb2gca/appProdProjectContainer.php on line 2197 and exactly 1 expected

And why shouldn’t it, we are giving no such parameter anywhere, we are only defining it in services.yml

AppBundle\EventListener\ObjectListener:

tags:
- { name: kernel.event_listener, event:pimcore.dataobject.preAdd, method: onPreAdd }
- { name: kernel.event_listener, event:pimcore.dataobject.postAdd, method: onPostAdd }

Is there something I am missing out on?
Regards.


#8

Whenever you are type-hinting another service inside your service’s constructor, you have to explicitly pass the service as an argument. In your case you have to register your ObjectListener as service and pass it the Workflow Registry as argument like so:

# src/AppBundle/Resources/config/services.yml

services:
    AppBundle\EventListener\ObjectListener:
        arguments:
            - '@workflow.registry'
        tags:
            - { name: kernel.event_listener, event: pimcore.dataobject.preAdd, method: onPreAdd }
            - { name: kernel.event_listener, event: pimcore.dataobject.postAdd, method: onPostAdd }

#9

Hi,
I just tried it on a clean installation and it worked.
If you didn’t change the default service configuration autowiring should work and the workflow registry should be injected automatically in your constructor.
Here is my services.yml file and my test listener:

app/config/services.yml

services:
    # default configuration for services in *this* file
    _defaults:
        # automatically injects dependencies in your services
        autowire: true
        # automatically registers your services as commands, event subscribers, etc.
        autoconfigure: true
        # this means you cannot fetch services directly from the container via $container->get()
        # if you need to do this, you can override this setting on individual services
        public: false

    # Example custom templating helper
    # AppBundle\Templating\Helper\Example:
    #     # templating helpers need to be public as they
    #     # are fetched from the container on demand
    #     public: true
    #     tags:
    #         - { name: templating.helper, alias: fooBar }

    # Example event listener for objects
    # AppBundle\EventListener\TestListener:
    #     tags:
    #         - { name: kernel.event_listener, event: pimcore.dataobject.preUpdate, method: onObjectPreUpdate }

    AppBundle\EventListener\TestListener:
        tags:
            - { name: kernel.event_listener, event: pimcore.dataobject.preAdd, method: onPreUpdate }
            - { name: kernel.event_listener, event: pimcore.dataobject.preUpdate, method: onPreUpdate }

src/AppBundle/EventListener/TestListener.php

<?php
namespace AppBundle\EventListener;

use Pimcore\Event\Model\ElementEventInterface;
use Symfony\Component\Workflow\Registry;

class TestListener {

    private $workflowRegistry;

    public function __construct(Registry $workflowRegistry) {
        $this->workflowRegistry = $workflowRegistry;
    }

    public function onPreUpdate (ElementEventInterface $e) {

        dump($e);

        dump($this->workflowRegistry);
    }
}

#10

Thanks Alessandro and Aaron, both solutions worked out.
While Alessandro’s solution is applicable better here, Aaron’s solution gives better understanding of the system.