salesforce-8.x-4.x-dev/modules/salesforce_push/salesforce_push.module

modules/salesforce_push/salesforce_push.module
<?php

/**
 * @file
 * Push updates to Salesforce when a Drupal entity is updated.
 */

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\SynchronizableInterface;
use Drupal\salesforce\Event\SalesforceErrorEvent;
use Drupal\salesforce\Event\SalesforceEvents;
use Drupal\salesforce_mapping\Entity\MappedObject;
use Drupal\salesforce_mapping\Entity\MappedObjectInterface;
use Drupal\salesforce_mapping\Entity\SalesforceMappingInterface;
use Drupal\salesforce_mapping\Event\SalesforcePushAllowedEvent;
use Drupal\salesforce_mapping\Event\SalesforcePushOpEvent;
use Drupal\salesforce_mapping\MappingConstants;

/**
 * Implements hook_entity_insert().
 */
function salesforce_push_entity_insert(EntityInterface $entity) {
  salesforce_push_entity_crud($entity, MappingConstants::SALESFORCE_MAPPING_SYNC_DRUPAL_CREATE);
}

/**
 * Implements hook_entity_update().
 */
function salesforce_push_entity_update(EntityInterface $entity) {
  salesforce_push_entity_crud($entity, MappingConstants::SALESFORCE_MAPPING_SYNC_DRUPAL_UPDATE);
}

/**
 * Implements hook_entity_delete().
 */
function salesforce_push_entity_delete(EntityInterface $entity) {
  salesforce_push_entity_crud($entity, MappingConstants::SALESFORCE_MAPPING_SYNC_DRUPAL_DELETE);
}

/**
 * Push entities to Salesforce.
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   The entity object.
 * @param string $op
 *   The trigger being responded to.
 *   One of push_create, push_update, push_delete.
 */
function salesforce_push_entity_crud(EntityInterface $entity, $op) {
  // Don't allow mapped objects or mappings to be pushed!
  if ($entity instanceof MappedObjectInterface || $entity instanceof SalesforceMappingInterface) {
    return;
  }
  // Do not push entities which are synchronizing currently.
  if ($entity instanceof SynchronizableInterface && $entity->isSyncing()) {
    return;
  }

  $properties = [];

  if ($entity_type = $entity->getEntityTypeId()) {
    $properties['drupal_entity_type'] = $entity_type;
  }
  if ($bundle = $entity->bundle()) {
    $properties['drupal_bundle'] = $bundle;
  }

  /** @var \Drupal\salesforce_mapping\Entity\SalesforceMapping[] $mappings */
  $mappings = \Drupal::service('entity_type.manager')
    ->getStorage('salesforce_mapping')
    ->loadPushMappingsByProperties($properties);
  if (empty($mappings)) {
    return;
  }

  foreach ($mappings as $mapping) {
    if (!$mapping->checkTriggers([$op])) {
      continue;
    }
    try {
      salesforce_push_entity_crud_mapping($entity, $op, $mapping);
    }
    catch (\Exception $e) {
      // Do not allow any exception to prevent entity CRUD.
      \Drupal::service('event_dispatcher')->dispatch(new SalesforceErrorEvent($e), SalesforceEvents::ERROR);
    }
  }
}

/**
 * Helper method for salesforce_push_entity_crud()
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   The entity.
 * @param string $op
 *   The current CRUD operation.
 * @param \Drupal\salesforce_mapping\Entity\SalesforceMappingInterface $mapping
 *   The mapping.
 *
 * @throws \Drupal\Core\Entity\EntityStorageException
 */
function salesforce_push_entity_crud_mapping(EntityInterface $entity, $op, SalesforceMappingInterface $mapping) {
  $mapped_object = NULL;

  // Look for existing mapped object or create a new one (except for deletes).
  $props = [
    'drupal_entity__target_type' => $entity->getEntityTypeId(),
    'drupal_entity__target_id' => $entity->id(),
    'salesforce_mapping' => $mapping->id(),
  ];

  $mapped_objects = \Drupal::service('entity_type.manager')
    ->getStorage('salesforce_mapped_object')
    ->loadByProperties($props);

  if (empty($mapped_objects)) {
    // No mappings found.
    if ($op == MappingConstants::SALESFORCE_MAPPING_SYNC_DRUPAL_DELETE) {
      // If no existing mapping, and this is a delete, purge any entries from
      // push queue and we're done.
      \Drupal::service('queue.salesforce_push')
        ->setName($mapping->id())
        ->deleteItemByEntity($entity);
      return;
    }
    $mapped_object = new MappedObject([]);
    $mapped_object->salesforce_mapping = $mapping;
    $mapped_object->setDrupalEntity($entity);
  }
  else {
    // There should really only be one in this case, since we're loading on a
    // multi-field unique key, but loadByProperties returns an array.
    $mapped_object = current($mapped_objects);
  }

  // Event subscribers should call $event->disallowPush() to prevent push.
  $event = \Drupal::service('event_dispatcher')->dispatch(
    new SalesforcePushAllowedEvent($mapped_object, $op),
    SalesforceEvents::PUSH_ALLOWED
  );
  if ($event->isPushAllowed() === FALSE) {
    return;
  }

  // Enqueue async push if the mapping is configured to do so, and quit.
  if ($mapping->async) {
    try {
      salesforce_push_enqueue_async($entity, $mapping, $mapped_object, $op);
    }
    catch (\Exception $e) {
      \Drupal::service('event_dispatcher')->dispatch(new SalesforceErrorEvent($e), SalesforceEvents::ERROR);
    }
    return;
  }

  // Attempt real-time push. Enqueue async push on failure.
  try {
    \Drupal::service('event_dispatcher')->dispatch(
      new SalesforcePushOpEvent($mapped_object, $op),
      SalesforceEvents::PUSH_MAPPING_OBJECT
    );

    // If this is a delete, destroy the SF object.
    if ($op == MappingConstants::SALESFORCE_MAPPING_SYNC_DRUPAL_DELETE) {
      $mapped_object->pushDelete();
    }
    else {
      // Otherwise, push to SF. This also saves the mapped object.
      $mapped_object->push();
    }

    // On success, delete any push queue items for this entity.
    \Drupal::service('queue.salesforce_push')
      ->setName($mapping->id())
      ->deleteItemByEntity($entity);
  }
  catch (\Exception $e) {

    \Drupal::service('event_dispatcher')->dispatch(
      new SalesforcePushOpEvent($mapped_object, $op),
      SalesforceEvents::PUSH_FAIL
    );

    \Drupal::service('event_dispatcher')->dispatch(new SalesforceErrorEvent($e), SalesforceEvents::ERROR);
    try {
      salesforce_push_enqueue_async($entity, $mapping, $mapped_object, $op);
    }
    catch (\Exception $e) {
      \Drupal::service('event_dispatcher')->dispatch(new SalesforceErrorEvent($e), SalesforceEvents::ERROR);
    }

    if (!$mapped_object->isNew()) {
      // Only update existing mapped objects.
      $mapped_object->setNewRevision(TRUE);
      $mapped_object
        ->set('last_sync_action', $op)
        ->set('last_sync_status', FALSE)
        ->set('revision_log_message', $e->getMessage())
        ->save();
    }
  }
}

/**
 * Insert a new queue item into the async push queue for the given mapping.
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
 *   The entity.
 * @param \Drupal\salesforce_mapping\Entity\SalesforceMappingInterface $mapping
 *   The mapping.
 * @param string $op
 *   The operation.
 */
function salesforce_push_enqueue_async(EntityInterface $entity, SalesforceMappingInterface $mapping, MappedObjectInterface $mapped_object = NULL, $op) {
  // Each mapping has its own queue, so that like entries can be easily grouped
  // for batching. Each queue item is a unique array of entity ids to be
  // pushed. The async queue worker loads the queue item and works through as
  // many entities as possible, up to the async limit for this mapping.
  $props = [
    'name' => $mapping->id(),
    'entity_id' => $entity->id(),
    'op' => $op,
  ];
  if ($mapped_object) {
    $props['mapped_object_id'] = $mapped_object->id();
  }

  \Drupal::service('queue.salesforce_push')->createItem($props);
}

/**
 * Implements hook_cron().
 */
function salesforce_push_cron() {
  $queue = \Drupal::service('queue.salesforce_push');
  if (\Drupal::config('salesforce.settings')->get('standalone')) {
    // If global standalone processing is enabled, stop here.
    return;
  }
  try {
    // Process mappings only for those which are not marked standalone.
    $mappings = \Drupal::service('entity_type.manager')
      ->getStorage('salesforce_mapping')
      ->loadCronPushMappings();
    if (empty($mappings)) {
      return;
    }
    $queue->processQueues($mappings);
  }
  catch (\Exception $e) {
    \Drupal::service('event_dispatcher')->dispatch(new SalesforceErrorEvent($e), SalesforceEvents::ERROR);
  }
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc