Get In Touch
Questions? Comments? We want to know! Drop us a line and let’s start talking.
Learn More11.26.2012 Technical Innovation
The Drupal Salesforce Suite has been around since Drupal 5, having undergone many transformations in trying to keep pace with both Drupal and Salesforce API changes. The result is a feature set as impressive as it is ambitious, although the incremental updates and additions have come at a cost of significant technical debt, inconsistent API usage, a monolithic architecture, and fragility.
ThinkShout, not being strangers to major rewrites, even of our own modules, and driven by our need to integrate Salesforce with our native Drupal CRM, RedHen, undertook the challenge to completely rewrite the Salesforce suite this fall.
We started by reaching out to the current module maintainers to better understand the state of the module, it’s roadmap, if any, and the current teams involvement, as well as to feel out their interest in participating in a rewrite. The entire team, kostajh in particular, has been very receptive and helpful, and we eventually agreed that ThinkShout would do the rewrite in a new branch, 7.x-3.x, in the current project. There was talk of collaboration, but busy schedules and priorities got in the way as they often do and we’re approaching an MVP release on our own. The maintainers gave ThinkShout access to the repository and project page, but not administrative control over the repository, understandably. That put us in a minor bind, however, as we are committing many hundreds of hours to a project we don't have any control over. As a result, we're developing the project on [GitHub](https://github.com/thinkshout/salesforce) and mirroring the code to [7.x-3.x branch on Drupal.org](http://drupalcode.org/project/salesforce.git/tree/refs/heads/7.x-3.x). This will likely change, but that's our plan for now. UPDATE: Project development is now taking place on Drupal.org, although we’ll continue mirroring to GitHub.
In addition, with the systems modular OO design, we are laying the groundwork for a contrib ecosystem to handle more specific needs like Webform integration and lead generation. And, of course, developers can use the module as a starting point for their own solutions, be it importing Drupal users as contacts, lead generation through blog comments, etc.
Salesforce provides a veritable alphabet soup of API options, including SOAP, bulk, meta, streaming, apex, and REST. In their own words, the REST API is the best choice for “mobile applications and Web projects”. Well, Drupal is certainly a web platform, so we figured that’s the right place to start. In addition, we found the REST API provided the following benefits:
In addition, the REST API allows, or rather requires, the use of OAuath 2.0 for authorization. While not perfect, the OAuth flow is more secure and flexible than providing a single username and password. The OAuth process, in short:
As of writing, the Drupal OAuth module, which we preferred to leverage, did not yet support the OAuth 2.0 specification, so we were forced to go on our own. If/when a stable OAuth 2.0 library is released within Drupal, we’d certainly rather take advantage of that then reinvent any wheels.
Are, simply put, awesome. The Entity API metadata wrappers provided a silky smooth unified process for getting and setting an entity’s fields and properties. To demonstrate, this little snippet of code handles the mapping of Drupal data to Salesforce for some 90% of use cases, <?php $drupal_fields_array = explode(‘:’, $fieldmap[‘drupal_field’][‘fieldmap_value’]); $parent = $entity_wrapper; foreach ($drupal_fields_array as $drupal_field) { if ($parent instanceof EntityListWrapper) { // First list<> types, get the property from the first item $child_wrapper = $parent->get(0)->{$drupal_field}; } else { $child_wrapper = $parent->{$drupal_field}; } $parent = $child_wrapper; }
$value = $child_wrapper->value(); ?>
Similiarly, when importing Salesforce data, we can set entity values like this, <?php $drupal_fields_array = explode(‘:’, $field_map[‘drupal_field’][‘fieldmap_value’]); $parent = $entity_wrapper; foreach ($drupal_fields_array as $drupal_field) { if ($parent instanceof EntityListWrapper) { $child_wrapper = $parent->get(0)->{$drupal_field}; } else { $child_wrapper = $parent->{$drupal_field}; } $parent = $child_wrapper; } $fieldmap_type = salesforce_mapping_get_fieldmap_types($field_map[‘drupal_field’][‘fieldmap_type’]); $value = call_user_func($fieldmap_type[‘pull_value_callback’], $parent, $sf_object, $field_map);
// Allow this value to be altered before assigning to the entity. drupal_alter(‘salesforce_pull_entity_value’, $value, $field_map, $sf_object); if (isset($value)) { if ($parent instanceof EntityListWrapper) { $parent->offsetSet(0, $value); } else { $parent->set($value); } } ?>
Salesforce field mappings are the configuraiton that guides how Salesforce objects and Drupal entities are syncronized. Highlihts include:
When mapping fields, we needed a flexible system to handle different type of data mappings and how to derive the correct values. We modeled the fieldmap type system very loosely after Drupal entity definition hooks. Any module can implement hook_salesforce_mapping_fieldmap_type()
to define a type of field mapping. The module ships with 4 fieldmap types:
Each fieldmap type must define:
A fieldmap type definition will look like this, <?php /**
return $types; } ?>
The fieldmap UI allows an admin to select a fieldmap type which then presents either a list of options, E.g. a list of fields and properties in the case of a Property fieldmap type, or a textbox, E.g., for Tokens. After passing an optional validation step, the value is saved with the field mapping. When data is synced, the push or pull value callback is used to get the correct value. We’re hopeful this approach will provide the right balance between flexibility and out of the box utility in mapping simple and complex data structures.
We’ll be launching several sites before years using the new version of the Salesforce module and are including it in a private distribution we’ve developed for the Forum of Regional Associations of Grantmakers, who have generously sponsored the initial development, and we already feel it’s alpha quality and at the “MVP” stage. There are certain to be lots of bugs, and perhaps even major API changes, but that’s to be expected for a project of this complexity and with a such a wide array of use cases. We’re hoping to engage even more with the community at this time to gather architectural feedback and help work out the kinks.
Salesforce is a very widely used, powerful platform, and having a canonical, robust Drupal integration is a major win for the entire community. We’re hopeful this is a good starting point to achieve that goal.
Questions? Comments? We want to know! Drop us a line and let’s start talking.
Learn More