Problem/Motivation

Even though it's really quite simple, it took me a while to understand how to setup a loop - I was looking for something more complex. I'm sharing my solution here in case it helps others.

On my site, user profiles have an entity reference field that points to taxonomy terms called "networks". A user can belong to an unlimited number of networks (currently there are about a dozen). When a user profile is updated, I wanted a model to check if there had been any changes to the networks the user had selected. If there have been changes, I wanted to take different actions based on additions and deletions.

For demonstration purposes, the end result displays a message for each addition, deletion or no change. The final product will be somewhat simplified - unnecessary actions will be removed as I don't care about no-changes, just additions and deletions. However, I included them as I was building my model to ensure I understood and checked each step.

Commentary

Sorry there are so many steps in my example. I wanted to provide an opportunity to review each event, condition and action so that details weren't missed. Module maintainers - you have a mind for elegant/simple solutions, feedback is welcome!

Example with Explanation

1. Starting event: Update Content Entity

  • Type (and bundle) = user:user

 model highlighting initial event

2. Action: Entity Load

  • Name of token » unchanged-user
  • Load entity from » current scope (default value)
  • Entity type » user
  • Load unchanged values » yes

 model highlighting first action

3. Condition: Compare two scalar values

  • First value » [unchanged-user:field_user_networks]
  • Comparison operator » equals
  • Second value » [user:field_user_networks]

 model highlighting a condition after the first action

4. Action: Display a message to the user

  • Message » No changes to networks

 model highlighting an action at the end of a branch of the model

5. Condition: Compare two scalar values (same as step 3 but negated)

  • First value » [unchanged-user:field_user_networks]
  • Comparison operator » equals
  • Second value » [user:field_user_networks]
  • Negate the condition » Yes

 model highlighting another condition after the first action

6. Action: Entity - get field value "new"

  • Field name » field_user_networks
  • Name of token » new-networks
  • Entity » User

 model highlighting an action after the previous condition

7. Action: Entity - get field value "original"

  • Field name » field_user_networks
  • Name of token » orig-networks
  • Entity » unchanged-user

 model highlighting a second action after the previous condition

8. Action: Trigger a custom event (entity aware) "additions"

  • Event ID » additions
  • Tokens to forward » orig-networks
  • Entity » new-networks

 model highlighting a terminus action on this branch of the model

9. Action: Trigger a custom event (entity aware) "deletions"

  • Event ID » deletions
  • Tokens to forward » new-networks *
  • Entity » orig-networks *
  • * Note reversal from previous step

 model highlighting an action that triggers an event

10. Action: ECA Custom Event (entity-aware) "additions"

  • Event ID » additions

 model highlighting a new event with the same name as the trigger

11. Action: Entity Load (this is the current item from the list)

  • Name of token » loaded-term
  • Load entity from » Current scope (default value)
  • Entity type » Taxonomy term

 model highlighting the first action after the event

12. Condition: Compare two scalar values (does the list of original networks contain the current item?)

  • First value » [orig-networks]
  • Comparison operator » contains
  • Second value » [loaded-term]
  • Negate the condition » yes

 model highlighting a condition between two actions

13. Action: Display a message to the user (show the new item's name)

  • Message » new item: [loaded-term:name]

 model highlighting an action that shows a message

14. Condition: Compare two scalar values (same as step 12 but not negated)

  • First value » [orig-networks]
  • Comparison operator » contains
  • Second value » [loaded-term]

 model highlighting a condition between two actions

15. Action: Display a message to the user (show the existing item's name)

  • Message » item exist already: [loaded-term:name]

 model highlighting an action that shows a message

16. Action: ECA Custom Event (entity-aware) "deletions"

  • Event Id » deletions

 model highlighting a new event next with the same name as the trigger

17. Action: Entity Load (same as step 11, but in a different pathway)

  • Name of token » loaded-term
  • Load entity from » Current scope (default value)
  • Entity type » Taxonomy term

 model highlighting the first action after the event is triggered

18. Condition: compare two scalar values (check if the new list of networks contains the current item)

  • First value » [new-networks]
  • Comparison operator » contains
  • Second value » [loaded-term]
  • Negate the condition » yes

 model highlighting the second last condition

19. Action: Display a message to the user (show the deleted item's name)

  • Message » deleted item: [loaded-term:name]

 model highlighting the second last action

20. Condition: Compare two scalar values (same as step 18 but not negated)

  • First value » [new-networks]
  • Comparison operator » contains
  • Second value » [loaded-term]

 model highlighting the final condition

21. Action: Display a message to the user

  • Message » item remains: [loaded-term:name]

 model highlighting the final action

22. Save and test your model!

  • Save the model
  • Edit a user
  • Remove one item from their list of networks
  • Add one item
  • Save user
  • Check the status message

 model highlighting the status message

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

btown created an issue. See original summary.

btown’s picture

jurgenhaas’s picture

Oh wow!!! @btown you're really mastering ECA and bpmn_io. Like I mentioned in #3317070: Help - comparing changes after updating user, this could be published to the ECA Guide library.

jurgenhaas’s picture

Status: Active » Postponed (maintainer needs more info)

Can we publish this on the ECA Guide?

rodmarasi’s picture

@btown can i get the export file? image file cannot be exported to get better overview

jurgenhaas’s picture

Status: Postponed (maintainer needs more info) » Fixed
jurgenhaas’s picture

FYI, I have copied this great description over into our ECA Guide as a tutorial under https://ecaguide.org/resources/tutorials/btown-1/

I had to make smaller changes to it and then also built the model following the tutorial. That model is available for download from https://ecaguide.org/library/use%20case/user_network_changes/

Thanks a lot @btown for this amazing contribution!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.