Conditionally Triggering Salesforce Push Operations in Drupal 8
The user interface for the Salesforce Suite in Drupal 8 is fantastic. The suite itself is incredibly powerful. Among the many options, for each mapping you create you can specify what operations should trigger a synchronization. Here’s an example:
We recently faced an issue with the “Drupal entity update” trigger being called too often. The salesforce_push module implements hook_entity_update() , which gets called a lot. After looking at how the functions are called in salesforce_push.module I realized there were two choices:
- Disable the “Drupal entity update” trigger in the mapping settings, then clone salesforce_push_entity_crud() into a utility/service class of my own and call it when I wanted a sync
- Implement an event subscriber for SalesforceEvents::PUSH_ALLOWED which lets you disallow a push based on whatever logic you’d like.
The latter seemed safer for various reasons, so I took that approach. Unfortunately the only information available in the event is the entity, the mapping, and some other odds and ends.
You do, however, have the ability to load / leverage whatever you want from Drupal. So, I got creative and decided to use the path info to determine whether or not to allow the push. Basically I only wanted the update push when a user actually edited their account. I don’t want a push when some other Drupal module alters the account.
Here’s what I ended up with:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
/** * {@inheritdoc} */ public static function getSubscribedEvents() { $events = [ SalesforceEvents::PUSH_ALLOWED => 'pushAllowed', ]; return $events; } /** * SalesforcePushAllowedEvent callback. * * @param \Drupal\salesforce_mapping\Event\SalesforcePushAllowedEvent $event * The push allowed event. */ public function pushAllowed(SalesforcePushAllowedEvent $event) { // Only allow push_update if a user (or admin) is directly editing the user. // This prevents extra syncs. Example of an extra sync: when a user views a // workshop the group functionality will automatically re-save the user // entity, triggering salesforce_push_entity_update() in salesforce.module. // salesforce_push_entity_update will still be called, but // $event->disallowPush() below will prevent the push. if ($event->getMapping()->id() === 'users' && $event->getOp() === 'push_update') { $path_info = \Drupal::request()->getPathInfo(); $salesforce_update_triggering_paths = [ '/user-update-profile', '/user-change-password', '/get-started', '/user/', ]; foreach ($salesforce_update_triggering_paths as $path) { if (strpos($path_info, $path) !== FALSE) { return; } } $event->disallowPush(); } } |
Is this bullet proof? No, probably not; it may require updating as we think of new cases for allowing the push_update operation. Does it get the job done? Yes! It’s easy enough to modify as needed, and it leverages a built in event that is unlikely to change. This approach seemed much safer than cloning a bunch of code from the salesforce_push module.