From b2a4ec972baac842250471320d28d3cc1823f227 Mon Sep 17 00:00:00 2001 From: Buba Suma Date: Fri, 20 Sep 2019 17:40:55 -0500 Subject: [PATCH 1/8] MC-20225: Low performance in getting configurable product attribute options functionality - Fix performance issue related to AbstractAttribute::getOptions due to the expansive cost of the function AbstractAttribute::convertToObjects - Fix performance issue related to loading options multiple times --- .../DataProvider/Product/Form/Modifier/Eav.php | 5 +++++ .../Edit/Tab/Variations/Config/Matrix.php | 12 +++++++----- .../Form/Modifier/Data/AssociatedProducts.php | 17 +++++++++++------ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index 5d1e853cef3d1..4039ff862f6fe 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -46,6 +46,7 @@ * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyFields) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.ExcessiveClassLength) * @since 101.0.0 */ class Eav extends AbstractModifier @@ -1048,6 +1049,10 @@ private function isScopeGlobal($attribute) */ private function getAttributeModel($attribute) { + // The statement below solves performance issue related to loading same attribute options on different models + if ($attribute instanceof EavAttribute) { + return $attribute; + } $attributeId = $attribute->getAttributeId(); if (!array_key_exists($attributeId, $this->attributesCache)) { diff --git a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php index 4874dc8ea03ae..11384263b59a2 100644 --- a/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php +++ b/app/code/Magento/ConfigurableProduct/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php @@ -197,6 +197,7 @@ protected function getAttributes() foreach ($attributes as $key => $attribute) { if (isset($configurableData[$key])) { $attributes[$key] = array_replace_recursive($attribute, $configurableData[$key]); + // phpcs:ignore Magento2.Performance.ForeachArrayMerge $attributes[$key]['values'] = array_merge( isset($attribute['values']) ? $attribute['values'] : [], isset($configurableData[$key]['values']) @@ -412,14 +413,15 @@ private function prepareAttributes( 'position' => $configurableAttributes[$attribute->getAttributeId()]['position'], 'chosen' => [], ]; - foreach ($attribute->getOptions() as $option) { - if (!empty($option->getValue())) { + $options = $attribute->usesSource() ? $attribute->getSource()->getAllOptions() : []; + foreach ($options as $option) { + if (!empty($option['value'])) { $attributes[$attribute->getAttributeId()]['options'][] = [ 'attribute_code' => $attribute->getAttributeCode(), 'attribute_label' => $attribute->getStoreLabel(0), - 'id' => $option->getValue(), - 'label' => $option->getLabel(), - 'value' => $option->getValue(), + 'id' => $option['value'], + 'label' => $option['label'], + 'value' => $option['value'], '__disableTmpl' => true, ]; } diff --git a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php index c474acbec5094..4bde97fa8022a 100644 --- a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php +++ b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php @@ -21,6 +21,8 @@ use Magento\Framework\Escaper; /** + * Associated products helper + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class AssociatedProducts @@ -231,6 +233,8 @@ public function getConfigurableAttributesData() * * @return void * @throws \Zend_Currency_Exception + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * phpcs:disable Generic.Metrics.NestingLevel */ protected function prepareVariations() { @@ -262,14 +266,15 @@ protected function prepareVariations() 'position' => $configurableAttributes[$attribute->getAttributeId()]['position'], 'chosen' => [], ]; - foreach ($attribute->getOptions() as $option) { - if (!empty($option->getValue())) { - $attributes[$attribute->getAttributeId()]['options'][$option->getValue()] = [ + $options = $attribute->usesSource() ? $attribute->getSource()->getAllOptions() : []; + foreach ($options as $option) { + if (!empty($option['value'])) { + $attributes[$attribute->getAttributeId()]['options'][$option['value']] = [ 'attribute_code' => $attribute->getAttributeCode(), 'attribute_label' => $attribute->getStoreLabel(0), - 'id' => $option->getValue(), - 'label' => $option->getLabel(), - 'value' => $option->getValue(), + 'id' => $option['value'], + 'label' => $option['label'], + 'value' => $option['value'], ]; } } From 28f00aa2e1a59df9fdde12654ec9d96413d7599c Mon Sep 17 00:00:00 2001 From: Oleksandr Dubovyk Date: Mon, 23 Sep 2019 16:44:55 -0500 Subject: [PATCH 2/8] MC-20212: [On premise] Data loss due to core cron job called sales_clean_quotes - fixed - modified tests --- .../Magento/Sales/Cron/CleanExpiredQuotes.php | 70 ++++--------- .../Sales/Helper/ExpiredQuotesCollection.php | 99 +++++++++++++++++++ .../Test/Unit/Cron/CleanExpiredQuotesTest.php | 84 ---------------- 3 files changed, 116 insertions(+), 137 deletions(-) create mode 100644 app/code/Magento/Sales/Helper/ExpiredQuotesCollection.php delete mode 100644 app/code/Magento/Sales/Test/Unit/Cron/CleanExpiredQuotesTest.php diff --git a/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php b/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php index a5c7f71df66c5..04db058f4231a 100644 --- a/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php +++ b/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php @@ -5,40 +5,35 @@ */ namespace Magento\Sales\Cron; -use Magento\Store\Model\StoresConfig; +use Magento\Quote\Model\ResourceModel\Quote\Collection; +use Magento\Sales\Helper\ExpiredQuotesCollection; +use Magento\Store\Model\StoreManagerInterface; /** * Class CleanExpiredQuotes */ class CleanExpiredQuotes { - const LIFETIME = 86400; - - /** - * @var StoresConfig - */ - protected $storesConfig; - /** - * @var \Magento\Quote\Model\ResourceModel\Quote\CollectionFactory + * @var ExpiredQuotesCollection */ - protected $quoteCollectionFactory; + private $expiredQuotesCollection; /** - * @var array + * @var StoreManagerInterface */ - protected $expireQuotesFilterFields = []; + private $storeManager; /** - * @param StoresConfig $storesConfig - * @param \Magento\Quote\Model\ResourceModel\Quote\CollectionFactory $collectionFactory + * @param StoreManagerInterface $storeManager + * @param ExpiredQuotesCollection $expiredQuotesCollection */ public function __construct( - StoresConfig $storesConfig, - \Magento\Quote\Model\ResourceModel\Quote\CollectionFactory $collectionFactory + StoreManagerInterface $storeManager, + ExpiredQuotesCollection $expiredQuotesCollection ) { - $this->storesConfig = $storesConfig; - $this->quoteCollectionFactory = $collectionFactory; + $this->storeManager = $storeManager; + $this->expiredQuotesCollection = $expiredQuotesCollection; } /** @@ -48,42 +43,11 @@ public function __construct( */ public function execute() { - $lifetimes = $this->storesConfig->getStoresConfigByPath('checkout/cart/delete_quote_after'); - foreach ($lifetimes as $storeId => $lifetime) { - $lifetime *= self::LIFETIME; - - /** @var $quotes \Magento\Quote\Model\ResourceModel\Quote\Collection */ - $quotes = $this->quoteCollectionFactory->create(); - - $quotes->addFieldToFilter('store_id', $storeId); - $quotes->addFieldToFilter('updated_at', ['to' => date("Y-m-d", time() - $lifetime)]); - - foreach ($this->getExpireQuotesAdditionalFilterFields() as $field => $condition) { - $quotes->addFieldToFilter($field, $condition); - } - + $stores = $this->storeManager->getStores(true); + foreach ($stores as $store) { + /** @var $quotes Collection */ + $quotes = $this->expiredQuotesCollection->getExpiredQuotes($store); $quotes->walk('delete'); } } - - /** - * Retrieve expire quotes additional fields to filter - * - * @return array - */ - protected function getExpireQuotesAdditionalFilterFields() - { - return $this->expireQuotesFilterFields; - } - - /** - * Set expire quotes additional fields to filter - * - * @param array $fields - * @return void - */ - public function setExpireQuotesAdditionalFilterFields(array $fields) - { - $this->expireQuotesFilterFields = $fields; - } } diff --git a/app/code/Magento/Sales/Helper/ExpiredQuotesCollection.php b/app/code/Magento/Sales/Helper/ExpiredQuotesCollection.php new file mode 100644 index 0000000000000..5b62a8251d54d --- /dev/null +++ b/app/code/Magento/Sales/Helper/ExpiredQuotesCollection.php @@ -0,0 +1,99 @@ +config = $config; + $this->quoteCollectionFactory = $collectionFactory; + } + + /** + * Gets expired quotes + * + * Quote is considered expired if the latest update date + * of the quote is greater than lifetime threshold + * + * @param StoreInterface $store + * @return Collection + */ + public function getExpiredQuotes(StoreInterface $store) + { + $lifetime = $this->config->getValue( + self::QUOTE_LIFETIME, + ScopeInterface::SCOPE_STORE, + $store->getCode() + ); + $lifetime *= self::SECONDS_IN_DAY; + + /** @var $quotes Collection */ + $quotes = $this->quoteCollectionFactory->create(); + $quotes->addFieldToFilter('store_id', $store->getId()); + $quotes->addFieldToFilter('updated_at', ['to' => date("Y-m-d", time() - $lifetime)]); + + foreach ($this->getExpireQuotesAdditionalFilterFields() as $field => $condition) { + $quotes->addFieldToFilter($field, $condition); + } + + return $quotes; + } + + /** + * Retrieve expire quotes additional fields to filter + * + * @return array + */ + private function getExpireQuotesAdditionalFilterFields() + { + return $this->expireQuotesFilterFields; + } + + /** + * Set expire quotes additional fields to filter + * + * @param array $fields + * @return void + */ + public function setExpireQuotesAdditionalFilterFields(array $fields) + { + $this->expireQuotesFilterFields = $fields; + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Cron/CleanExpiredQuotesTest.php b/app/code/Magento/Sales/Test/Unit/Cron/CleanExpiredQuotesTest.php deleted file mode 100644 index ad6a3e03ba679..0000000000000 --- a/app/code/Magento/Sales/Test/Unit/Cron/CleanExpiredQuotesTest.php +++ /dev/null @@ -1,84 +0,0 @@ -storesConfigMock = $this->createMock(\Magento\Store\Model\StoresConfig::class); - - $this->quoteFactoryMock = $this->getMockBuilder( - \Magento\Quote\Model\ResourceModel\Quote\CollectionFactory::class - ) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - - $this->observer = new CleanExpiredQuotes($this->storesConfigMock, $this->quoteFactoryMock); - } - - /** - * @param array $lifetimes - * @param array $additionalFilterFields - * @dataProvider cleanExpiredQuotesDataProvider - */ - public function testExecute($lifetimes, $additionalFilterFields) - { - $this->storesConfigMock->expects($this->once()) - ->method('getStoresConfigByPath') - ->with($this->equalTo('checkout/cart/delete_quote_after')) - ->will($this->returnValue($lifetimes)); - - $quotesMock = $this->getMockBuilder(\Magento\Quote\Model\ResourceModel\Quote\Collection::class) - ->disableOriginalConstructor() - ->getMock(); - $this->quoteFactoryMock->expects($this->exactly(count($lifetimes))) - ->method('create') - ->will($this->returnValue($quotesMock)); - $quotesMock->expects($this->exactly((2 + count($additionalFilterFields)) * count($lifetimes))) - ->method('addFieldToFilter'); - if (!empty($lifetimes)) { - $quotesMock->expects($this->exactly(count($lifetimes))) - ->method('walk') - ->with('delete'); - } - $this->observer->setExpireQuotesAdditionalFilterFields($additionalFilterFields); - $this->observer->execute(); - } - - /** - * @return array - */ - public function cleanExpiredQuotesDataProvider() - { - return [ - [[], []], - [[1 => 100, 2 => 200], []], - [[1 => 100, 2 => 200], ['field1' => 'condition1', 'field2' => 'condition2']], - ]; - } -} From 4844c67145e87ae77dc30b09907fa3dfbf181fd5 Mon Sep 17 00:00:00 2001 From: Dmytro Horytskyi Date: Tue, 24 Sep 2019 12:51:58 -0500 Subject: [PATCH 3/8] MC-20381: Elasticsearch doesn't find products by dropdown attribute values on Frontend --- .../SearchAdapter/Query/Builder/Match.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder/Match.php b/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder/Match.php index afd383c13421f..ddf75c0a78e25 100644 --- a/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder/Match.php +++ b/app/code/Magento/Elasticsearch/SearchAdapter/Query/Builder/Match.php @@ -138,7 +138,12 @@ protected function buildQueries(array $matches, array $queryValue) $transformedTypes = []; foreach ($matches as $match) { - $attributeAdapter = $this->attributeProvider->getByAttributeCode($match['field']); + $resolvedField = $this->fieldMapper->getFieldName( + $match['field'], + ['type' => FieldMapperInterface::TYPE_QUERY] + ); + + $attributeAdapter = $this->attributeProvider->getByAttributeCode($resolvedField); $fieldType = $this->fieldTypeResolver->getFieldType($attributeAdapter); $valueTransformer = $this->valueTransformerPool->get($fieldType ?? 'text'); $valueTransformerHash = \spl_object_hash($valueTransformer); @@ -151,10 +156,6 @@ protected function buildQueries(array $matches, array $queryValue) continue; } - $resolvedField = $this->fieldMapper->getFieldName( - $match['field'], - ['type' => FieldMapperInterface::TYPE_QUERY] - ); $conditions[] = [ 'condition' => $queryValue['condition'], 'body' => [ From 1fa73b7fa97c3faab2eb7356e5b6bb8c9753efb0 Mon Sep 17 00:00:00 2001 From: Oleksandr Dubovyk Date: Tue, 24 Sep 2019 13:22:16 -0500 Subject: [PATCH 4/8] MC-20212: [On premise] Data loss due to core cron job called sales_clean_quotes - small refactor --- .../Magento/Sales/Cron/CleanExpiredQuotes.php | 2 +- .../Collection}/ExpiredQuotesCollection.php | 43 +++++-------------- 2 files changed, 11 insertions(+), 34 deletions(-) rename app/code/Magento/Sales/{Helper => Model/ResourceModel/Collection}/ExpiredQuotesCollection.php (66%) diff --git a/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php b/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php index 04db058f4231a..ca5e850038d85 100644 --- a/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php +++ b/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php @@ -6,7 +6,7 @@ namespace Magento\Sales\Cron; use Magento\Quote\Model\ResourceModel\Quote\Collection; -use Magento\Sales\Helper\ExpiredQuotesCollection; +use Magento\Sales\Model\ResourceModel\ExpiredQuotesCollection; use Magento\Store\Model\StoreManagerInterface; /** diff --git a/app/code/Magento/Sales/Helper/ExpiredQuotesCollection.php b/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php similarity index 66% rename from app/code/Magento/Sales/Helper/ExpiredQuotesCollection.php rename to app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php index 5b62a8251d54d..9865951c9f55e 100644 --- a/app/code/Magento/Sales/Helper/ExpiredQuotesCollection.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php @@ -16,18 +16,20 @@ */ class ExpiredQuotesCollection { - const SECONDS_IN_DAY = 86400; - const QUOTE_LIFETIME = 'checkout/cart/delete_quote_after'; + /** + * @var int + */ + private $secondsInDay = 86400; /** - * @var CollectionFactory + * @var string */ - private $quoteCollectionFactory; + private $quoteLifetime = 'checkout/cart/delete_quote_after'; /** - * @var array + * @var CollectionFactory */ - private $expireQuotesFilterFields = []; + private $quoteCollectionFactory; /** * @var ScopeConfigInterface @@ -58,42 +60,17 @@ public function __construct( public function getExpiredQuotes(StoreInterface $store) { $lifetime = $this->config->getValue( - self::QUOTE_LIFETIME, + $this->quoteLifetime, ScopeInterface::SCOPE_STORE, $store->getCode() ); - $lifetime *= self::SECONDS_IN_DAY; + $lifetime *= $this->secondsInDay; /** @var $quotes Collection */ $quotes = $this->quoteCollectionFactory->create(); $quotes->addFieldToFilter('store_id', $store->getId()); $quotes->addFieldToFilter('updated_at', ['to' => date("Y-m-d", time() - $lifetime)]); - foreach ($this->getExpireQuotesAdditionalFilterFields() as $field => $condition) { - $quotes->addFieldToFilter($field, $condition); - } - return $quotes; } - - /** - * Retrieve expire quotes additional fields to filter - * - * @return array - */ - private function getExpireQuotesAdditionalFilterFields() - { - return $this->expireQuotesFilterFields; - } - - /** - * Set expire quotes additional fields to filter - * - * @param array $fields - * @return void - */ - public function setExpireQuotesAdditionalFilterFields(array $fields) - { - $this->expireQuotesFilterFields = $fields; - } } From ee5e71612a7a3251d11df6a7e81b854cfed1ad14 Mon Sep 17 00:00:00 2001 From: Oleksandr Dubovyk Date: Tue, 24 Sep 2019 14:03:32 -0500 Subject: [PATCH 5/8] MC-20212: [On premise] Data loss due to core cron job called sales_clean_quotes - static test fix --- .../Model/ResourceModel/Collection/ExpiredQuotesCollection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php b/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php index 9865951c9f55e..390f8e51499fb 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php @@ -3,7 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Sales\Helper; +namespace Magento\Sales\Model\ResourceModel\Collection; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Quote\Model\ResourceModel\Quote\Collection; From b00b336dc7356e1d775217eddc0f217e75f58b6d Mon Sep 17 00:00:00 2001 From: Oleksandr Dubovyk Date: Tue, 24 Sep 2019 16:04:26 -0500 Subject: [PATCH 6/8] MC-20212: [On premise] Data loss due to core cron job called sales_clean_quotes - static test fails namespaces --- app/code/Magento/Sales/Cron/CleanExpiredQuotes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php b/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php index ca5e850038d85..a3242228b28e0 100644 --- a/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php +++ b/app/code/Magento/Sales/Cron/CleanExpiredQuotes.php @@ -6,7 +6,7 @@ namespace Magento\Sales\Cron; use Magento\Quote\Model\ResourceModel\Quote\Collection; -use Magento\Sales\Model\ResourceModel\ExpiredQuotesCollection; +use Magento\Sales\Model\ResourceModel\Collection\ExpiredQuotesCollection; use Magento\Store\Model\StoreManagerInterface; /** From 9c9172f2e5ecf68257fc14968b0775714418e10c Mon Sep 17 00:00:00 2001 From: Oleksandr Dubovyk Date: Tue, 24 Sep 2019 17:10:25 -0500 Subject: [PATCH 7/8] MC-20212: [On premise] Data loss due to core cron job called sales_clean_quotes - small changes --- .../ResourceModel/Collection/ExpiredQuotesCollection.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php b/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php index 390f8e51499fb..785427b7040d1 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php @@ -3,6 +3,8 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Sales\Model\ResourceModel\Collection; use Magento\Framework\App\Config\ScopeConfigInterface; @@ -57,7 +59,7 @@ public function __construct( * @param StoreInterface $store * @return Collection */ - public function getExpiredQuotes(StoreInterface $store) + public function getExpiredQuotes(StoreInterface $store): Collection { $lifetime = $this->config->getValue( $this->quoteLifetime, From 87d6d063e160bb8e23503fc52cc8e687633508a7 Mon Sep 17 00:00:00 2001 From: Oleksandr Dubovyk Date: Wed, 25 Sep 2019 10:12:15 -0500 Subject: [PATCH 8/8] MC-20212: [On premise] Data loss due to core cron job called sales_clean_quotes - changed return type --- .../ResourceModel/Collection/ExpiredQuotesCollection.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php b/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php index 785427b7040d1..895d73cc4cfff 100644 --- a/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php +++ b/app/code/Magento/Sales/Model/ResourceModel/Collection/ExpiredQuotesCollection.php @@ -8,6 +8,7 @@ namespace Magento\Sales\Model\ResourceModel\Collection; use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection; use Magento\Quote\Model\ResourceModel\Quote\Collection; use Magento\Quote\Model\ResourceModel\Quote\CollectionFactory; use Magento\Store\Api\Data\StoreInterface; @@ -57,9 +58,9 @@ public function __construct( * of the quote is greater than lifetime threshold * * @param StoreInterface $store - * @return Collection + * @return AbstractCollection */ - public function getExpiredQuotes(StoreInterface $store): Collection + public function getExpiredQuotes(StoreInterface $store): AbstractCollection { $lifetime = $this->config->getValue( $this->quoteLifetime,