function commerce_registration_commerce_cart_order_refresh in Commerce Registration 7.2
Implements hook_commerce_cart_order_refresh().
Alter the line items to make sure we are not overbooking a registration prod Based on https://www.drupal.org/node/2126417
@todo - can we do this in one pass rather than 3?
File
- ./
commerce_registration.module, line 1480 - Commerce Registration module code.
Code
function commerce_registration_commerce_cart_order_refresh($order_wrapper) {
$order = $order_wrapper
->value();
// Make sure registration entities still match up to products.
if (isset($order->data['register_entities'])) {
// Save a copy of register_entities to find registrations no longer associated with a product.
$register_entities = $order->data['register_entities'];
foreach ($order_wrapper->commerce_line_items as $line_item_wrapper) {
if (!in_array($line_item_wrapper->type
->value(), commerce_product_line_item_types())) {
continue;
}
$product = $line_item_wrapper->commerce_product;
$line_item_id = $line_item_wrapper->line_item_id
->value();
if (isset($order->data['register_entities'][$line_item_id . 'prod-' . $product->sku
->value()])) {
// This registration still has a product.
unset($register_entities[$line_item_id . 'prod-' . $product->sku
->value()]);
}
}
// Delete registrations which no longer have a matching product in the cart.
$orphan_registration_ids = array();
foreach ($register_entities as $key => $registrations) {
foreach ($registrations as $registration) {
$orphan_registration_ids[] = $registration->registration_id;
}
unset($order->data['register_entities'][$key]);
}
registration_delete_multiple($orphan_registration_ids);
}
// Stop users overbooking registrations
if (!commerce_cart_order_is_cart($order_wrapper
->value())) {
return FALSE;
}
// Keep an array with the sum of qty
$qty_sum = array();
// Keep an array with the list of potentially overbooked line items
$overbooked_prod_id = array();
// Keep list of Warning Messages
$msg_array = array();
// Set the message we will show to the user if they need to change the quantity in their cart
$adjust_qty_text = arg(0) == 'cart' ? t('Please adjust your cart quantity.') : l(t('Please adjust your cart quantity.'), 'cart');
// ** First Pass:
// Make sure individual line items do not exceed available registrations
// For each of the line items in the order
foreach ($order_wrapper->commerce_line_items as $delta => $line_item_wrapper) {
if (!in_array($line_item_wrapper->type
->value(), commerce_product_line_item_types())) {
return FALSE;
}
// Get the line item so we can work on it
$line_item = $line_item_wrapper
->value();
// Gets the quantity of this line item in the cart
$qty = $line_item_wrapper->quantity
->value();
// Gets the unique product id for the line item
$product_id = $line_item_wrapper->commerce_product->product_id
->value();
// Attempt to get registration settings for this product
$settings = registration_entity_settings('commerce_product', $product_id);
// Check if this product is registration enabled
if (!empty($settings) && $settings['status'] == 1) {
// For this product id, see how many are available
$capacity = (int) $settings['capacity'];
$filled = (int) registration_event_count('commerce_product', $product_id);
// Add order registrations offset
$order_registrations = 0;
// Get registrations from current order if they have been created
if (isset($order->data['register_entities'])) {
// loop through registrations
foreach ($order->data['register_entities'] as $key => $registrations) {
foreach ($registrations as $registration) {
if ($registration->order_id == $order->order_id && $registration->entity_id == $product_id) {
// this registration belongs to the current order and current product; add to order registrations
$order_registrations++;
}
}
}
}
// Check if $capacity is set to 0 (unlimited) and ensure $avail isn't
// negative which can cause too many registrations to be removed.
$avail = 0;
if ($capacity > 0) {
$avail = $capacity - $filled + $order_registrations;
}
if ($avail < 0) {
$avail = 0;
}
// If the line item qty is more than available, set the
// line item to availability to avoid over booking
if ($capacity > 0 && $qty > $avail) {
// Set line item qty to availability
_commerce_registration_set_line_item_qty($line_item, $avail);
if (!array_key_exists($product_id, $qty_sum)) {
$qty_sum[$product_id] = $avail;
}
else {
$qty_sum[$product_id] += $avail;
}
// Display a warning message.
$msg_array[$product_id] = t("There are only @num available slots for @title. !adjust_text", array(
'@num' => $avail,
'@title' => $line_item_wrapper->commerce_product->title
->value(),
'!adjust_text' => $adjust_qty_text,
));
}
else {
// Let's add up the sum of all the same products in the cart
// needed since disabled the
// 'Attempt to combine like products on the same line item in the cart.'
if (!array_key_exists($product_id, $qty_sum)) {
$qty_sum[$product_id] = $line_item_wrapper->quantity
->value();
}
else {
$qty_sum[$product_id] += $line_item_wrapper->quantity
->value();
}
}
// Check if the sum in cart would result in overbooking
if ($capacity > 0 && $qty_sum[$product_id] > $avail) {
$overbooked_prod_id[$product_id] = TRUE;
}
}
}
// ** Second Pass:
// if Sum of line item quantities would cause overbooking
// First try setting all of those products quantity to the slots available
// then re-check qty sum. if still exceeds, then remove line item
$qty_sum = array();
// reset
// For each of the line items in the order
if (!empty($overbooked_prod_id)) {
foreach ($order_wrapper->commerce_line_items as $delta => $line_item_wrapper) {
// If this line item product id is in the overbooked array, set qty 1
$line_item = $line_item_wrapper
->value();
// Gets the unique product id for the line item
$product_id = $line_item_wrapper->commerce_product->product_id
->value();
if (isset($overbooked_prod_id[$product_id])) {
// Set line item qty to 1
_commerce_registration_set_line_item_qty($line_item, $avail);
if (!array_key_exists($product_id, $qty_sum)) {
$qty_sum[$product_id] = $avail;
}
else {
$qty_sum[$product_id] += $avail;
}
// For this product id, see how many are available
// Attempt to get registration settings for this product
$settings = registration_entity_settings('commerce_product', $product_id);
$capacity = (int) $settings['capacity'];
$filled = (int) registration_event_count('commerce_product', $product_id);
$avail = $capacity - $filled;
// Warning Message
$msg_array[$product_id] = t("There are only @num available slots for @title. !adjust_text", array(
'@num' => $avail,
'@title' => $line_item_wrapper->commerce_product->title
->value(),
'!adjust_text' => $adjust_qty_text,
));
// Check if the sum in cart would result in overbooking
// This time, we remove it.
if ($qty_sum[$product_id] > $avail) {
// Delete the line item
// do not need to save order, as done after the hook for us
commerce_cart_order_product_line_item_delete($order_wrapper
->value(), $line_item->line_item_id, $skip_save = TRUE);
// $order_wrapper->value(), $line_item->line_item_id );
$qty_sum[$product_id] -= 1.0;
// Warning Message
$msg_array[$product_id] = t("There are only @num available slots for @title. Item was removed from your cart", array(
'@num' => $avail,
'@title' => $line_item_wrapper->commerce_product->title
->value(),
));
}
}
}
}
// ** Third Pass:
// Verify if registration is possible
// We have already checked capacity, check open/close dates and reg status
// if not available, then remove
foreach ($order_wrapper->commerce_line_items as $delta => $line_item_wrapper) {
if (!in_array($line_item_wrapper->type
->value(), commerce_product_line_item_types())) {
continue;
}
// Get the line item so we can work on it
$line_item = $line_item_wrapper
->value();
// Gets the unique product id for the line item
$product_id = $line_item_wrapper->commerce_product->product_id
->value();
// Attempt to get registration settings for this product
$settings = registration_entity_settings('commerce_product', $product_id);
// Check if this product is registration enabled
if (!empty($settings)) {
$status = $settings['status'];
$open = isset($settings['open']) ? strtotime($settings['open']) : NULL;
$close = isset($settings['close']) ? strtotime($settings['close']) : NULL;
$now = REQUEST_TIME;
// remove line item if not open
if ($status) {
// check open date range
if (isset($open) && $now < $open) {
$status = FALSE;
}
// check close date range
if (isset($close) && $now >= $close) {
$status = FALSE;
}
}
// Delete the line item
if ($status == FALSE) {
// do not need to save order, as done after the hook for us
commerce_cart_order_product_line_item_delete($order_wrapper
->value(), $line_item->line_item_id, $skip_save = TRUE);
// Warning Message
$msg_array[$product_id] = t("Registration is not available for @product. Item was removed from your cart.", array(
'@product' => $line_item_wrapper->commerce_product->title
->value(),
));
}
}
}
// Display warning messages for any products that were overbooked
foreach ($msg_array as $msg) {
drupal_set_message($msg, 'warning', TRUE);
}
}