Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 123
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
Jetpack_Newsletter_Dashboard_Widget
0.00% covered (danger)
0.00%
0 / 119
0.00% covered (danger)
0.00%
0 / 5
812
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_config_data
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
210
 wp_dashboard_setup
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
20
 render
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 load_admin_scripts
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 1
56
1<?php
2/**
3 * Jetpack Newsletter Dashboard Widget.
4 *
5 * @package jetpack
6 */
7
8use Automattic\Jetpack\Connection\Client;
9use Automattic\Jetpack\Modules;
10
11/**
12 * Class that adds the Jetpack Newsletter Dashboard Widget to the WordPress admin dashboard.
13 */
14class Jetpack_Newsletter_Dashboard_Widget {
15    /**
16     * Indicates whether the class initialized or not.
17     *
18     * @var bool
19     */
20    private static $initialized = false;
21
22    /**
23     * The Widget ID.
24     *
25     * @var string
26     */
27    private static $widget_id = 'jetpack_newsletter_dashboard_widget';
28
29    /**
30     * Initialize the class by calling the setup static function.
31     *
32     * @return void
33     */
34    public static function init() {
35        if ( ! self::$initialized ) {
36            self::$initialized = true;
37            self::wp_dashboard_setup();
38        }
39    }
40
41    /**
42     * Get the config data for the Jetpack Newsletter widget.
43     *
44     * @return array
45     */
46    public static function get_config_data() {
47        $config_data = array(
48            'emailSubscribers'       => 0,
49            'paidSubscribers'        => 0,
50            'allSubscribers'         => 0,
51            'subscriberTotalsByDate' => array(),
52            'isStatsModuleActive'    => false,
53            'showHeader'             => false,
54            'showChart'              => false,
55            'isWidgetVisible'        => false,
56        );
57
58        if ( Jetpack::is_connection_ready() ) {
59            $site_id  = Jetpack_Options::get_option( 'id' );
60            $api_path = sprintf( '/sites/%d/subscribers/stats', $site_id );
61            $response = Client::wpcom_json_api_request_as_blog(
62                $api_path,
63                '2',
64                array(),
65                null,
66                'wpcom'
67            );
68
69            if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
70                $subscriber_counts = json_decode( wp_remote_retrieve_body( $response ), true );
71                if ( isset( $subscriber_counts['counts']['email_subscribers'] ) ) {
72                    $config_data['emailSubscribers'] = (int) $subscriber_counts['counts']['email_subscribers'];
73                }
74
75                if ( isset( $subscriber_counts['counts']['paid_subscribers'] ) ) {
76                    $config_data['paidSubscribers'] = (int) $subscriber_counts['counts']['paid_subscribers'];
77                }
78
79                if ( isset( $subscriber_counts['counts']['all_subscribers'] ) ) {
80                    $config_data['allSubscribers'] = (int) $subscriber_counts['counts']['all_subscribers'];
81                }
82
83                if ( isset( $subscriber_counts['aggregate'] ) ) {
84                    $config_data['subscriberTotalsByDate'] = $subscriber_counts['aggregate'];
85                }
86            }
87
88            $config_data['isStatsModuleActive'] = ( new Modules() )->is_active( 'stats' );
89
90            $config_data['showHeader'] = $config_data['isStatsModuleActive'] && ( $config_data['allSubscribers'] > 0 || $config_data['paidSubscribers'] > 0 );
91            foreach ( $config_data['subscriberTotalsByDate'] as $day ) {
92                if ( $day && ( $day['all'] >= 5 || $day['paid'] > 0 ) ) {
93                    $config_data['showChart'] = true;
94                    break;
95                }
96            }
97
98            $config_data['isWidgetVisible'] = $config_data['showHeader'] || $config_data['showChart'];
99        }
100
101        return $config_data;
102    }
103
104    /**
105     * Sets up the Jetpack Newsletter widget in the WordPress admin dashboard.
106     */
107    public static function wp_dashboard_setup() {
108        // Do not show the widget to non-admins.
109        if ( ! current_user_can( 'manage_options' ) ) {
110            return;
111        }
112
113        if ( Jetpack::is_connection_ready() ) {
114            $config_data = static::get_config_data();
115
116            if ( ! $config_data['isWidgetVisible'] ) {
117                return;
118            }
119
120            static::load_admin_scripts(
121                'jp-newsletter-widget',
122                'newsletter-widget',
123                array(
124                    'config_variable_name' => 'jetpackNewsletterWidgetConfigData',
125                    'config_data'          => $config_data,
126                    'load_minified_js'     => false,
127                )
128            );
129
130            $widget_title = sprintf(
131                __( 'Newsletter', 'jetpack' )
132            );
133
134            wp_add_dashboard_widget(
135                self::$widget_id,
136                $widget_title,
137                array( static::class, 'render' ),
138                // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- Core should ideally document null for no-callback arg. https://core.trac.wordpress.org/ticket/52539.
139                null,
140                array(),
141                'side',
142                'high'
143            );
144        }
145    }
146
147    /**
148     * Render the Jetpack Newsletter widget.
149     *
150     * @return void
151     */
152    public static function render() {
153        ?>
154        <div id="wpcom">
155            <div id="newsletter-widget-app"></div>
156        </div>
157        <?php
158    }
159
160    /**
161     * Load the admin scripts for the Jetpack Newsletter widget.
162     *
163     * @param string $asset_handle The handle of the asset.
164     * @param string $asset_name The name of the asset.
165     * @param array  $options The options for the asset.
166     * @return void
167     */
168    public static function load_admin_scripts( $asset_handle, $asset_name, $options = array() ) {
169        $default_options = array(
170            'config_data'          => array(),
171            'config_variable_name' => 'configData',
172            'enqueue_css'          => true,
173            'load_minified_js'     => true,
174        );
175        $options         = wp_parse_args( $options, $default_options );
176
177        // Get the asset file path
178        $asset_path = JETPACK__PLUGIN_DIR . '_inc/build/' . $asset_name . '.min.asset.php';
179
180        // Get dependencies and version from asset file
181        $dependencies = array();
182        $version      = JETPACK__VERSION;
183
184        if ( file_exists( $asset_path ) ) {
185            $asset        = require $asset_path;
186            $dependencies = $asset['dependencies'];
187            $version      = $asset['version'];
188        }
189
190        $file_extension = '.min.js';
191        if ( ! $options['load_minified_js'] ) {
192            $file_extension = '.js';
193        }
194        // Register and enqueue the script
195        wp_register_script(
196            $asset_handle,
197            plugins_url( '_inc/build/' . $asset_name . $file_extension, JETPACK__PLUGIN_FILE ),
198            $dependencies,
199            $version,
200            true
201        );
202        wp_enqueue_script( $asset_handle );
203        if ( in_array( 'wp-i18n', $dependencies, true ) ) {
204            wp_set_script_translations( $asset_handle, 'jetpack' );
205        }
206
207        // Enqueue the CSS if enabled
208        if ( $options['enqueue_css'] ) {
209            wp_enqueue_style(
210                $asset_handle,
211                plugins_url( '_inc/build/' . $asset_name . '.css', JETPACK__PLUGIN_FILE ),
212                array(),
213                $version
214            );
215
216            // Enqueue RTL stylesheet if needed
217            if ( is_rtl() ) {
218                wp_enqueue_style(
219                    $asset_handle . '-rtl',
220                    plugins_url( '_inc/build/' . $asset_name . '.rtl.css', JETPACK__PLUGIN_FILE ),
221                    array( $asset_handle ),
222                    $version
223                );
224            }
225        }
226
227        // Add any configuration data if needed
228        if ( ! empty( $options['config_data'] ) ) {
229            wp_add_inline_script(
230                $asset_handle,
231                "window.{$options['config_variable_name']} = " . wp_json_encode( $options['config_data'], JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) . ';',
232                'before'
233            );
234        }
235    }
236}
237
238add_action(
239    'wp_dashboard_setup',
240    array( 'Jetpack_Newsletter_Dashboard_Widget', 'init' )
241);