From c81f63b33b7132cce90ac458d7079d69558c386e Mon Sep 17 00:00:00 2001
From: Aaron Bauman <aaron@messageagency.com>
Date: Wed, 21 Aug 2019 14:51:32 -0400
Subject: [PATCH] Add salesforce_push:requeue drush9 command

---
 .../src/Commands/SalesforcePushCommands.php   | 67 ++++++++++++++++++-
 modules/salesforce_push/src/PushQueue.php     |  2 +-
 2 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/modules/salesforce_push/src/Commands/SalesforcePushCommands.php b/modules/salesforce_push/src/Commands/SalesforcePushCommands.php
index 7b5fff64..5bc62228 100644
--- a/modules/salesforce_push/src/Commands/SalesforcePushCommands.php
+++ b/modules/salesforce_push/src/Commands/SalesforcePushCommands.php
@@ -6,6 +6,7 @@ use Drupal\Core\Database\Connection;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\salesforce_mapping\Commands\SalesforceMappingCommandsBase;
 use Drupal\salesforce\Rest\RestClient;
+use Drupal\salesforce_mapping\MappingConstants;
 use Drupal\salesforce_push\PushQueue;
 use Symfony\Component\Console\Input\Input;
 use Symfony\Component\Console\Output\Output;
@@ -82,6 +83,15 @@ class SalesforcePushCommands extends SalesforceMappingCommandsBase {
     return $this->interactPushMappings($input, $output, 'Choose a Salesforce mapping', 'Push All');
   }
 
+  /**
+   * Collect a mapping interactively.
+   *
+   * @hook interact salesforce_push:requeue
+   */
+  public function interactRequeue(Input $input, Output $output) {
+    return $this->interactPushMappings($input, $output, 'Choose a Salesforce mapping', 'Push All');
+  }
+
   /**
    * Process push queues for one or all Salesforce Mappings.
    *
@@ -107,6 +117,59 @@ class SalesforcePushCommands extends SalesforceMappingCommandsBase {
     }
   }
 
+  /**
+   * Requeue mapped entities for asynchronous push.
+   *
+   * Addresses the frequent need to re-push all entities for a given mapping.
+   * Given a mapping, re-queue all the mapped objects to the Salesforce push
+   * queue. The push queue will not be processed by this command, and no data
+   * will be pushed to salesforce. Run salesforce_push:push-queue to proceess
+   * the records queued by this command.
+   *
+   * NOTE: Existing push queue records will be replaced by this operation.
+   *
+   * @param string $name
+   *   The Drupal machine name of the mapping for the entities.
+   * @param array $options
+   *   An associative array of options whose values come from cli, aliases,
+   *   config, etc.
+   *
+   * @option ids
+   *   If provided, only requeue the entities given by these ids.
+   *   Comma-delimited.
+   * @usage drush sfpu foo
+   *   Requeue all drupal entities mapped objects for mapping "foo".
+   * @usage drush sfpu foo --ids=1,2,3,4
+   *   Requeue entities for mapping "foo" with ids 1, 2, 3, 4, if they exist.
+   *
+   * @command salesforce_push:requeue
+   * @aliases sfrq,salesforce-push-requeue
+   * @see salesforce_push:push-queue
+   */
+  public function requeue($name, array $options = ['ids' => '']) {
+    // Dummy call to create item, to ensure table exists.
+    try {
+      \Drupal::service('queue.salesforce_push')->createItem(NULL);
+    }
+    catch (\Exception $e) {
+
+    }
+    $mappings = $this->getPushMappingsFromName($name);
+    foreach ($mappings as $mapping) {
+      $ids = array_filter(array_map('intval', explode(',', $options['ids'])));
+      $mapping_name = $mapping->id();
+      $op = MappingConstants::SALESFORCE_MAPPING_SYNC_DRUPAL_UPDATE;
+      $time = time();
+      $insertQuery = "REPLACE INTO salesforce_push_queue (name, entity_id, mapped_object_id, op, failures, expire, created, updated) 
+          (SELECT '$mapping_name', drupal_entity__target_id, id, '$op', 0, 0, $time, $time FROM salesforce_mapped_object";
+      if (!empty($ids)) {
+        $insertQuery .= " WHERE drupal_entity__target_id IN (" . implode(',', $ids) . ")";
+      }
+      $insertQuery .= ")";
+      $this->database->query($insertQuery)->execute();
+    }
+  }
+
   /**
    * Push entities of a mapped type that are not linked to Salesforce Objects.
    *
@@ -129,7 +192,7 @@ class SalesforcePushCommands extends SalesforceMappingCommandsBase {
    * @command salesforce_push:push-unmapped
    * @aliases sfpu,salesforce-push-unmapped,salesforce_push:unmapped
    */
-  public function pushUnmapped($name, array $options = ['count' => NULL]) {
+  public function pushUnmapped($name, array $options = ['count' => 50]) {
     $mappings = $this->getPushMappingsFromName($name);
     foreach ($mappings as $mapping) {
       $entity_type = $mapping->get('drupal_entity_type');
@@ -144,7 +207,7 @@ class SalesforcePushCommands extends SalesforceMappingCommandsBase {
       }
       $query->fields('b', [$id_key]);
       $query->isNull('m.drupal_entity__target_id');
-      $results = $query->range(0, drush_get_option('count', 50))
+      $results = $query->range(0, $options['count'])
         ->execute()
         ->fetchAllAssoc($id_key);
       $entities = $entity_storage->loadMultiple(array_keys($results));
diff --git a/modules/salesforce_push/src/PushQueue.php b/modules/salesforce_push/src/PushQueue.php
index 6a070588..c3d14cd3 100644
--- a/modules/salesforce_push/src/PushQueue.php
+++ b/modules/salesforce_push/src/PushQueue.php
@@ -258,7 +258,7 @@ class PushQueue extends DatabaseQueue implements PushQueueInterface {
     $ret = $query->execute();
 
     // Drupal still doesn't support now() https://www.drupal.org/node/215821
-    // 9 years.
+    // 11 years.
     if ($ret == Merge::STATUS_INSERT) {
       $this->connection->merge(static::TABLE_NAME)
         ->key(['name' => $this->name, 'entity_id' => $data['entity_id']])
-- 
GitLab