Drupal: 8.7.2 Commerce: 2.13
I have a custom module set up that adds the following functionality to Commerce:
It prevents the user from adding more than one item to their cart. If they try to add a second item, it removes the first item from their cart and adds the second item.
When clicking "Add to Cart", it redirects the user to a confirmation page.
On that page is a button that links to the order's checkout page.
I am handling all of these via queries that use the user ID and order ID to pull the correct order/cart information.
This all works great for logged in users. Most of our customers will be anonymous, though. It does work for anonymous users, but my concern is that if multiple anonymous users are placing orders at the same time, their carts will get mixed up, because all anonymous users have a UID of 0.
How can I better differentiate between anonymous user's carts? Is there a way to store their IP in the database, and then use that?
Here is my module's code:
commerce_custom.module (handles removing first item from cart, redirecting to confirmation page):
<?php
use Drupal\Core\Form\FormStateInterface;
use Drupal\commerce_order\Entity\Order;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Implements hook_form_FORM_ID_alter().
*/
function commerce_custom_form_commerce_order_item_add_to_cart_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$form['actions']['submit']['#value']='Sponsor';
$form['#validate'][] = 'commerce_custom_form_validate';
$form['actions']['submit']['#submit'][] = 'commerce_custom_cart_alter_redirect';
}
function commerce_custom_form_validate(array &$form, FormStateInterface $form_state) {
$user = \Drupal::currentUser()->id();
$connection = \Drupal::database();
$query = $connection->query("select * from commerce_order_item join commerce_order on commerce_order_item.order_id = commerce_order.order_id where uid = :user and state = 'draft'", [':user' => $user]);
$result = $query->fetchAll();
//dpm($result);
$cart_count = $result[0]->quantity;
$order_id = $result[0]->order_id;
if ($cart_count > 0 && $order_id) {
$order = \Drupal::entityTypeManager()->getStorage('commerce_order')->load($order_id);
$items = $order->getItems();
foreach($items as $item_key => $item) {
$order->removeItem($item);
$item->delete();
}
}
}
function commerce_custom_cart_alter_redirect(&$form, FormStateInterface $form_state) {
$responce = new RedirectResponse('/how-it-works');
$responce->send();
}
ContinueCheckoutBlock.php (creates block with button linking to checkout page):
<?php
namespace Drupal\commerce_custom\Plugin\Block;
use Drupal\Core\Block\BlockBase;
class ContinueCheckoutBlock extends BlockBase {
public function build() {
$user = \Drupal::currentUser()->id();
$connection = \Drupal::database();
$query = $connection->query("select * from commerce_order_item join commerce_order on commerce_order_item.order_id = commerce_order.order_id where uid = :user and state = 'draft'", [':user' => $user]);
$result = $query->fetchAll();
$order_id = $result[0]->order_id;
return array(
'#type' =>'markup',
'#markup' => '<a href=checkout/' . $order_id . '/order_information class=button>Continue</a>',
);
}
}