From 7fdde1657ee39a8abfa26f37a2b2838ac6d7413d Mon Sep 17 00:00:00 2001 From: Rob Date: Mon, 20 Feb 2017 11:14:52 -0800 Subject: [PATCH 1/7] fix #2853527 - implement cart expiration --- modules/cart/commerce_cart.module | 37 +++++++++++++++++++ .../src/Plugin/QueueWorker/CartExpire.php | 33 +++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 modules/cart/src/Plugin/QueueWorker/CartExpire.php diff --git a/modules/cart/commerce_cart.module b/modules/cart/commerce_cart.module index dad71bfc43..4213c822d7 100644 --- a/modules/cart/commerce_cart.module +++ b/modules/cart/commerce_cart.module @@ -157,6 +157,7 @@ function commerce_cart_form_commerce_order_type_form_alter(array &$form, FormSta $order_type = $form_state->getFormObject()->getEntity(); $cart_form_view = $order_type->getThirdPartySetting('commerce_cart', 'cart_form_view', 'commerce_cart_form'); $cart_block_view = $order_type->getThirdPartySetting('commerce_cart', 'cart_block_view', 'commerce_cart_block'); + $cart_expiry = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiry'); // Prepare a list of views tagged 'commerce_cart_form'. $view_storage = \Drupal::entityTypeManager()->getStorage('view'); $available_form_views = []; @@ -191,6 +192,27 @@ function commerce_cart_form_commerce_order_type_form_alter(array &$form, FormSta '#default_value' => $cart_block_view, ]; + $form['commerce_cart']['enable_expiration'] = [ + '#type' => 'checkbox', + '#title' => t('Enable cart expiration for this order type'), + '#default_value' => !empty($cart_expiry), + ]; + + $form['commerce_cart']['cart_expiration'] = [ + '#type' => 'number', + '#title' => t('Days until cart expires'), + '#description' => t('The cart will be removed in the number of days ' . + 'specified. Set to 0 disable cart expiry.'), + '#default_value' => $cart_expiry ?: 0, + '#required' => TRUE, + '#states' => [ + 'visible' => [ + ':input[name="commerce_cart[enable_expiration]"]' => + ['checked' => TRUE], + ], + ], + ]; + $form['actions']['submit']['#submit'][] = 'commerce_cart_order_type_form_submit'; } @@ -201,6 +223,9 @@ function commerce_cart_order_type_form_submit($form, FormStateInterface $form_st $settings = &$form_state->getValue('commerce_cart'); $order_type = $form_state->getFormObject()->getEntity(); // @todo open follow up and fix cart_form_view, commerce_cart_block saving. + + $cart_expiry = $settings['enable_expiration'] ?: 0; + $order_type->setThirdPartySetting('commerce_cart', 'cart_expiry', $cart_expiry); $order_type->save(); } @@ -226,3 +251,15 @@ function commerce_cart_views_data_alter(array &$data) { function template_preprocess_commerce_cart_block(&$variables) { $variables['attributes']['class'][] = 'cart--cart-block'; } + +/** + * Implements hook_cron(). + */ +function commerce_cart_cron() { + $queue = \Drupal::queue('cart_expiries'); + + $order_storage = \Drupal::entityTypeManager()->getStorage('commerce_order'); + foreach($order_storage->loadMultiple() as $order) { + $queue->createItem($order); + } +} diff --git a/modules/cart/src/Plugin/QueueWorker/CartExpire.php b/modules/cart/src/Plugin/QueueWorker/CartExpire.php new file mode 100644 index 0000000000..76d1c8fbaa --- /dev/null +++ b/modules/cart/src/Plugin/QueueWorker/CartExpire.php @@ -0,0 +1,33 @@ +getCompletedTime() > 0) { + $order_type_storage = \Drupal::entityTypeManager()->getStorage('commerce_order_type'); + $order_type = $order_type_storage->load($data->bundle()); + $elapsed = REQUEST_TIME - $data->getCreatedTime(); + $expiry = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiry') * 3600 * 24; + if ($elapsed >= $expiry) { + $data->delete(); + } + } + } +} \ No newline at end of file From 4bb0616e177560a14482f2dd0966e31b78f3e37a Mon Sep 17 00:00:00 2001 From: Rob Date: Thu, 23 Feb 2017 14:20:01 -0800 Subject: [PATCH 2/7] fix formatting compliance and queue orders in groups of 50 --- modules/cart/commerce_cart.module | 43 ++++++++++--------- .../src/Plugin/QueueWorker/CartExpire.php | 36 ++++++++++------ 2 files changed, 45 insertions(+), 34 deletions(-) diff --git a/modules/cart/commerce_cart.module b/modules/cart/commerce_cart.module index 4213c822d7..639c6cf1a1 100644 --- a/modules/cart/commerce_cart.module +++ b/modules/cart/commerce_cart.module @@ -193,24 +193,23 @@ function commerce_cart_form_commerce_order_type_form_alter(array &$form, FormSta ]; $form['commerce_cart']['enable_expiration'] = [ - '#type' => 'checkbox', - '#title' => t('Enable cart expiration for this order type'), - '#default_value' => !empty($cart_expiry), + '#type' => 'checkbox', + '#title' => t('Enable cart expiration for this order type'), + '#default_value' => !empty($cart_expiry), ]; - $form['commerce_cart']['cart_expiration'] = [ - '#type' => 'number', - '#title' => t('Days until cart expires'), - '#description' => t('The cart will be removed in the number of days ' . - 'specified. Set to 0 disable cart expiry.'), - '#default_value' => $cart_expiry ?: 0, - '#required' => TRUE, - '#states' => [ - 'visible' => [ - ':input[name="commerce_cart[enable_expiration]"]' => - ['checked' => TRUE], - ], + $form['commerce_cart']['cart_expiration'] = [ + '#type' => 'number', + '#title' => t('Days until cart expires'), + '#description' => t('The cart will be removed in the number of days specified. Set to 0 disable cart expiry.'), + '#default_value' => $cart_expiry ?: 0, + '#required' => TRUE, + '#states' => [ + 'visible' => [ + ':input[name="commerce_cart[enable_expiration]"]' => + ['checked' => TRUE], ], + ], ]; $form['actions']['submit']['#submit'][] = 'commerce_cart_order_type_form_submit'; @@ -256,10 +255,14 @@ function template_preprocess_commerce_cart_block(&$variables) { * Implements hook_cron(). */ function commerce_cart_cron() { - $queue = \Drupal::queue('cart_expiries'); + $queue = \Drupal::queue('cart_expiries'); - $order_storage = \Drupal::entityTypeManager()->getStorage('commerce_order'); - foreach($order_storage->loadMultiple() as $order) { - $queue->createItem($order); - } + $ids = \Drupal::entityQuery('commerce_order') + ->notExists('completed') + ->execute(); + + // Queue ids in groups of 50. + for ($i = 0; $i < count($ids); $i += 50) { + $queue->createItem(array_slice($ids, $i, $i + 50)); + } } diff --git a/modules/cart/src/Plugin/QueueWorker/CartExpire.php b/modules/cart/src/Plugin/QueueWorker/CartExpire.php index 76d1c8fbaa..ab6c9e02d2 100644 --- a/modules/cart/src/Plugin/QueueWorker/CartExpire.php +++ b/modules/cart/src/Plugin/QueueWorker/CartExpire.php @@ -6,7 +6,7 @@ use Drupal\Core\Queue\QueueWorkerBase; /** - * Removes an expired Cart + * Removes an expired Cart. * * @QueueWorker( * id = "cart_expiries", @@ -15,19 +15,27 @@ * ) */ class CartExpire extends QueueWorkerBase { - /** - * {@inheritdoc} - */ - public function processItem($data) - { - if ($data instanceof OrderInterface && $data->getCompletedTime() > 0) { - $order_type_storage = \Drupal::entityTypeManager()->getStorage('commerce_order_type'); - $order_type = $order_type_storage->load($data->bundle()); - $elapsed = REQUEST_TIME - $data->getCreatedTime(); - $expiry = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiry') * 3600 * 24; - if ($elapsed >= $expiry) { - $data->delete(); - } + + /** + * {@inheritdoc} + */ + public function processItem($data) { + $orders = \Drupal::entityTypeManager()->getStorage('commerce_order') + ->loadMultiple($data); + foreach ($orders as $order) { + // Ensure that orders slated for clearing have not been completed since + // they were last queued. + if ($order instanceof OrderInterface && is_null($order->getCompletedTime())) { + $order_type_storage = \Drupal::entityTypeManager() + ->getStorage('commerce_order_type'); + $order_type = $order_type_storage->load($order->bundle()); + $elapsed = REQUEST_TIME - $order->getCreatedTime(); + $expiry = $order_type->getThirdPartySetting('commerce_cart', + 'cart_expiry') * 3600 * 24; + if ($elapsed >= $expiry) { + $order->delete(); } + } } + } } \ No newline at end of file From 6b8135319727e3a82c6d1192c975f94fc580dbe2 Mon Sep 17 00:00:00 2001 From: Rob Date: Thu, 23 Feb 2017 14:29:10 -0800 Subject: [PATCH 3/7] fix Drupal format compliance issue --- modules/cart/src/Plugin/QueueWorker/CartExpire.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/cart/src/Plugin/QueueWorker/CartExpire.php b/modules/cart/src/Plugin/QueueWorker/CartExpire.php index ab6c9e02d2..b5b814b698 100644 --- a/modules/cart/src/Plugin/QueueWorker/CartExpire.php +++ b/modules/cart/src/Plugin/QueueWorker/CartExpire.php @@ -38,4 +38,5 @@ public function processItem($data) { } } } -} \ No newline at end of file + +} From 1cee76d330ad2f29794afb66c8facecfaf9ab217 Mon Sep 17 00:00:00 2001 From: Rob Date: Thu, 23 Feb 2017 17:02:12 -0800 Subject: [PATCH 4/7] fix issues raised by mglaman --- modules/cart/commerce_cart.module | 8 +-- .../src/Plugin/QueueWorker/CartExpire.php | 70 ++++++++++++++++--- 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/modules/cart/commerce_cart.module b/modules/cart/commerce_cart.module index 639c6cf1a1..29cb90cbde 100644 --- a/modules/cart/commerce_cart.module +++ b/modules/cart/commerce_cart.module @@ -157,7 +157,7 @@ function commerce_cart_form_commerce_order_type_form_alter(array &$form, FormSta $order_type = $form_state->getFormObject()->getEntity(); $cart_form_view = $order_type->getThirdPartySetting('commerce_cart', 'cart_form_view', 'commerce_cart_form'); $cart_block_view = $order_type->getThirdPartySetting('commerce_cart', 'cart_block_view', 'commerce_cart_block'); - $cart_expiry = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiry'); + $cart_expiry = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiration'); // Prepare a list of views tagged 'commerce_cart_form'. $view_storage = \Drupal::entityTypeManager()->getStorage('view'); $available_form_views = []; @@ -224,7 +224,7 @@ function commerce_cart_order_type_form_submit($form, FormStateInterface $form_st // @todo open follow up and fix cart_form_view, commerce_cart_block saving. $cart_expiry = $settings['enable_expiration'] ?: 0; - $order_type->setThirdPartySetting('commerce_cart', 'cart_expiry', $cart_expiry); + $order_type->setThirdPartySetting('commerce_cart', 'cart_expiration', $cart_expiry); $order_type->save(); } @@ -255,10 +255,10 @@ function template_preprocess_commerce_cart_block(&$variables) { * Implements hook_cron(). */ function commerce_cart_cron() { - $queue = \Drupal::queue('cart_expiries'); + $queue = \Drupal::queue('cart_expirations'); $ids = \Drupal::entityQuery('commerce_order') - ->notExists('completed') + ->condition('cart', TRUE) ->execute(); // Queue ids in groups of 50. diff --git a/modules/cart/src/Plugin/QueueWorker/CartExpire.php b/modules/cart/src/Plugin/QueueWorker/CartExpire.php index b5b814b698..43aca52694 100644 --- a/modules/cart/src/Plugin/QueueWorker/CartExpire.php +++ b/modules/cart/src/Plugin/QueueWorker/CartExpire.php @@ -2,36 +2,90 @@ namespace Drupal\commerce_cart\Plugin\QueueWorker; +use Drupal\commerce\TimeInterface; use Drupal\commerce_order\Entity\OrderInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; use Drupal\Core\Queue\QueueWorkerBase; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Removes an expired Cart. * * @QueueWorker( - * id = "cart_expiries", + * id = "cart_expirations", * title = @Translation("Commerce Cart expiration"), * cron = {} * ) */ -class CartExpire extends QueueWorkerBase { +class CartExpire extends QueueWorkerBase implements ContainerFactoryPluginInterface { + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * The commerce time service. + * + * @var \Drupal\commerce\Time + */ + protected $time; + + /** + * Constructs a new CartBlock. + * + * @param array $configuration + * A configuration array containing information about the plugin instance. + * @param string $plugin_id + * The plugin ID for the plugin instance. + * @param mixed $plugin_definition + * The plugin implementation definition. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. + * @param \Drupal\commerce\TimeInterface $time + * The time service. + */ + public function __construct(array $configuration, + $plugin_id, + $plugin_definition, + EntityTypeManagerInterface $entity_type_manager, + TimeInterface $time) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + + $this->entityTypeManager = $entity_type_manager; + $this->time = $time; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager'), + $container->get('commerce.time') + ); + } /** * {@inheritdoc} */ public function processItem($data) { - $orders = \Drupal::entityTypeManager()->getStorage('commerce_order') + $orders = $this->entityTypeManager->getStorage('commerce_order') ->loadMultiple($data); foreach ($orders as $order) { // Ensure that orders slated for clearing have not been completed since // they were last queued. - if ($order instanceof OrderInterface && is_null($order->getCompletedTime())) { - $order_type_storage = \Drupal::entityTypeManager() + if ($order instanceof OrderInterface && $order->cart->value == 1) { + $order_type_storage = $this->entityTypeManager ->getStorage('commerce_order_type'); $order_type = $order_type_storage->load($order->bundle()); - $elapsed = REQUEST_TIME - $order->getCreatedTime(); - $expiry = $order_type->getThirdPartySetting('commerce_cart', - 'cart_expiry') * 3600 * 24; + $elapsed = $this->time->getCurrentTime() - $order->getCreatedTime(); + $expiry = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiration') * 3600 * 24; if ($elapsed >= $expiry) { $order->delete(); } From 04d02198c0c6897f687944f1ba6c5ededed1d919 Mon Sep 17 00:00:00 2001 From: Rob Date: Fri, 24 Feb 2017 17:25:31 -0800 Subject: [PATCH 5/7] fix wording in form, improve how items are checked and queued, streamlined queue worker --- modules/cart/commerce_cart.module | 25 ++++++++++---- .../config/schema/commerce_cart.schema.yml | 3 ++ .../src/Plugin/QueueWorker/CartExpire.php | 33 ++++++++++--------- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/modules/cart/commerce_cart.module b/modules/cart/commerce_cart.module index 29cb90cbde..cbdc4af8ec 100644 --- a/modules/cart/commerce_cart.module +++ b/modules/cart/commerce_cart.module @@ -201,7 +201,7 @@ function commerce_cart_form_commerce_order_type_form_alter(array &$form, FormSta $form['commerce_cart']['cart_expiration'] = [ '#type' => 'number', '#title' => t('Days until cart expires'), - '#description' => t('The cart will be removed in the number of days specified. Set to 0 disable cart expiry.'), + '#description' => t('The cart will be removed in the number of days specified. Set to 0 disable cart expiration.'), '#default_value' => $cart_expiry ?: 0, '#required' => TRUE, '#states' => [ @@ -257,12 +257,23 @@ function template_preprocess_commerce_cart_block(&$variables) { function commerce_cart_cron() { $queue = \Drupal::queue('cart_expirations'); - $ids = \Drupal::entityQuery('commerce_order') - ->condition('cart', TRUE) - ->execute(); + $time = \Drupal::service('commerce.time'); + $type_storage = \Drupal::entityTypeManager()->getStorage('commerce_order_type'); + $order_types = $type_storage->loadMultiple(); - // Queue ids in groups of 50. - for ($i = 0; $i < count($ids); $i += 50) { - $queue->createItem(array_slice($ids, $i, $i + 50)); + foreach ($order_types as $order_type) { + $expiration_days = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiration'); + if ($expiration_days > 0) { + $expiration = $time->getCurrentTime() - ($expiration_days * 3600 * 24); + + // Queue abandoned carts in groups of 50. + $ids = \Drupal::entityQuery('commerce_order') + ->condition('cart', TRUE) + ->condition('changed', $expiration, '<') + ->range(0, 50) + ->execute(); + + $queue->createItem($ids); + } } } diff --git a/modules/cart/config/schema/commerce_cart.schema.yml b/modules/cart/config/schema/commerce_cart.schema.yml index d395311fed..30524a38e1 100644 --- a/modules/cart/config/schema/commerce_cart.schema.yml +++ b/modules/cart/config/schema/commerce_cart.schema.yml @@ -5,6 +5,9 @@ commerce_order.commerce_order_type.*.third_party.commerce_cart: cart_form_view: type: string label: 'Shopping cart form view' + cart_expiration: + type: integer + label: 'Shopping cart expiration' block.settings.commerce_cart: type: block_settings diff --git a/modules/cart/src/Plugin/QueueWorker/CartExpire.php b/modules/cart/src/Plugin/QueueWorker/CartExpire.php index 43aca52694..6a73d6aec0 100644 --- a/modules/cart/src/Plugin/QueueWorker/CartExpire.php +++ b/modules/cart/src/Plugin/QueueWorker/CartExpire.php @@ -20,11 +20,18 @@ */ class CartExpire extends QueueWorkerBase implements ContainerFactoryPluginInterface { /** - * The entity type manager. + * The order storage. * - * @var \Drupal\Core\Entity\EntityTypeManagerInterface + * @var \Drupal\Core\Entity\EntityStorageInterface */ - protected $entityTypeManager; + protected $orderStorage; + + /** + * The order type storage. + * + * @var \Drupal\Core\Entity\EntityStorageInterface + */ + protected $orderTypeStorage; /** * The commerce time service. @@ -34,7 +41,7 @@ class CartExpire extends QueueWorkerBase implements ContainerFactoryPluginInterf protected $time; /** - * Constructs a new CartBlock. + * Constructs a new CartExpire object. * * @param array $configuration * A configuration array containing information about the plugin instance. @@ -47,14 +54,11 @@ class CartExpire extends QueueWorkerBase implements ContainerFactoryPluginInterf * @param \Drupal\commerce\TimeInterface $time * The time service. */ - public function __construct(array $configuration, - $plugin_id, - $plugin_definition, - EntityTypeManagerInterface $entity_type_manager, - TimeInterface $time) { + public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, TimeInterface $time) { parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->entityTypeManager = $entity_type_manager; + $this->orderStorage = $entity_type_manager->getStorage('commerce_order'); + $this->orderTypeStorage = $entity_type_manager->getStorage('commerce_order_type'); $this->time = $time; } @@ -75,16 +79,13 @@ public static function create(ContainerInterface $container, array $configuratio * {@inheritdoc} */ public function processItem($data) { - $orders = $this->entityTypeManager->getStorage('commerce_order') - ->loadMultiple($data); + $orders = $this->orderStorage->loadMultiple($data); foreach ($orders as $order) { // Ensure that orders slated for clearing have not been completed since // they were last queued. if ($order instanceof OrderInterface && $order->cart->value == 1) { - $order_type_storage = $this->entityTypeManager - ->getStorage('commerce_order_type'); - $order_type = $order_type_storage->load($order->bundle()); - $elapsed = $this->time->getCurrentTime() - $order->getCreatedTime(); + $order_type = $this->orderTypeStorage->load($order->bundle()); + $elapsed = $this->time->getCurrentTime() - $order->getChangedTime(); $expiry = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiration') * 3600 * 24; if ($elapsed >= $expiry) { $order->delete(); From 11ce66462a08493fe0e2429ac8da664e2a3ce7c2 Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Fri, 3 Mar 2017 13:07:44 +0000 Subject: [PATCH 6/7] Add kernel test for cart expiration --- modules/cart/commerce_cart.module | 10 +- .../tests/src/Kernel/CartExpirationTest.php | 163 ++++++++++++++++++ 2 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 modules/cart/tests/src/Kernel/CartExpirationTest.php diff --git a/modules/cart/commerce_cart.module b/modules/cart/commerce_cart.module index cbdc4af8ec..0915a92bbd 100644 --- a/modules/cart/commerce_cart.module +++ b/modules/cart/commerce_cart.module @@ -256,24 +256,28 @@ function template_preprocess_commerce_cart_block(&$variables) { */ function commerce_cart_cron() { $queue = \Drupal::queue('cart_expirations'); - $time = \Drupal::service('commerce.time'); + $order_storage = \Drupal::entityTypeManager()->getStorage('commerce_order'); $type_storage = \Drupal::entityTypeManager()->getStorage('commerce_order_type'); $order_types = $type_storage->loadMultiple(); foreach ($order_types as $order_type) { $expiration_days = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiration'); + if ($expiration_days > 0) { $expiration = $time->getCurrentTime() - ($expiration_days * 3600 * 24); // Queue abandoned carts in groups of 50. - $ids = \Drupal::entityQuery('commerce_order') + $ids = $order_storage->getQuery() + ->condition('type', $order_type->id()) ->condition('cart', TRUE) ->condition('changed', $expiration, '<') ->range(0, 50) ->execute(); - $queue->createItem($ids); + if (!empty($ids)) { + $queue->createItem($ids); + } } } } diff --git a/modules/cart/tests/src/Kernel/CartExpirationTest.php b/modules/cart/tests/src/Kernel/CartExpirationTest.php new file mode 100644 index 0000000000..e1e01cf3dd --- /dev/null +++ b/modules/cart/tests/src/Kernel/CartExpirationTest.php @@ -0,0 +1,163 @@ +installEntitySchema('commerce_order'); + $this->installConfig(['commerce_order']); + + $user = $this->createUser(); + $this->user = $this->reloadEntity($user); + $this->orderStorage = $this->container->get('entity_type.manager')->getStorage('commerce_order'); + } + + /** + * Install commerce cart. + * + * Due to issues with hook_entity_bundle_create, we need to run this manually + * and cannot add commerce_cart to the $modules property. + * + * @see https://www.drupal.org/node/2711645 + * + * @todo patch core so it doesn't explode in Kernel tests. + */ + protected function installCommerceCart() { + $this->enableModules(['commerce_cart']); + $this->installConfig('commerce_cart'); + $this->container->get('entity.definition_update_manager')->applyUpdates(); + $this->cartProvider = $this->container->get('commerce_cart.cart_provider'); + $this->cartManager = $this->container->get('commerce_cart.cart_manager'); + } + + /** + * Sets an expiration time for default order type, verifies it works. + */ + public function testExpiration() { + $this->installCommerceCart(); + + // Set expiration to 3 days. + $order_type = OrderType::load('default'); + $order_type->setThirdPartySetting('commerce_cart', 'cart_expiration', 3); + $order_type->save(); + + /** @var \Drupal\commerce\TimeInterface $time */ + $time = \Drupal::service('commerce.time'); + $four_days_ago = $time->getRequestTime() - (86400 * 4); + $two_days_ago = $time->getRequestTime() - (86400 * 2); + $one_day_ago = $time->getRequestTime() - 86400; + + /** @var \Drupal\commerce_order\Entity\OrderInterface $cart1 */ + $cart1 = $this->orderStorage->create([ + 'type' => $order_type->id(), + 'store_id' => $this->store->id(), + 'uid' => $this->createUser()->id(), + 'cart' => TRUE, + 'created' => $four_days_ago, + 'changed' => $four_days_ago, + ]); + $cart1->save(); + $cart2 = $this->orderStorage->create([ + 'type' => $order_type->id(), + 'store_id' => $this->store->id(), + 'uid' => $this->createUser()->id(), + 'cart' => TRUE, + 'created' => $four_days_ago, + 'changed' => $four_days_ago, + ]); + $cart2->save(); + $this->orderStorage->create([ + 'type' => $order_type->id(), + 'store_id' => $this->store->id(), + 'uid' => $this->createUser()->id(), + 'cart' => TRUE, + 'created' => $two_days_ago, + 'changed' => $two_days_ago, + ])->save(); + $this->orderStorage->create([ + 'type' => $order_type->id(), + 'store_id' => $this->store->id(), + 'uid' => $this->createUser()->id(), + 'cart' => TRUE, + 'created' => $one_day_ago, + 'changed' => $one_day_ago, + ])->save(); + $this->orderStorage->create([ + 'type' => $order_type->id(), + 'store_id' => $this->store->id(), + 'uid' => $this->createUser()->id(), + 'cart' => TRUE, + ])->save(); + + // Setting the `changed` attribute doesn't work in save. Manually change. + $count = db_update('commerce_order') + ->fields(['changed' => $four_days_ago]) + ->condition('order_id', [$cart1->id(), $cart2->id()], 'IN') + ->execute(); + $this->assertEquals(2, $count); + + $this->container->get('cron')->run(); + + $orders = $this->orderStorage->loadMultiple(); + $this->assertEquals(3, count($orders)); + $this->assertNull($this->orderStorage->load($cart1->id())); + $this->assertNull($this->orderStorage->load($cart2->id())); + } + +} From 2323857b1f154da613c4f5e2274207d8eb33337b Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Fri, 17 Mar 2017 16:09:25 -0500 Subject: [PATCH 7/7] Store expiration as seconds --- modules/cart/commerce_cart.module | 18 ++++++++++-------- .../cart/src/Plugin/QueueWorker/CartExpire.php | 6 +++--- .../tests/src/Kernel/CartExpirationTest.php | 4 ++-- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/modules/cart/commerce_cart.module b/modules/cart/commerce_cart.module index 0915a92bbd..bfdac82b19 100644 --- a/modules/cart/commerce_cart.module +++ b/modules/cart/commerce_cart.module @@ -157,7 +157,7 @@ function commerce_cart_form_commerce_order_type_form_alter(array &$form, FormSta $order_type = $form_state->getFormObject()->getEntity(); $cart_form_view = $order_type->getThirdPartySetting('commerce_cart', 'cart_form_view', 'commerce_cart_form'); $cart_block_view = $order_type->getThirdPartySetting('commerce_cart', 'cart_block_view', 'commerce_cart_block'); - $cart_expiry = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiration'); + $cart_expiration = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiration'); // Prepare a list of views tagged 'commerce_cart_form'. $view_storage = \Drupal::entityTypeManager()->getStorage('view'); $available_form_views = []; @@ -195,14 +195,14 @@ function commerce_cart_form_commerce_order_type_form_alter(array &$form, FormSta $form['commerce_cart']['enable_expiration'] = [ '#type' => 'checkbox', '#title' => t('Enable cart expiration for this order type'), - '#default_value' => !empty($cart_expiry), + '#default_value' => !empty($cart_expiration), ]; $form['commerce_cart']['cart_expiration'] = [ '#type' => 'number', '#title' => t('Days until cart expires'), '#description' => t('The cart will be removed in the number of days specified. Set to 0 disable cart expiration.'), - '#default_value' => $cart_expiry ?: 0, + '#default_value' => $cart_expiration ?: 0, '#required' => TRUE, '#states' => [ 'visible' => [ @@ -223,8 +223,10 @@ function commerce_cart_order_type_form_submit($form, FormStateInterface $form_st $order_type = $form_state->getFormObject()->getEntity(); // @todo open follow up and fix cart_form_view, commerce_cart_block saving. - $cart_expiry = $settings['enable_expiration'] ?: 0; - $order_type->setThirdPartySetting('commerce_cart', 'cart_expiration', $cart_expiry); + // Cart expiration is saved as seconds. + $cart_expiration = $settings['enable_expiration'] ?: 0; + $cart_expiration = $cart_expiration * 60 * 60 * 24; + $order_type->setThirdPartySetting('commerce_cart', 'cart_expiration', $cart_expiration); $order_type->save(); } @@ -262,10 +264,10 @@ function commerce_cart_cron() { $order_types = $type_storage->loadMultiple(); foreach ($order_types as $order_type) { - $expiration_days = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiration'); + $cart_expiration = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiration'); - if ($expiration_days > 0) { - $expiration = $time->getCurrentTime() - ($expiration_days * 3600 * 24); + if ($cart_expiration > 0) { + $expiration = $time->getCurrentTime() - $cart_expiration; // Queue abandoned carts in groups of 50. $ids = $order_storage->getQuery() diff --git a/modules/cart/src/Plugin/QueueWorker/CartExpire.php b/modules/cart/src/Plugin/QueueWorker/CartExpire.php index 6a73d6aec0..961f1d17a7 100644 --- a/modules/cart/src/Plugin/QueueWorker/CartExpire.php +++ b/modules/cart/src/Plugin/QueueWorker/CartExpire.php @@ -83,11 +83,11 @@ public function processItem($data) { foreach ($orders as $order) { // Ensure that orders slated for clearing have not been completed since // they were last queued. - if ($order instanceof OrderInterface && $order->cart->value == 1) { + if ($order instanceof OrderInterface && $order->get('cart')->value == TRUE) { $order_type = $this->orderTypeStorage->load($order->bundle()); $elapsed = $this->time->getCurrentTime() - $order->getChangedTime(); - $expiry = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiration') * 3600 * 24; - if ($elapsed >= $expiry) { + $cart_expiration = $order_type->getThirdPartySetting('commerce_cart', 'cart_expiration'); + if ($elapsed >= $cart_expiration) { $order->delete(); } } diff --git a/modules/cart/tests/src/Kernel/CartExpirationTest.php b/modules/cart/tests/src/Kernel/CartExpirationTest.php index e1e01cf3dd..74784c94cf 100644 --- a/modules/cart/tests/src/Kernel/CartExpirationTest.php +++ b/modules/cart/tests/src/Kernel/CartExpirationTest.php @@ -94,7 +94,7 @@ public function testExpiration() { // Set expiration to 3 days. $order_type = OrderType::load('default'); - $order_type->setThirdPartySetting('commerce_cart', 'cart_expiration', 3); + $order_type->setThirdPartySetting('commerce_cart', 'cart_expiration', (3 * 60 * 60 * 24)); $order_type->save(); /** @var \Drupal\commerce\TimeInterface $time */ @@ -154,7 +154,7 @@ public function testExpiration() { $this->container->get('cron')->run(); - $orders = $this->orderStorage->loadMultiple(); + $orders = $this->orderStorage->getQuery()->execute(); $this->assertEquals(3, count($orders)); $this->assertNull($this->orderStorage->load($cart1->id())); $this->assertNull($this->orderStorage->load($cart2->id()));