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