From efb7c618a35cb59b392a09572595c26d73488521 Mon Sep 17 00:00:00 2001
From: Dmytro Horytskyi
Date: Thu, 1 Aug 2019 12:11:44 -0500
Subject: [PATCH 01/17] MC-18833: Tier price API doesn't take into account
indexers mode
---
.../Catalog/Model/Indexer/Product/Price.php | 60 ++---
.../Model/Product/Price/TierPriceStorage.php | 133 ++++------
.../Product/Price/TierPriceStorageTest.php | 231 +++++++++---------
.../Indexer/Model/Indexer/CacheCleaner.php | 100 ++++++++
app/code/Magento/Indexer/etc/di.xml | 3 +
5 files changed, 294 insertions(+), 233 deletions(-)
create mode 100644 app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Price.php b/app/code/Magento/Catalog/Model/Indexer/Product/Price.php
index c9936f7e6c691..b703ba82a4052 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Price.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Price.php
@@ -5,43 +5,56 @@
*/
namespace Magento\Catalog\Model\Indexer\Product;
+use Magento\Catalog\Model\Category as CategoryModel;
+use Magento\Catalog\Model\Indexer\Product\Price\Action\Full as FullAction;
+use Magento\Catalog\Model\Indexer\Product\Price\Action\Row as RowAction;
+use Magento\Catalog\Model\Indexer\Product\Price\Action\Rows as RowsAction;
+use Magento\Catalog\Model\Product as ProductModel;
+use Magento\Framework\Indexer\ActionInterface as IndexerActionInterface;
use Magento\Framework\Indexer\CacheContext;
+use Magento\Framework\Mview\ActionInterface as MviewActionInterface;
-class Price implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
+/**
+ * Price indexer
+ */
+class Price implements IndexerActionInterface, MviewActionInterface
{
/**
- * @var \Magento\Catalog\Model\Indexer\Product\Price\Action\Row
+ * @var RowAction
*/
protected $_productPriceIndexerRow;
/**
- * @var \Magento\Catalog\Model\Indexer\Product\Price\Action\Rows
+ * @var RowsAction
*/
protected $_productPriceIndexerRows;
/**
- * @var \Magento\Catalog\Model\Indexer\Product\Price\Action\Full
+ * @var FullAction
*/
protected $_productPriceIndexerFull;
/**
- * @var \Magento\Framework\Indexer\CacheContext
+ * @var CacheContext
*/
private $cacheContext;
/**
- * @param Price\Action\Row $productPriceIndexerRow
- * @param Price\Action\Rows $productPriceIndexerRows
- * @param Price\Action\Full $productPriceIndexerFull
+ * @param RowAction $productPriceIndexerRow
+ * @param RowsAction $productPriceIndexerRows
+ * @param FullAction $productPriceIndexerFull
+ * @param CacheContext $cacheContext
*/
public function __construct(
- \Magento\Catalog\Model\Indexer\Product\Price\Action\Row $productPriceIndexerRow,
- \Magento\Catalog\Model\Indexer\Product\Price\Action\Rows $productPriceIndexerRows,
- \Magento\Catalog\Model\Indexer\Product\Price\Action\Full $productPriceIndexerFull
+ RowAction $productPriceIndexerRow,
+ RowsAction $productPriceIndexerRows,
+ FullAction $productPriceIndexerFull,
+ CacheContext $cacheContext
) {
$this->_productPriceIndexerRow = $productPriceIndexerRow;
$this->_productPriceIndexerRows = $productPriceIndexerRows;
$this->_productPriceIndexerFull = $productPriceIndexerFull;
+ $this->cacheContext = $cacheContext;
}
/**
@@ -53,7 +66,7 @@ public function __construct(
public function execute($ids)
{
$this->_productPriceIndexerRows->execute($ids);
- $this->getCacheContext()->registerEntities(\Magento\Catalog\Model\Product::CACHE_TAG, $ids);
+ $this->cacheContext->registerEntities(ProductModel::CACHE_TAG, $ids);
}
/**
@@ -64,10 +77,10 @@ public function execute($ids)
public function executeFull()
{
$this->_productPriceIndexerFull->execute();
- $this->getCacheContext()->registerTags(
+ $this->cacheContext->registerTags(
[
- \Magento\Catalog\Model\Category::CACHE_TAG,
- \Magento\Catalog\Model\Product::CACHE_TAG
+ CategoryModel::CACHE_TAG,
+ ProductModel::CACHE_TAG
]
);
}
@@ -81,6 +94,7 @@ public function executeFull()
public function executeList(array $ids)
{
$this->_productPriceIndexerRows->execute($ids);
+ $this->cacheContext->registerEntities(ProductModel::CACHE_TAG, $ids);
}
/**
@@ -92,20 +106,6 @@ public function executeList(array $ids)
public function executeRow($id)
{
$this->_productPriceIndexerRow->execute($id);
- }
-
- /**
- * Get cache context
- *
- * @return \Magento\Framework\Indexer\CacheContext
- * @deprecated 100.0.11
- */
- protected function getCacheContext()
- {
- if (!($this->cacheContext instanceof CacheContext)) {
- return \Magento\Framework\App\ObjectManager::getInstance()->get(CacheContext::class);
- } else {
- return $this->cacheContext;
- }
+ $this->cacheContext->registerEntities(ProductModel::CACHE_TAG, [$id]);
}
}
diff --git a/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php b/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
index 3ee064670a460..6efff27fa2287 100644
--- a/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
+++ b/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
@@ -7,11 +7,15 @@
namespace Magento\Catalog\Model\Product\Price;
use Magento\Catalog\Api\Data\TierPriceInterface;
+use Magento\Catalog\Api\TierPriceStorageInterface;
+use Magento\Catalog\Model\Indexer\Product\Price\Processor as PriceIndexerProcessor;
+use Magento\Catalog\Model\Product\Price\Validation\TierPriceValidator;
+use Magento\Catalog\Model\ProductIdLocatorInterface;
/**
* Tier price storage.
*/
-class TierPriceStorage implements \Magento\Catalog\Api\TierPriceStorageInterface
+class TierPriceStorage implements TierPriceStorageInterface
{
/**
* Tier price resource model.
@@ -23,7 +27,7 @@ class TierPriceStorage implements \Magento\Catalog\Api\TierPriceStorageInterface
/**
* Tier price validator.
*
- * @var \Magento\Catalog\Model\Product\Price\Validation\TierPriceValidator
+ * @var TierPriceValidator
*/
private $tierPriceValidator;
@@ -35,65 +39,38 @@ class TierPriceStorage implements \Magento\Catalog\Api\TierPriceStorageInterface
private $tierPriceFactory;
/**
- * Price indexer.
+ * Price index processor.
*
- * @var \Magento\Catalog\Model\Indexer\Product\Price
+ * @var PriceIndexerProcessor
*/
- private $priceIndexer;
+ private $priceIndexProcessor;
/**
* Product ID locator.
*
- * @var \Magento\Catalog\Model\ProductIdLocatorInterface
+ * @var ProductIdLocatorInterface
*/
private $productIdLocator;
- /**
- * Page cache config.
- *
- * @var \Magento\PageCache\Model\Config
- */
- private $config;
-
- /**
- * Cache type list.
- *
- * @var \Magento\Framework\App\Cache\TypeListInterface
- */
- private $typeList;
-
- /**
- * Indexer chunk value.
- *
- * @var int
- */
- private $indexerChunkValue = 500;
-
/**
* @param TierPricePersistence $tierPricePersistence
- * @param \Magento\Catalog\Model\Product\Price\Validation\TierPriceValidator $tierPriceValidator
+ * @param TierPriceValidator $tierPriceValidator
* @param TierPriceFactory $tierPriceFactory
- * @param \Magento\Catalog\Model\Indexer\Product\Price $priceIndexer
- * @param \Magento\Catalog\Model\ProductIdLocatorInterface $productIdLocator
- * @param \Magento\PageCache\Model\Config $config
- * @param \Magento\Framework\App\Cache\TypeListInterface $typeList
+ * @param PriceIndexerProcessor $priceIndexProcessor
+ * @param ProductIdLocatorInterface $productIdLocator
*/
public function __construct(
TierPricePersistence $tierPricePersistence,
- \Magento\Catalog\Model\Product\Price\Validation\TierPriceValidator $tierPriceValidator,
+ TierPriceValidator $tierPriceValidator,
TierPriceFactory $tierPriceFactory,
- \Magento\Catalog\Model\Indexer\Product\Price $priceIndexer,
- \Magento\Catalog\Model\ProductIdLocatorInterface $productIdLocator,
- \Magento\PageCache\Model\Config $config,
- \Magento\Framework\App\Cache\TypeListInterface $typeList
+ PriceIndexerProcessor $priceIndexProcessor,
+ ProductIdLocatorInterface $productIdLocator
) {
$this->tierPricePersistence = $tierPricePersistence;
$this->tierPriceValidator = $tierPriceValidator;
$this->tierPriceFactory = $tierPriceFactory;
- $this->priceIndexer = $priceIndexer;
+ $this->priceIndexProcessor = $priceIndexProcessor;
$this->productIdLocator = $productIdLocator;
- $this->config = $config;
- $this->typeList = $typeList;
}
/**
@@ -102,8 +79,10 @@ public function __construct(
public function get(array $skus)
{
$skus = $this->tierPriceValidator->validateSkus($skus);
+ $skuByIdLookup = $this->buildSkuByIdLookup($skus);
+ $prices = $this->getExistingPrices($skuByIdLookup);
- return $this->getExistingPrices($skus);
+ return $prices;
}
/**
@@ -111,18 +90,21 @@ public function get(array $skus)
*/
public function update(array $prices)
{
- $affectedIds = $this->retrieveAffectedProductIdsForPrices($prices);
$skus = array_unique(
- array_map(function ($price) {
- return $price->getSku();
- }, $prices)
+ array_map(
+ function (TierPriceInterface $price) {
+ return $price->getSku();
+ },
+ $prices
+ )
);
- $result = $this->tierPriceValidator->retrieveValidationResult($prices, $this->getExistingPrices($skus, true));
+ $skuByIdLookup = $this->buildSkuByIdLookup($skus);
+ $existingPrices = $this->getExistingPrices($skuByIdLookup, true);
+ $result = $this->tierPriceValidator->retrieveValidationResult($prices, $existingPrices);
$prices = $this->removeIncorrectPrices($prices, $result->getFailedRowIds());
$formattedPrices = $this->retrieveFormattedPrices($prices);
$this->tierPricePersistence->update($formattedPrices);
- $this->reindexPrices($affectedIds);
- $this->invalidateFullPageCache();
+ $this->reindexPrices(array_keys($skuByIdLookup));
return $result->getFailedItems();
}
@@ -138,7 +120,6 @@ public function replace(array $prices)
$formattedPrices = $this->retrieveFormattedPrices($prices);
$this->tierPricePersistence->replace($formattedPrices, $affectedIds);
$this->reindexPrices($affectedIds);
- $this->invalidateFullPageCache();
return $result->getFailedItems();
}
@@ -154,7 +135,6 @@ public function delete(array $prices)
$priceIds = $this->retrieveAffectedPriceIds($prices);
$this->tierPricePersistence->delete($priceIds);
$this->reindexPrices($affectedIds);
- $this->invalidateFullPageCache();
return $result->getFailedItems();
}
@@ -162,18 +142,16 @@ public function delete(array $prices)
/**
* Get existing prices by SKUs.
*
- * @param array $skus
+ * @param array $skuByIdLookup
* @param bool $groupBySku [optional]
* @return array
*/
- private function getExistingPrices(array $skus, $groupBySku = false)
+ private function getExistingPrices(array $skuByIdLookup, bool $groupBySku = false): array
{
- $ids = $this->retrieveAffectedIds($skus);
- $rawPrices = $this->tierPricePersistence->get($ids);
+ $rawPrices = $this->tierPricePersistence->get(array_keys($skuByIdLookup));
$prices = [];
if ($rawPrices) {
$linkField = $this->tierPricePersistence->getEntityLinkField();
- $skuByIdLookup = $this->buildSkuByIdLookup($skus);
foreach ($rawPrices as $rawPrice) {
$sku = $skuByIdLookup[$rawPrice[$linkField]];
$price = $this->tierPriceFactory->create($rawPrice, $sku);
@@ -194,7 +172,7 @@ private function getExistingPrices(array $skus, $groupBySku = false)
* @param array $prices
* @return array
*/
- private function retrieveFormattedPrices(array $prices)
+ private function retrieveFormattedPrices(array $prices): array
{
$formattedPrices = [];
@@ -215,12 +193,15 @@ private function retrieveFormattedPrices(array $prices)
* @param TierPriceInterface[] $prices
* @return array
*/
- private function retrieveAffectedProductIdsForPrices(array $prices)
+ private function retrieveAffectedProductIdsForPrices(array $prices): array
{
$skus = array_unique(
- array_map(function ($price) {
- return $price->getSku();
- }, $prices)
+ array_map(
+ function (TierPriceInterface $price) {
+ return $price->getSku();
+ },
+ $prices
+ )
);
return $this->retrieveAffectedIds($skus);
@@ -232,7 +213,7 @@ private function retrieveAffectedProductIdsForPrices(array $prices)
* @param array $skus
* @return array
*/
- private function retrieveAffectedIds(array $skus)
+ private function retrieveAffectedIds(array $skus): array
{
$affectedIds = [];
@@ -249,7 +230,7 @@ private function retrieveAffectedIds(array $skus)
* @param array $prices
* @return array
*/
- private function retrieveAffectedPriceIds(array $prices)
+ private function retrieveAffectedPriceIds(array $prices): array
{
$affectedIds = $this->retrieveAffectedProductIdsForPrices($prices);
$formattedPrices = $this->retrieveFormattedPrices($prices);
@@ -270,7 +251,7 @@ private function retrieveAffectedPriceIds(array $prices)
* @param array $existingPrices
* @return int|null
*/
- private function retrievePriceId(array $price, array $existingPrices)
+ private function retrievePriceId(array $price, array $existingPrices): ?int
{
$linkField = $this->tierPricePersistence->getEntityLinkField();
@@ -281,7 +262,7 @@ private function retrievePriceId(array $price, array $existingPrices)
&& $this->isCorrectPriceValue($existingPrice, $price)
&& $existingPrice[$linkField] == $price[$linkField]
) {
- return $existingPrice['value_id'];
+ return (int) $existingPrice['value_id'];
}
}
@@ -295,7 +276,7 @@ private function retrievePriceId(array $price, array $existingPrices)
* @param array $price
* @return bool
*/
- private function isCorrectPriceValue(array $existingPrice, array $price)
+ private function isCorrectPriceValue(array $existingPrice, array $price): bool
{
return ($existingPrice['value'] != 0 && $existingPrice['value'] == $price['value'])
|| ($existingPrice['percentage_value'] !== null
@@ -308,7 +289,7 @@ private function isCorrectPriceValue(array $existingPrice, array $price)
* @param array $skus
* @return array
*/
- private function buildSkuByIdLookup($skus)
+ private function buildSkuByIdLookup(array $skus): array
{
$lookup = [];
foreach ($this->productIdLocator->retrieveProductIdsBySkus($skus) as $sku => $ids) {
@@ -320,28 +301,16 @@ private function buildSkuByIdLookup($skus)
return $lookup;
}
- /**
- * Invalidate full page cache.
- *
- * @return void
- */
- private function invalidateFullPageCache()
- {
- if ($this->config->isEnabled()) {
- $this->typeList->invalidate('full_page');
- }
- }
-
/**
* Reindex prices.
*
* @param array $ids
* @return void
*/
- private function reindexPrices(array $ids)
+ private function reindexPrices(array $ids): void
{
- foreach (array_chunk($ids, $this->indexerChunkValue) as $affectedIds) {
- $this->priceIndexer->execute($affectedIds);
+ if (!empty($ids)) {
+ $this->priceIndexProcessor->reindexList($ids);
}
}
@@ -352,7 +321,7 @@ private function reindexPrices(array $ids)
* @param array $ids
* @return array
*/
- private function removeIncorrectPrices(array $prices, array $ids)
+ private function removeIncorrectPrices(array $prices, array $ids): array
{
foreach ($ids as $id) {
unset($prices[$id]);
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/TierPriceStorageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/TierPriceStorageTest.php
index a97f2281125a6..34f43b725da57 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/TierPriceStorageTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Price/TierPriceStorageTest.php
@@ -6,46 +6,44 @@
namespace Magento\Catalog\Test\Unit\Model\Product\Price;
+use Magento\Catalog\Api\Data\TierPriceInterface;
+use Magento\Catalog\Model\Indexer\Product\Price\Processor as PriceIndexerProcessor;
+use Magento\Catalog\Model\Product\Price\TierPriceFactory;
+use Magento\Catalog\Model\Product\Price\TierPricePersistence;
+use Magento\Catalog\Model\Product\Price\Validation\Result as PriceValidationResult;
+use Magento\Catalog\Model\Product\Price\Validation\TierPriceValidator;
+use Magento\Catalog\Model\ProductIdLocatorInterface;
+
/**
* TierPriceStorage test.
*/
class TierPriceStorageTest extends \PHPUnit\Framework\TestCase
{
/**
- * @var \Magento\Catalog\Model\Product\Price\TierPricePersistence|\PHPUnit_Framework_MockObject_MockObject
+ * @var TierPricePersistence|\PHPUnit_Framework_MockObject_MockObject
*/
private $tierPricePersistence;
/**
- * @var \Magento\Catalog\Model\Product\Price\Validation\TierPriceValidator|\PHPUnit_Framework_MockObject_MockObject
+ * @var TierPriceValidator|\PHPUnit_Framework_MockObject_MockObject
*/
private $tierPriceValidator;
/**
- * @var \Magento\Catalog\Model\Product\Price\TierPriceFactory|\PHPUnit_Framework_MockObject_MockObject
+ * @var TierPriceFactory|\PHPUnit_Framework_MockObject_MockObject
*/
private $tierPriceFactory;
/**
- * @var \Magento\Catalog\Model\Indexer\Product\Price|\PHPUnit_Framework_MockObject_MockObject
+ * @var PriceIndexerProcessor|\PHPUnit_Framework_MockObject_MockObject
*/
- private $priceIndexer;
+ private $priceIndexProcessor;
/**
- * @var \Magento\Catalog\Model\ProductIdLocatorInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var ProductIdLocatorInterface|\PHPUnit_Framework_MockObject_MockObject
*/
private $productIdLocator;
- /**
- * @var \Magento\PageCache\Model\Config|\PHPUnit_Framework_MockObject_MockObject
- */
- private $config;
-
- /**
- * @var \Magento\Framework\App\Cache\TypeListInterface|\PHPUnit_Framework_MockObject_MockObject
- */
- private $typeList;
-
/**
* @var \Magento\Catalog\Model\Product\Price\TierPriceStorage
*/
@@ -56,36 +54,13 @@ class TierPriceStorageTest extends \PHPUnit\Framework\TestCase
*/
protected function setUp()
{
- $this->tierPricePersistence = $this->getMockBuilder(
- \Magento\Catalog\Model\Product\Price\TierPricePersistence::class
- )
- ->disableOriginalConstructor()
- ->getMock();
- $this->tierPricePersistence->expects($this->any())
- ->method('getEntityLinkField')
- ->willReturn('row_id');
- $this->tierPriceValidator = $this->getMockBuilder(
- \Magento\Catalog\Model\Product\Price\Validation\TierPriceValidator::class
- )
- ->disableOriginalConstructor()
- ->getMock();
- $this->tierPriceFactory = $this->getMockBuilder(
- \Magento\Catalog\Model\Product\Price\TierPriceFactory::class
- )
- ->disableOriginalConstructor()
- ->getMock();
- $this->priceIndexer = $this->getMockBuilder(\Magento\Catalog\Model\Indexer\Product\Price::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->productIdLocator = $this->getMockBuilder(\Magento\Catalog\Model\ProductIdLocatorInterface::class)
- ->disableOriginalConstructor()
- ->getMockForAbstractClass();
- $this->config = $this->getMockBuilder(\Magento\PageCache\Model\Config::class)
- ->disableOriginalConstructor()
- ->getMock();
- $this->typeList = $this->getMockBuilder(\Magento\Framework\App\Cache\TypeListInterface::class)
- ->disableOriginalConstructor()
- ->getMockForAbstractClass();
+ $this->tierPricePersistence = $this->createMock(TierPricePersistence::class);
+ $this->tierPricePersistence->method('getEntityLinkField')
+ ->willReturn('entity_id');
+ $this->tierPriceValidator = $this->createMock(TierPriceValidator::class);
+ $this->tierPriceFactory = $this->createMock(TierPriceFactory::class);
+ $this->priceIndexProcessor = $this->createMock(PriceIndexerProcessor::class);
+ $this->productIdLocator = $this->createMock(ProductIdLocatorInterface::class);
$objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
$this->tierPriceStorage = $objectManager->getObject(
@@ -94,10 +69,8 @@ protected function setUp()
'tierPricePersistence' => $this->tierPricePersistence,
'tierPriceValidator' => $this->tierPriceValidator,
'tierPriceFactory' => $this->tierPriceFactory,
- 'priceIndexer' => $this->priceIndexer,
+ 'priceIndexProcessor' => $this->priceIndexProcessor,
'productIdLocator' => $this->productIdLocator,
- 'config' => $this->config,
- 'typeList' => $this->typeList,
]
);
}
@@ -125,7 +98,7 @@ public function testGet()
[
[
'value_id' => 1,
- 'row_id' => 2,
+ 'entity_id' => 2,
'all_groups' => 1,
'customer_group_id' => 0,
'qty' => 2.0000,
@@ -135,7 +108,7 @@ public function testGet()
],
[
'value_id' => 2,
- 'row_id' => 3,
+ 'entity_id' => 3,
'all_groups' => 1,
'customer_group_id' => 0,
'qty' => 3.0000,
@@ -145,7 +118,7 @@ public function testGet()
]
]
);
- $price = $this->getMockBuilder(\Magento\Catalog\Api\Data\TierPriceInterface::class)->getMockForAbstractClass();
+ $price = $this->getMockBuilder(TierPriceInterface::class)->getMockForAbstractClass();
$this->tierPriceFactory->expects($this->atLeastOnce())->method('create')->willReturn($price);
$prices = $this->tierPriceStorage->get($skus);
$this->assertNotEmpty($prices);
@@ -183,36 +156,37 @@ public function testGetWithoutTierPrices()
*/
public function testUpdate()
{
- $price = $this->getMockBuilder(\Magento\Catalog\Api\Data\TierPriceInterface::class)->getMockForAbstractClass();
- $result = $this->getMockBuilder(\Magento\Catalog\Model\Product\Price\Validation\Result::class)
- ->disableOriginalConstructor()
- ->getMock();
- $result->expects($this->atLeastOnce())->method('getFailedRowIds')->willReturn([]);
+ $price = $this->createMock(TierPriceInterface::class);
+ $result = $this->createMock(PriceValidationResult::class);
+ $result->expects($this->once())
+ ->method('getFailedRowIds')
+ ->willReturn([]);
$this->productIdLocator->expects($this->atLeastOnce())
->method('retrieveProductIdsBySkus')
->willReturn(['simple' => ['2' => 'simple'], 'virtual' => ['3' => 'virtual']]);
- $this->tierPriceValidator
- ->expects($this->atLeastOnce())
+ $this->tierPriceValidator->expects($this->once())
->method('retrieveValidationResult')
->willReturn($result);
- $this->tierPriceFactory->expects($this->atLeastOnce())->method('createSkeleton')->willReturn(
- [
- 'row_id' => 2,
- 'all_groups' => 1,
- 'customer_group_id' => 0,
- 'qty' => 2,
- 'value' => 3,
- 'percentage_value' => null,
- 'website_id' => 0
- ]
- );
+ $this->tierPriceFactory->expects($this->once())
+ ->method('createSkeleton')
+ ->willReturn(
+ [
+ 'entity_id' => 2,
+ 'all_groups' => 1,
+ 'customer_group_id' => 0,
+ 'qty' => 2,
+ 'value' => 3,
+ 'percentage_value' => null,
+ 'website_id' => 0
+ ]
+ );
$this->tierPricePersistence->expects($this->once())
->method('get')
->willReturn(
[
[
'value_id' => 1,
- 'row_id' => 2,
+ 'entity_id' => 2,
'all_groups' => 1,
'customer_group_id' => 0,
'qty' => 2.0000,
@@ -222,11 +196,15 @@ public function testUpdate()
]
]
);
- $this->tierPricePersistence->expects($this->atLeastOnce())->method('update');
- $this->priceIndexer->expects($this->atLeastOnce())->method('execute');
- $this->config->expects($this->atLeastOnce())->method('isEnabled')->willReturn(true);
- $this->typeList->expects($this->atLeastOnce())->method('invalidate');
- $price->expects($this->atLeastOnce())->method('getSku')->willReturn('simple');
+ $this->tierPricePersistence->expects($this->once())
+ ->method('update');
+ $this->priceIndexProcessor->expects($this->once())
+ ->method('reindexList')
+ ->with([2, 3]);
+ $price->expects($this->atLeastOnce())
+ ->method('getSku')
+ ->willReturn('simple');
+
$this->assertEmpty($this->tierPriceStorage->update([$price]));
}
@@ -237,35 +215,41 @@ public function testUpdate()
*/
public function testReplace()
{
- $price = $this->getMockBuilder(\Magento\Catalog\Api\Data\TierPriceInterface::class)->getMockForAbstractClass();
- $price->expects($this->atLeastOnce())->method('getSku')->willReturn('virtual');
- $result = $this->getMockBuilder(\Magento\Catalog\Model\Product\Price\Validation\Result::class)
- ->disableOriginalConstructor()
- ->getMock();
- $result->expects($this->atLeastOnce())->method('getFailedRowIds')->willReturn([]);
+ $price = $this->createMock(TierPriceInterface::class);
+ $price->expects($this->atLeastOnce())
+ ->method('getSku')
+ ->willReturn('virtual');
+ $result = $this->createMock(PriceValidationResult::class);
+ $result->expects($this->once())
+ ->method('getFailedRowIds')
+ ->willReturn([]);
$this->productIdLocator->expects($this->atLeastOnce())
->method('retrieveProductIdsBySkus')
->willReturn(['simple' => ['2' => 'simple'], 'virtual' => ['3' => 'virtual']]);
$this->tierPriceValidator
- ->expects($this->atLeastOnce())
+ ->expects($this->once())
->method('retrieveValidationResult')
->willReturn($result);
- $this->tierPriceFactory->expects($this->atLeastOnce())->method('createSkeleton')->willReturn(
- [
- 'row_id' => 3,
- 'all_groups' => 1,
- 'customer_group_id' => 0,
- 'qty' => 3,
- 'value' => 7,
- 'percentage_value' => null,
- 'website_id' => 0
- ]
- );
- $this->tierPricePersistence->expects($this->atLeastOnce())->method('replace');
- $this->priceIndexer->expects($this->atLeastOnce())->method('execute');
- $this->config->expects($this->atLeastOnce())->method('isEnabled')->willReturn(true);
- $this->typeList->expects($this->atLeastOnce())->method('invalidate');
+ $this->tierPriceFactory->expects($this->once())
+ ->method('createSkeleton')
+ ->willReturn(
+ [
+ 'entity_id' => 3,
+ 'all_groups' => 1,
+ 'customer_group_id' => 0,
+ 'qty' => 3,
+ 'value' => 7,
+ 'percentage_value' => null,
+ 'website_id' => 0
+ ]
+ );
+ $this->tierPricePersistence->expects($this->once())
+ ->method('replace');
+ $this->priceIndexProcessor->expects($this->once())
+ ->method('reindexList')
+ ->with([2, 3]);
+
$this->assertEmpty($this->tierPriceStorage->replace([$price]));
}
@@ -276,13 +260,15 @@ public function testReplace()
*/
public function testDelete()
{
- $price = $this->getMockBuilder(\Magento\Catalog\Api\Data\TierPriceInterface::class)->getMockForAbstractClass();
- $price->expects($this->atLeastOnce())->method('getSku')->willReturn('simple');
- $result = $this->getMockBuilder(\Magento\Catalog\Model\Product\Price\Validation\Result::class)
- ->disableOriginalConstructor()
- ->getMock();
- $result->expects($this->atLeastOnce())->method('getFailedRowIds')->willReturn([]);
- $this->tierPriceValidator->expects($this->atLeastOnce())
+ $price = $this->createMock(TierPriceInterface::class);
+ $price->expects($this->atLeastOnce())
+ ->method('getSku')
+ ->willReturn('simple');
+ $result = $this->createMock(PriceValidationResult::class);
+ $result->expects($this->once())
+ ->method('getFailedRowIds')
+ ->willReturn([]);
+ $this->tierPriceValidator->expects($this->once())
->method('retrieveValidationResult')
->willReturn($result);
$this->productIdLocator->expects($this->atLeastOnce())
@@ -294,7 +280,7 @@ public function testDelete()
[
[
'value_id' => 7,
- 'row_id' => 7,
+ 'entity_id' => 7,
'all_groups' => 1,
'customer_group_id' => 0,
'qty' => 5.0000,
@@ -304,21 +290,24 @@ public function testDelete()
]
]
);
- $this->tierPriceFactory->expects($this->atLeastOnce())->method('createSkeleton')->willReturn(
- [
- 'row_id' => 3,
- 'all_groups' => 1,
- 'customer_group_id' => 0,
- 'qty' => 3,
- 'value' => 7,
- 'percentage_value' => null,
- 'website_id' => 0
- ]
- );
- $this->tierPricePersistence->expects($this->atLeastOnce())->method('delete');
- $this->priceIndexer->expects($this->atLeastOnce())->method('execute');
- $this->config->expects($this->atLeastOnce())->method('isEnabled')->willReturn(true);
- $this->typeList->expects($this->atLeastOnce())->method('invalidate');
+ $this->tierPriceFactory->expects($this->once())
+ ->method('createSkeleton')->willReturn(
+ [
+ 'entity_id' => 3,
+ 'all_groups' => 1,
+ 'customer_group_id' => 0,
+ 'qty' => 3,
+ 'value' => 7,
+ 'percentage_value' => null,
+ 'website_id' => 0
+ ]
+ );
+ $this->tierPricePersistence->expects($this->once())
+ ->method('delete');
+ $this->priceIndexProcessor->expects($this->once())
+ ->method('reindexList')
+ ->with([2]);
+
$this->assertEmpty($this->tierPriceStorage->delete([$price]));
}
}
diff --git a/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php b/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php
new file mode 100644
index 0000000000000..c75a3541ba9c3
--- /dev/null
+++ b/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php
@@ -0,0 +1,100 @@
+eventManager = $eventManager;
+ $this->cacheContext = $cacheContext;
+ $this->appCache = $appCache;
+ }
+
+ /**
+ * Clean cache after full reindex.
+ *
+ * @param ActionInterface $subject
+ * @return void
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function afterExecuteFull(ActionInterface $subject)
+ {
+ $this->cleanCache();
+ }
+
+ /**
+ * Clean cache after reindexed list.
+ *
+ * @param ActionInterface $subject
+ * @return void
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function afterExecuteList(ActionInterface $subject)
+ {
+ $this->cleanCache();
+ }
+
+ /**
+ * Clean cache after reindexed row.
+ *
+ * @param ActionInterface $subject
+ * @return void
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function afterExecuteRow(ActionInterface $subject)
+ {
+ $this->cleanCache();
+ }
+
+ /**
+ * Clean cache.
+ *
+ * @return void
+ */
+ private function cleanCache()
+ {
+ $this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
+
+ $identities = $this->cacheContext->getIdentities();
+ if (!empty($identities)) {
+ $this->appCache->clean($identities);
+ }
+ }
+}
diff --git a/app/code/Magento/Indexer/etc/di.xml b/app/code/Magento/Indexer/etc/di.xml
index 76e7e7a46224b..9496f29cb1d87 100644
--- a/app/code/Magento/Indexer/etc/di.xml
+++ b/app/code/Magento/Indexer/etc/di.xml
@@ -67,4 +67,7 @@
Magento\Indexer\Model\Indexer
+
+
+
From a4f09b45dbaa3e42420922ef6befffeff9bdccb1 Mon Sep 17 00:00:00 2001
From: Dmytro Horytskyi
Date: Thu, 1 Aug 2019 13:56:01 -0500
Subject: [PATCH 02/17] MC-18833: Tier price API doesn't take into account
indexers mode
---
.../Magento/Catalog/Model/Product/Price/TierPriceStorage.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php b/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
index 6efff27fa2287..0c371a48fde96 100644
--- a/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
+++ b/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
@@ -218,10 +218,10 @@ private function retrieveAffectedIds(array $skus): array
$affectedIds = [];
foreach ($this->productIdLocator->retrieveProductIdsBySkus($skus) as $productId) {
- $affectedIds = array_merge($affectedIds, array_keys($productId));
+ $affectedIds[] = array_keys($productId);
}
- return array_unique($affectedIds);
+ return array_unique(array_merge(...$affectedIds));
}
/**
From 814c68a48d433ff8f73c63352618b8dcb0e38c33 Mon Sep 17 00:00:00 2001
From: Dmytro Horytskyi
Date: Fri, 2 Aug 2019 02:49:10 -0500
Subject: [PATCH 03/17] MC-18833: Tier price API doesn't take into account
indexers mode
---
.../Magento/Catalog/Model/Product/Price/TierPriceStorage.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php b/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
index 0c371a48fde96..b9e1a27e46e41 100644
--- a/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
+++ b/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
@@ -221,7 +221,7 @@ private function retrieveAffectedIds(array $skus): array
$affectedIds[] = array_keys($productId);
}
- return array_unique(array_merge(...$affectedIds));
+ return $affectedIds ? array_unique(array_merge(...$affectedIds)) : [];
}
/**
From 98272e90d737e2bb9dd54ca3e5f81737bf848bd6 Mon Sep 17 00:00:00 2001
From: Dmytro Horytskyi
Date: Fri, 2 Aug 2019 15:03:51 -0500
Subject: [PATCH 04/17] MC-18833: Tier price API doesn't take into account
indexers mode
---
.../Model/Product/Price/TierPriceStorage.php | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php b/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
index b9e1a27e46e41..36ef1826462b0 100644
--- a/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
+++ b/app/code/Magento/Catalog/Model/Product/Price/TierPriceStorage.php
@@ -79,10 +79,8 @@ public function __construct(
public function get(array $skus)
{
$skus = $this->tierPriceValidator->validateSkus($skus);
- $skuByIdLookup = $this->buildSkuByIdLookup($skus);
- $prices = $this->getExistingPrices($skuByIdLookup);
- return $prices;
+ return $this->getExistingPrices($skus);
}
/**
@@ -90,6 +88,7 @@ public function get(array $skus)
*/
public function update(array $prices)
{
+ $affectedIds = $this->retrieveAffectedProductIdsForPrices($prices);
$skus = array_unique(
array_map(
function (TierPriceInterface $price) {
@@ -98,13 +97,11 @@ function (TierPriceInterface $price) {
$prices
)
);
- $skuByIdLookup = $this->buildSkuByIdLookup($skus);
- $existingPrices = $this->getExistingPrices($skuByIdLookup, true);
- $result = $this->tierPriceValidator->retrieveValidationResult($prices, $existingPrices);
+ $result = $this->tierPriceValidator->retrieveValidationResult($prices, $this->getExistingPrices($skus, true));
$prices = $this->removeIncorrectPrices($prices, $result->getFailedRowIds());
$formattedPrices = $this->retrieveFormattedPrices($prices);
$this->tierPricePersistence->update($formattedPrices);
- $this->reindexPrices(array_keys($skuByIdLookup));
+ $this->reindexPrices($affectedIds);
return $result->getFailedItems();
}
@@ -142,16 +139,18 @@ public function delete(array $prices)
/**
* Get existing prices by SKUs.
*
- * @param array $skuByIdLookup
+ * @param array $skus
* @param bool $groupBySku [optional]
* @return array
*/
- private function getExistingPrices(array $skuByIdLookup, bool $groupBySku = false): array
+ private function getExistingPrices(array $skus, bool $groupBySku = false): array
{
- $rawPrices = $this->tierPricePersistence->get(array_keys($skuByIdLookup));
+ $ids = $this->retrieveAffectedIds($skus);
+ $rawPrices = $this->tierPricePersistence->get($ids);
$prices = [];
if ($rawPrices) {
$linkField = $this->tierPricePersistence->getEntityLinkField();
+ $skuByIdLookup = $this->buildSkuByIdLookup($skus);
foreach ($rawPrices as $rawPrice) {
$sku = $skuByIdLookup[$rawPrice[$linkField]];
$price = $this->tierPriceFactory->create($rawPrice, $sku);
From 417dd7756fd27f2b63020426bf5fe9a69eb173e0 Mon Sep 17 00:00:00 2001
From: Dmytro Horytskyi
Date: Mon, 5 Aug 2019 13:01:30 -0500
Subject: [PATCH 05/17] MC-18833: Tier price API doesn't take into account
indexers mode
---
app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php | 5 -----
1 file changed, 5 deletions(-)
diff --git a/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php b/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php
index c75a3541ba9c3..25b4ae286e332 100644
--- a/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php
+++ b/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php
@@ -91,10 +91,5 @@ public function afterExecuteRow(ActionInterface $subject)
private function cleanCache()
{
$this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
-
- $identities = $this->cacheContext->getIdentities();
- if (!empty($identities)) {
- $this->appCache->clean($identities);
- }
}
}
From 3121dfe97a5d4a18ae0d0ef27a9d32fd62e8da1f Mon Sep 17 00:00:00 2001
From: Dmytro Horytskyi
Date: Mon, 5 Aug 2019 13:02:11 -0500
Subject: [PATCH 06/17] MC-18833: Tier price API doesn't take into account
indexers mode
---
app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php b/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php
index 25b4ae286e332..4a5ea36a68a61 100644
--- a/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php
+++ b/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php
@@ -90,6 +90,9 @@ public function afterExecuteRow(ActionInterface $subject)
*/
private function cleanCache()
{
- $this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
+ $identities = $this->cacheContext->getIdentities();
+ if (!empty($identities)) {
+ $this->appCache->clean($identities);
+ }
}
}
From 7d3d37cb3b011f4eddb123ed50eef08520fba167 Mon Sep 17 00:00:00 2001
From: Dmytro Horytskyi
Date: Fri, 9 Aug 2019 14:22:59 -0500
Subject: [PATCH 07/17] MC-18833: Tier price API doesn't take into account
indexers mode
---
app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php | 2 ++
1 file changed, 2 insertions(+)
diff --git a/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php b/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php
index 4a5ea36a68a61..c75a3541ba9c3 100644
--- a/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php
+++ b/app/code/Magento/Indexer/Model/Indexer/CacheCleaner.php
@@ -90,6 +90,8 @@ public function afterExecuteRow(ActionInterface $subject)
*/
private function cleanCache()
{
+ $this->eventManager->dispatch('clean_cache_by_tags', ['object' => $this->cacheContext]);
+
$identities = $this->cacheContext->getIdentities();
if (!empty($identities)) {
$this->appCache->clean($identities);
From 0b47e429e64e36c048bcfd2df2b4c70fd59c4803 Mon Sep 17 00:00:00 2001
From: Oleksandr Iegorov
Date: Mon, 12 Aug 2019 12:56:47 -0500
Subject: [PATCH 08/17] MC-19090: Category Image from Gallery is not saved
---
.../Catalog/Model/Category/Attribute/Backend/Image.php | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
index 6a035a4681a54..073b1fa44a07e 100644
--- a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
+++ b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
@@ -125,7 +125,9 @@ public function beforeSave($object)
}
if ($imageName = $this->getUploadedImageName($value)) {
- $imageName = $this->checkUniqueImageName($imageName);
+ if (!$this->fileResidesOutsideCategoryDir($object->getData($attributeName))) {
+ $imageName = $this->checkUniqueImageName($imageName);
+ }
$object->setData($this->additionalData . $attributeName, $value);
$object->setData($attributeName, $imageName);
} elseif (!is_string($value)) {
From 5b2f43e3d95a2c6d4371ed4fd46c51a86907e8e4 Mon Sep 17 00:00:00 2001
From: Oleksandr Iegorov
Date: Mon, 12 Aug 2019 15:34:39 -0500
Subject: [PATCH 09/17] MC-19090: Category Image from Gallery is not saved
---
.../Category/Attribute/Backend/ImageTest.php | 18 +++++-------------
1 file changed, 5 insertions(+), 13 deletions(-)
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Backend/ImageTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Backend/ImageTest.php
index dc74cdfc642e3..a76ae5244076f 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Backend/ImageTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/Attribute/Backend/ImageTest.php
@@ -179,27 +179,19 @@ public function testBeforeSaveAttributeFileNameOutsideOfCategoryDir()
{
$model = $this->setUpModelForAfterSave();
$model->setAttribute($this->attribute);
-
- $mediaDirectoryMock = $this->createMock(WriteInterface::class);
- $this->filesystem->expects($this->once())
- ->method('getDirectoryWrite')
- ->with(DirectoryList::MEDIA)
- ->willReturn($mediaDirectoryMock);
+ $imagePath = '/pub/media/wysiwyg/test123.jpg';
$this->filesystem
- ->expects($this->once())
+ ->expects($this->exactly(2))
->method('getUri')
->with(DirectoryList::MEDIA)
->willReturn('pub/media');
- $mediaDirectoryMock->expects($this->once())
- ->method('getAbsolutePath')
- ->willReturn('/pub/media/wysiwyg/test123.jpg');
$object = new \Magento\Framework\DataObject(
[
'test_attribute' => [
[
'name' => 'test123.jpg',
- 'url' => '/pub/media/wysiwyg/test123.jpg',
+ 'url' => $imagePath,
],
],
]
@@ -207,9 +199,9 @@ public function testBeforeSaveAttributeFileNameOutsideOfCategoryDir()
$model->beforeSave($object);
- $this->assertEquals('test123.jpg', $object->getTestAttribute());
+ $this->assertEquals($imagePath, $object->getTestAttribute());
$this->assertEquals(
- [['name' => '/pub/media/wysiwyg/test123.jpg', 'url' => '/pub/media/wysiwyg/test123.jpg']],
+ [['name' => $imagePath, 'url' => $imagePath]],
$object->getData('_additional_data_test_attribute')
);
}
From b19440d0539e2dbe95ba92b8ffd743f2893997cb Mon Sep 17 00:00:00 2001
From: Oleksandr Iegorov
Date: Thu, 15 Aug 2019 10:20:19 -0500
Subject: [PATCH 10/17] MC-19090: Category Image from Gallery is not saved
---
.../Catalog/Model/Category/Attribute/Backend/Image.php | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
index 073b1fa44a07e..07fd1a50edc97 100644
--- a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
+++ b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
@@ -125,7 +125,7 @@ public function beforeSave($object)
}
if ($imageName = $this->getUploadedImageName($value)) {
- if (!$this->fileResidesOutsideCategoryDir($object->getData($attributeName))) {
+ if (!$this->fileResidesOutsideCategoryDir($value)) {
$imageName = $this->checkUniqueImageName($imageName);
}
$object->setData($this->additionalData . $attributeName, $value);
@@ -178,13 +178,15 @@ private function fileResidesOutsideCategoryDir($value)
}
$fileUrl = ltrim($value[0]['url'], '/');
- $baseMediaDir = $this->_filesystem->getUri(DirectoryList::MEDIA);
+ $imageUploader = $this->getImageUploader();
+ $baseMediaDir = $this->_filesystem->getUri(DirectoryList::MEDIA)
+ . DIRECTORY_SEPARATOR . $imageUploader->getBasePath();
if (!$baseMediaDir) {
return false;
}
- return strpos($fileUrl, $baseMediaDir) === 0;
+ return strpos($fileUrl, $baseMediaDir) === false;
}
/**
From c7293b05ec6224d2525c9c9d55e8d2138a53cbcf Mon Sep 17 00:00:00 2001
From: Oleksandr Iegorov
Date: Thu, 15 Aug 2019 17:48:36 -0500
Subject: [PATCH 11/17] MC-19090: Category Image from Gallery is not saved
---
.../Catalog/Model/Category/Attribute/Backend/Image.php | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
index 07fd1a50edc97..32b5d066193ca 100644
--- a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
+++ b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
@@ -178,15 +178,13 @@ private function fileResidesOutsideCategoryDir($value)
}
$fileUrl = ltrim($value[0]['url'], '/');
- $imageUploader = $this->getImageUploader();
- $baseMediaDir = $this->_filesystem->getUri(DirectoryList::MEDIA)
- . DIRECTORY_SEPARATOR . $imageUploader->getBasePath();
+ $baseMediaDir = $this->_filesystem->getUri(DirectoryList::MEDIA);
if (!$baseMediaDir) {
return false;
}
- return strpos($fileUrl, $baseMediaDir) === false;
+ return strpos($fileUrl, $baseMediaDir) !== false;
}
/**
From 60c78c1489ed1fb92000af44ed19a02e20f28203 Mon Sep 17 00:00:00 2001
From: Oleksandr Iegorov
Date: Thu, 15 Aug 2019 17:50:07 -0500
Subject: [PATCH 12/17] MC-19090: Category Image from Gallery is not saved
---
.../Catalog/Model/Category/FileInfo.php | 41 +++++++++++++++++--
1 file changed, 38 insertions(+), 3 deletions(-)
diff --git a/app/code/Magento/Catalog/Model/Category/FileInfo.php b/app/code/Magento/Catalog/Model/Category/FileInfo.php
index d77f472c6be90..0973db756df87 100644
--- a/app/code/Magento/Catalog/Model/Category/FileInfo.php
+++ b/app/code/Magento/Catalog/Model/Category/FileInfo.php
@@ -10,6 +10,8 @@
use Magento\Framework\Filesystem;
use Magento\Framework\Filesystem\Directory\WriteInterface;
use Magento\Framework\Filesystem\Directory\ReadInterface;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Store\Model\StoreManagerInterface;
/**
* Class FileInfo
@@ -48,16 +50,26 @@ class FileInfo
*/
private $pubDirectory;
+ /**
+ * Store manager
+ *
+ * @var \Magento\Store\Model\StoreManagerInterface
+ */
+ private $storeManager;
+
/**
* @param Filesystem $filesystem
* @param Mime $mime
+ * @param StoreManagerInterface $storeManager
*/
public function __construct(
Filesystem $filesystem,
- Mime $mime
+ Mime $mime,
+ StoreManagerInterface $storeManager
) {
$this->filesystem = $filesystem;
$this->mime = $mime;
+ $this->storeManager = $storeManager;
}
/**
@@ -152,7 +164,8 @@ public function isExist($fileName)
*/
private function getFilePath($fileName)
{
- $filePath = ltrim($fileName, '/');
+ $filePath = $this->removeStorePath($fileName);
+ $filePath = ltrim($filePath, '/');
$mediaDirectoryRelativeSubpath = $this->getMediaDirectoryPathRelativeToBaseDirectoryPath($filePath);
$isFileNameBeginsWithMediaDirectoryPath = $this->isBeginsWithMediaDirectoryPath($fileName);
@@ -177,7 +190,8 @@ private function getFilePath($fileName)
*/
public function isBeginsWithMediaDirectoryPath($fileName)
{
- $filePath = ltrim($fileName, '/');
+ $filePath = $this->removeStorePath($fileName);
+ $filePath = ltrim($filePath, '/');
$mediaDirectoryRelativeSubpath = $this->getMediaDirectoryPathRelativeToBaseDirectoryPath($filePath);
$isFileNameBeginsWithMediaDirectoryPath = strpos($filePath, (string) $mediaDirectoryRelativeSubpath) === 0;
@@ -185,6 +199,27 @@ public function isBeginsWithMediaDirectoryPath($fileName)
return $isFileNameBeginsWithMediaDirectoryPath;
}
+ /**
+ * Clean store path in case if it's exists
+ *
+ * @param string $path
+ * @return string
+ */
+ private function removeStorePath(string $path): string
+ {
+ $result = $path;
+ try {
+ $storeUrl = $this->storeManager->getStore()->getUrl();
+ } catch (NoSuchEntityException $e) {
+ return $result;
+ }
+ $path = parse_url($path, PHP_URL_PATH);
+ $storePath = parse_url($storeUrl, PHP_URL_PATH);
+ $result = ltrim($path, $storePath);
+
+ return $result;
+ }
+
/**
* Get media directory subpath relative to base directory path
*
From 43e454de018e7c0b54773f0d88cf8412fd4a5356 Mon Sep 17 00:00:00 2001
From: Oleksandr Iegorov
Date: Fri, 16 Aug 2019 10:28:13 -0500
Subject: [PATCH 13/17] MC-19090: Category Image from Gallery is not saved
---
.../Category/Attribute/Backend/Image.php | 1 +
.../Test/Unit/Model/Category/FileInfoTest.php | 25 ++++++++++++++++++-
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
index 32b5d066193ca..4af2df37dea0d 100644
--- a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
+++ b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
@@ -121,6 +121,7 @@ public function beforeSave($object)
if ($this->fileResidesOutsideCategoryDir($value)) {
// use relative path for image attribute so we know it's outside of category dir when we fetch it
+ $value[0]['url'] = parse_url($value[0]['url'], PHP_URL_PATH);
$value[0]['name'] = $value[0]['url'];
}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php
index 6c6a69ec39c85..71f5ca33d1303 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php
@@ -13,6 +13,8 @@
use Magento\Framework\Filesystem\Directory\WriteInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
+use Magento\Store\Model\StoreManagerInterface;
+use Magento\Store\Model\Store;
/**
* Test for Magento\Catalog\Model\Category\FileInfo class.
@@ -44,6 +46,16 @@ class FileInfoTest extends TestCase
*/
private $pubDirectory;
+ /**
+ * @var StoreManagerInterface|MockObject
+ */
+ private $storeManager;
+
+ /**
+ * @var Store|MockObject
+ */
+ private $store;
+
/**
* @var FileInfo
*/
@@ -60,6 +72,16 @@ protected function setUp()
$this->pubDirectory = $pubDirectory = $this->getMockBuilder(ReadInterface::class)
->getMockForAbstractClass();
+ $this->store = $this->getMockBuilder(Store::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $this->storeManager = $this->getMockBuilder(StoreManagerInterface::class)
+ ->setMethods(['getStore'])
+ ->getMockForAbstractClass();
+ $this->storeManager->expects($this->any())
+ ->method('getStore')
+ ->willReturn($this->store);
+
$this->filesystem = $this->getMockBuilder(Filesystem::class)
->disableOriginalConstructor()
->getMock();
@@ -94,7 +116,8 @@ function ($arg) use ($baseDirectory, $pubDirectory) {
$this->model = new FileInfo(
$this->filesystem,
- $this->mime
+ $this->mime,
+ $this->storeManager
);
}
From 8072515c720734c42071c1b78b44c007a0731238 Mon Sep 17 00:00:00 2001
From: Oleksandr Iegorov
Date: Fri, 16 Aug 2019 10:51:39 -0500
Subject: [PATCH 14/17] MC-19090: Category Image from Gallery is not saved
---
.../Magento/Catalog/Model/Category/Attribute/Backend/Image.php | 1 +
app/code/Magento/Catalog/Model/Category/FileInfo.php | 2 ++
2 files changed, 3 insertions(+)
diff --git a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
index 4af2df37dea0d..4880214e5c6a6 100644
--- a/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
+++ b/app/code/Magento/Catalog/Model/Category/Attribute/Backend/Image.php
@@ -121,6 +121,7 @@ public function beforeSave($object)
if ($this->fileResidesOutsideCategoryDir($value)) {
// use relative path for image attribute so we know it's outside of category dir when we fetch it
+ // phpcs:ignore Magento2.Functions.DiscouragedFunction
$value[0]['url'] = parse_url($value[0]['url'], PHP_URL_PATH);
$value[0]['name'] = $value[0]['url'];
}
diff --git a/app/code/Magento/Catalog/Model/Category/FileInfo.php b/app/code/Magento/Catalog/Model/Category/FileInfo.php
index 0973db756df87..66a251f7ed448 100644
--- a/app/code/Magento/Catalog/Model/Category/FileInfo.php
+++ b/app/code/Magento/Catalog/Model/Category/FileInfo.php
@@ -213,7 +213,9 @@ private function removeStorePath(string $path): string
} catch (NoSuchEntityException $e) {
return $result;
}
+ // phpcs:ignore Magento2.Functions.DiscouragedFunction
$path = parse_url($path, PHP_URL_PATH);
+ // phpcs:ignore Magento2.Functions.DiscouragedFunction
$storePath = parse_url($storeUrl, PHP_URL_PATH);
$result = ltrim($path, $storePath);
From 053123c290fac941009bfcfa0aade416439177a5 Mon Sep 17 00:00:00 2001
From: Roman Lytvynenko
Date: Fri, 16 Aug 2019 16:59:50 -0500
Subject: [PATCH 15/17] MC-19238: Subscribe to Order Status RSS gives error
page
---
.../Magento/Sales/Model/Rss/OrderStatus.php | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/app/code/Magento/Sales/Model/Rss/OrderStatus.php b/app/code/Magento/Sales/Model/Rss/OrderStatus.php
index c3c4456c6b7ca..e03cbbee1b50c 100644
--- a/app/code/Magento/Sales/Model/Rss/OrderStatus.php
+++ b/app/code/Magento/Sales/Model/Rss/OrderStatus.php
@@ -217,11 +217,12 @@ protected function getEntries()
if ($type && $type != 'order') {
$urlAppend = $type;
}
- $type = __(ucwords($type));
- $title = __('Details for %1 #%2', $type, $result['increment_id']);
- $description = '' . __('Notified Date: %1', $this->localeDate->formatDate($result['created_at']))
+ $type = __(ucwords($type))->render();
+ $title = __('Details for %1 #%2', $type, $result['increment_id'])->render();
+ $description = '
'
+ . __('Notified Date: %1', $this->localeDate->formatDate($result['created_at']))->render()
. '
'
- . __('Comment: %1
', $result['comment']) . '
';
+ . __('Comment: %1
', $result['comment'])->render() . '
';
$url = $this->urlBuilder->getUrl(
'sales/order/' . $urlAppend,
['order_id' => $this->order->getId()]
@@ -233,10 +234,10 @@ protected function getEntries()
'Order #%1 created at %2',
$this->order->getIncrementId(),
$this->localeDate->formatDate($this->order->getCreatedAt())
- );
+ )->render();
$url = $this->urlBuilder->getUrl('sales/order/view', ['order_id' => $this->order->getId()]);
- $description = '' . __('Current Status: %1
', $this->order->getStatusLabel()) .
- __('Total: %1
', $this->order->formatPrice($this->order->getGrandTotal())) . '
';
+ $description = '' . __('Current Status: %1
', $this->order->getStatusLabel())->render() .
+ __('Total: %1
', $this->order->formatPrice($this->order->getGrandTotal()))->render() . '
';
$entries[] = ['title' => $title, 'link' => $url, 'description' => $description];
@@ -250,7 +251,7 @@ protected function getEntries()
*/
protected function getHeader()
{
- $title = __('Order # %1 Notification(s)', $this->order->getIncrementId());
+ $title = __('Order # %1 Notification(s)', $this->order->getIncrementId())->render();
$newUrl = $this->urlBuilder->getUrl('sales/order/view', ['order_id' => $this->order->getId()]);
return ['title' => $title, 'description' => $title, 'link' => $newUrl, 'charset' => 'UTF-8'];
From eec9c26a44f3a62ef426f9ac326ff36269a77d7b Mon Sep 17 00:00:00 2001
From: Dmytro Horytskyi
Date: Mon, 19 Aug 2019 08:21:01 +0000
Subject: [PATCH 16/17] MC-19407: Number of the rows increase very fast in
changelog table
---
lib/internal/Magento/Framework/Mview/View/Subscription.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/internal/Magento/Framework/Mview/View/Subscription.php b/lib/internal/Magento/Framework/Mview/View/Subscription.php
index 67dff1a2cc5db..ddfa39f0a089f 100644
--- a/lib/internal/Magento/Framework/Mview/View/Subscription.php
+++ b/lib/internal/Magento/Framework/Mview/View/Subscription.php
@@ -214,7 +214,7 @@ protected function buildStatement($event, $changelog)
$columns = [];
foreach ($columnNames as $columnName) {
$columns[] = sprintf(
- 'NEW.%1$s <=> OLD.%1$s',
+ 'NOT(NEW.%1$s <=> OLD.%1$s)',
$this->connection->quoteIdentifier($columnName)
);
}
From 629ccde3e6cea99b79e53b9acd8459d758ce27be Mon Sep 17 00:00:00 2001
From: Oleksandr Iegorov
Date: Wed, 21 Aug 2019 11:32:38 -0500
Subject: [PATCH 17/17] MC-19090: Category Image from Gallery is not saved
---
app/code/Magento/Catalog/Model/Category/FileInfo.php | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/app/code/Magento/Catalog/Model/Category/FileInfo.php b/app/code/Magento/Catalog/Model/Category/FileInfo.php
index 66a251f7ed448..76b6a2e75d0ea 100644
--- a/app/code/Magento/Catalog/Model/Category/FileInfo.php
+++ b/app/code/Magento/Catalog/Model/Category/FileInfo.php
@@ -209,7 +209,7 @@ private function removeStorePath(string $path): string
{
$result = $path;
try {
- $storeUrl = $this->storeManager->getStore()->getUrl();
+ $storeUrl = $this->storeManager->getStore()->getBaseUrl();
} catch (NoSuchEntityException $e) {
return $result;
}
@@ -217,8 +217,9 @@ private function removeStorePath(string $path): string
$path = parse_url($path, PHP_URL_PATH);
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$storePath = parse_url($storeUrl, PHP_URL_PATH);
- $result = ltrim($path, $storePath);
+ $storePath = rtrim($storePath, '/');
+ $result = preg_replace('/^' . preg_quote($storePath, '/') . '/', '', $path);
return $result;
}