Skip to content

Commit b9c13fd

Browse files
authored
Merge pull request #6136 from magento-mpi/MPI-2020-09-14
[MPI] Bug Fixes
2 parents 70223c0 + 9c5d1be commit b9c13fd

File tree

35 files changed

+1477
-119
lines changed

35 files changed

+1477
-119
lines changed

app/code/Magento/Catalog/Model/Product/Gallery/CreateHandler.php

+12-1
Original file line numberDiff line numberDiff line change
@@ -596,10 +596,21 @@ private function canRemoveImage(ProductInterface $product, string $imageFile) :b
596596
$canRemoveImage = true;
597597
$gallery = $this->getImagesForAllStores($product);
598598
$storeId = $product->getStoreId();
599+
$storeIds = [];
600+
$storeIds[] = 0;
601+
$websiteIds = array_map('intval', $product->getWebsiteIds() ?? []);
602+
foreach ($this->storeManager->getStores() as $store) {
603+
if (in_array((int) $store->getWebsiteId(), $websiteIds, true)) {
604+
$storeIds[] = (int) $store->getId();
605+
}
606+
}
599607

600608
if (!empty($gallery)) {
601609
foreach ($gallery as $image) {
602-
if ($image['filepath'] === $imageFile && (int) $image['store_id'] !== $storeId) {
610+
if (in_array((int) $image['store_id'], $storeIds)
611+
&& $image['filepath'] === $imageFile
612+
&& (int) $image['store_id'] !== $storeId
613+
) {
603614
$canRemoveImage = false;
604615
}
605616
}

app/code/Magento/Catalog/Model/Product/Gallery/UpdateHandler.php

+89-5
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,69 @@
55
*/
66
namespace Magento\Catalog\Model\Product\Gallery;
77

8+
use Magento\Catalog\Api\Data\ProductInterface;
9+
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
10+
use Magento\Catalog\Model\Product;
11+
use Magento\Catalog\Model\Product\Media\Config;
812
use Magento\Catalog\Model\ResourceModel\Product\Gallery;
9-
use Magento\Framework\EntityManager\Operation\ExtensionInterface;
13+
use Magento\Eav\Model\ResourceModel\AttributeValue;
14+
use Magento\Framework\App\ObjectManager;
15+
use Magento\Framework\EntityManager\MetadataPool;
16+
use Magento\Framework\Filesystem;
17+
use Magento\Framework\Json\Helper\Data;
18+
use Magento\MediaStorage\Helper\File\Storage\Database;
19+
use Magento\Store\Model\Store;
20+
use Magento\Store\Model\StoreManagerInterface;
1021

1122
/**
1223
* Update handler for catalog product gallery.
1324
*
1425
* @api
1526
* @since 101.0.0
27+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1628
*/
17-
class UpdateHandler extends \Magento\Catalog\Model\Product\Gallery\CreateHandler
29+
class UpdateHandler extends CreateHandler
1830
{
31+
/**
32+
* @var AttributeValue
33+
*/
34+
private $attributeValue;
35+
36+
/**
37+
* @param MetadataPool $metadataPool
38+
* @param ProductAttributeRepositoryInterface $attributeRepository
39+
* @param Gallery $resourceModel
40+
* @param Data $jsonHelper
41+
* @param Config $mediaConfig
42+
* @param Filesystem $filesystem
43+
* @param Database $fileStorageDb
44+
* @param StoreManagerInterface|null $storeManager
45+
* @param AttributeValue|null $attributeValue
46+
*/
47+
public function __construct(
48+
MetadataPool $metadataPool,
49+
ProductAttributeRepositoryInterface $attributeRepository,
50+
Gallery $resourceModel,
51+
Data $jsonHelper,
52+
Config $mediaConfig,
53+
Filesystem $filesystem,
54+
Database $fileStorageDb,
55+
StoreManagerInterface $storeManager = null,
56+
?AttributeValue $attributeValue = null
57+
) {
58+
parent::__construct(
59+
$metadataPool,
60+
$attributeRepository,
61+
$resourceModel,
62+
$jsonHelper,
63+
$mediaConfig,
64+
$filesystem,
65+
$fileStorageDb,
66+
$storeManager
67+
);
68+
$this->attributeValue = $attributeValue ?: ObjectManager::getInstance()->get(AttributeValue::class);
69+
}
70+
1971
/**
2072
* @inheritdoc
2173
*
@@ -26,6 +78,7 @@ protected function processDeletedImages($product, array &$images)
2678
$filesToDelete = [];
2779
$recordsToDelete = [];
2880
$picturesInOtherStores = [];
81+
$imagesToDelete = [];
2982

3083
foreach ($this->resourceModel->getProductImages($product, $this->extractStoreIds($product)) as $image) {
3184
$picturesInOtherStores[$image['filepath']] = true;
@@ -38,6 +91,7 @@ protected function processDeletedImages($product, array &$images)
3891
continue;
3992
}
4093
$recordsToDelete[] = $image['value_id'];
94+
$imagesToDelete[] = $image['file'];
4195
$catalogPath = $this->mediaConfig->getBaseMediaPath();
4296
$isFile = $this->mediaDirectory->isFile($catalogPath . $image['file']);
4397
// only delete physical files if they are not used by any other products and if this file exist
@@ -48,8 +102,8 @@ protected function processDeletedImages($product, array &$images)
48102
}
49103
}
50104

105+
$this->deleteMediaAttributeValues($product, $imagesToDelete);
51106
$this->resourceModel->deleteGallery($recordsToDelete);
52-
53107
$this->removeDeletedImages($filesToDelete);
54108
}
55109

@@ -94,14 +148,14 @@ protected function processNewImage($product, array &$image)
94148
/**
95149
* Retrieve store ids from product.
96150
*
97-
* @param \Magento\Catalog\Model\Product $product
151+
* @param Product $product
98152
* @return array
99153
* @since 101.0.0
100154
*/
101155
protected function extractStoreIds($product)
102156
{
103157
$storeIds = $product->getStoreIds();
104-
$storeIds[] = \Magento\Store\Model\Store::DEFAULT_STORE_ID;
158+
$storeIds[] = Store::DEFAULT_STORE_ID;
105159

106160
// Removing current storeId.
107161
$storeIds = array_flip($storeIds);
@@ -125,5 +179,35 @@ protected function removeDeletedImages(array $files)
125179
foreach ($files as $filePath) {
126180
$this->mediaDirectory->delete($catalogPath . '/' . $filePath);
127181
}
182+
return null;
183+
}
184+
185+
/**
186+
* Delete media attributes values for given images
187+
*
188+
* @param Product $product
189+
* @param string[] $images
190+
*/
191+
private function deleteMediaAttributeValues(Product $product, array $images): void
192+
{
193+
if ($images) {
194+
$values = $this->attributeValue->getValues(
195+
ProductInterface::class,
196+
$product->getData($this->metadata->getLinkField()),
197+
$this->mediaConfig->getMediaAttributeCodes()
198+
);
199+
$valuesToDelete = [];
200+
foreach ($values as $value) {
201+
if (in_array($value['value'], $images, true)) {
202+
$valuesToDelete[] = $value;
203+
}
204+
}
205+
if ($valuesToDelete) {
206+
$this->attributeValue->deleteValues(
207+
ProductInterface::class,
208+
$valuesToDelete
209+
);
210+
}
211+
}
128212
}
129213
}

app/code/Magento/Catalog/view/adminhtml/web/js/product-gallery.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,17 @@ define([
188188
_addItem: function (event, imageData) {
189189
var count = this.element.find(this.options.imageSelector).length,
190190
element,
191-
imgElement;
191+
imgElement,
192+
position = count + 1,
193+
lastElement = this.element.find(this.options.imageSelector + ':last');
192194

195+
if (lastElement.length === 1) {
196+
position = parseInt(lastElement.data('imageData').position || count, 10) + 1;
197+
}
193198
imageData = $.extend({
194199
'file_id': imageData['value_id'] ? imageData['value_id'] : Math.random().toString(33).substr(2, 18),
195200
'disabled': imageData.disabled ? imageData.disabled : 0,
196-
'position': count + 1,
201+
'position': position,
197202
sizeLabel: bytesToSize(imageData.size)
198203
}, imageData);
199204

@@ -206,7 +211,7 @@ define([
206211
if (count === 0) {
207212
element.prependTo(this.element);
208213
} else {
209-
element.insertAfter(this.element.find(this.options.imageSelector + ':last'));
214+
element.insertAfter(lastElement);
210215
}
211216

212217
if (!this.options.initialized &&
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogInventory\Model\ResourceModel;
9+
10+
use Magento\CatalogInventory\Api\Data\StockStatusInterface;
11+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
12+
use Magento\CatalogInventory\Model\Stock;
13+
use Magento\Framework\App\ResourceConnection;
14+
use Magento\Framework\DB\Select;
15+
16+
/**
17+
* Generic in-stock status filter
18+
*/
19+
class StockStatusFilter implements StockStatusFilterInterface
20+
{
21+
private const TABLE_NAME = 'cataloginventory_stock_status';
22+
/**
23+
* @var ResourceConnection
24+
*/
25+
private $resource;
26+
27+
/**
28+
* @var StockConfigurationInterface
29+
*/
30+
private $stockConfiguration;
31+
32+
/**
33+
* @param ResourceConnection $resource
34+
* @param StockConfigurationInterface $stockConfiguration
35+
*/
36+
public function __construct(
37+
ResourceConnection $resource,
38+
StockConfigurationInterface $stockConfiguration
39+
) {
40+
$this->resource = $resource;
41+
$this->stockConfiguration = $stockConfiguration;
42+
}
43+
44+
/**
45+
* @inheritDoc
46+
*/
47+
public function execute(
48+
Select $select,
49+
string $productTableAlias,
50+
string $stockStatusTableAlias = self::TABLE_ALIAS,
51+
?int $websiteId = null
52+
): Select {
53+
$stockStatusTable = $this->resource->getTableName(self::TABLE_NAME);
54+
$joinCondition = [
55+
"{$stockStatusTableAlias}.product_id = {$productTableAlias}.entity_id",
56+
$select->getConnection()->quoteInto(
57+
"{$stockStatusTableAlias}.website_id = ?",
58+
$this->stockConfiguration->getDefaultScopeId()
59+
),
60+
$select->getConnection()->quoteInto(
61+
"{$stockStatusTableAlias}.stock_id = ?",
62+
Stock::DEFAULT_STOCK_ID
63+
)
64+
];
65+
$select->join(
66+
[$stockStatusTableAlias => $stockStatusTable],
67+
implode(' AND ', $joinCondition),
68+
[]
69+
);
70+
$select->where("{$stockStatusTableAlias}.stock_status = ?", StockStatusInterface::STATUS_IN_STOCK);
71+
72+
return $select;
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\CatalogInventory\Model\ResourceModel;
9+
10+
use Magento\Framework\DB\Select;
11+
12+
/**
13+
* In stock status filter interface.
14+
*/
15+
interface StockStatusFilterInterface
16+
{
17+
public const TABLE_ALIAS = 'stock_status';
18+
19+
/**
20+
* Add in-stock status constraint to the select.
21+
*
22+
* @param Select $select
23+
* @param string $productTableAliasAlias
24+
* @param string $stockStatusTableAlias
25+
* @param int|null $websiteId
26+
* @return Select
27+
*/
28+
public function execute(
29+
Select $select,
30+
string $productTableAliasAlias,
31+
string $stockStatusTableAlias = self::TABLE_ALIAS,
32+
?int $websiteId = null
33+
): Select;
34+
}

app/code/Magento/CatalogInventory/etc/di.xml

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<preference for="Magento\CatalogInventory\Model\Spi\StockStateProviderInterface" type="Magento\CatalogInventory\Model\StockStateProvider" />
3333

3434
<preference for="Magento\CatalogInventory\Model\ResourceModel\QtyCounterInterface" type="Magento\CatalogInventory\Model\ResourceModel\Stock" />
35+
<preference for="Magento\CatalogInventory\Model\ResourceModel\StockStatusFilterInterface" type="Magento\CatalogInventory\Model\ResourceModel\StockStatusFilter" />
3536
<type name="Magento\Catalog\Model\Product\Attribute\Repository">
3637
<plugin name="filterCustomAttribute" type="Magento\CatalogInventory\Model\Plugin\FilterCustomAttribute" />
3738
</type>

app/code/Magento/Checkout/Model/Session.php

+5-1
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ public function getQuote()
291291
}
292292
} else {
293293
$quote->setIsCheckoutCart(true);
294+
$quote->setCustomerIsGuest(1);
294295
$this->_eventManager->dispatch('checkout_quote_init', ['quote' => $quote]);
295296
}
296297
}
@@ -382,8 +383,10 @@ public function loadCustomerQuote()
382383

383384
if ($customerQuote->getId() && $this->getQuoteId() != $customerQuote->getId()) {
384385
if ($this->getQuoteId()) {
386+
$quote = $this->getQuote();
387+
$quote->setCustomerIsGuest(0);
385388
$this->quoteRepository->save(
386-
$customerQuote->merge($this->getQuote())->collectTotals()
389+
$customerQuote->merge($quote)->collectTotals()
387390
);
388391
$newQuote = $this->quoteRepository->get($customerQuote->getId());
389392
$this->quoteRepository->save(
@@ -402,6 +405,7 @@ public function loadCustomerQuote()
402405
$this->getQuote()->getBillingAddress();
403406
$this->getQuote()->getShippingAddress();
404407
$this->getQuote()->setCustomer($this->_customerSession->getCustomerDataObject())
408+
->setCustomerIsGuest(0)
405409
->setTotalsCollectedFlag(false)
406410
->collectTotals();
407411
$this->quoteRepository->save($this->getQuote());

0 commit comments

Comments
 (0)