diff --git a/modules/payment/commerce_payment.post_update.php b/modules/payment/commerce_payment.post_update.php new file mode 100644 index 0000000000..a4d977e20a --- /dev/null +++ b/modules/payment/commerce_payment.post_update.php @@ -0,0 +1,87 @@ +exists('commerce_remote_id')->count()->execute()) { + // The count of entities visited so far. + $sandbox['current'] = 0; + // Total entities that must be visited. + $sandbox['max'] = $count; + + // Get the first payment gateway for every payment module. + $payment_gateways_by_module = []; + /** @var \Drupal\commerce_payment\PaymentGatewayStorageInterface $payment_gateway_storage */ + $payment_gateway_storage = \Drupal::entityTypeManager()->getStorage('commerce_payment_gateway'); + $payment_gateways = $payment_gateway_storage->loadMultiple(); + uasort($payment_gateways, [$payment_gateway_storage->getEntityType()->getClass(), 'sort']); + foreach ($payment_gateways as $payment_gateway) { + $payment_gateway_data = $payment_gateway->toArray(); + $module = reset($payment_gateway_data['dependencies']['module']); + if (!isset($payment_gateways_by_module[$module])) { + $payment_gateways_by_module[$module] = $payment_gateway; + } + } + $sandbox['payment_gateways'] = $payment_gateways; + $sandbox['payment_gateways_by_module'] = $payment_gateways_by_module; + $sandbox['user_storage'] = \Drupal::entityTypeManager()->getStorage('user'); + } + else { + return t('No user Remote ID field data to update.'); + } + } + + // Process entities by groups of 20. + $limit = 20; + // Get the user ids that have 'commerce_remote_id' field not empty. + $result = \Drupal::entityQuery('user') + ->exists('commerce_remote_id') + ->range($sandbox['current'], $limit) + ->execute(); + + foreach ($result as $uid) { + $user = $sandbox['user_storage']->load($uid); + + $save = FALSE; + /** @var \Drupal\commerce\Plugin\Field\FieldType\RemoteIdFieldItemListInterface $remote_ids */ + $remote_ids = $user->commerce_remote_id; + /** @var \Drupal\commerce\Plugin\Field\FieldType\RemoteIdItem $item */ + foreach ($remote_ids as $index => $item) { + $current_provider = $item->getValue()['provider']; + if (in_array($current_provider, array_keys($sandbox['payment_gateways_by_module']))) { + $payment_gateway = $sandbox['payment_gateways_by_module'][$current_provider]; + $item->set('provider', $payment_gateway->id() . '-' . $payment_gateway->getPlugin()->getMode()); + $save = TRUE; + } + elseif (!in_array($current_provider, array_keys($sandbox['payment_gateways']))) { + // Delete "orphaned" Remote Ids. + $remote_ids->removeItem($index); + $save = TRUE; + } + } + if ($save) { + $user->save(); + } + + // Update our progress information. + $sandbox['current']++; + } + + $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['current'] / $sandbox['max']); + + if ($sandbox['#finished'] >= 1) { + return t('The user Remote ID field data for payments updated.'); + } + +} diff --git a/modules/payment/src/Plugin/Commerce/PaymentGateway/PaymentGatewayBase.php b/modules/payment/src/Plugin/Commerce/PaymentGateway/PaymentGatewayBase.php index e732b56115..c38543aec9 100644 --- a/modules/payment/src/Plugin/Commerce/PaymentGateway/PaymentGatewayBase.php +++ b/modules/payment/src/Plugin/Commerce/PaymentGateway/PaymentGatewayBase.php @@ -12,6 +12,7 @@ use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Plugin\PluginBase; use Drupal\Core\Plugin\PluginWithFormsTrait; +use Drupal\user\UserInterface; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -319,4 +320,25 @@ public function buildPaymentOperations(PaymentInterface $payment) { return $operations; } + /** + * {@inheritdoc} + */ + public function getOwnerRemoteId(UserInterface $user) { + $remote_id = NULL; + if ($user->isAuthenticated()) { + $remote_id = $user->commerce_remote_id->getByProvider($this->entityId . '-' . $this->getMode()); + } + return $remote_id; + } + + /** + * {@inheritdoc} + */ + public function setOwnerRemoteId(UserInterface $user, $remote_id) { + if ($user->isAuthenticated()) { + $user->commerce_remote_id->setByProvider($this->entityId . '-' . $this->getMode(), $remote_id); + $user->save(); + } + } + } diff --git a/modules/payment/src/Plugin/Commerce/PaymentGateway/PaymentGatewayInterface.php b/modules/payment/src/Plugin/Commerce/PaymentGateway/PaymentGatewayInterface.php index 0d94eee8d8..cbe373a0c1 100644 --- a/modules/payment/src/Plugin/Commerce/PaymentGateway/PaymentGatewayInterface.php +++ b/modules/payment/src/Plugin/Commerce/PaymentGateway/PaymentGatewayInterface.php @@ -7,6 +7,7 @@ use Drupal\Component\Plugin\DerivativeInspectionInterface; use Drupal\Core\Plugin\PluginFormInterface; use Drupal\Core\Plugin\PluginWithFormsInterface; +use Drupal\user\UserInterface; /** * Defines the base interface for payment gateways. @@ -112,4 +113,25 @@ public function getCreditCardTypes(); */ public function buildPaymentOperations(PaymentInterface $payment); + /** + * Gets the user remote ID for the payment gateway if any. + * + * @param \Drupal\user\UserInterface $user + * The user. + * + * @return string|null + * The user remote ID for the payment gateway or NULL. + */ + public function getOwnerRemoteId(UserInterface $user); + + /** + * Sets the user remote ID for the payment gateway. + * + * @param \Drupal\user\UserInterface $user + * The user. + * @param string $remote_id + * The remote ID. + */ + public function setOwnerRemoteId(UserInterface $user, $remote_id); + } diff --git a/modules/payment/tests/src/FunctionalJavascript/PaymentCheckoutTest.php b/modules/payment/tests/src/FunctionalJavascript/PaymentCheckoutTest.php index bebd9b80c1..5d266eb6de 100644 --- a/modules/payment/tests/src/FunctionalJavascript/PaymentCheckoutTest.php +++ b/modules/payment/tests/src/FunctionalJavascript/PaymentCheckoutTest.php @@ -227,8 +227,14 @@ public function testCheckoutWithExistingPaymentMethod() { $this->assertSession()->pageTextContains('Your order number is 1. You can view your order on your account page when logged in.'); $order = Order::load(1); - $this->assertEquals('onsite', $order->get('payment_gateway')->target_id); - $this->assertEquals('1', $order->get('payment_method')->target_id); + /** @var \Drupal\commerce_payment\Entity\PaymentMethodInterface $payment_method */ + $payment_method = $order->get('payment_method')->entity; + $this->assertEquals('1', $payment_method->id()); + /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface $payment_gateway */ + $payment_gateway = $order->get('payment_gateway')->entity; + $this->assertEquals('onsite', $payment_gateway->id()); + $payment_gateway_plugin = $payment_gateway->getPlugin(); + $this->assertNull($payment_gateway_plugin->getOwnerRemoteId($payment_method->getOwner())); // Verify that a payment was created. $payment = Payment::load(1); @@ -283,6 +289,11 @@ public function testCheckoutWithNewPaymentMethod() { $payment_method = $order->get('payment_method')->entity; $this->assertEquals('1881', $payment_method->get('card_number')->value); $this->assertEquals('123 New York Drive', $payment_method->getBillingProfile()->get('address')->address_line1); + /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface $payment_gateway */ + $payment_gateway = $order->get('payment_gateway')->entity; + $payment_gateway_plugin = $payment_gateway->getPlugin(); + $owner = $payment_method->getOwner(); + $this->assertEquals($owner->id(), $payment_gateway_plugin->getOwnerRemoteId($owner)); // Verify that a payment was created. $payment = Payment::load(1); diff --git a/modules/payment_example/src/Plugin/Commerce/PaymentGateway/Onsite.php b/modules/payment_example/src/Plugin/Commerce/PaymentGateway/Onsite.php index 9c22df1744..7c7ca7b062 100644 --- a/modules/payment_example/src/Plugin/Commerce/PaymentGateway/Onsite.php +++ b/modules/payment_example/src/Plugin/Commerce/PaymentGateway/Onsite.php @@ -209,6 +209,12 @@ public function createPaymentMethod(PaymentMethodInterface $payment_method, arra } } + // Payment method remote owner id. + $owner = $payment_method->getOwner(); + if (!$this->getOwnerRemoteId($owner)) { + $this->setOwnerRemoteId($owner, $owner->id()); + } + // Perform the create request here, throw an exception if it fails. // See \Drupal\commerce_payment\Exception for the available exceptions. // You might need to do different API requests based on whether the