Skip to content

Commit cef1abf

Browse files
committed
MAGETWO-62915: [Backport] - [Github] Directive values are not quote-escaped #3860 - for 2.0
1 parent 54d4e70 commit cef1abf

File tree

6 files changed

+551
-17
lines changed

6 files changed

+551
-17
lines changed

app/code/Magento/CatalogWidget/Block/Product/Widget/Conditions.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,19 @@ public function __construct(
8282
protected function _construct()
8383
{
8484
$widget = $this->registry->registry('current_widget_instance');
85+
8586
if ($widget) {
8687
$widgetParameters = $widget->getWidgetParameters();
87-
if (isset($widgetParameters['conditions'])) {
88-
$this->rule->loadPost($widgetParameters);
88+
} else {
89+
$widgetOptions = $this->getLayout()->getBlock('wysiwyg_widget.options');
90+
if ($widgetOptions) {
91+
$widgetParameters = $widgetOptions->getWidgetValues();
8992
}
9093
}
94+
95+
if (isset($widgetParameters['conditions'])) {
96+
$this->rule->loadPost($widgetParameters);
97+
}
9198
}
9299

93100
/**
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\CatalogWidget\Test\Unit\Block\Product\Widget;
7+
8+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
9+
use Magento\CatalogWidget\Block\Product\Widget\Conditions;
10+
use Magento\Framework\Registry;
11+
use Magento\Backend\Block\Template\Context;
12+
use Magento\CatalogWidget\Model\Rule;
13+
use Magento\Framework\View\LayoutInterface;
14+
use Magento\Framework\View\Element\BlockInterface;
15+
16+
/**
17+
* Test class for \Magento\CatalogWidget\Block\Product\Widget\Conditions
18+
*/
19+
class ConditionsTest extends \PHPUnit_Framework_TestCase
20+
{
21+
/**
22+
* @var ObjectManagerHelper
23+
*/
24+
private $objectManagerHelper;
25+
26+
/**
27+
* @var Registry|\PHPUnit_Framework_MockObject_MockObject
28+
*/
29+
private $registryMock;
30+
31+
/**
32+
* @var Context|\PHPUnit_Framework_MockObject_MockObject
33+
*/
34+
private $contextMock;
35+
36+
/**
37+
* @var Rule|\PHPUnit_Framework_MockObject_MockObject
38+
*/
39+
protected $ruleMock;
40+
41+
/**
42+
* @var LayoutInterface|\PHPUnit_Framework_MockObject_MockObject
43+
*/
44+
private $layoutMock;
45+
46+
/**
47+
* @var BlockInterface|\PHPUnit_Framework_MockObject_MockObject
48+
*/
49+
private $blockMock;
50+
51+
protected function setUp()
52+
{
53+
$this->objectManagerHelper = new ObjectManagerHelper($this);
54+
$this->ruleMock = $this->getMockBuilder(Rule::class)
55+
->disableOriginalConstructor()
56+
->getMock();
57+
$this->registryMock = $this->getMockBuilder(Registry::class)
58+
->disableOriginalConstructor()
59+
->getMock();
60+
$this->layoutMock = $this->getMockForAbstractClass(LayoutInterface::class);
61+
$this->blockMock = $this->getMockBuilder(BlockInterface::class)
62+
->setMethods(['getWidgetValues'])
63+
->getMockForAbstractClass();
64+
$this->contextMock = $this->getMockBuilder(Context::class)
65+
->disableOriginalConstructor()
66+
->getMock();
67+
$this->contextMock->expects($this->once())
68+
->method('getLayout')
69+
->willReturn($this->layoutMock);
70+
}
71+
72+
public function testConstructWithEmptyData()
73+
{
74+
$this->registryMock->expects($this->once())
75+
->method('registry')
76+
->with('current_widget_instance')
77+
->willReturn(null);
78+
$this->layoutMock->expects($this->once())
79+
->method('getBlock')
80+
->with('wysiwyg_widget.options')
81+
->willReturn(null);
82+
$this->blockMock->expects($this->never())
83+
->method('getWidgetValues');
84+
$this->ruleMock->expects($this->never())
85+
->method('loadPost');
86+
87+
$this->objectManagerHelper->getObject(
88+
Conditions::class,
89+
[
90+
'context' => $this->contextMock,
91+
'registry' => $this->registryMock,
92+
'rule' => $this->ruleMock,
93+
]
94+
);
95+
}
96+
97+
public function testConstructWithWidgetInstance()
98+
{
99+
$widgetParams = ['conditions' => 'some conditions'];
100+
101+
/** @var \Magento\Widget\Model\Widget\Instance|\PHPUnit_Framework_MockObject_MockObject $widgetMock */
102+
$widgetMock = $this->getMockBuilder(\Magento\Widget\Model\Widget\Instance::class)
103+
->disableOriginalConstructor()
104+
->getMock();
105+
$widgetMock->expects($this->once())
106+
->method('getWidgetParameters')
107+
->willReturn($widgetParams);
108+
109+
$this->layoutMock->expects($this->never())
110+
->method('getBlock');
111+
$this->blockMock->expects($this->never())
112+
->method('getWidgetValues');
113+
$this->registryMock->expects($this->once())
114+
->method('registry')
115+
->with('current_widget_instance')
116+
->willReturn($widgetMock);
117+
$this->ruleMock->expects($this->once())
118+
->method('loadPost')
119+
->with($widgetParams)
120+
->willReturnSelf();
121+
122+
$this->objectManagerHelper->getObject(
123+
Conditions::class,
124+
[
125+
'context' => $this->contextMock,
126+
'registry' => $this->registryMock,
127+
'rule' => $this->ruleMock,
128+
]
129+
);
130+
}
131+
132+
public function testConstructWithParamsFromBlock()
133+
{
134+
$widgetParams = ['conditions' => 'some conditions'];
135+
136+
$this->registryMock->expects($this->once())
137+
->method('registry')
138+
->with('current_widget_instance')
139+
->willReturn(null);
140+
$this->layoutMock->expects($this->once())
141+
->method('getBlock')
142+
->with('wysiwyg_widget.options')
143+
->willReturn($this->blockMock);
144+
$this->blockMock->expects($this->once())
145+
->method('getWidgetValues')
146+
->willReturn($widgetParams);
147+
$this->ruleMock->expects($this->once())
148+
->method('loadPost')
149+
->with($widgetParams)
150+
->willReturnSelf();
151+
152+
$this->objectManagerHelper->getObject(
153+
Conditions::class,
154+
[
155+
'context' => $this->contextMock,
156+
'registry' => $this->registryMock,
157+
'rule' => $this->ruleMock,
158+
]
159+
);
160+
}
161+
}

app/code/Magento/Widget/Controller/Adminhtml/Widget/LoadOptions.php

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,21 @@
44
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
55
* See COPYING.txt for license details.
66
*/
7+
78
namespace Magento\Widget\Controller\Adminhtml\Widget;
89

10+
use Magento\Framework\App\ObjectManager;
11+
12+
/**
13+
* Load widget options
14+
*/
915
class LoadOptions extends \Magento\Backend\App\Action
1016
{
17+
/**
18+
* @var \Magento\Widget\Helper\Conditions
19+
*/
20+
private $conditionsHelper;
21+
1122
/**
1223
* Ajax responder for loading plugin options form
1324
*
@@ -17,14 +28,22 @@ public function execute()
1728
{
1829
try {
1930
$this->_view->loadLayout();
20-
if ($paramsJson = $this->getRequest()->getParam('widget')) {
21-
$request = $this->_objectManager->get('Magento\Framework\Json\Helper\Data')->jsonDecode($paramsJson);
31+
$paramsJson = $this->getRequest()->getParam('widget');
32+
33+
if ($paramsJson) {
34+
$request = $this->_objectManager->get(\Magento\Framework\Json\Helper\Data::class)
35+
->jsonDecode($paramsJson);
2236
if (is_array($request)) {
2337
$optionsBlock = $this->_view->getLayout()->getBlock('wysiwyg_widget.options');
2438
if (isset($request['widget_type'])) {
2539
$optionsBlock->setWidgetType($request['widget_type']);
2640
}
2741
if (isset($request['values'])) {
42+
$request['values'] = array_map('htmlspecialchars_decode', $request['values']);
43+
if (isset($request['values']['conditions_encoded'])) {
44+
$request['values']['conditions'] =
45+
$this->getConditionsHelper()->decode($request['values']['conditions_encoded']);
46+
}
2847
$optionsBlock->setWidgetValues($request['values']);
2948
}
3049
}
@@ -33,8 +52,21 @@ public function execute()
3352
} catch (\Magento\Framework\Exception\LocalizedException $e) {
3453
$result = ['error' => true, 'message' => $e->getMessage()];
3554
$this->getResponse()->representJson(
36-
$this->_objectManager->get('Magento\Framework\Json\Helper\Data')->jsonEncode($result)
55+
$this->_objectManager->get(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($result)
3756
);
3857
}
3958
}
59+
60+
/**
61+
* @return \Magento\Widget\Helper\Conditions
62+
* @deprecated
63+
*/
64+
private function getConditionsHelper()
65+
{
66+
if (!$this->conditionsHelper) {
67+
$this->conditionsHelper = ObjectManager::getInstance()->get(\Magento\Widget\Helper\Conditions::class);
68+
}
69+
70+
return $this->conditionsHelper;
71+
}
4072
}

app/code/Magento/Widget/Model/Widget.php

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
/**
99
* Widget model for different purposes
10+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1011
*/
1112
class Widget
1213
{
@@ -50,6 +51,11 @@ class Widget
5051
*/
5152
protected $conditionsHelper;
5253

54+
/**
55+
* @var \Magento\Framework\Math\Random
56+
*/
57+
private $mathRandom;
58+
5359
/**
5460
* @param \Magento\Framework\Escaper $escaper
5561
* @param \Magento\Widget\Model\Config\Data $dataStorage
@@ -74,6 +80,21 @@ public function __construct(
7480
$this->conditionsHelper = $conditionsHelper;
7581
}
7682

83+
/**
84+
* @return \Magento\Framework\Math\Random
85+
*
86+
* @deprecated
87+
*/
88+
private function getMathRandom()
89+
{
90+
if ($this->mathRandom === null) {
91+
$this->mathRandom = \Magento\Framework\App\ObjectManager::getInstance()
92+
->get(\Magento\Framework\Math\Random::class);
93+
}
94+
95+
return $this->mathRandom;
96+
}
97+
7798
/**
7899
* Return widget config based on its class type
79100
*
@@ -294,9 +315,12 @@ public function getWidgetDeclaration($type, $params = [], $asIs = true)
294315
}
295316
}
296317
if ($value) {
297-
$directive .= sprintf(' %s="%s"', $name, $value);
318+
$directive .= sprintf(' %s="%s"', $name, $this->escaper->escapeQuote($value));
298319
}
299320
}
321+
322+
$directive .= $this->getWidgetPageVarName($params);
323+
300324
$directive .= '}}';
301325

302326
if ($asIs) {
@@ -309,9 +333,29 @@ public function getWidgetDeclaration($type, $params = [], $asIs = true)
309333
$this->getPlaceholderImageUrl($type),
310334
$this->escaper->escapeUrl($directive)
311335
);
336+
312337
return $html;
313338
}
314339

340+
/**
341+
* @param array $params
342+
* @return string
343+
* @throws \Magento\Framework\Exception\LocalizedException
344+
*/
345+
private function getWidgetPageVarName($params = [])
346+
{
347+
$pageVarName = '';
348+
if (array_key_exists('show_pager', $params) && (bool)$params['show_pager']) {
349+
$pageVarName = sprintf(
350+
' %s="%s"',
351+
'page_var_name',
352+
'p' . $this->getMathRandom()->getRandomString(5, \Magento\Framework\Math\Random::CHARS_LOWERS)
353+
);
354+
}
355+
356+
return $pageVarName;
357+
}
358+
315359
/**
316360
* Get image URL of WYSIWYG placeholder image
317361
*

0 commit comments

Comments
 (0)