You are here

public function SalesforcePullCommands::pullFile in Salesforce Suite 5.0.x

Same name and namespace in other branches
  1. 8.4 modules/salesforce_pull/src/Commands/SalesforcePullCommands.php \Drupal\salesforce_pull\Commands\SalesforcePullCommands::pullFile()
  2. 8.3 modules/salesforce_pull/src/Commands/SalesforcePullCommands.php \Drupal\salesforce_pull\Commands\SalesforcePullCommands::pullFile()

Given a mapping, enqueue a list of object IDs to be pulled from CSV file.

E.g. a Salesforce report. The first column of the CSV file must be SFIDs. Additional columns will be ignored.

@command salesforce_pull:pull-file @aliases sfpf,sfif,sf-pull-file,salesforce_pull:file

Parameters

string $file: CSV file name of 15- or 18-character Salesforce ids to be pulled.

string $name: Machine name of the Salesforce Mapping for which to queue pull records.

File

modules/salesforce_pull/src/Commands/SalesforcePullCommands.php, line 224

Class

SalesforcePullCommands
A Drush commandfile.

Namespace

Drupal\salesforce_pull\Commands

Code

public function pullFile($file, $name) {

  /** @var \Drupal\salesforce_mapping\Entity\SalesforceMapping $mapping */
  if (!($mapping = $this->mappingStorage
    ->load($name))) {
    $this
      ->logger()
      ->error(dt('Failed to load mapping "%name"', [
      '%name' => $name,
    ]));
    return;
  }

  // Fetch the base query to make sure we can pull using this mapping.
  $soql = $mapping
    ->getPullQuery([], 1, 0);
  if (empty($soql)) {
    $this
      ->logger()
      ->error(dt('Failed to load mapping "%name"', [
      '%name' => $name,
    ]));
    return;
  }
  $rows = array_map('str_getcsv', file($file));

  // Track IDs to avoid duplicates.
  $seen = [];

  // Max length for SOQL query is 20,000 characters. Chunk the IDs into
  // smaller units to avoid this limit. 1000 IDs per query * 18 chars per ID,
  // up to 18000 characters per query, plus up to 2000 for fields, where
  // condition, etc.
  $queries = [];
  foreach (array_chunk($rows, 1000) as $i => $chunk) {

    // Reset our base query:
    $soql = $mapping
      ->getPullQuery([], 1, 0);

    // Now add all the IDs to it.
    $sfids = [];
    foreach ($chunk as $j => $row) {
      if (empty($row) || empty($row[0])) {
        $this->logger
          ->warning(dt('Skipping row !n, no SFID found.', [
          '!n' => $j,
        ]));
        continue;
      }
      try {
        $sfid = new SFID($row[0]);

        // Sanity check to make sure the key-prefix is correct.
        // If so, this is probably a good SFID.
        // If not, it is definitely not a good SFID.
        if ($mapping
          ->getSalesforceObjectType() != $this->client
          ->getObjectTypeName($sfid)) {
          $this
            ->logger()
            ->error(dt('SFID !sfid does not match type !type', [
            '!sfid' => (string) $sfid,
            '!type' => $mapping
              ->getSalesforceObjectType(),
          ]));
          continue;
        }
      } catch (\Exception $e) {
        $this->logger
          ->warning(dt('Skipping row !n, no SFID found.', [
          '!n' => $j,
        ]));
        continue;
      }
      $sfid = (string) $sfid;
      if (empty($sfids[$sfid])) {
        $sfids[] = $sfid;
        $seen[$sfid] = $sfid;
      }
    }
    $soql
      ->addCondition('Id', $sfids, 'IN');
    $queries[] = $soql;
  }
  if (empty($seen)) {
    $this
      ->logger()
      ->error('No SFIDs found in the given file.');
    return;
  }
  if (!$this
    ->io()
    ->confirm(dt('Ready to enqueue !count records for pull?', [
    '!count' => count($seen),
  ]))) {
    return;
  }
  foreach ($queries as $soql) {
    $this->eventDispatcher
      ->dispatch(new SalesforceQueryEvent($mapping, $soql), SalesforceEvents::PULL_QUERY);
    $this
      ->logger()
      ->info(dt('Issuing pull query: !query', [
      '!query' => (string) $soql,
    ]));
    $results = $this->client
      ->query($soql);
    if (empty($results)) {
      $this
        ->logger()
        ->warning('No records found to pull.');
      continue;
    }
    $this->pullQueue
      ->enqueueAllResults($mapping, $results);
    $this
      ->logger()
      ->info(dt('Queued !count items for pull.', [
      '!count' => $results
        ->size(),
    ]));
  }
}