Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
Jetpack_Subscribe_Modal_Button
0.00% covered (danger)
0.00%
0 / 45
0.00% covered (danger)
0.00%
0 / 8
210
0.00% covered (danger)
0.00%
0 / 1
 init
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 get_block_template_part_id
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 enqueue_assets
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 add_subscribe_modal_button_to_frontend
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 get_block_template_filter
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
20
 get_template
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
2
 get_subscribe_modal_button_template_content
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * Adds support for a local pop-up shown when a visitor clicks a "Button
4 * only" style Subscribe block, before the subscribe.wordpress.com checkout
5 * iframe opens.
6 *
7 * @package automattic/jetpack
8 * @since $$next-version$$
9 */
10
11/**
12 * Jetpack_Subscribe_Modal_Button class.
13 */
14class Jetpack_Subscribe_Modal_Button {
15    /**
16     * Jetpack_Subscribe_Modal_Button singleton instance.
17     *
18     * @var Jetpack_Subscribe_Modal_Button|null
19     */
20    private static $instance;
21
22    /**
23     * Jetpack_Subscribe_Modal_Button instance init.
24     */
25    public static function init() {
26        if ( self::$instance === null ) {
27            self::$instance = new Jetpack_Subscribe_Modal_Button();
28        }
29
30        return self::$instance;
31    }
32
33    const BLOCK_TEMPLATE_PART_SLUG = 'jetpack-subscribe-modal-button';
34
35    /**
36     * Returns the block template part ID.
37     *
38     * @return string
39     */
40    public static function get_block_template_part_id() {
41        return get_stylesheet() . '//' . self::BLOCK_TEMPLATE_PART_SLUG;
42    }
43
44    /**
45     * Jetpack_Subscribe_Modal_Button class constructor.
46     */
47    public function __construct() {
48        add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_assets' ) );
49        add_action( 'wp_footer', array( $this, 'add_subscribe_modal_button_to_frontend' ) );
50        add_filter( 'get_block_template', array( $this, 'get_block_template_filter' ), 10, 3 );
51    }
52
53    /**
54     * Enqueues the pop-up's stylesheet. Unlike Jetpack_Subscribe_Modal, this
55     * pop-up is click-triggered rather than scroll/timer-triggered, so it's
56     * printed unconditionally (cheap no-op if no "Button only" Subscribe
57     * block is present on the page — nothing ever opens it).
58     *
59     * @return void
60     */
61    public function enqueue_assets() {
62        wp_enqueue_style( 'subscribe-modal-button-css', plugins_url( 'subscribe-modal-button.css', __FILE__ ), array(), JETPACK__VERSION );
63        wp_enqueue_script( 'subscribe-modal-button-js', plugins_url( 'subscribe-modal-button.js', __FILE__ ), array( 'wp-dom-ready' ), JETPACK__VERSION, true );
64    }
65
66    /**
67     * Adds the (initially closed) pop-up markup to the page footer.
68     *
69     * @return void
70     */
71    public function add_subscribe_modal_button_to_frontend() {
72        ?>
73        <div class="jetpack-subscribe-modal-button">
74            <div class="jetpack-subscribe-modal-button__modal-content">
75                <?php block_template_part( self::BLOCK_TEMPLATE_PART_SLUG ); ?>
76            </div>
77        </div>
78        <?php
79    }
80
81    /**
82     * Makes get_block_template return the WP_Block_Template for this pop-up.
83     *
84     * @param WP_Block_Template $block_template The block template to be returned.
85     * @param string            $id Template unique identifier (example: theme_slug//template_slug).
86     * @param string            $template_type Template type: `'wp_template'` or '`wp_template_part'`.
87     *
88     * @return WP_Block_Template
89     */
90    public function get_block_template_filter( $block_template, $id, $template_type ) {
91        if ( empty( $block_template ) && $template_type === 'wp_template_part' ) {
92            if ( $id === self::get_block_template_part_id() ) {
93                return $this->get_template();
94            }
95        }
96
97        return $block_template;
98    }
99
100    /**
101     * Returns a custom template for the pop-up.
102     *
103     * @return WP_Block_Template
104     */
105    public function get_template() {
106        $template                 = new WP_Block_Template();
107        $template->theme          = get_stylesheet();
108        $template->slug           = self::BLOCK_TEMPLATE_PART_SLUG;
109        $template->id             = self::get_block_template_part_id();
110        $template->area           = 'uncategorized';
111        $template->content        = $this->get_subscribe_modal_button_template_content();
112        $template->source         = 'plugin';
113        $template->type           = 'wp_template_part';
114        $template->title          = __( 'Jetpack Subscribe button modal', 'jetpack' );
115        $template->status         = 'publish';
116        $template->has_theme_file = false;
117        $template->is_custom      = true;
118        $template->description    = __( 'The pop-up shown when a visitor clicks a "Button only" style Subscribe block.', 'jetpack' );
119
120        return $template;
121    }
122
123    /**
124     * Returns the initial content of the pop-up template.
125     * This can then be edited by the user.
126     *
127     * Seeds the heading from the legacy `subscribe_modal_heading` site
128     * setting when present, so a site that already customized it via the
129     * Newsletter settings page doesn't silently lose that text the first
130     * time this ships. Once the owner edits this template part directly, the
131     * template part becomes the sole source of truth for the heading.
132     *
133     * @return string
134     */
135    public function get_subscribe_modal_button_template_content() {
136        $subscription_options = (array) get_option( 'subscription_options', array() );
137        $legacy_heading       = isset( $subscription_options['subscribe_modal_heading'] )
138            ? trim( (string) $subscription_options['subscribe_modal_heading'] )
139            : '';
140        $heading_text         = '' !== $legacy_heading
141            ? $legacy_heading
142            : __( 'Subscribe now to stay ahead and never miss a beat!', 'jetpack' );
143
144        $group_block_name = esc_attr__( 'Subscribe button pop-up container', 'jetpack' );
145
146        return <<<HTML
147    <!-- wp:group {"metadata":{"name":"$group_block_name"},"style":{"spacing":{"padding":{"top":"32px","bottom":"32px","left":"32px","right":"32px"},"margin":{"top":"0","bottom":"0"}},"border":{"color":"#dddddd","width":"1px"}},"layout":{"type":"constrained","contentSize":"450px"}} -->
148    <div class="wp-block-group has-border-color" style="border-color:#dddddd;border-width:1px;margin-top:0;margin-bottom:0;padding-top:32px;padding-right:32px;padding-bottom:32px;padding-left:32px">
149
150    <!-- wp:heading {"textAlign":"center","level":3,"style":{"typography":{"fontStyle":"normal","fontWeight":"600","fontSize":"22px"},"spacing":{"margin":{"top":"4px","bottom":"10px"}}}} -->
151        <h3 class="wp-block-heading has-text-align-center" style="margin-top:4px;margin-bottom:10px;font-size:22px;font-style:normal;font-weight:600">$heading_text</h3>
152        <!-- /wp:heading -->
153
154        <!-- wp:jetpack/subscriptions {"borderRadius":50,"className":"is-style-compact","appSource":"subscribe-modal-button"} /-->
155    </div>
156    <!-- /wp:group -->
157HTML;
158    }
159}
160
161Jetpack_Subscribe_Modal_Button::init();
162
163add_action(
164    'rest_api_switched_to_blog',
165    function () {
166        Jetpack_Subscribe_Modal_Button::init();
167    }
168);