You are here

salesforce_mapping.module in Salesforce Suite 8.3

Manages Salesforce object and Drupal entity mappings.

File

modules/salesforce_mapping/salesforce_mapping.module
View source
<?php

/**
 * @file
 * Manages Salesforce object and Drupal entity mappings.
 */
use Drupal\Core\Entity\EntityInterface;

/**
 * Implements hook_entity_type_alter().
 */
function salesforce_mapping_entity_type_alter(array &$entity_types) {

  // There's no good way to add a link template based on existing mapping
  // definitions while we're building entity type definitions. We can't load
  // existing mappings, because to do that we need to load entity types which
  // creates an infinite recursion. So, we set the link template on any
  // mappable entity, and hide it for any entity types that don't have
  // mappings.
  foreach ($entity_types as $entity_type_id => $entity_type) {
    if ($entity_type
      ->hasViewBuilderClass() && $entity_type
      ->hasLinkTemplate('canonical')) {
      $entity_type
        ->setLinkTemplate('salesforce', "/{$entity_type_id}/{{$entity_type_id}}/salesforce");
    }
  }
}

/**
 * Implements hook_local_actions_alter().
 */
function salesforce_mapping_menu_local_actions_alter(&$local_actions) {
  foreach (\Drupal::entityManager()
    ->getDefinitions() as $entity_type_id => $entity_type) {
    if (\Drupal::entityTypeManager()
      ->getStorage('salesforce_mapping')
      ->loadByDrupal($entity_type_id)) {
      $local_actions['salesforce_mapped_object.add_action']['appears_on'][] = "entity.{$entity_type_id}.salesforce";
    }
  }
}

/**
 * Implements hook_entity_operation().
 */
function salesforce_mapping_entity_operation(EntityInterface $entity) {
  $operations = [];
  if (\Drupal::entityTypeManager()
    ->getStorage('salesforce_mapping')
    ->loadByEntity($entity)) {
    $operations['salesforce'] = [
      'title' => t('Salesforce'),
      'weight' => 200,
      'url' => $entity
        ->toUrl('salesforce'),
    ];
  }
  return $operations;
}

/**
 * Implements hook_entity_extra_field_info().
 */
function salesforce_mapping_entity_extra_field_info() {

  // Include Salesforce data for mapped entities.
  // @TODO: these don't actually show up on the entity view. Have to implement hook_entity_view as well?
  $extra = [];
  $mappings = \Drupal::service('entity.manager')
    ->getStorage('salesforce_mapping')
    ->loadPushMappings();
  foreach ($mappings as $mapping) {
    $extra[$mapping->drupal_entity_type][$mapping->drupal_bundle] = [
      'display' => [
        'salesforce_id' => [
          'label' => t('Salesforce Id'),
          'description' => t('ID of a linked Salesforce object.'),
          'weight' => 0,
        ],
        'salesforce_last_sync' => [
          'label' => t('Salesforce last sync'),
          'description' => t('Timestamp for the latest sync with Salesforce.'),
          'weight' => 0,
        ],
      ],
    ];
  }
  return $extra;
}

/**
 * Implements hook_entity_update().
 *
 * Ensures drupal entity has an update timestamp.
 */
function salesforce_mapping_entity_update(EntityInterface $entity) {

  // Check for mappings (much faster than looking for mapped objects.)
  $mappings = \Drupal::service('entity.manager')
    ->getStorage('salesforce_mapping')
    ->loadByDrupal($entity
    ->getEntityTypeId());
  if (empty($mappings)) {
    return;
  }

  // If mappings, check for mapped objects.
  $mapped_objects = \Drupal::service('entity.manager')
    ->getStorage('salesforce_mapped_object')
    ->loadByDrupal($entity
    ->getEntityTypeId(), $entity
    ->id());
  foreach ($mapped_objects as $mapped_object) {

    // Resaving the object should update the timestamp.
    // NB: we are purposefully not creating a new revision here.
    $mapped_object
      ->set('entity_updated', \Drupal::time()
      ->getRequestTime())
      ->save();
  }
}

/**
 * Implements hook_entity_delete().
 *
 * Delete any corresponding Mapped Objects when an entity is deleted.
 */
function salesforce_mapping_entity_delete(EntityInterface $entity) {
  $storage = \Drupal::entityTypeManager()
    ->getStorage('salesforce_mapped_object');
  if (\Drupal::moduleHandler()
    ->moduleExists('salesforce_push') && \Drupal::database()
    ->schema()
    ->tableExists('salesforce_push_queue')) {
    $mapped_objects = $storage
      ->loadByEntity($entity);
    if (!$mapped_objects) {
      return;
    }
    foreach ($mapped_objects as $mapped_object) {
      $mapping = $mapped_object
        ->getMapping();
      $queued_items = \Drupal::database()
        ->select('salesforce_push_queue', 'spq')
        ->fields('spq', [
        'item_id',
      ])
        ->condition('entity_id', $entity
        ->id())
        ->condition('name', $mapping
        ->id())
        ->condition('op', 'push_delete')
        ->execute();

      // If this was queued to be deleted, don't delete the mapping yet, defer
      // to salesforce_push.
      if (!$queued_items
        ->fetch()) {
        $mapped_object
          ->delete();
      }
    }
  }
  else {
    $storage
      ->delete($storage
      ->loadByEntity($entity));
  }
}

/**
 * Implements hook_field_formatter_info_alter().
 */
function salesforce_mapping_field_formatter_info_alter(array &$info) {
  $info['link']['field_types'][] = 'mapped_entity_link';
  $info['link']['field_types'][] = 'salesforce_link';
}

/**
 * Implements hook_module_implements_alter().
 */
function salesforce_mapping_module_implements_alter(&$implementations, $hook) {

  // This needs to go last to make sure the mapping isn't deleted before
  // everything is done being cleaned up.
  switch ($hook) {
    case 'entity_delete':
      $group = $implementations['salesforce_mapping'];
      unset($implementations['salesforce_mapping']);
      $implementations['salesforce_mapping'] = $group;
      break;
  }
}