You are here

public function MappedObject::pull in Salesforce Suite 5.0.x

Same name and namespace in other branches
  1. 8.4 modules/salesforce_mapping/src/Entity/MappedObject.php \Drupal\salesforce_mapping\Entity\MappedObject::pull()
  2. 8.3 modules/salesforce_mapping/src/Entity/MappedObject.php \Drupal\salesforce_mapping\Entity\MappedObject::pull()

Pull the mapped SF object data from Salesforce.

Return value

$this

Overrides MappedObjectInterface::pull

File

modules/salesforce_mapping/src/Entity/MappedObject.php, line 506

Class

MappedObject
Defines a Salesforce Mapped Object entity class.

Namespace

Drupal\salesforce_mapping\Entity

Code

public function pull() {
  $mapping = $this
    ->getMapping();

  // If the pull isn't coming from a cron job.
  if ($this->sfObject == NULL) {
    if ($this
      ->sfid()) {
      $this->sfObject = $this
        ->client()
        ->objectRead($mapping
        ->getSalesforceObjectType(), $this
        ->sfid());
    }
    elseif ($mapping
      ->hasKey()) {
      $this->sfObject = $this
        ->client()
        ->objectReadbyExternalId($mapping
        ->getSalesforceObjectType(), $mapping
        ->getKeyField(), $mapping
        ->getKeyValue($this
        ->getMappedEntity()));
      $this
        ->set('salesforce_id', (string) $this->sfObject
        ->id());
    }
  }

  // No object found means there's nothing to pull.
  if (!$this->sfObject instanceof SObject) {
    throw new SalesforceException('Nothing to pull. Please specify a Salesforce ID, or choose a mapping with an Upsert Key defined.');
  }

  // @TODO better way to handle push/pull:
  $fields = $mapping
    ->getPullFields();

  /** @var \Drupal\Core\Entity\FieldableEntityInterface $drupal_entity */
  $drupal_entity = $this
    ->getMappedEntity() ?: $this
    ->getDrupalEntityStub();

  /** @var \Drupal\salesforce_mapping\SalesforceMappingFieldPluginInterface $field */
  foreach ($fields as $field) {
    try {
      $value = $field
        ->pullValue($this->sfObject, $drupal_entity, $mapping);
    } catch (\Exception $e) {

      // Field missing from SObject? Skip it.
      $message = 'Field @sobj.@sffield not found on @sfid';
      $args = [
        '@sobj' => $mapping
          ->getSalesforceObjectType(),
        '@sffield' => $field
          ->config('salesforce_field'),
        '@sfid' => $this
          ->sfid(),
      ];
      $this
        ->eventDispatcher()
        ->dispatch(new SalesforceNoticeEvent($e, $message, $args), SalesforceEvents::NOTICE);
      continue;
    }
    $this
      ->eventDispatcher()
      ->dispatch(new SalesforcePullEntityValueEvent($value, $field, $this), SalesforceEvents::PULL_ENTITY_VALUE);
    try {

      // If $value is TypedData, it should have been set during pullValue().
      if (!$value instanceof TypedDataInterface) {
        $drupal_field = $field
          ->get('drupal_field_value');
        $drupal_entity
          ->set($drupal_field, $value);
      }
    } catch (\Exception $e) {
      $message = 'Exception during pull for @sfobj.@sffield @sfid to @dobj.@dprop @did with value @v';
      $args = [
        '@sfobj' => $mapping
          ->getSalesforceObjectType(),
        '@sffield' => $field
          ->config('salesforce_field'),
        '@sfid' => $this
          ->sfid(),
        '@dobj' => $drupal_entity
          ->getEntityTypeId(),
        '@dprop' => $field
          ->get('drupal_field_value'),
        '@did' => $drupal_entity
          ->id(),
        '@v' => $value,
      ];
      $this
        ->eventDispatcher()
        ->dispatch(new SalesforceWarningEvent($e, $message, $args), SalesforceEvents::WARNING);
      continue;
    }
  }

  // @TODO: Event dispatching and entity saving should not be happening in this context, but inside a controller. This class needs to be more model-like.
  $this
    ->eventDispatcher()
    ->dispatch(new SalesforcePullEvent($this, $drupal_entity
    ->isNew() ? MappingConstants::SALESFORCE_MAPPING_SYNC_SF_CREATE : MappingConstants::SALESFORCE_MAPPING_SYNC_SF_UPDATE), SalesforceEvents::PULL_PRESAVE);

  // Set a flag here to indicate that a pull is happening, to avoid
  // triggering a push.
  $drupal_entity->salesforce_pull = TRUE;
  $drupal_entity
    ->save();

  // Update mapping object.
  $this
    ->set('drupal_entity', $drupal_entity)
    ->set('entity_updated', $this
    ->getRequestTime())
    ->set('last_sync_action', 'pull')
    ->set('last_sync_status', TRUE)
    ->set('force_pull', 0)
    ->save();
  return $this;
}