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,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