View source
<?php
namespace Drupal\commerce_xquantity\Form;
use Drupal\commerce\Context;
use Drupal\Core\Form\FormStateInterface;
use Drupal\commerce_cart\Form\AddToCartForm;
use Drupal\Component\Utility\NestedArray;
use Drupal\xnumber\Utility\Xnumber as Numeric;
class XquantityAddTocartForm extends AddToCartForm {
protected static $formIds = [];
public $quantityPrices = [];
public $quantityScale;
public function getFormId() {
if (empty($this->formId)) {
$this->formId = $this
->getBaseFormId();
}
$id = $this->formId;
if (!in_array($id, static::$formIds)) {
$order_item = $this->entity;
if ($purchased_entity = $order_item
->getPurchasedEntity()) {
extract($purchased_entity
->toArray());
}
else {
extract($order_item
->toArray());
}
$properties = [
'variation_id' => !isset($variation_id) ?: $variation_id,
'uuid' => !isset($uuid) ?: $uuid,
'uid' => !isset($uid) ?: $uid,
'product_id' => !isset($product_id) ?: $product_id,
'created' => !isset($created) ?: $created,
];
$this->formId .= '_' . sha1(serialize($properties));
}
else {
$base_id = $this
->getBaseFormId();
while (in_array($id, static::$formIds)) {
$id = $base_id . '_' . sha1($id . $id);
}
$this->formId = $id;
}
static::$formIds[] = $this->formId;
return $this->formId;
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$item = NULL;
$order_item = $this->entity;
$purchased_entity = $order_item
->getPurchasedEntity();
$form_object = $form_state
->getFormObject();
if ($id = $form_state
->getValue('purchased_entity')) {
if (!empty($id[0]['variation']) && $id[0]['variation'] != $purchased_entity
->id()) {
$this
->setEntity($this
->buildEntity($form, $form_state));
$order_item = $this->entity;
$purchased_entity = $purchased_entity
->load($id[0]['variation']);
$order_item
->setQuantityPrices($form_object, $order_item
->getFormDisplayWidget(), $form_state);
}
}
if ($qty = $form_state
->getValue('quantity')) {
if (!empty($qty[0]['value'])) {
$quantity = $qty[0]['value'];
}
}
else {
$quantity = $order_item
->getQuantity();
}
if ($form_object->quantityScale !== NULL) {
$scale = $form_object->quantityScale ?: 0;
$order_type_id = $this->orderTypeResolver
->resolve($order_item);
$store = $this
->selectStore($purchased_entity);
$cart = $this->cartProvider
->getCart($order_type_id, $store);
if ($cart && ($items = $cart
->getItems())) {
$matcher = \Drupal::service('commerce_cart.order_item_matcher');
if ($item = $matcher
->match($order_item, $items)) {
$quantity = bcadd($quantity, $item
->getQuantity(), $scale);
}
}
if ($price = $order_item
->getQuantityPrice($form_object, $purchased_entity, $quantity)) {
$this->entity
->setUnitPrice($price, TRUE);
if ($item && !$price
->equals($item
->getUnitPrice())) {
$item
->setUnitPrice($price, TRUE);
$this->cartManager
->updateOrderItem($cart, $item, FALSE);
}
}
}
parent::submitForm($form, $form_state);
$messenger = $this
->messenger();
$messages = $messenger
->messagesByType('status');
$messenger
->deleteByType('status');
foreach ($messages as $msg) {
if (preg_match('/\\<a href\\="\\/cart"\\>.*\\<\\/a\\>/', $msg
->__toString(), $matches)) {
$this->moduleHandler
->alter("xquantity_added_to_cart_msg", $msg, $this);
$msg && $messenger
->addMessage($msg);
}
else {
$messenger
->addMessage($msg);
}
}
}
public function validateForm(array &$form, FormStateInterface $form_state) {
$order_item = $this->entity;
$settings = $order_item
->getQuantityWidgetSettings();
$default = $step = $settings['step'] ?: $settings['base_step'];
$scale = Numeric::getDecimalDigits($step);
$min = $settings['min'] && $step <= $settings['min'] ? $settings['min'] : $step;
$max = $settings['max'] && $step <= $settings['max'] ? $settings['max'] : $step;
$default = $settings['default_value'] ?: ($settings['base_default_value'] ?: $min);
$value = $form_state
->getValue([
'quantity',
0,
'value',
]);
$quantity = $cart_quantity = $value !== NULL ? $value : $default;
if (!$quantity || $quantity < $min) {
$form_state
->setErrorByName('quantity', $this
->t('The quantity should be no less than %min', [
'%min' => $min,
]));
return;
}
parent::validateForm($form, $form_state);
if ($form_state
->getTriggeringElement()['#type'] == 'submit' && ($id = NestedArray::getValue($form, [
'purchased_entity',
'widget',
'0',
'variation',
'#value',
]))) {
$purchased_entity = $order_item
->getPurchasedEntity()::load($id);
if ($available = $purchased_entity && $this->moduleHandler
->moduleExists('xquantity_stock')) {
$availability = \Drupal::service('xquantity_stock.availability_checker');
if ($availability
->applies($order_item)) {
$store = $this
->selectStore($purchased_entity);
$context = new Context($this->currentUser, $store, time(), [
'xquantity' => 'add_to_cart',
]);
$available = !$availability
->check($order_item, $context, $quantity)
->isUnavailable();
if (!$available && $order_item
->rotateStock($purchased_entity, $quantity, $context)) {
$available = !$availability
->check($order_item, $context, $quantity)
->isUnavailable();
}
}
}
if (!$available) {
$args = [
'%quantity' => $quantity,
'%label' => $purchased_entity ? $purchased_entity
->label() : $this
->t('???'),
':href' => $purchased_entity ? $purchased_entity
->toUrl()
->toString() : '/',
];
$msg = $this
->t('Unfortunately, the quantity %quantity of the %label is not available right at the moment.', $args);
\Drupal::logger('xquantity_stock')
->warning($this
->t('Possibly the <a href=":href">%label</a> with the quantity %quantity is out of stock.', $args));
$purchased_entity && $this->moduleHandler
->alter("xquantity_add_to_cart_not_available_msg", $msg, $quantity, $purchased_entity);
$form_state
->setErrorByName('quantity', $msg);
}
$order_type_id = $this->orderTypeResolver
->resolve($order_item);
$store = $this
->selectStore($purchased_entity);
$cart = $this->cartProvider
->getCart($order_type_id, $store);
if ($cart && ($items = $cart
->getItems())) {
$matcher = \Drupal::service('commerce_cart.order_item_matcher');
if ($item = $matcher
->match($order_item, $items)) {
$cart_quantity = bcadd($cart_quantity, $item
->getQuantity(), $scale);
}
}
if (bccomp($cart_quantity, $max, $scale) === 1) {
$form_state
->setErrorByName('quantity', $this
->t('Only %max items of the %label can be added to the shopping cart. You have %items items left to add.', [
'%max' => $max,
'%label' => $purchased_entity
->label(),
'%items' => bcsub($max, bcsub($cart_quantity, $quantity, $scale), $scale),
]));
}
}
}
}