55 */
66namespace 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)
1525class 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,6 +143,7 @@ public function getWidgetByClassType($type)
131143 */
132144 public function getConfigAsXml ($ type )
133145 {
146+ // phpstan:ignore
134147 return $ this ->getXmlElementByType ($ type );
135148 }
136149
@@ -296,42 +309,70 @@ public function getWidgetsArray($filters = [])
296309 */
297310 public function getWidgetDeclaration ($ type , $ params = [], $ asIs = true )
298311 {
299- $ directive = '{{widget type=" ' . $ type . '" ' ;
300312 $ widget = $ this ->getConfigAsObject ($ type );
301313
314+ $ params = array_filter ($ params , function ($ value ) {
315+ return $ value !== null && $ value !== '' ;
316+ });
317+
318+ $ directiveParams = '' ;
302319 foreach ($ params as $ name => $ value ) {
303320 // Retrieve default option value if pre-configured
304- if ($ name == 'conditions ' ) {
305- $ name = 'conditions_encoded ' ;
306- $ value = $ this ->conditionsHelper ->encode ($ value );
307- } elseif (is_array ($ value )) {
308- $ value = implode (', ' , $ value );
309- } elseif (trim ($ value ) == '' ) {
310- $ parameters = $ widget ->getParameters ();
311- if (isset ($ parameters [$ name ]) && is_object ($ parameters [$ name ])) {
312- $ value = $ parameters [$ name ]->getValue ();
313- }
314- }
315- if (isset ($ value )) {
316- $ directive .= sprintf (' %s="%s" ' , $ name , $ this ->escaper ->escapeHtmlAttr ($ value , false ));
317- }
321+ $ directiveParams .= $ this ->getDirectiveParam ($ widget , $ name , $ value );
318322 }
319323
320- $ directive .= $ this ->getWidgetPageVarName ($ params );
321-
322- $ directive .= '}} ' ;
324+ $ directive = sprintf ('{{widget type="%s"%s%s}} ' , $ type , $ directiveParams , $ this ->getWidgetPageVarName ($ params ));
323325
324326 if ($ asIs ) {
325327 return $ directive ;
326328 }
327329
328- $ html = sprintf (
330+ return sprintf (
329331 '<img id="%s" src="%s" title="%s"> ' ,
330332 $ this ->idEncode ($ directive ),
331333 $ this ->getPlaceholderImageUrl ($ type ),
332334 $ this ->escaper ->escapeUrl ($ directive )
333335 );
334- return $ html ;
336+ }
337+
338+ /**
339+ * Returns directive param with prepared value
340+ *
341+ * @param DataObject $widget
342+ * @param string $name
343+ * @param string|array $value
344+ * @return string
345+ */
346+ private function getDirectiveParam (DataObject $ widget , string $ name , $ value ): string
347+ {
348+ if ($ name === 'conditions ' ) {
349+ $ name = 'conditions_encoded ' ;
350+ $ value = $ this ->conditionsHelper ->encode ($ value );
351+ } elseif (is_array ($ value )) {
352+ $ value = implode (', ' , $ value );
353+ } elseif (trim ($ value ) === '' ) {
354+ $ parameters = $ widget ->getParameters ();
355+ if (isset ($ parameters [$ name ]) && is_object ($ parameters [$ name ])) {
356+ $ value = $ parameters [$ name ]->getValue ();
357+ }
358+ } else {
359+ $ value = $ this ->getPreparedValue ($ value );
360+ }
361+
362+ return sprintf (' %s="%s" ' , $ name , $ this ->escaper ->escapeHtmlAttr ($ value , false ));
363+ }
364+
365+ /**
366+ * Returns encoded value if it contains reserved chars
367+ *
368+ * @param string $value
369+ * @return string
370+ */
371+ private function getPreparedValue (string $ value ): string
372+ {
373+ $ pattern = sprintf ('/%s/ ' , implode ('| ' , $ this ->reservedChars ));
374+
375+ return preg_match ($ pattern , $ value ) ? rawurlencode ($ value ) : $ value ;
335376 }
336377
337378 /**
0 commit comments