Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 33
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
WPCOMSH_MailPoet_Subscribers_Stats_Report
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 3
210
0.00% covered (danger)
0.00%
0 / 1
 init_wp_cron
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 report_stats
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
90
 bump_report_status
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * MailPoet Subcribers stats reporting.
4 *
5 * @package wpcomsh
6 */
7
8/**
9 * Initializes and processes wp-cron job that reports subscribers stats to MC Stats.
10 */
11class WPCOMSH_MailPoet_Subscribers_Stats_Report {
12
13    const STATUS_STATS_GROUP = 'mailpoet-subscriber-stats'; // Reporting stats data
14    const REPORT_STATS_GROUP = 'mailpoet-subscriber-reports'; // Reporting successful and failed attempts for reporting stats
15    const STATS_SERVICE_URL  = 'http://pixel.wp.com/g.gif';
16    const WP_CRON_HOOK       = 'wpcomsh_mailpoet_subscribers_stats';
17
18    const ALLOWED_STATUSES = array(
19        'subscribed'   => 1,
20        'inactive'     => 1,
21        'unsubscribed' => 1,
22        'unconfirmed'  => 1,
23        'bounced'      => 1,
24    );
25
26    /**
27     * When MailPoet plugin is detected active the method schedules a weekly wp-cron job
28     * for reporting subscribers stats to MC Stats
29     *
30     * @return void
31     */
32    public static function init_wp_cron() {
33        // Always handle the cron hook so it has a chance to unschedule itself after mailpoet deactivation
34        add_action( self::WP_CRON_HOOK, array( self::class, 'report_stats' ) );
35
36        if (
37            is_plugin_active( 'mailpoet/mailpoet.php' ) &&
38            false === wp_next_scheduled( self::WP_CRON_HOOK )
39        ) {
40            wp_schedule_event( time(), 'weekly', self::WP_CRON_HOOK );
41        }
42    }
43
44    /**
45     * Reports subscriber counts by status to MC Stats and also increases stats counting sites that sent the report.
46     *
47     * @return void
48     */
49    public static function report_stats() {
50        // Cleanup wp-cron in case the MailPoet plugin was deactivated
51        if ( ! is_plugin_active( 'mailpoet/mailpoet.php' ) ) {
52            $timestamp = wp_next_scheduled( self::WP_CRON_HOOK );
53            if ( $timestamp !== false ) {
54                wp_unschedule_event( $timestamp, self::WP_CRON_HOOK );
55            }
56            return;
57        }
58
59        global $wpdb;
60
61        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
62        $stats_data = $wpdb->get_results( 'SELECT count(id) as `count`, `status` FROM ' . $wpdb->prefix . 'mailpoet_subscribers GROUP BY `status`', ARRAY_A ); // db call ok; no-cache ok
63        $query_args = array( 'v' => 'wpcom-no-pv' );
64
65        if ( ! is_array( $stats_data ) ) {
66            self::bump_report_status( 'db_fetch_error' );
67            return;
68        }
69
70        foreach ( $stats_data as $status_data ) {
71            if ( (int) $status_data['count'] === 0 || ! isset( self::ALLOWED_STATUSES[ $status_data['status'] ] ) ) {
72                continue;
73            }
74            $query_args[ 'x_' . self::STATUS_STATS_GROUP . '/' . $status_data['status'] ] = $status_data['count'];
75        }
76
77        // Increase success count of sites that reported stats
78        $result = self::bump_report_status( 'success' );
79        if ( $result === false ) {
80            return;
81        }
82
83        // Report subscribers status stats
84        $stats_track_url = self::STATS_SERVICE_URL . '?' . http_build_query( $query_args );
85        $result          = wp_remote_get( $stats_track_url );
86        if ( $result instanceof \WP_Error ) {
87            error_log( 'WPComSH: ' . $result->get_error_message() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
88        }
89    }
90
91    /**
92     * Reports status of subscriber stats report to the MC Stats.
93     *
94     * @param string $status Status of the report. Possible values: success, db_fetch_error.
95     * @return bool True if success otherwise false
96     */
97    public static function bump_report_status( string $status ) {
98        $stats_report_track_url = self::STATS_SERVICE_URL . '?v=wpcom-no-pv&x_' . self::REPORT_STATS_GROUP . '=' . $status;
99        $result                 = wp_remote_get( $stats_report_track_url );
100        if ( $result instanceof \WP_Error ) {
101            error_log( 'WPComSH: ' . $result->get_error_message() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
102            return false;
103        }
104        return true;
105    }
106}
107
108add_action( 'init', array( WPCOMSH_MailPoet_Subscribers_Stats_Report::class, 'init_wp_cron' ) );