Skip to content

Commit ae3d3df

Browse files
fix widget with special char page tittle
1 parent f55eeb4 commit ae3d3df

File tree

2 files changed

+85
-117
lines changed

2 files changed

+85
-117
lines changed

app/code/Magento/Widget/Block/Adminhtml/Widget/Options.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ public function addFields()
136136
* @return \Magento\Framework\Data\Form\Element\AbstractElement
137137
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
138138
* @SuppressWarnings(PHPMD.NPathComplexity)
139-
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
140139
*/
141140
protected function _addField($parameter)
142141
{
@@ -159,10 +158,6 @@ protected function _addField($parameter)
159158
$data['value'] = $parameter->getValue();
160159
}
161160

162-
if ($parameter->getType() == 'text' && $data['value'] != '') {
163-
$data['value'] = $this->_widget->decodeReservedChars($data['value']);
164-
}
165-
166161
//prepare unique id value
167162
if ($fieldName == 'unique_id' && $data['value'] == '') {
168163
$data['value'] = hash('sha256', microtime(1));

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

Lines changed: 85 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@
55
*/
66
namespace Magento\Widget\Model;
77

8+
use Magento\Framework\App\Cache\Type\Config;
9+
use Magento\Framework\DataObject;
10+
use Magento\Framework\Escaper;
11+
use Magento\Framework\Math\Random;
12+
use Magento\Framework\View\Asset\Repository;
13+
use Magento\Framework\View\Asset\Source;
14+
use Magento\Framework\View\FileSystem;
15+
use Magento\Widget\Helper\Conditions;
16+
use Magento\Widget\Model\Config\Data;
17+
818
/**
919
* Widget model for different purposes
1020
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -15,32 +25,32 @@
1525
class Widget
1626
{
1727
/**
18-
* @var \Magento\Widget\Model\Config\Data
28+
* @var Data
1929
*/
2030
protected $dataStorage;
2131

2232
/**
23-
* @var \Magento\Framework\App\Cache\Type\Config
33+
* @var Config
2434
*/
2535
protected $configCacheType;
2636

2737
/**
28-
* @var \Magento\Framework\View\Asset\Repository
38+
* @var Repository
2939
*/
3040
protected $assetRepo;
3141

3242
/**
33-
* @var \Magento\Framework\View\Asset\Source
43+
* @var Source
3444
*/
3545
protected $assetSource;
3646

3747
/**
38-
* @var \Magento\Framework\View\FileSystem
48+
* @var FileSystem
3949
*/
4050
protected $viewFileSystem;
4151

4252
/**
43-
* @var \Magento\Framework\Escaper
53+
* @var Escaper
4454
*/
4555
protected $escaper;
4656

@@ -50,30 +60,35 @@ class Widget
5060
protected $widgetsArray = [];
5161

5262
/**
53-
* @var \Magento\Widget\Helper\Conditions
63+
* @var Conditions
5464
*/
5565
protected $conditionsHelper;
5666

5767
/**
58-
* @var \Magento\Framework\Math\Random
68+
* @var Random
5969
*/
6070
private $mathRandom;
6171

6272
/**
63-
* @param \Magento\Framework\Escaper $escaper
64-
* @param \Magento\Widget\Model\Config\Data $dataStorage
65-
* @param \Magento\Framework\View\Asset\Repository $assetRepo
66-
* @param \Magento\Framework\View\Asset\Source $assetSource
67-
* @param \Magento\Framework\View\FileSystem $viewFileSystem
68-
* @param \Magento\Widget\Helper\Conditions $conditionsHelper
73+
* @var string[]
74+
*/
75+
private $reservedChars = ['}', '{'];
76+
77+
/**
78+
* @param Escaper $escaper
79+
* @param Data $dataStorage
80+
* @param Repository $assetRepo
81+
* @param Source $assetSource
82+
* @param FileSystem $viewFileSystem
83+
* @param Conditions $conditionsHelper
6984
*/
7085
public function __construct(
71-
\Magento\Framework\Escaper $escaper,
72-
\Magento\Widget\Model\Config\Data $dataStorage,
73-
\Magento\Framework\View\Asset\Repository $assetRepo,
74-
\Magento\Framework\View\Asset\Source $assetSource,
75-
\Magento\Framework\View\FileSystem $viewFileSystem,
76-
\Magento\Widget\Helper\Conditions $conditionsHelper
86+
Escaper $escaper,
87+
Data $dataStorage,
88+
Repository $assetRepo,
89+
Source $assetSource,
90+
FileSystem $viewFileSystem,
91+
Conditions $conditionsHelper
7792
) {
7893
$this->escaper = $escaper;
7994
$this->dataStorage = $dataStorage;
@@ -110,14 +125,11 @@ public function getWidgetByClassType($type)
110125
$widgets = $this->getWidgets();
111126
/** @var array $widget */
112127
foreach ($widgets as $widget) {
113-
if (isset($widget['@'])) {
114-
if (isset($widget['@']['type'])) {
115-
if ($type === $widget['@']['type']) {
116-
return $widget;
117-
}
118-
}
128+
if (isset($widget['@']['type']) && $type === $widget['@']['type']) {
129+
return $widget;
119130
}
120131
}
132+
121133
return null;
122134
}
123135

@@ -131,8 +143,7 @@ public function getWidgetByClassType($type)
131143
*/
132144
public function getConfigAsXml($type)
133145
{
134-
// phpstan:ignore
135-
return $this->getXmlElementByType($type);
146+
return $this->getWidgetByClassType($type);
136147
}
137148

138149
/**
@@ -294,48 +305,71 @@ public function getWidgetsArray($filters = [])
294305
* @param array $params Pre-configured Widget Params
295306
* @param bool $asIs Return result as widget directive(true) or as placeholder image(false)
296307
* @return string Widget directive ready to parse
297-
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
298308
*/
299309
public function getWidgetDeclaration($type, $params = [], $asIs = true)
300310
{
301-
$directive = '{{widget type="' . $type . '"';
302311
$widget = $this->getConfigAsObject($type);
303312

313+
$directiveParams = '';
304314
foreach ($params as $name => $value) {
305315
// Retrieve default option value if pre-configured
306-
if ($name == 'conditions') {
307-
$name = 'conditions_encoded';
308-
$value = $this->conditionsHelper->encode($value);
309-
} elseif ($this->isTextType($widget, $name)) {
310-
$value = $this->encodeReservedChars($value);
311-
} elseif (is_array($value)) {
312-
$value = implode(',', $value);
313-
} elseif (trim($value) == '') {
314-
$parameters = $widget->getParameters();
315-
if (isset($parameters[$name]) && is_object($parameters[$name])) {
316-
$value = $parameters[$name]->getValue();
317-
}
318-
}
319-
if (isset($value)) {
320-
$directive .= sprintf(' %s="%s"', $name, $this->escaper->escapeHtmlAttr($value, false));
321-
}
316+
$directiveParams .= $this->getDirectiveParam($widget, $name, $value);
322317
}
323318

324-
$directive .= $this->getWidgetPageVarName($params);
325-
326-
$directive .= '}}';
319+
$directive = sprintf('{{widget type="%s"%s%s}}', $type, $directiveParams, $this->getWidgetPageVarName($params));
327320

328321
if ($asIs) {
329322
return $directive;
330323
}
331324

332-
$html = sprintf(
325+
return sprintf(
333326
'<img id="%s" src="%s" title="%s">',
334327
$this->idEncode($directive),
335328
$this->getPlaceholderImageUrl($type),
336329
$this->escaper->escapeUrl($directive)
337330
);
338-
return $html;
331+
}
332+
333+
/**
334+
* Returns directive param with prepared value
335+
*
336+
* @param DataObject $widget
337+
* @param string $name
338+
* @param string|array $value
339+
* @return string
340+
*/
341+
private function getDirectiveParam(DataObject $widget, string $name, $value): string
342+
{
343+
if ($name === 'conditions') {
344+
$name = 'conditions_encoded';
345+
$value = $this->conditionsHelper->encode($value);
346+
} elseif (is_array($value)) {
347+
$value = implode(',', $value);
348+
} elseif (trim($value) === '') {
349+
$parameters = $widget->getParameters();
350+
if (isset($parameters[$name]) && is_object($parameters[$name])) {
351+
$value = $parameters[$name]->getValue();
352+
}
353+
} else {
354+
$value = $this->getPreparedValue($value);
355+
}
356+
357+
return $value !== null
358+
? sprintf(' %s="%s"', $name, $this->escaper->escapeHtmlAttr($value, false))
359+
: '';
360+
}
361+
362+
/**
363+
* Returns encoded value if it contains reserved chars
364+
*
365+
* @param string $value
366+
* @return string
367+
*/
368+
private function getPreparedValue(string $value): string
369+
{
370+
$pattern = sprintf('/%s/', implode('|', $this->reservedChars));
371+
372+
return preg_match($pattern, $value) ? rawurlencode($value) : $value;
339373
}
340374

341375
/**
@@ -460,65 +494,4 @@ protected function sortParameters($firstElement, $secondElement)
460494
$bOrder = (int)$secondElement->getData('sort_order');
461495
return $aOrder < $bOrder ? -1 : ($aOrder > $bOrder ? 1 : 0);
462496
}
463-
464-
/**
465-
* Encode reserved chars
466-
*
467-
* @param string $string
468-
* @return string|string[]
469-
*/
470-
private function encodeReservedChars($string)
471-
{
472-
$map = [
473-
'{' => urlencode('{'),
474-
'}' => urlencode('}')
475-
];
476-
477-
return str_replace(
478-
array_keys($map),
479-
array_values($map),
480-
$string
481-
);
482-
}
483-
484-
/**
485-
* Decode reserved chars
486-
*
487-
* @param string $string
488-
* @return array
489-
*/
490-
public function decodeReservedChars($string)
491-
{
492-
$map = [
493-
'{' => urlencode('{'),
494-
'}' => urlencode('}')
495-
];
496-
497-
return str_replace(
498-
array_values($map),
499-
array_keys($map),
500-
$string
501-
);
502-
}
503-
504-
/**
505-
* Is text type Widget parameter
506-
*
507-
* @param \Magento\Framework\DataObject $widget
508-
* @param string $name
509-
* @return bool
510-
*/
511-
private function isTextType($widget, $name)
512-
{
513-
$parameters = $widget->getParameters();
514-
515-
if (isset($parameters[$name]) && is_object($parameters[$name])) {
516-
$type = $parameters[$name]->getType();
517-
if ($type == 'text') {
518-
return true;
519-
}
520-
}
521-
522-
return false;
523-
}
524497
}

0 commit comments

Comments
 (0)