Problem / Motivation
Currently, Workflow API exposes a bunch of hooks for interacting with Workflows. Hooks are procedural by nature, and leave a lot to be desired, especially with complex cases. As I understand it, Drupal 9 will be eliminating hooks, possibly in favor of HookEvent. Even if all hooks aren't deprecated, implementing Events should provide some advantages for other modules to subscribe to Workflow events and obtain relevant information ( such as $entity, $wid, $from_sid, $to_sid, etc ).
Proposed resolution
Register Events for the various Workflow transitions, dispatch the events when the transitions occur. The existing hooks could remain side-by-side with the new events to prevent a breaking change.
Remaining tasks
Define the events and create a dispatcher.
API changes
For D8, all the hooks would stay in place, the event system would basically be an additional layer.
Data model changes
I don't think any data model changes would be necessary to add an event system. I could be wrong, I am just getting into the event system :)
| Comment | File | Size | Author |
|---|---|---|---|
| #20 | workflow-event-dispatcher-3038853-20.patch | 5.08 KB | ayalon |
Comments
Comment #2
johnv"Drupal 9 will be eliminating hooks, possibly in favor of HookEvent."
Can you share some references to this change?
Thanks.
Comment #3
scottsawyer@johnv, sorry for the slow response, I somehow missed the notification that you responded.
My language was too precise, I don't think there are final decisions, but discussions seemingly point that direction.
A few references:
While none of these posts are definitive, in my interpretation, hooks may be on the way out, and implementing Events in Workflow could offer advantages.
For my part, I am still learning the Event system, so I am not really ready to submit a patch.
Comment #4
sagesolutions commentedHello!
I've created a patch that dispatches events upon workflow transitions.
I heavily used the state_machine module as a reference.
In your event subscriber, you can do the following as an example
It triggers on pre and post save actions, both of which you can target. For example:
'my_custom_workflow.my_custom_transition.pre_transition'.Comment #5
sagesolutions commentedComment #6
johnvMarking this as a D9 feature.
Comment #7
sagesolutions commentedNew simplified patch to work on latest dev
Comment #8
sagesolutions commentedComment #10
johnvhttps://www.drupal.org/node/2544874
https://www.drupal.org/docs/creating-custom-modules/subscribe-to-and-dis...
https://www.youtube.com/watch?v=r4VZLV1LPJ0
https://www.youtube.com/watch?v=DzoqAVa1Bys
Comment #11
johnvGenerally, I do like new features, and usage of existing architecture.
In this module, I removed some custom hooks, in favour of hook_entity_* hooks.
Please see below code from EntityStrageBase.php, that calls the pre- and post- hooks.
I was looking into that code, hoping to find general events from core.
We can do add example code in workflow.api.php, adding the event call in the hook :
- hook_ENTITY_TYPE_presave()
- hook_entity_presave()
postSave():
- hook_ENTITY_TYPE_insert()
- hook_ENTITY_TYPE_update()
The hook contains the Transitions entity, allowing all data to be fetched.
Your event adds get-fucntions for all attributes of the Transition.
Even though this is more explicit, isn't it sufficient to only add the Transition entity? It contains all requested data.
Comment #12
johnvI will try to create a patch with new hooks for workflow_transition CRUD.
Comment #13
ayalon commentedIt is very sad, that patch #7 still is not commited. Its such a superb feature for all developers. The patch does not break any existing functionalities, it just add support for event subscribers.
We are using it on productions since month and it works flawlessly. Please consider merging this patch in the next release.
Comment #14
ayalon commentedComment #15
rudi teschner commentedI think the patch in #7 should be updated and i.e. include event classes so that handling of events and subscriptions is consistent across modules.
Also, it does not seem to work for D10 since the event dispatcher changed.
Comment #16
rudi teschner commentedHere is a version that works for me on a D10 website with D10.1.4 and workflow 8.x-1.7
Along with some exemplary code on how to use them in a custom module:
Comment #17
yassersammanComment #18
ayalon commentedI have tested #10 and using the patch. It works well with Drupal 10. Using this patch since ages.
Comment #19
ayalon commentedHere is an updated patch following the event naming from Patch #7.
I prefer this approach as it is more flexible.
Comment #20
ayalon commentedFor some reasons the patch did not properly export. Please use this file:
Comment #22
johnvThanks, I committed a patch with some changes.
Only 1 TransactionEvent type was committed. The Event interface allows to only use the $event_name. So adding multiple subevents does not have added value.
All functions to read attributes of the $transition are not committed, while redundant. You can to $event->getTransition()->getFromSid().
For that, i assured the WorkflowTransitionInterface was completed here: #3418871: Improve WorkflowTransitionInterface
To make the impact of the commit smaller, the following was needed: #3418870: Restructure save() method, avoiding duplicate inserts
This way, the dispatchEvent() function can be inside, not around the save() function. This way, the events are also triggered for ScheduledTransitions.
I hope these changes do not ruin you project code too much.
Comment #25
johnvThe EventSubscriber from #16 is added with dummy code.
Comment #26
sagesolutions commented@johnv
Was it intentional to remove the entity and workflow from the WorkflowTransitionEvent?
In my eventsubscriber, I used the $event->getEntity() method to get the node.
Also, I used a specific event to trigger my subscribed events. For example
'permit_status_workflow.permit_status_workflow_open.post_transition' => 'onOpenTransition',Is this still possible? I think this functionality has been removed??
Comment #27
sagesolutions commentedComment #28
johnvFor the first block, you can make the following modifications. They will work anyway. As stated, you can get the info using the TransitionInterface:
perhaps changing the constructor to
public function __construct(WorkflowTransition $transition, WorkflowInterface $workflow = NULL, EntityInterface $entity = NULL) {}or
public function __construct(WorkflowTransition $transition) {}Comment #30
johnv@sagesolutions,
for your second block, yes, you still can do what you need to do. Please see below code suggestion:
Comment #31
sagesolutions commentedHi @johnv,
I like the getEntity() and getWorkflow() methods in the WorkflowTransistionEvent class. I can work with that. Please commit these updates :)
For the subscribed events, I liked the ability of what was there before. Using the original patch, I can subscribe to each individual workflow change. For example:
But now, I can only subscribe to the one post transition event. Then in the called function, I need to check the transition to/from and break apart from there. This seems a bit messier than before.
Comment #32
sagesolutions commentedI've managed to update my EventSubscriber to work with the new workflow updates. Below is what works for me, maybe it will help others while upgrading.
Comment #34
johnvThanks, I added the code to the EventSubscriber.
Comment #36
johnvSome example code is added to the workflow_devel module.
Comment #40
johnv