Skip to content

Commit 68cc5a4

Browse files
committed
#10208: Fix getImage method when sending product alert email
- Reduced Coupling between Objects
1 parent 75a769b commit 68cc5a4

File tree

4 files changed

+201
-110
lines changed

4 files changed

+201
-110
lines changed

app/code/Magento/ProductAlert/Block/Email/AbstractEmail.php

Lines changed: 17 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,21 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6-
7-
// @codingStandardsIgnoreFile
8-
96
namespace Magento\ProductAlert\Block\Email;
107

118
use Magento\Framework\Pricing\PriceCurrencyInterface;
9+
use Magento\Framework\App\ObjectManager;
10+
use Magento\ProductAlert\Block\Product\ImageProvider;
1211

1312
/**
1413
* Product Alert Abstract Email Block
15-
*
16-
* @author Magento Core Team <core@magentocommerce.com>
1714
*/
1815
abstract class AbstractEmail extends \Magento\Framework\View\Element\Template
1916
{
2017
/**
2118
* Product collection array
2219
*
23-
* @var array
20+
* @var \Magento\Catalog\Model\Product[]
2421
*/
2522
protected $_products = [];
2623

@@ -42,44 +39,43 @@ abstract class AbstractEmail extends \Magento\Framework\View\Element\Template
4239
protected $priceCurrency;
4340

4441
/**
45-
* @var \Magento\Catalog\Helper\Image
42+
* @var \Magento\Catalog\Block\Product\ImageBuilder
4643
*/
4744
protected $imageBuilder;
4845

4946
/**
50-
* @var \Magento\Store\Model\App\Emulation
47+
* @var ImageProvider
5148
*/
52-
private $appEmulation;
49+
private $imageProvider;
5350

5451
/**
5552
* @param \Magento\Framework\View\Element\Template\Context $context
5653
* @param \Magento\Framework\Filter\Input\MaliciousCode $maliciousCode
5754
* @param PriceCurrencyInterface $priceCurrency
5855
* @param \Magento\Catalog\Block\Product\ImageBuilder $imageBuilder
5956
* @param array $data
60-
* @param \Magento\Store\Model\App\Emulation $appEmulation
57+
* @param ImageProvider $imageProvider
6158
*/
6259
public function __construct(
6360
\Magento\Framework\View\Element\Template\Context $context,
6461
\Magento\Framework\Filter\Input\MaliciousCode $maliciousCode,
6562
PriceCurrencyInterface $priceCurrency,
6663
\Magento\Catalog\Block\Product\ImageBuilder $imageBuilder,
6764
array $data = [],
68-
\Magento\Store\Model\App\Emulation $appEmulation = null
65+
ImageProvider $imageProvider = null
6966
) {
7067
$this->imageBuilder = $imageBuilder;
7168
$this->priceCurrency = $priceCurrency;
7269
$this->_maliciousCode = $maliciousCode;
73-
$this->appEmulation = $appEmulation
74-
?: \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Store\Model\App\Emulation::class);
70+
$this->imageProvider = $imageProvider ?: ObjectManager::getInstance()->get(ImageProvider::class);
7571

7672
parent::__construct($context, $data);
7773
}
7874

79-
/**
75+
/**
8076
* Filter malicious code before insert content to email
8177
*
82-
* @param string|array $content
78+
* @param string|array $content
8379
* @return string|array
8480
*/
8581
public function getFilteredContent($content)
@@ -114,7 +110,7 @@ public function setStore($store)
114110
*/
115111
public function getStore()
116112
{
117-
if (is_null($this->_store)) {
113+
if ($this->_store === null) {
118114
$this->_store = $this->_storeManager->getStore();
119115
}
120116
return $this->_store;
@@ -124,9 +120,9 @@ public function getStore()
124120
* Convert price from default currency to current currency
125121
*
126122
* @param float $price
127-
* @param boolean $format Format price to currency format
128-
* @param boolean $includeContainer Enclose into <span class="price"><span>
129-
* @return float
123+
* @param bool $format Format price to currency format
124+
* @param bool $includeContainer Enclose into <span class="price"><span>
125+
* @return float|string
130126
*/
131127
public function formatPrice($price, $format = true, $includeContainer = true)
132128
{
@@ -159,7 +155,7 @@ public function addProduct(\Magento\Catalog\Model\Product $product)
159155
/**
160156
* Retrieve product collection array
161157
*
162-
* @return array
158+
* @return \Magento\Catalog\Model\Product[]
163159
*/
164160
public function getProducts()
165161
{
@@ -228,28 +224,9 @@ public function getProductPriceHtml(
228224
* @param string $imageId
229225
* @param array $attributes
230226
* @return \Magento\Catalog\Block\Product\Image
231-
* @throws \Exception
232227
*/
233228
public function getImage($product, $imageId, $attributes = [])
234229
{
235-
$this->appEmulation->startEnvironmentEmulation(
236-
$this->_storeManager->getStore()->getId(),
237-
\Magento\Framework\App\Area::AREA_FRONTEND,
238-
true
239-
);
240-
241-
try {
242-
$image = $this->imageBuilder->setProduct($product)
243-
->setImageId($imageId)
244-
->setAttributes($attributes)
245-
->create();
246-
} catch (\Exception $e) {
247-
$this->appEmulation->stopEnvironmentEmulation();
248-
throw $e;
249-
}
250-
251-
$this->appEmulation->stopEnvironmentEmulation();
252-
253-
return $image;
230+
return $this->imageProvider->getImage($product, $imageId, $attributes);
254231
}
255232
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\ProductAlert\Block\Product;
7+
8+
use Magento\Store\Model\App\Emulation;
9+
use Magento\Catalog\Block\Product\ImageBuilder;
10+
use Magento\Catalog\Model\Product;
11+
use Magento\Store\Model\StoreManagerInterface;
12+
use Magento\Framework\App\Area;
13+
use Magento\Catalog\Block\Product\Image;
14+
15+
/**
16+
* Provides product image to be used in the Product Alert Email.
17+
*/
18+
class ImageProvider
19+
{
20+
/**
21+
* @var ImageBuilder
22+
*/
23+
private $imageBuilder;
24+
25+
/**
26+
* @var StoreManagerInterface
27+
*/
28+
private $storeManager;
29+
30+
/**
31+
* @var Emulation
32+
*/
33+
private $appEmulation;
34+
35+
/**
36+
* @param ImageBuilder $imageBuilder
37+
* @param StoreManagerInterface $storeManager
38+
* @param Emulation $appEmulation
39+
*/
40+
public function __construct(
41+
ImageBuilder $imageBuilder,
42+
StoreManagerInterface $storeManager,
43+
Emulation $appEmulation
44+
) {
45+
$this->imageBuilder = $imageBuilder;
46+
$this->storeManager = $storeManager;
47+
$this->appEmulation = $appEmulation;
48+
}
49+
50+
/**
51+
* @param Product $product
52+
* @param string $imageId
53+
* @param array $attributes
54+
* @return Image
55+
* @throws \Exception
56+
*/
57+
public function getImage(Product $product, $imageId, $attributes = [])
58+
{
59+
$storeId = $this->storeManager->getStore()->getId();
60+
$this->appEmulation->startEnvironmentEmulation($storeId, Area::AREA_FRONTEND, true);
61+
62+
try {
63+
$image = $this->imageBuilder->setProduct($product)
64+
->setImageId($imageId)
65+
->setAttributes($attributes)
66+
->create();
67+
} catch (\Exception $exception) {
68+
$this->appEmulation->stopEnvironmentEmulation();
69+
throw $exception;
70+
}
71+
72+
$this->appEmulation->stopEnvironmentEmulation();
73+
return $image;
74+
}
75+
}

app/code/Magento/ProductAlert/Test/Unit/Block/Email/StockTest.php

Lines changed: 6 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,10 @@ class StockTest extends \PHPUnit_Framework_TestCase
2424
* @var \Magento\Catalog\Block\Product\ImageBuilder|\PHPUnit_Framework_MockObject_MockObject
2525
*/
2626
protected $imageBuilder;
27-
28-
/**
29-
* @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject
30-
*/
31-
private $storeManagerMock;
32-
3327
/**
34-
* @var \Magento\Store\Model\App\Emulation|\PHPUnit_Framework_MockObject_MockObject
28+
* @var \Magento\ProductAlert\Block\Product\ImageProvider|\PHPUnit_Framework_MockObject_MockObject
3529
*/
36-
private $appEmulationMock;
30+
protected $imageProviderMock;
3731

3832
protected function setUp()
3933
{
@@ -49,25 +43,17 @@ protected function setUp()
4943
$this->imageBuilder = $this->getMockBuilder(\Magento\Catalog\Block\Product\ImageBuilder::class)
5044
->disableOriginalConstructor()
5145
->getMock();
52-
$this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)
53-
->disableOriginalConstructor()
54-
->getMock();
55-
$this->appEmulationMock = $this->getMockBuilder(\Magento\Store\Model\App\Emulation::class)
56-
->disableOriginalConstructor()
57-
->getMock();
5846

59-
$contextMock = $this->getMockBuilder(\Magento\Framework\View\Element\Template\Context::class)
47+
$this->imageProviderMock = $this->getMockBuilder(\Magento\ProductAlert\Block\Product\ImageProvider::class)
6048
->disableOriginalConstructor()
6149
->getMock();
62-
$contextMock->expects($this->any())->method('getStoreManager')->willReturn($this->storeManagerMock);
6350

6451
$this->_block = $objectManager->getObject(
6552
\Magento\ProductAlert\Block\Email\Stock::class,
6653
[
6754
'maliciousCode' => $this->_filter,
6855
'imageBuilder' => $this->imageBuilder,
69-
'context' => $contextMock,
70-
'appEmulation' => $this->appEmulationMock
56+
'imageProvider' => $this->imageProviderMock
7157
]
7258
);
7359
}
@@ -100,65 +86,15 @@ public function testGetImage()
10086
$productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
10187
->disableOriginalConstructor()
10288
->getMock();
103-
104-
$imageMock = $this->getMockBuilder(\Magento\Catalog\Block\Product\Image::class)
105-
->disableOriginalConstructor()
106-
->getMock();
107-
108-
$storeMock = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)
89+
$productImageMock = $this->getMockBuilder(\Magento\Catalog\Block\Product\Image::class)
10990
->disableOriginalConstructor()
11091
->getMock();
11192

112-
$this->appEmulationMock->expects($this->once())->method('startEnvironmentEmulation');
113-
$this->storeManagerMock->expects($this->atLeastOnce())->method('getStore')->willReturn($storeMock);
114-
$storeMock->expects($this->atLeastOnce())->method('getId')->willReturn(42);
115-
$this->imageBuilder->expects($this->once())
116-
->method('setProduct')
117-
->with($productMock)
118-
->willReturnSelf();
119-
$this->imageBuilder->expects($this->once())
120-
->method('setImageId')
121-
->with($imageId)
122-
->willReturnSelf();
123-
$this->imageBuilder->expects($this->once())
124-
->method('setAttributes')
125-
->with($attributes)
126-
->willReturnSelf();
127-
$this->imageBuilder->expects($this->once())
128-
->method('create')
129-
->willReturn($imageMock);
130-
$this->appEmulationMock->expects($this->once())->method('stopEnvironmentEmulation');
93+
$this->imageProviderMock->expects($this->atLeastOnce())->method('getImage')->willReturn($productImageMock);
13194

13295
$this->assertInstanceOf(
13396
\Magento\Catalog\Block\Product\Image::class,
13497
$this->_block->getImage($productMock, $imageId, $attributes)
13598
);
13699
}
137-
138-
/**
139-
* Test that app emulation stops when exception occurs.
140-
*
141-
* @expectedException \Exception
142-
* @expectedExceptionMessage Image Builder Exception
143-
*/
144-
public function testGetImageThrowsAnException()
145-
{
146-
$productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class)
147-
->disableOriginalConstructor()
148-
->getMock();
149-
$storeMock = $this->getMockBuilder(\Magento\Store\Api\Data\StoreInterface::class)
150-
->disableOriginalConstructor()
151-
->getMock();
152-
153-
$this->appEmulationMock->expects($this->once())->method('startEnvironmentEmulation');
154-
$this->storeManagerMock->expects($this->atLeastOnce())->method('getStore')->willReturn($storeMock);
155-
$storeMock->expects($this->atLeastOnce())->method('getId')->willReturn(42);
156-
157-
$this->imageBuilder->expects($this->once())
158-
->method('setProduct')
159-
->willThrowException(new \Exception("Image Builder Exception"));
160-
$this->appEmulationMock->expects($this->once())->method('stopEnvironmentEmulation');
161-
162-
$this->_block->getImage($productMock, 1, []);
163-
}
164100
}

0 commit comments

Comments
 (0)