arch-8.x-1.x-dev/modules/stock/arch_stock.module
modules/stock/arch_stock.module
<?php
/**
* @file
* Stock module.
*/
use Drupal\arch_cart\Cart\CartInterface;
use Drupal\arch_order\Entity\OrderInterface;
use Drupal\arch_order\Plugin\Field\FieldType\OrderLineItemInterface;
use Drupal\arch_product\Entity\Product;
use Drupal\arch_product\Entity\ProductInterface;
use Drupal\arch_product\Entity\ProductTypeInterface;
use Drupal\arch_stock\Plugin\Field\FieldType\StockFieldItemList;
use Drupal\Component\Utility\Html;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
use Drupal\Core\Template\Attribute;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
/**
* Implements hook_entity_load().
*/
function arch_stock_entity_load(array $entities, $entity_type_id) {
/** @var \Drupal\arch_stock\Manager\WarehouseManager $warehouse_manager */
$warehouse_manager = Drupal::service('warehouse.manager');
$warehouses = $warehouse_manager->getFormOptions();
$fields = drupal_static(__FUNCTION__);
/** @var \Drupal\Core\Entity\EntityInterface $entity */
foreach ($entities as $entity) {
if ($entity->getEntityTypeId() != 'product') {
continue;
}
if (!$entity instanceof FieldableEntityInterface) {
continue;
}
if (!isset($fields[$entity->getEntityTypeId()][$entity->bundle()])) {
$fields[$entity->getEntityTypeId()][$entity->bundle()] = $entity->getFields();
}
foreach ($fields[$entity->getEntityTypeId()][$entity->bundle()] as $field) {
if (!$field instanceof StockFieldItemList) {
continue;
}
_arch_stock_prepare_stock_field_value($field, $warehouses);
}
}
}
/**
* Set stock field values to make sure every warehouse has value.
*
* @param \Drupal\arch_stock\Plugin\Field\FieldType\StockFieldItemList $field
* Stock field.
* @param array $warehouses
* Warehouse list.
*/
function _arch_stock_prepare_stock_field_value(StockFieldItemList $field, array $warehouses) {
$values = array_filter($field->getValue(), function ($item) use ($warehouses) {
return isset($warehouses[$item['warehouse']]);
});
$existing = array_column($values, 'warehouse');
foreach ($warehouses as $id => $label) {
if (in_array($id, $existing)) {
continue;
}
$values[] = [
'warehouse' => $id,
'quantity' => 0,
'cart_quantity' => 0,
];
}
$field->setValue($values);
}
/**
* Implements hook_theme().
*/
function arch_stock_theme() {
return [
'warehouse' => [
'render element' => 'elements',
],
'stock_form_table' => [
'render element' => 'element',
],
'stock_info_field' => [
'render element' => 'element',
],
];
}
/**
* Implements hook_theme_suggestions_HOOK().
*/
function arch_stock_theme_suggestions_warehouse(array $variables) {
$suggestions = [];
/** @var \Drupal\arch_stock\Entity\WarehouseInterface $warehouse */
$warehouse = $variables['elements']['#warehouse'];
$suggestions[] = 'warehouse__' . $warehouse->bundle();
$suggestions[] = 'warehouse__' . $warehouse->id();
$suggestions[] = 'warehouse__' . $warehouse->bundle() . '__' . $warehouse->id();
return $suggestions;
}
/**
* Prepares variables for warehouse templates.
*
* Default template: warehouse.html.twig.
*
* @param array $variables
* An associative array containing:
* - elements: An associative array containing the warehouse. Properties used:
* - #warehouse: A \Drupal\arch_stock\Entity\WarehouseInterface object.
* - #view_mode: The current view mode for this warehouse, e.g.
* 'full' or 'teaser'.
* - attributes: HTML attributes for the containing element.
*/
function template_preprocess_warehouse(array &$variables) {
$variables['view_mode'] = $variables['elements']['#view_mode'];
$variables['warehouse'] = $variables['elements']['#warehouse'];
/** @var \Drupal\arch_stock\Entity\WarehouseInterface $warehouse */
// Helpful $content variable for templates.
$variables['content'] = [];
foreach (Element::children($variables['elements']) as $key) {
$variables['content'][$key] = $variables['elements'][$key];
}
}
/**
* Preprocess arch stock form table.
*
* @param array $variables
* Variables array.
*/
function template_preprocess_stock_form_table(array &$variables) {
$element = $variables['element'];
$variables['multiple'] = $element['#cardinality_multiple'];
$variables['label'] = [
'#theme' => 'form_element_label',
'#title' => $element['#title'],
'#title_display' => 'above',
];
$table_id = Html::getUniqueId($element['#field_name'] . '_values');
$order_class = $element['#field_name'] . '-delta-order';
$header = [];
if ($variables['multiple']) {
$header['drag'] = [
'data' => NULL,
];
$header['warehouse'] = [
'data' => t('Warehouse', [], ['context' => 'arch_stock']),
'class' => ['header-value', 'header-value--type', 'col-narrow'],
];
}
$header['quantity'] = [
'data' => t('Quantity', [], ['context' => 'arch_stock']),
'class' => ['header-value', 'header-value--vat', 'col-narrow'],
];
if ($variables['multiple']) {
$header['sort'] = t('Order', [], ['context' => 'Sort order']);
}
$rows = [];
// Sort items according to '_weight' (needed when the form comes back after
// preview or failed validation).
$items = [];
$variables['button'] = [];
$fields = [
'warehouse' => [
'#title_display' => 'invisible',
],
'quantity' => [
'#title_display' => 'invisible',
],
];
foreach (Element::children($element) as $key) {
if ($key === 'add_more') {
$variables['button'] = &$element[$key];
}
else {
$items[] = &$element[$key];
}
}
usort($items, '_field_multiple_value_form_sort_helper');
// Add the items as table rows.
foreach ($items as $item) {
$item['_weight']['#attributes']['class'] = [$order_class];
// Remove weight form element from item render array so it can be rendered
// in a separate table column.
$delta_element = $item['_weight'];
unset($item['_weight']);
foreach ($fields as $field => $settings) {
if (isset($item[$field])) {
$item[$field] = array_merge($item[$field], $settings);
}
}
$cells = [];
if ($variables['multiple']) {
$cells['drag'] = [
'data' => '',
'class' => ['field-multiple-drag'],
];
$cells['warehouse'] = [
'data' => $item['warehouse'],
'class' => ['value', 'value--warehouse', 'col-narrow'],
];
}
$cells['quantity'] = [
'data' => $item['quantity'],
'class' => ['value', 'value--quantity', 'col-narrow'],
];
if ($variables['multiple']) {
$cells['sort'] = ['data' => $delta_element, 'class' => ['delta-order']];
}
$rows[] = [
'data' => $cells,
'class' => ['draggable'],
];
}
$variables['table'] = [
'#type' => 'table',
'#header' => $header,
'#rows' => $rows,
'#attributes' => [
'id' => $table_id,
'class' => [
'field-multiple-table',
'stock-edit-table',
],
],
];
if ($variables['multiple']) {
$variables['table']['#tabledrag'] = [
[
'action' => 'order',
'relationship' => 'sibling',
'group' => $order_class,
],
];
}
if (!empty($element['#description'])) {
$description_id = $element['#attributes']['aria-describedby'];
$description_attributes['id'] = $description_id;
$variables['description']['attributes'] = new Attribute($description_attributes);
$variables['description']['content'] = $element['#description'];
// Add the description's id to the table aria attributes.
$variables['table']['#attributes']['aria-describedby'] = $element['#attributes']['aria-describedby'];
}
/** @var \Drupal\arch_stock\StockCartInfoInterface $stock_cart_info */
$stock_cart_info = \Drupal::service('stock_cart.info');
$in_cart = $stock_cart_info->quantityInCarts($element['#product_id']);
$desc = new PluralTranslatableMarkup(
$in_cart,
'Currently @count item in customer cart',
'Currently @count items in customer cart',
['@count' => $in_cart],
['context' => 'arch_stock']
);
$variables += [
'description' => [],
];
$variables['description'] += ['attributes' => []];
$variables['description']['attributes']['class'][] = 'description';
$variables['description']['content'][] = ['#markup' => $desc];
}
/**
* Preprocess arch stock info field.
*
* @param array $variables
* Variables array.
*/
function template_preprocess_stock_info_field(array &$variables) {
$element = $variables['element'];
/** @var \Drupal\arch_product\Entity\ProductInterface $product */
$product = $element['#product'];
$variables['status'] = $element['#status'];
$variables['attributes'] = [];
$variables['attributes']['class'][] = 'stock-info';
$variables['attributes']['class'][] = 'stock-info--' . $product->id();
$variables['attributes']['class'][] = Html::cleanCssIdentifier('stock-info--' . $variables['status']);
$variables['label'] = $element['#status_label'];
}
/**
* Implements hook_form_alter().
*/
function arch_stock_form_alter(&$form, FormStateInterface $form_state, $form_id) {
if (!in_array($form_id, ['product_type_add_form', 'product_type_edit_form'])) {
return;
}
/** @var \Drupal\arch_product\Form\ProductTypeForm $form_object */
$form_object = $form_state->getFormObject();
/** @var \Drupal\arch_product\Entity\ProductType $product_type */
$product_type = $form_object->getEntity();
$form['stock'] = [
'#type' => 'details',
'#title' => t('Stock settings', [], ['context' => 'arch_stock']),
'#group' => 'product_type_features',
'#weight' => -100,
];
$form['stock']['stock_enable'] = [
'#type' => 'checkbox',
'#title' => t('Enable inventory management', [], ['context' => 'arch_stock']),
'#default_value' => $product_type->getThirdPartySetting('arch_stock', 'stock_enable'),
];
$form['stock']['out_of_stock'] = [
'#type' => 'textfield',
'#default_value' => $product_type->getThirdPartySetting('arch_stock', 'out_of_stock'),
'#title' => t('Out of stock text', [], ['context' => 'arch_stock']),
'#description' => t('Leave this empty to display default "@default_text" message.', [
'@default_text' => t('Out of stock', [], ['context' => 'arch_stock']),
], ['context' => 'arch_stock']),
];
/** @var \Drupal\arch_stock\StockInfoInterface $stock_info */
$stock_info = \Drupal::service('arch_stock.info');
if ($stock_info->typeHasStockData($product_type)) {
$form['stock']['stock_enable']['#disabled'] = TRUE;
$form['stock']['stock_enable']['#description'] = t('There are products with stock info in this type.', [], ['context' => 'arch_stock']);
}
$form['#entity_builders'][] = 'arch_stock_form_product_type_form_builder';
}
/**
* Entity builder for the product type form with inventory options.
*
* @see arch_stock_form_product_type_edit_form_alter()
*/
function arch_stock_form_product_type_form_builder($entity_type, ProductTypeInterface $type, &$form, FormStateInterface $form_state) {
if ($form_state->getValue('stock_enable')) {
$type->setThirdPartySetting('arch_stock', 'stock_enable', TRUE);
}
else {
$type->unsetThirdPartySetting('arch_stock', 'stock_enable');
}
if ($out_of_stock = $form_state->getValue('out_of_stock')) {
$type->setThirdPartySetting('arch_stock', 'out_of_stock', $out_of_stock);
}
else {
$type->unsetThirdPartySetting('arch_stock', 'out_of_stock');
}
}
/**
* Implements hook_entity_update().
*/
function arch_stock_entity_update(EntityInterface $entity) {
if (\Drupal::isConfigSyncing()) {
// Do not change data while config import in progress.
return;
}
if ($entity->getEntityTypeId() == 'product_type') {
/** @var \Drupal\arch_product\Entity\ProductTypeInterface $entity */
if ($entity->getThirdPartySetting('arch_stock', 'stock_enable')) {
_arch_stock_add_stock_field($entity);
}
else {
_arch_stock_remove_stock_field($entity);
}
}
elseif ($entity->getEntityTypeId() == 'order') {
/** @var \Drupal\arch_order\Entity\OrderInterface $entity */
_arch_stock_handle_stock_change_on_order_update($entity);
}
}
/**
* Implements hook_ENTITY_TYPE_presave().
*/
function arch_stock_order_presave(EntityInterface $entity) {
if ($entity->isNew()) {
/** @var \Drupal\arch_order\Entity\OrderInterface $entity */
$entity->setDataKey('stock__save_stock_changes', TRUE);
}
}
/**
* Implements hook_entity_insert().
*/
function arch_stock_entity_insert(EntityInterface $entity) {
if (\Drupal::isConfigSyncing()) {
// Do not change data while config import in progress.
return;
}
if ($entity->getEntityTypeId() == 'product_type') {
/** @var \Drupal\arch_product\Entity\ProductTypeInterface $entity */
if ($entity->getThirdPartySetting('arch_stock', 'stock_enable')) {
_arch_stock_add_stock_field($entity);
}
}
}
/**
* Check if product has enough stock for given customer.
*
* @param \Drupal\arch_product\Entity\ProductInterface $product
* Product.
* @param \Drupal\Core\Session\AccountInterface $account
* Customer.
* @param int|float $amount
* Required amount.
*
* @return bool
* Return TRUE if product has minimum $amount of stock.
*/
function _arch_stock_product_available_for_sell(ProductInterface $product, AccountInterface $account, $amount = 1) {
/** @var \Drupal\arch_stock\StockKeeperInterface $stock_keeper */
$stock_keeper = \Drupal::service('arch_stock.stock_keeper');
return $stock_keeper->hasProductEnoughStock($product, $account);
}
/**
* Implements hook_product_available_for_sell().
*/
function arch_stock_product_available_for_sell(ProductInterface $product, AccountInterface $account) {
if (!$product) {
return AccessResult::neutral();
}
/** @var \Drupal\arch_stock\StockKeeperInterface $stock_keeper */
$stock_keeper = \Drupal::service('arch_stock.stock_keeper');
if (!$stock_keeper->isProductManagingStock($product)) {
return AccessResult::neutral();
}
$result = _arch_stock_product_available_for_sell($product, $account);
return $result ? AccessResult::neutral() : AccessResult::forbidden();
}
/**
* Implements hook_preprocess_add_to_api_cart().
*/
function arch_stock_preprocess_add_to_api_cart(&$variables) {
/** @var \Drupal\arch_product\Entity\ProductInterface $product */
$product = &$variables['product'];
if (!$product) {
return;
}
/** @var \Drupal\arch_stock\StockKeeperInterface $stock_keeper */
$stock_keeper = \Drupal::service('arch_stock.stock_keeper');
if (!$stock_keeper->isProductManagingStock($product)) {
return;
}
/** @var \Drupal\Core\Session\AccountInterface $account */
$account = $variables['user'];
if (!_arch_stock_product_available_for_sell($product, $account, 1)) {
$variables['not_available_text'] = t('Out of stock', [], ['context' => 'arch_stock_add_to_cart']);
$variables['available_for_sell'] = FALSE;
}
}
/**
* Update stock of products in order.
*
* @param \Drupal\arch_order\Entity\OrderInterface $order
* Updated order.
*/
function _arch_stock_handle_stock_change_on_order_update(OrderInterface $order) {
$old_status = $order->original->get('status')->getValue()[0]['value'];
$new_status = $order->get('status')->getValue()[0]['value'];
// If order status has not changed wo do nothing.
if ($old_status == $new_status) {
return;
}
// If the order not completed yet, wo do nothing.
if ($new_status != 'completed') {
return;
}
// If save_stock_changes flag is empty stock was already reduced.
if (!$order->getDataKey('stock__save_stock_changes')) {
return;
}
/** @var \Drupal\Core\Session\AccountInterface $user */
$user = $order->getOwner();
/** @var \Drupal\arch_stock\StockKeeperInterface $stock_keeper */
$stock_keeper = \Drupal::service('arch_stock.stock_keeper');
foreach ($order->getProducts() as $line_item) {
/** @var Drupal\arch_order\Plugin\Field\FieldType\OrderLineItemFieldItem $line_item */
if (!$line_item->isProduct()) {
continue;
}
/** @var \Drupal\arch_product\Entity\ProductInterface $product */
$product = $line_item->getProduct();
if (!$product) {
continue;
}
if ($stock_keeper->isProductManagingStock($product)) {
$amount = $line_item->getQuantity();
$stock_keeper->reduceStock($product, $amount, $order, $user);
}
}
$order->setDataKey('stock__save_stock_changes', NULL);
}
/**
* Add stock field to product type.
*
* @param \Drupal\arch_product\Entity\ProductTypeInterface $product_type
* Product type.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* @throws \Drupal\Core\Entity\EntityStorageException
*/
function _arch_stock_add_stock_field(ProductTypeInterface $product_type) {
$definition = [
'name' => 'stock',
'form_display' => [
'type' => 'stock_default',
],
'display' => [
'default' => [
'label' => 'hidden',
'type' => 'stock_default',
],
'teaser' => [
'label' => 'hidden',
'type' => 'stock_default',
],
],
];
// Add or remove the description field, as needed.
$field_storage = FieldStorageConfig::loadByName('product', $definition['name']);
if (!$field_storage) {
$field_storage = FieldStorageConfig::create([
'status' => TRUE,
'dependencies' => [
'module' => [
'arch_stock',
'arch_product',
],
],
'id' => 'product.stock',
'field_name' => 'stock',
'entity_type' => 'product',
'type' => 'stock',
'module' => 'arch_stock',
'locked' => TRUE,
'cardinality' => -1,
'translatable' => FALSE,
]);
$field_storage->save();
}
$field = FieldConfig::loadByName('product', $product_type->id(), $definition['name']);
if (empty($field)) {
$field = FieldConfig::create([
'label' => 'Stock',
'field_storage' => $field_storage,
'bundle' => $product_type->id(),
]);
$field->save();
$entity_form_display = \Drupal::entityTypeManager()->getStorage('entity_form_display')
->load('product.' . $product_type->id() . '.default');
if (empty($entity_form_display)) {
$entity_form_display = EntityFormDisplay::create([
'targetEntityType' => 'product',
'bundle' => $product_type->id(),
'mode' => 'default',
'status' => TRUE,
]);
}
// Assign widget settings for the 'default' form mode.
$entity_form_display
->setComponent($definition['name'], $definition['form_display'])
->save();
// The teaser view mode is created by the Standard profile and therefore
// might not exist.
$view_modes = \Drupal::service('entity_display.repository')->getViewModes('product');
// Assign display settings for the 'default' and 'teaser' view modes.
foreach ($definition['display'] as $view_mode => $config) {
if (isset($view_modes[$view_mode]) || 'default' == $view_mode) {
$entity_display = \Drupal::entityTypeManager()->getStorage('entity_view_display')
->load('product.' . $product_type->id() . '.' . $view_mode);
if (!$entity_display) {
$entity_display = EntityViewDisplay::create([
'targetEntityType' => 'product',
'bundle' => $product_type->id(),
'mode' => $view_mode,
'status' => TRUE,
]);
}
$entity_display
->setComponent($definition['name'], $definition['display'][$view_mode])
->save();
}
}
}
}
/**
* Remove stock field from product type.
*
* @param \Drupal\arch_product\Entity\ProductTypeInterface $product_type
* Product type.
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
function _arch_stock_remove_stock_field(ProductTypeInterface $product_type) {
$field = FieldConfig::loadByName('product', $product_type->id(), 'stock');
if ($field) {
$field->delete();
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function arch_stock_form_arch_cart_form_alter(&$form, FormStateInterface $form_state, $form_id) {
if (empty($form['#cart'])) {
return;
}
/** @var \Drupal\arch_cart\Cart\CartInterface $cart */
$cart = $form['#cart'];
/** @var \Drupal\arch_stock\StockKeeperInterface $stock_keeper */
$stock_keeper = \Drupal::service('arch_stock.stock_keeper');
/** @var \Drupal\Core\Session\AccountInterface $account */
$account = \Drupal::currentUser();
foreach ($cart->getProducts() as $item) {
$item_id = $item['type'] . ':' . $item['id'];
/** @var \Drupal\arch_product\Entity\ProductInterface $product */
if (empty($form['products'][$item_id]['#product'])) {
continue;
}
$product = $form['products'][$item_id]['#product'];
if (
$stock_keeper->isProductManagingStock($product)
&& !$stock_keeper->isNegativeStockAllowed($product, $account)
) {
$form['products'][$item_id]['quantity']['#max'] = $stock_keeper->getTotalProductStock($product, $account);
}
}
}
/**
* Implements hook_api_cart_data_alter().
*/
function arch_stock_api_cart_data_alter(array &$data, CartInterface $cart) {
/** @var \Drupal\arch_stock\StockKeeperInterface $stock_keeper */
$stock_keeper = \Drupal::service('arch_stock.stock_keeper');
/** @var \Drupal\arch_product\Entity\Storage\ProductStorageInterface $product_storage */
$product_storage = \Drupal::service('entity_type.manager')->getStorage('product');
/** @var \Drupal\Core\Session\AccountInterface $account */
$account = \Drupal::currentUser();
foreach ($cart->getProducts() as $key => $item) {
/** @var \Drupal\arch_product\Entity\ProductInterface $product */
$product = $product_storage->load($item['id']);
if (!$product) {
continue;
}
if (
$stock_keeper->isProductManagingStock($product)
&& !$stock_keeper->isNegativeStockAllowed($product, $account)
) {
$data['cart']['items'][$key]['_line_item']['max_quantity'] = $stock_keeper->getTotalProductStock($product, $account);
}
}
}
/**
* Implements hook_arch_order_create_from_cart_data_alter().
*/
function arch_stock_arch_order_create_from_cart_data_alter(array &$data, CartInterface $cart) {
/** @var \Drupal\arch_stock\StockKeeperInterface $stock_keeper */
$stock_keeper = \Drupal::service('arch_stock.stock_keeper');
/** @var \Drupal\arch_product\Entity\Storage\ProductStorageInterface $product_storage */
$product_storage = \Drupal::service('entity_type.manager')->getStorage('product');
/** @var \Drupal\Core\Session\AccountInterface $account */
$account = \Drupal::currentUser();
foreach ($data['line_items'] as $index => $line_item) {
if ($line_item['type'] != OrderLineItemInterface::ORDER_LINE_ITEM_TYPE_PRODUCT) {
continue;
}
$remove = FALSE;
/** @var \Drupal\arch_product\Entity\ProductInterface $product */
$product = $product_storage->load($line_item['product_id']);
if (
!$product
|| empty($line_item['quantity'])
) {
$remove = TRUE;
}
elseif (
$stock_keeper->isProductManagingStock($product)
&& !$stock_keeper->hasProductEnoughStock($product, $account)
) {
$remove = TRUE;
}
if ($remove) {
unset($data['line_items'][$index]);
}
}
}
/**
* Implements hook_arch_cart_change().
*/
function arch_stock_arch_cart_change($type, &$item, &$old_item, array &$items, CartInterface $cart) {
if (in_array($type, [CartInterface::ITEM_NEW, CartInterface::ITEM_UPDATE])) {
/** @var \Drupal\arch_stock\StockKeeperInterface $stock_keeper */
$stock_keeper = \Drupal::service('arch_stock.stock_keeper');
$current_user = \Drupal::currentUser();
foreach ($items as &$item) {
if (empty($item['type']) || $item['type'] !== 'product') {
continue;
}
/** @var \Drupal\arch_product\Entity\ProductInterface $product */
$product = Product::load($item['id']);
if (!$product) {
continue;
}
if (
!$stock_keeper->isProductManagingStock($product)
|| $stock_keeper->isNegativeStockAllowed($product, $current_user)
) {
continue;
}
$total = $stock_keeper->getTotalProductStock($product, $current_user);
if ($item['quantity'] > $total) {
$item['quantity'] = $total;
$cart->addMessage(t('We have only %amount of this product', ['%amount' => $total], ['context' => 'arch_stock']));
}
}
}
// @todo Implement following stock changes.
// @todo Implement Stock lock when customer add product to cart.
// /** @var \Drupal\arch_stock\StockCartInfoInterface $cart_stock_info */
// @codingStandardsIgnoreStart
// $cart_stock_info = \Drupal::service('stock_cart.info');
// if ($type === CartInterface::ITEM_NEW) {
// $cart_stock_info->addItem($item['id'], $item['quantity']);
// }
// elseif ($type === CartInterface::ITEM_UPDATE) {
// $cart_stock_info->updateItem($item['id'], $item['quantity']);
// }
// elseif ($type === CartInterface::ITEM_REMOVE) {
// $cart_stock_info->removeItem($old_item['id'], $old_item['quantity']);
// }
// @codingStandardsIgnoreEnd
}
/**
* Implements hook_cron().
*/
function arch_stock_cron() {
// @todo Implement Stock lock release.
// /** @var \Drupal\arch_stock\StockCartInfoInterface $cart_stock_info */
// $cart_stock_info = \Drupal::service('stock_cart.info');
// $cart_stock_info->garbageCollection();
}
