Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 195
0.00% covered (danger)
0.00%
0 / 8
CRAP
n/a
0 / 0
Automattic\Jetpack\Extensions\Mailchimp\register_block
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
20
Automattic\Jetpack\Extensions\Mailchimp\load_assets
0.00% covered (danger)
0.00%
0 / 73
0.00% covered (danger)
0.00%
0 / 1
182
Automattic\Jetpack\Extensions\Mailchimp\verify_connection
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
Automattic\Jetpack\Extensions\Mailchimp\get_attributes_with_defaults
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
12
Automattic\Jetpack\Extensions\Mailchimp\render_button
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
Automattic\Jetpack\Extensions\Mailchimp\render_deprecated_button
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 1
30
Automattic\Jetpack\Extensions\Mailchimp\register_admin_settings
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
2
Automattic\Jetpack\Extensions\Mailchimp\update_settings
0.00% covered (danger)
0.00%
0 / 33
0.00% covered (danger)
0.00%
0 / 1
182
1<?php
2/**
3 * Mailchimp Block.
4 *
5 * @since 7.1.0
6 *
7 * @package automattic/jetpack
8 */
9
10namespace Automattic\Jetpack\Extensions\Mailchimp;
11
12use Automattic\Jetpack\Assets;
13use Automattic\Jetpack\Blocks;
14use Automattic\Jetpack\Connection\Client;
15use Automattic\Jetpack\Connection\Manager as Connection_Manager;
16use Automattic\Jetpack\External_Connections;
17use Automattic\Jetpack\Status\Host;
18use Jetpack;
19use Jetpack_Gutenberg;
20use Jetpack_Options;
21
22if ( ! defined( 'ABSPATH' ) ) {
23    exit( 0 );
24}
25
26/**
27 * Registers the block for use in Gutenberg
28 * This is done via an action so that we can disable
29 * registration if we need to.
30 */
31function register_block() {
32    if (
33        ( defined( 'IS_WPCOM' ) && IS_WPCOM )
34        || Jetpack::is_connection_ready()
35    ) {
36        Blocks::jetpack_register_block(
37            __DIR__,
38            array(
39                'render_callback' => __NAMESPACE__ . '\load_assets',
40            )
41        );
42
43        register_admin_settings();
44    }
45}
46add_action( 'init', __NAMESPACE__ . '\register_block' );
47
48/**
49 * Mailchimp block registration/dependency declaration.
50 *
51 * @param array  $attr - Array containing the Mailchimp block attributes.
52 * @param string $content - Mailchimp block content.
53 *
54 * @return string
55 */
56function load_assets( $attr, $content ) {
57
58    if ( ! verify_connection() ) {
59        return null;
60    }
61
62    $values  = get_attributes_with_defaults( $attr );
63    $blog_id = ( defined( 'IS_WPCOM' ) && IS_WPCOM )
64        ? get_current_blog_id()
65        : Jetpack_Options::get_option( 'id' );
66    Jetpack_Gutenberg::load_assets_as_required( __DIR__ );
67    $wrapper_attributes = \WP_Block_Supports::get_instance()->apply_block_supports();
68    $classes            = ! empty( $wrapper_attributes['class'] ) ? $wrapper_attributes['class'] : '';
69    $amp_form_action    = sprintf( 'https://public-api.wordpress.com/rest/v1.1/sites/%s/email_follow/amp/subscribe/', $blog_id );
70    $is_amp_request     = Blocks::is_amp_request();
71
72    ob_start();
73    ?>
74
75    <div class="<?php echo esc_attr( $classes ); ?>"<?php echo ! empty( $wrapper_attributes['style'] ) ? ' style="' . esc_attr( $wrapper_attributes['style'] ) . '"' : ''; ?> data-blog-id="<?php echo esc_attr( $blog_id ); ?>">
76        <form
77            aria-describedby="wp-block-jetpack-mailchimp_consent-text"
78            <?php if ( $is_amp_request ) : ?>
79                action-xhr="<?php echo esc_url( $amp_form_action ); ?>"
80                method="post"
81                id="mailchimp_form"
82                target="_top"
83                on="submit-success:AMP.setState( { mailing_list_status: 'subscribed', mailing_list_email: event.response.email } )"
84            <?php endif; ?>
85        >
86            <p>
87                <input
88                    aria-label="<?php echo esc_attr( $values['emailPlaceholder'] ); ?>"
89                    placeholder="<?php echo esc_attr( $values['emailPlaceholder'] ); ?>"
90                    required
91                    title="<?php echo esc_attr( $values['emailPlaceholder'] ); ?>"
92                    type="email"
93                    name="email"
94                />
95            </p>
96            <?php foreach ( is_array( $values['interests'] ) ? $values['interests'] : array() as $interest ) : ?>
97                <input
98                    name="interests[<?php echo esc_attr( $interest ); ?>]"
99                    type="hidden"
100                    class="mc-submit-param"
101                    value="1"
102                />
103            <?php endforeach; ?>
104            <?php
105            if (
106                ! empty( $values['signupFieldTag'] )
107                && ! empty( $values['signupFieldValue'] )
108                ) :
109                ?>
110                <input
111                    name="merge_fields[<?php echo esc_attr( $values['signupFieldTag'] ); ?>]"
112                    type="hidden"
113                    class="mc-submit-param"
114                    value="<?php echo esc_attr( $values['signupFieldValue'] ); ?>"
115                />
116            <?php endif; ?>
117            <?php echo render_button( $attr, $content ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
118            <p id="wp-block-jetpack-mailchimp_consent-text">
119                <?php echo wp_kses_post( $values['consentText'] ); ?>
120            </p>
121
122            <?php if ( $is_amp_request ) : ?>
123
124                <div submit-success>
125                    <template type="amp-mustache">
126                        <div class="wp-block-jetpack-mailchimp_notification wp-block-jetpack-mailchimp_success wp-block-jetpack-mailchimp__is-amp">
127                            <?php echo esc_html( $values['successLabel'] ); ?>
128                        </div>
129                    </template>
130                </div>
131                <div submit-error>
132                    <template type="amp-mustache">
133                        <div class="wp-block-jetpack-mailchimp_notification wp-block-jetpack-mailchimp_error wp-block-jetpack-mailchimp__is-amp">
134                            <?php echo esc_html( $values['errorLabel'] ); ?>
135                        </div>
136                    </template>
137                </div>
138                <div submitting>
139                    <template type="amp-mustache">
140                        <div class="wp-block-jetpack-mailchimp_notification wp-block-jetpack-mailchimp_processing wp-block-jetpack-mailchimp__is-amp" role="status">
141                            <?php echo esc_html( $values['processingLabel'] ); ?>
142                        </div>
143                    </template>
144                </div>
145
146            <?php endif; ?>
147
148        </form>
149        <?php if ( ! $is_amp_request ) : ?>
150
151            <div class="wp-block-jetpack-mailchimp_notification wp-block-jetpack-mailchimp_processing" role="status">
152                <?php echo esc_html( $values['processingLabel'] ); ?>
153            </div>
154            <div class="wp-block-jetpack-mailchimp_notification wp-block-jetpack-mailchimp_success" role="status">
155                <?php echo esc_html( $values['successLabel'] ); ?>
156            </div>
157            <div class="wp-block-jetpack-mailchimp_notification wp-block-jetpack-mailchimp_error" role="alert">
158                <?php echo esc_html( $values['errorLabel'] ); ?>
159            </div>
160
161        <?php endif; ?>
162    </div>
163    <?php
164    $html = ob_get_clean();
165    return $html;
166}
167
168/**
169 * Mailchimp connection/list selection verification.
170 *
171 * @return boolean
172 */
173function verify_connection() {
174    $option = get_option( 'jetpack_mailchimp' );
175    if ( ! $option ) {
176        return false;
177    }
178    $data = json_decode( $option, true );
179    if ( ! $data ) {
180        return false;
181    }
182    return isset( $data['follower_list_id'] ) && isset( $data['keyring_id'] );
183}
184
185/**
186 * Builds complete set of attributes using default values where needed.
187 *
188 * @param array $attr Saved set of attributes for the Mailchimp block.
189 * @return array
190 */
191function get_attributes_with_defaults( $attr ) {
192    $values   = array();
193    $defaults = array(
194        'emailPlaceholder' => esc_html__( 'Enter your email', 'jetpack' ),
195        'consentText'      => esc_html__( 'By clicking submit, you agree to share your email address with the site owner and Mailchimp to receive marketing, updates, and other emails from the site owner. Use the unsubscribe link in those emails to opt out at any time.', 'jetpack' ),
196        'processingLabel'  => esc_html__( 'Processing…', 'jetpack' ),
197        'successLabel'     => esc_html__( 'Success! You\'re on the list.', 'jetpack' ),
198        'errorLabel'       => esc_html__( 'Whoops! There was an error and we couldn\'t process your subscription. Please reload the page and try again.', 'jetpack' ),
199        'interests'        => array(),
200        'signupFieldTag'   => '',
201        'signupFieldValue' => '',
202    );
203
204    foreach ( $defaults as $id => $default ) {
205        $values[ $id ] = isset( $attr[ $id ] ) ? $attr[ $id ] : $default;
206    }
207
208    return $values;
209}
210
211/**
212 * Renders the Mailchimp block button using inner block content if available
213 * otherwise generating the HTML button from deprecated attributes.
214 *
215 * @param array  $attr Attributes for the Mailchimp block.
216 * @param string $content Mailchimp block content.
217 *
218 * @return string
219 */
220function render_button( $attr, $content ) {
221    if ( ! empty( $content ) ) {
222        $block_id = wp_unique_id( 'mailchimp-button-block-' );
223        return str_replace( 'mailchimp-widget-id', $block_id, $content );
224    }
225
226    return render_deprecated_button( $attr );
227}
228
229/**
230 * Renders HTML button from deprecated Mailchimp block attributes.
231 *
232 * @param array $attr Mailchimp block attributes.
233 * @return string
234 */
235function render_deprecated_button( $attr ) {
236    $default       = esc_html__( 'Join my email list', 'jetpack' );
237    $text          = empty( $attr['submitButtonText'] ) ? $default : $attr['submitButtonText'];
238    $button_styles = array();
239
240    if ( ! empty( $attr['customBackgroundButtonColor'] ) ) {
241        array_push(
242            $button_styles,
243            sprintf(
244                'background-color: %s',
245                sanitize_hex_color( $attr['customBackgroundButtonColor'] )
246            )
247        );
248    }
249
250    if ( ! empty( $attr['customTextButtonColor'] ) ) {
251        array_push(
252            $button_styles,
253            sprintf(
254                'color: %s',
255                sanitize_hex_color( $attr['customTextButtonColor'] )
256            )
257        );
258    }
259
260    $button_styles  = implode( ';', $button_styles );
261    $button_classes = 'components-button is-button is-primary ';
262
263    if ( ! empty( $attr['submitButtonClasses'] ) ) {
264        $button_classes .= $attr['submitButtonClasses'];
265    }
266
267    return sprintf(
268        '<p><button type="submit" class="%s" style="%s">%s</button></p>',
269        esc_attr( $button_classes ),
270        esc_attr( $button_styles ),
271        wp_kses_post( $text )
272    );
273}
274
275/**
276 * Registers the settings to manage the Mailchimp connection.
277 */
278function register_admin_settings() {
279    Assets::register_script(
280        'jetpack-mailchimp-admin-extra-settings',
281        Jetpack_Gutenberg::get_blocks_directory() . '/mailchimp/admin.js',
282        JETPACK__PLUGIN_FILE,
283        array(
284            'textdomain' => 'jetpack',
285        )
286    );
287
288    External_Connections::add_settings_for_service(
289        'writing',
290        array(
291            'service'      => 'mailchimp',
292            'title'        => __( 'Mailchimp', 'jetpack' ),
293            'signup_link'  => 'https://public-api.wordpress.com/rest/v1.1/sharing/mailchimp/signup',
294            'description'  => __( 'Allow users to sign up to your Mailchimp mailing list.', 'jetpack' ),
295            'script'       => 'jetpack-mailchimp-admin-extra-settings',
296            'support_link' => array(
297                'wpcom'   => 'https://wordpress.com/support/wordpress-editor/blocks/mailchimp-block/',
298                'jetpack' => 'mailchimp-block',
299            ),
300        )
301    );
302
303    add_action( 'load-options.php', __NAMESPACE__ . '\update_settings' );
304}
305
306/**
307 * Update the site options that are related to Mailchimp.
308 */
309function update_settings() {
310    $action      = ! empty( $_REQUEST['action'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ) : '';
311    $option_page = ! empty( $_REQUEST['option_page'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['option_page'] ) ) : '';
312    $audience    = ! empty( $_REQUEST['jetpack-mailchimp-audience'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['jetpack-mailchimp-audience'] ) ) : '';
313    if ( $action !== 'update' || $option_page !== 'writing' || ! current_user_can( 'manage_options' ) || $audience === '' ) {
314        return;
315    }
316
317    check_admin_referer( 'writing-options' );
318
319    $site_id = Connection_Manager::get_site_id();
320    if ( is_wp_error( $site_id ) ) {
321        return;
322    }
323
324    if ( $audience === 'none' ) {
325        $data = array(
326            'follower_list_id' => '0',
327            'keyring_id'       => '0',
328        );
329    } else {
330        $connection = External_Connections::get_connection( 'mailchimp' );
331        if ( empty( $connection ) ) {
332            return;
333        }
334        $data = array(
335            'follower_list_id' => $audience,
336            'keyring_id'       => $connection['ID'],
337        );
338    }
339
340    if ( ( new Host() )->is_wpcom_simple() ) {
341        require_lib( 'mailchimp' );
342        $response = \MailchimpApi::save_settings( $site_id, $data );
343    } else {
344        $response = Client::wpcom_json_api_request_as_user(
345            sprintf( '/sites/%d/mailchimp/settings', $site_id ),
346            '1.1',
347            array( 'method' => 'POST' ),
348            $data,
349            'rest'
350        );
351    }
352    if ( is_wp_error( $response ) ) {
353        add_settings_error( 'general', 'settings_updated', __( 'Settings save failed.', 'jetpack' ), 'error' );
354    }
355}