PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 8.9.4
Jetpack – WP Security, Backup, Speed, & Growth v8.9.4
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 All 500 releases
jetpack / modules / shortcodes / mailchimp.php
mailchimp.php
224 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php //phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 /**
3 * MailChimp Subscriber Popup Form shortcode
4 *
5 * Example:
6 * [mailchimp_subscriber_popup baseUrl="mc.us11.list-manage.com" uuid="1ca7856462585a934b8674c71" lid="2d24f1898b"]
7 *
8 * Embed code example:
9 * <script type="text/javascript" src="//downloads.mailchimp.com/js/signup-forms/popup/unique-methods/embed.js" data-dojo-config="usePlainJson: true, isDebug: false"></script><script type="text/javascript">window.dojoRequire(["mojo/signup-forms/Loader"], function(L) { L.start({"baseUrl":"mc.us11.list-manage.com","uuid":"1ca7856462585a934b8674c71","lid":"2d24f1898b","uniqueMethods":true}) })</script>
10 */
11
12 /**
13 * Register [mailchimp_subscriber_popup] shortcode and add a filter to 'pre_kses' queue to reverse MailChimp embed to shortcode.
14 *
15 * @since 4.5.0
16 */
17 function jetpack_mailchimp_subscriber_popup() {
18 add_shortcode(
19 'mailchimp_subscriber_popup',
20 array(
21 'MailChimp_Subscriber_Popup',
22 'shortcode',
23 )
24 );
25 add_filter(
26 'pre_kses',
27 array(
28 'MailChimp_Subscriber_Popup',
29 'reversal',
30 )
31 );
32 }
33
34 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
35 add_action( 'init', 'jetpack_mailchimp_subscriber_popup' );
36 } else {
37 jetpack_mailchimp_subscriber_popup();
38 }
39
40 /**
41 * Class MailChimp_Subscriber_Popup
42 *
43 * @since 4.5.0
44 */
45 class MailChimp_Subscriber_Popup {
46
47 /**
48 * Regular expressions to reverse script tags to shortcodes.
49 *
50 * @var array
51 */
52 private static $reversal_regexes = array(
53 /* raw examplejs */
54 '/<script type="text\/javascript" src="(https?:)?\/\/downloads\.mailchimp\.com\/js\/signup-forms\/popup\/unique-methods\/embed\.js" data-dojo-config="([^"]*?)"><\/script><script type="text\/javascript">window.dojoRequire\(\["mojo\/signup-forms\/Loader"\]\, function\(L\) { L\.start\({([^}]*?)}\) }\)<\/script>/s', //phpcs:ignore
55 /* visual editor */
56 '/&lt;script type="text\/javascript" src="(https?:)?\/\/downloads\.mailchimp\.com\/js\/signup-forms\/popup\/unique-methods\/embed\.js" data-dojo-config="([^"]*?)"&gt;&lt;\/script&gt;&lt;script type="text\/javascript"&gt;window.dojoRequire\(\["mojo\/signup-forms\/Loader"]\, function\(L\) { L\.start\({([^}]*?)}\) }\)&lt;\/script&gt;/s',
57 );
58
59 /**
60 * Allowed configuration attributes. Used in reversal when checking allowed attributes.
61 *
62 * @var array
63 */
64 private static $allowed_config = array(
65 'usePlainJson' => 'true',
66 'isDebug' => 'false',
67 );
68
69 /**
70 * Allowed JS variables. Used in reversal to whitelist variables.
71 *
72 * @var array
73 */
74 private static $allowed_js_vars = array(
75 'baseUrl',
76 'uuid',
77 'lid',
78 );
79
80 /**
81 * Runs the whole reversal.
82 *
83 * @since 4.5.0
84 *
85 * @param string $content Post Content.
86 *
87 * @return string Content with embeds replaced
88 */
89 public static function reversal( $content ) {
90 // Bail without the js src.
91 if ( ! is_string( $content ) || false === stripos( $content, 'downloads.mailchimp.com/js/signup-forms/popup/unique-methods/embed.js' ) ) {
92 return $content;
93 }
94
95 // loop through our rules and find valid embeds.
96 foreach ( self::$reversal_regexes as $regex ) {
97
98 if ( ! preg_match_all( $regex, $content, $matches ) ) {
99 continue;
100 }
101
102 foreach ( $matches[3] as $index => $js_vars ) {
103 // the regex rule for a specific embed.
104 $replace_regex = sprintf( '#\s*%s\s*#', preg_quote( $matches[0][ $index ], '#' ) );
105
106 $attrs = json_decode( '{' . $js_vars . '}' );
107
108 if ( $matches[2][ $index ] ) {
109 $config_attrs = json_decode( '{' . $matches[2][ $index ] . '}' );
110 foreach ( $config_attrs as $key => $value ) {
111 $attrs->$key = ( 1 === $value ) ? 'true' : 'false';
112 }
113 }
114
115 $shortcode = self::build_shortcode_from_reversal_attrs( $attrs );
116
117 $content = preg_replace( $replace_regex, "\n\n$shortcode\n\n", $content );
118
119 /** This action is documented in modules/widgets/social-media-icons.php */
120 do_action( 'jetpack_bump_stats_extras', 'html_to_shortcode', 'mailchimp_subscriber_popup' );
121 }
122 }
123
124 return $content;
125 }
126
127 /**
128 * Builds the actual shortcode based on passed in attributes.
129 *
130 * @since 4.5.0
131 *
132 * @param array $attrs A valid list of attributes (gets matched against self::$allowed_config and self::$allowed_js_vars).
133 *
134 * @return string
135 */
136 private static function build_shortcode_from_reversal_attrs( $attrs ) {
137 $shortcode = '[mailchimp_subscriber_popup ';
138
139 foreach ( $attrs as $key => $value ) {
140 // skip unsupported keys.
141 if (
142 ! in_array( $key, array_keys( self::$allowed_config ), true )
143 && ! in_array( $key, self::$allowed_js_vars, true )
144 ) {
145 continue;
146 }
147
148 $value = esc_attr( $value );
149 $shortcode .= "$key='$value' ";
150 }
151 return trim( $shortcode ) . ']';
152 }
153
154 /**
155 * Parses the shortcode back out to embedded information.
156 *
157 * @since 4.5.0
158 *
159 * @param array $lcase_attrs Lowercase shortcode attributes.
160 *
161 * @return string
162 */
163 public static function shortcode( $lcase_attrs ) {
164 static $displayed_once = false;
165
166 // Limit to one form per page load.
167 if ( $displayed_once ) {
168 return '';
169 }
170
171 if ( empty( $lcase_attrs ) ) {
172 return '<!-- Missing MailChimp baseUrl, uuid or lid -->';
173 }
174
175 $defaults = array_fill_keys( self::$allowed_js_vars, '' );
176 $defaults = array_merge( $defaults, self::$allowed_config );
177
178 // Convert $attrs back to proper casing since they come through in all lowercase.
179 $attrs = array();
180 foreach ( $defaults as $key => $value ) {
181 if ( array_key_exists( strtolower( $key ), $lcase_attrs ) ) {
182 $attrs[ $key ] = $lcase_attrs[ strtolower( $key ) ];
183 }
184 }
185 $attrs = array_map( 'esc_js', array_filter( shortcode_atts( $defaults, $attrs ) ) );
186
187 // Split config & js vars.
188 $js_vars = array();
189 $config_vars = array();
190 foreach ( $attrs as $key => $value ) {
191 if (
192 'baseUrl' === $key
193 && (
194 ! preg_match( '#mc\.us\d+\.list-manage\d?\.com#', $value, $matches )
195 || $value !== $matches[0]
196 )
197 ) {
198 return '<!-- Invalid MailChimp baseUrl -->';
199 }
200
201 if ( in_array( $key, self::$allowed_js_vars, true ) ) {
202 $js_vars[ $key ] = $value;
203 } else {
204 $config_vars[] = "$key: $value";
205 }
206 }
207
208 // If one of these parameters is missing we can't render the form so exist.
209 if ( empty( $js_vars['baseUrl'] ) || empty( $js_vars['uuid'] ) || empty( $js_vars['lid'] ) ) {
210 return '<!-- Missing MailChimp baseUrl, uuid or lid -->';
211 }
212
213 // Add a uniqueMethods parameter if it is missing from the data we got from the embed code.
214 $js_vars['uniqueMethods'] = true;
215
216 /** This action is already documented in modules/widgets/gravatar-profile.php */
217 do_action( 'jetpack_stats_extra', 'mailchimp_subscriber_popup', 'view' );
218
219 $displayed_once = true;
220
221 return "\n\n" . '<script type="text/javascript" data-dojo-config="' . esc_attr( implode( ', ', $config_vars ) ) . '">jQuery.getScript( "//downloads.mailchimp.com/js/signup-forms/popup/unique-methods/embed.js", function( data, textStatus, jqxhr ) { window.dojoRequire(["mojo/signup-forms/Loader"], function(L) { L.start(' . wp_json_encode( $js_vars ) . ') });} );</script>' . "\n\n";
222 }
223 }
224