Skip to content

Commit 3a0c345

Browse files
committed
Merge remote-tracking branch 'main-ce/develop' into MAGETWO-58299
2 parents 58e2db2 + 0aff845 commit 3a0c345

File tree

91 files changed

+3987
-256
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+3987
-256
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ protected function processDeletedImages($product, array &$images)
2929
if (!empty($image['removed'])) {
3030
if (!empty($image['value_id']) && !isset($picturesInOtherStores[$image['file']])) {
3131
$recordsToDelete[] = $image['value_id'];
32-
$filesToDelete[] = ltrim($image['file'], '/');
32+
// only delete physical files if they are not used by any other products
33+
if (!$this->resourceModel->countImageUses($image['file']) > 1) {
34+
$filesToDelete[] = ltrim($image['file'], '/');
35+
}
3336
}
3437
}
3538
}

app/code/Magento/Catalog/Model/Product/Pricing/Renderer/SalableResolver.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ class SalableResolver implements SalableResolverInterface
1919
*/
2020
public function isSalable(\Magento\Framework\Pricing\SaleableInterface $salableItem)
2121
{
22-
return $salableItem->getCanShowPrice() !== false && $salableItem->isSalable();
22+
return $salableItem->getCanShowPrice() !== false;
2323
}
2424
}

app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,16 +2195,22 @@ public function addMediaGalleryData()
21952195
$linkField = $this->getProductEntityMetadata()->getLinkField();
21962196
$items = $this->getItems();
21972197

2198-
$select->where('entity.' . $linkField . ' IN (?)', array_map(function ($item) {
2199-
return $item->getId();
2200-
}, $items));
2201-
2198+
$select->where(
2199+
'entity.' . $linkField . ' IN (?)',
2200+
array_map(
2201+
function ($item) use ($linkField) {
2202+
return $item->getData($linkField);
2203+
},
2204+
$items
2205+
)
2206+
);
22022207
foreach ($this->getConnection()->fetchAll($select) as $row) {
22032208
$mediaGalleries[$row[$linkField]][] = $row;
22042209
}
22052210

22062211
foreach ($items as $item) {
2207-
$mediaEntries = isset($mediaGalleries[$item->getId()]) ? $mediaGalleries[$item->getId()] : [];
2212+
$mediaEntries = isset($mediaGalleries[$item->getData($linkField)]) ?
2213+
$mediaGalleries[$item->getData($linkField)] : [];
22082214
$this->getGalleryReadHandler()->addMediaDataToProduct($item, $mediaEntries);
22092215
}
22102216

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,4 +449,21 @@ public function getProductImages($product, $storeIds)
449449

450450
return $this->getConnection()->fetchAll($select);
451451
}
452+
453+
/**
454+
* Counts uses of this image.
455+
*
456+
* @param string $image
457+
* @return int
458+
*/
459+
public function countImageUses($image)
460+
{
461+
$select = $this->getConnection()->select()
462+
->from([$this->getMainTableAlias() => $this->getMainTable()])
463+
->where(
464+
'value = ?',
465+
$image
466+
);
467+
return count($this->getConnection()->fetchAll($select));
468+
}
452469
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Catalog\Pricing\Price;
8+
9+
use Magento\Framework\Pricing\SaleableInterface;
10+
use Magento\Framework\Pricing\Amount\AmountInterface;
11+
12+
/**
13+
* Interface define methods which control display of "As low as" price
14+
*/
15+
interface MinimalPriceCalculatorInterface
16+
{
17+
/**
18+
* Get raw value for "as low as" price
19+
*
20+
* @param SaleableInterface $saleableItem
21+
* @return float|null
22+
*/
23+
public function getValue(SaleableInterface $saleableItem);
24+
25+
/**
26+
* Return structured object with "as low as" value
27+
*
28+
* @param SaleableInterface $saleableItem
29+
* @return AmountInterface|null
30+
*/
31+
public function getAmount(SaleableInterface $saleableItem);
32+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Catalog\Pricing\Price;
8+
9+
use Magento\Framework\Pricing\SaleableInterface;
10+
use Magento\Framework\Pricing\Adjustment\CalculatorInterface;
11+
use Magento\Framework\Pricing\Amount\AmountInterface;
12+
13+
/**
14+
* As Low As shows minimal value of Tier Prices
15+
*/
16+
class MinimalTierPriceCalculator implements MinimalPriceCalculatorInterface
17+
{
18+
/**
19+
* @var CalculatorInterface
20+
*/
21+
private $calculator;
22+
23+
/**
24+
* @param CalculatorInterface $calculator
25+
*/
26+
public function __construct(CalculatorInterface $calculator)
27+
{
28+
$this->calculator = $calculator;
29+
}
30+
31+
/**
32+
* Get raw value of "as low as" as a minimal among tier prices
33+
* {@inheritdoc}
34+
*/
35+
public function getValue(SaleableInterface $saleableItem)
36+
{
37+
/** @var TierPrice $price */
38+
$price = $saleableItem->getPriceInfo()->getPrice(TierPrice::PRICE_CODE);
39+
$tierPriceList = $price->getTierPriceList();
40+
41+
$tierPrices = [];
42+
foreach ($tierPriceList as $tierPrice) {
43+
/** @var AmountInterface $price */
44+
$price = $tierPrice['price'];
45+
$tierPrices[] = $price->getValue();
46+
}
47+
48+
return $tierPrices ? min($tierPrices) : null;
49+
}
50+
51+
/**
52+
* Return calculated amount object that keeps "as low as" value
53+
* {@inheritdoc}
54+
*/
55+
public function getAmount(SaleableInterface $saleableItem)
56+
{
57+
$value = $this->getValue($saleableItem);
58+
59+
return $value === null
60+
? null
61+
: $this->calculator->getAmount($value, $saleableItem);
62+
}
63+
}

app/code/Magento/Catalog/Pricing/Render/FinalPriceBox.php

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
namespace Magento\Catalog\Pricing\Render;
88

99
use Magento\Catalog\Pricing\Price;
10-
use Magento\Framework\Pricing\Render;
1110
use Magento\Framework\Pricing\Render\PriceBox as BasePriceBox;
1211
use Magento\Msrp\Pricing\Price\MsrpPrice;
1312
use Magento\Catalog\Model\Product\Pricing\Renderer\SalableResolverInterface;
1413
use Magento\Framework\View\Element\Template\Context;
1514
use Magento\Framework\Pricing\SaleableInterface;
1615
use Magento\Framework\Pricing\Price\PriceInterface;
1716
use Magento\Framework\Pricing\Render\RendererPool;
17+
use Magento\Framework\App\ObjectManager;
18+
use Magento\Catalog\Pricing\Price\MinimalPriceCalculatorInterface;
1819

1920
/**
2021
* Class for final_price rendering
@@ -29,25 +30,33 @@ class FinalPriceBox extends BasePriceBox
2930
*/
3031
private $salableResolver;
3132

33+
/**
34+
* @var MinimalPriceCalculatorInterface
35+
*/
36+
private $minimalPriceCalculator;
37+
3238
/**
3339
* @param Context $context
3440
* @param SaleableInterface $saleableItem
3541
* @param PriceInterface $price
3642
* @param RendererPool $rendererPool
3743
* @param array $data
3844
* @param SalableResolverInterface $salableResolver
45+
* @param MinimalPriceCalculatorInterface $minimalPriceCalculator
3946
*/
4047
public function __construct(
4148
Context $context,
4249
SaleableInterface $saleableItem,
4350
PriceInterface $price,
4451
RendererPool $rendererPool,
4552
array $data = [],
46-
SalableResolverInterface $salableResolver = null
53+
SalableResolverInterface $salableResolver = null,
54+
MinimalPriceCalculatorInterface $minimalPriceCalculator = null
4755
) {
4856
parent::__construct($context, $saleableItem, $price, $rendererPool, $data);
49-
$this->salableResolver = $salableResolver ?: \Magento\Framework\App\ObjectManager::getInstance()
50-
->get(SalableResolverInterface::class);
57+
$this->salableResolver = $salableResolver ?: ObjectManager::getInstance()->get(SalableResolverInterface::class);
58+
$this->minimalPriceCalculator = $minimalPriceCalculator
59+
?: ObjectManager::getInstance()->get(MinimalPriceCalculatorInterface::class);
5160
}
5261

5362
/**
@@ -117,11 +126,15 @@ protected function wrapResult($html)
117126
*/
118127
public function renderAmountMinimal()
119128
{
120-
/** @var \Magento\Catalog\Pricing\Price\FinalPrice $price */
121-
$price = $this->getPriceType(\Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE);
122129
$id = $this->getPriceId() ? $this->getPriceId() : 'product-minimal-price-' . $this->getSaleableItem()->getId();
130+
131+
$amount = $this->minimalPriceCalculator->getAmount($this->getSaleableItem());
132+
if ($amount === null) {
133+
return '';
134+
}
135+
123136
return $this->renderAmount(
124-
$price->getMinimalPrice(),
137+
$amount,
125138
[
126139
'display_label' => __('As low as'),
127140
'price_id' => $id,
@@ -150,13 +163,15 @@ public function hasSpecialPrice()
150163
*/
151164
public function showMinimalPrice()
152165
{
166+
$minTierPrice = $this->minimalPriceCalculator->getValue($this->getSaleableItem());
167+
153168
/** @var Price\FinalPrice $finalPrice */
154169
$finalPrice = $this->getPriceType(Price\FinalPrice::PRICE_CODE);
155170
$finalPriceValue = $finalPrice->getAmount()->getValue();
156-
$minimalPriceAValue = $finalPrice->getMinimalPrice()->getValue();
171+
157172
return $this->getDisplayMinimalPrice()
158-
&& $minimalPriceAValue
159-
&& $minimalPriceAValue < $finalPriceValue;
173+
&& $minTierPrice !== null
174+
&& $minTierPrice < $finalPriceValue;
160175
}
161176

162177
/**

app/code/Magento/Catalog/Test/Unit/Model/Product/Pricing/Renderer/SalableResolverTest.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ protected function setUp()
2222
{
2323
$this->product = $this->getMock(
2424
\Magento\Catalog\Model\Product::class,
25-
['__wakeup', 'getCanShowPrice', 'isSalable'],
25+
['__wakeup', 'getCanShowPrice'],
2626
[],
2727
'',
2828
false
@@ -40,8 +40,6 @@ public function testSalableItem()
4040
->method('getCanShowPrice')
4141
->willReturn(true);
4242

43-
$this->product->expects($this->any())->method('isSalable')->willReturn(true);
44-
4543
$result = $this->object->isSalable($this->product);
4644
$this->assertTrue($result);
4745
}
@@ -50,9 +48,7 @@ public function testNotSalableItem()
5048
{
5149
$this->product->expects($this->any())
5250
->method('getCanShowPrice')
53-
->willReturn(true);
54-
55-
$this->product->expects($this->any())->method('isSalable')->willReturn(false);
51+
->willReturn(false);
5652

5753
$result = $this->object->isSalable($this->product);
5854
$this->assertFalse($result);

app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CollectionTest.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,11 +224,12 @@ public function testAddProductCategoriesFilter()
224224
public function testAddMediaGalleryData()
225225
{
226226
$attributeId = 42;
227-
$itemId = 4242;
228-
$linkField = 'entity_id';
229-
$mediaGalleriesMock = [[$linkField => $itemId]];
227+
$rowId = 4;
228+
$linkField = 'row_id';
229+
$mediaGalleriesMock = [[$linkField => $rowId]];
230230
$itemMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
231231
->disableOriginalConstructor()
232+
->setMethods(['getData'])
232233
->getMock();
233234
$attributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute\AbstractAttribute::class)
234235
->disableOriginalConstructor()
@@ -248,13 +249,13 @@ public function testAddMediaGalleryData()
248249
$this->galleryResourceMock->expects($this->once())->method('createBatchBaseSelect')->willReturn($selectMock);
249250
$attributeMock->expects($this->once())->method('getAttributeId')->willReturn($attributeId);
250251
$this->entityMock->expects($this->once())->method('getAttribute')->willReturn($attributeMock);
251-
$itemMock->expects($this->atLeastOnce())->method('getId')->willReturn($itemId);
252-
$selectMock->expects($this->once())->method('where')->with('entity.' . $linkField . ' IN (?)', [$itemId]);
252+
$itemMock->expects($this->atLeastOnce())->method('getData')->willReturn($rowId);
253+
$selectMock->expects($this->once())->method('where')->with('entity.' . $linkField . ' IN (?)', [$rowId]);
253254
$this->metadataPoolMock->expects($this->once())->method('getMetadata')->willReturn($metadataMock);
254255
$metadataMock->expects($this->once())->method('getLinkField')->willReturn($linkField);
255256

256257
$this->connectionMock->expects($this->once())->method('fetchAll')->with($selectMock)->willReturn(
257-
[['entity_id' => $itemId]]
258+
[['row_id' => $rowId]]
258259
);
259260
$this->galleryReadHandlerMock->expects($this->once())->method('addMediaDataToProduct')
260261
->with($itemMock, $mediaGalleriesMock);

app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/GalleryTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,4 +443,33 @@ public function testDeleteGalleryValueInStore()
443443

444444
$this->resource->deleteGalleryValueInStore($valueId, $entityId, $storeId);
445445
}
446+
447+
public function testCountImageUses()
448+
{
449+
$results = [
450+
[
451+
'value_id' => '1',
452+
'attribute_id' => 90,
453+
'value' => '/d/o/download_7.jpg',
454+
'media_type' => 'image',
455+
'disabled' => '0',
456+
],
457+
];
458+
459+
$this->connection->expects($this->once())->method('select')->will($this->returnValue($this->select));
460+
$this->select->expects($this->at(0))->method('from')->with(
461+
[
462+
'main' => 'table',
463+
],
464+
'*'
465+
)->willReturnSelf();
466+
$this->select->expects($this->at(1))->method('where')->with(
467+
'value = ?',
468+
1
469+
)->willReturnSelf();
470+
$this->connection->expects($this->once())->method('fetchAll')
471+
->with($this->select)
472+
->willReturn($results);
473+
$this->assertEquals($this->resource->countImageUses(1), count($results));
474+
}
446475
}

0 commit comments

Comments
 (0)