View source
<?php
namespace Drupal\salesforce_pull\Plugin\QueueWorker;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Queue\QueueWorkerBase;
use Drupal\salesforce\Event\SalesforceErrorEvent;
use Drupal\salesforce\Event\SalesforceEvents;
use Drupal\salesforce\Event\SalesforceNoticeEvent;
use Drupal\salesforce\Rest\RestClientInterface;
use Drupal\salesforce\Rest\RestException;
use Drupal\salesforce\SObject;
use Drupal\salesforce_mapping\Entity\MappedObjectInterface;
use Drupal\salesforce_mapping\Entity\SalesforceMappingInterface;
use Drupal\salesforce_mapping\Event\SalesforcePullEvent;
use Drupal\salesforce_mapping\Event\SalesforcePushParamsEvent;
use Drupal\salesforce_mapping\MappingConstants;
use Drupal\salesforce_mapping\PushParams;
use Drupal\salesforce_pull\PullException;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
abstract class PullBase extends QueueWorkerBase implements ContainerFactoryPluginInterface {
protected $etm;
protected $client;
protected $mappingStorage;
protected $mappedObjectStorage;
protected $eventDispatcher;
public function __construct(EntityTypeManagerInterface $entity_type_manager, RestClientInterface $client, EventDispatcherInterface $event_dispatcher) {
$this->etm = $entity_type_manager;
$this->client = $client;
$this->eventDispatcher = $event_dispatcher;
$this->mappingStorage = $this->etm
->getStorage('salesforce_mapping');
$this->mappedObjectStorage = $this->etm
->getStorage('salesforce_mapped_object');
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($container
->get('entity_type.manager'), $container
->get('salesforce.client'), $container
->get('event_dispatcher'));
}
public function processItem($item) {
$sf_object = $item
->getSobject();
$mapping = $this->mappingStorage
->load($item
->getMappingId());
if (!$mapping) {
return;
}
$mapped_object = $this->mappedObjectStorage
->loadByProperties([
'salesforce_id' => (string) $sf_object
->id(),
'salesforce_mapping' => $mapping->id,
]);
$mapped_object = current($mapped_object);
if (!empty($mapped_object)) {
return $this
->updateEntity($mapping, $mapped_object, $sf_object, $item
->getForcePull());
}
else {
return $this
->createEntity($mapping, $sf_object);
}
}
protected function updateEntity(SalesforceMappingInterface $mapping, MappedObjectInterface $mapped_object, SObject $sf_object, $force_pull = FALSE) {
if (!$mapping
->checkTriggers([
MappingConstants::SALESFORCE_MAPPING_SYNC_SF_UPDATE,
])) {
return;
}
try {
$entity = $mapped_object
->getMappedEntity();
if (!$entity) {
$this->eventDispatcher
->dispatch(SalesforceEvents::ERROR, new SalesforceErrorEvent(NULL, 'Drupal entity existed at one time for Salesforce object %sfobjectid, but does not currently exist.', [
'%sfobjectid' => (string) $sf_object
->id(),
]));
return;
}
$entity->salesforce_pull = TRUE;
$entity_updated = !empty($entity->changed->value) ? $entity->changed->value : $mapped_object
->getChanged();
$pull_trigger_date = $sf_object
->field($mapping
->getPullTriggerDate());
$sf_record_updated = strtotime($pull_trigger_date);
$mapped_object
->setDrupalEntity($entity)
->setSalesforceRecord($sf_object);
if ($mapping
->hasKey() && $mapping
->checkTriggers([
MappingConstants::SALESFORCE_MAPPING_SYNC_DRUPAL_CREATE,
MappingConstants::SALESFORCE_MAPPING_SYNC_DRUPAL_UPDATE,
]) && $sf_object
->field($mapping
->getKeyField()) === NULL) {
$params = new PushParams($mapping, $entity);
$this->eventDispatcher
->dispatch(SalesforceEvents::PUSH_PARAMS, new SalesforcePushParamsEvent($mapped_object, $params));
$key_field = $mapping
->getKeyField();
$key_param = [
$key_field => $params
->getParam($key_field),
];
$sent_id = $this
->sendEntityId($mapping
->getSalesforceObjectType(), $mapped_object
->sfid(), $key_param);
if (!$sent_id) {
throw new PullException();
}
}
$event = $this->eventDispatcher
->dispatch(SalesforceEvents::PULL_PREPULL, new SalesforcePullEvent($mapped_object, MappingConstants::SALESFORCE_MAPPING_SYNC_SF_UPDATE));
if (!$event
->isPullAllowed()) {
$this->eventDispatcher
->dispatch(SalesforceEvents::NOTICE, new SalesforceNoticeEvent(NULL, 'Pull was not allowed for %label with %sfid', [
'%label' => $entity
->label(),
'%sfid' => (string) $sf_object
->id(),
]));
return FALSE;
}
if ($sf_record_updated > $entity_updated || $mapped_object->force_pull || $force_pull) {
$mapped_object
->pull();
$this->eventDispatcher
->dispatch(SalesforceEvents::NOTICE, new SalesforceNoticeEvent(NULL, 'Updated entity %label associated with Salesforce Object ID: %sfid', [
'%label' => $entity
->label(),
'%sfid' => (string) $sf_object
->id(),
]));
return MappingConstants::SALESFORCE_MAPPING_SYNC_SF_UPDATE;
}
} catch (\Exception $e) {
$this->eventDispatcher
->dispatch(SalesforceEvents::WARNING, new SalesforceErrorEvent($e, 'Failed to update entity %label from Salesforce object %sfobjectid.', [
'%label' => isset($entity) ? $entity
->label() : "Unknown",
'%sfobjectid' => (string) $sf_object
->id(),
]));
throw $e;
}
}
protected function createEntity(SalesforceMappingInterface $mapping, SObject $sf_object) {
if (!$mapping
->checkTriggers([
MappingConstants::SALESFORCE_MAPPING_SYNC_SF_CREATE,
])) {
return;
}
try {
$entity_type = $mapping
->getDrupalEntityType();
$entity_keys = $this->etm
->getDefinition($entity_type)
->getKeys();
$values = [];
if (isset($entity_keys['bundle']) && !empty($entity_keys['bundle'])) {
$values[$entity_keys['bundle']] = $mapping
->getDrupalBundle();
}
$values['salesforce_pull'] = TRUE;
$entity = $this->etm
->getStorage($entity_type)
->create($values);
$mapped_object = $this->mappedObjectStorage
->create([
'drupal_entity' => [
'target_type' => $entity_type,
],
'salesforce_mapping' => $mapping->id,
'salesforce_id' => (string) $sf_object
->id(),
]);
$mapped_object
->setDrupalEntity($entity)
->setSalesforceRecord($sf_object);
$event = $this->eventDispatcher
->dispatch(SalesforceEvents::PULL_PREPULL, new SalesforcePullEvent($mapped_object, MappingConstants::SALESFORCE_MAPPING_SYNC_SF_CREATE));
if (!$event
->isPullAllowed()) {
$this->eventDispatcher
->dispatch(SalesforceEvents::NOTICE, new SalesforceNoticeEvent(NULL, 'Pull was not allowed for %label with %sfid', [
'%label' => $entity
->label(),
'%sfid' => (string) $sf_object
->id(),
]));
return FALSE;
}
$mapped_object
->pull();
if ($mapping
->hasKey() && $mapping
->checkTriggers([
MappingConstants::SALESFORCE_MAPPING_SYNC_DRUPAL_CREATE,
MappingConstants::SALESFORCE_MAPPING_SYNC_DRUPAL_UPDATE,
]) && $sf_object
->field($mapping
->getKeyField()) === NULL) {
$params = new PushParams($mapping, $entity);
$this->eventDispatcher
->dispatch(SalesforceEvents::PUSH_PARAMS, new SalesforcePushParamsEvent($mapped_object, $params));
$key_field = $mapping
->getKeyField();
$key_param = [
$key_field => $params
->getParam($key_field),
];
$sent_id = $this
->sendEntityId($mapping
->getSalesforceObjectType(), $mapped_object
->sfid(), $key_param);
if (!$sent_id) {
throw new PullException();
}
}
$this->eventDispatcher
->dispatch(SalesforceEvents::NOTICE, new SalesforceNoticeEvent(NULL, 'Created entity %id %label associated with Salesforce Object ID: %sfid', [
'%id' => $entity
->id(),
'%label' => $entity
->label(),
'%sfid' => (string) $sf_object
->id(),
]));
return MappingConstants::SALESFORCE_MAPPING_SYNC_SF_CREATE;
} catch (\Exception $e) {
$this->eventDispatcher
->dispatch(SalesforceEvents::WARNING, new SalesforceNoticeEvent($e, 'Pull-create failed for Salesforce Object ID: %sfobjectid', [
'%sfobjectid' => (string) $sf_object
->id(),
]));
throw $e;
}
}
protected function sendEntityId(string $object_type, string $sfid, array $key_param) {
try {
$this->client
->objectUpdate($object_type, $sfid, $key_param);
return TRUE;
} catch (RestException $e) {
$this->eventDispatcher
->dispatch(SalesforceEvents::ERROR, new SalesforceErrorEvent($e));
return FALSE;
}
}
}