Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 58
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
jetpack_blog_stats_widget_init
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
Jetpack_Blog_Stats_Widget
0.00% covered (danger)
0.00%
0 / 53
0.00% covered (danger)
0.00%
0 / 7
182
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
2
 hide_widget_in_block_editor
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 defaults
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 get_stats
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 form
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 update
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 widget
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
30
1<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileNam
2/**
3 * Blog Stats Widget.
4 *
5 * @since 4.5.0
6 *
7 * @package automattic/jetpack
8 */
9
10// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move classes to appropriately-named class files.
11
12use Automattic\Jetpack\Stats\WPCOM_Stats;
13use Automattic\Jetpack\Status\Host;
14
15// Disable direct access/execution to/of the widget code.
16if ( ! defined( 'ABSPATH' ) ) {
17    exit( 0 );
18}
19
20/**
21 * Blog Stats Widget.
22 *
23 * Displays all time stats for that site.
24 *
25 * @since 4.5.0
26 */
27class Jetpack_Blog_Stats_Widget extends WP_Widget {
28
29    /**
30     * Constructor
31     */
32    public function __construct() {
33        $widget_ops = array(
34            'classname'                   => 'blog-stats',
35            'description'                 => esc_html__( 'Show a hit counter for your blog.', 'jetpack' ),
36            'customize_selective_refresh' => true,
37            'show_instance_in_rest'       => true,
38        );
39        parent::__construct(
40            'blog-stats',
41            /** This filter is documented in modules/widgets/facebook-likebox.php */
42            apply_filters( 'jetpack_widget_name', esc_html__( 'Blog Stats', 'jetpack' ) ),
43            $widget_ops
44        );
45        $this->alt_option_name = 'widget_statscounter';
46        add_filter( 'widget_types_to_hide_from_legacy_widget_block', array( $this, 'hide_widget_in_block_editor' ) );
47    }
48
49    /**
50     * Remove the "Blog Stats" widget from the Legacy Widget block
51     *
52     * @param array $widget_types List of widgets that are currently removed from the Legacy Widget block.
53     * @return array $widget_types New list of widgets that will be removed.
54     */
55    public function hide_widget_in_block_editor( $widget_types ) {
56        // @TODO: Hide for Simple sites when the block API starts working.
57        if ( ! ( new Host() )->is_wpcom_simple() ) {
58            $widget_types[] = 'blog-stats';
59        }
60        return $widget_types;
61    }
62
63    /**
64     * Return an associative array of default values
65     *
66     * These values are used in new widgets.
67     *
68     * @return array Array of default values for the Widget's options
69     */
70    public function defaults() {
71        return array(
72            'title' => esc_html__( 'Blog Stats', 'jetpack' ),
73            /* Translators: Number of views, plural */
74            'hits'  => esc_html__( 'hits', 'jetpack' ),
75        );
76    }
77
78    /**
79     * Return All Time Stats for that blog.
80     *
81     * We query the WordPress.com Stats REST API endpoint.
82     *
83     * @uses Automattic\Jetpack\Stats\WPCOM_Stats->get_stats. That function caches data locally for 5 minutes.
84     *
85     * @return string|false $views All Time Stats for that blog.
86     */
87    public function get_stats() {
88        $wpcom_stats = new WPCOM_Stats();
89        // Get data from the WordPress.com Stats REST API endpoint.
90        $stats = $wpcom_stats->convert_stats_array_to_object( $wpcom_stats->get_stats( array( 'fields' => 'stats' ) ) );
91
92        if ( isset( $stats->stats->views ) ) {
93            return $stats->stats->views;
94        } else {
95            return false;
96        }
97    }
98
99    /**
100     * Back end widget form.
101     *
102     * @see WP_Widget::form()
103     *
104     * @param array $instance Previously saved values from database.
105     *
106     * @return string|void
107     */
108    public function form( $instance ) {
109        $instance = wp_parse_args( $instance, $this->defaults() );
110        ?>
111
112        <p>
113            <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Title:', 'jetpack' ); ?></label>
114            <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>" />
115        </p>
116        <p>
117            <label for="<?php echo esc_attr( $this->get_field_id( 'hits' ) ); ?>"><?php esc_html_e( 'Pageview Description:', 'jetpack' ); ?></label>
118            <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'hits' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'hits' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['hits'] ); ?>" />
119        </p>
120        <p><?php esc_html_e( 'Hit counter is delayed by up to 5 minutes.', 'jetpack' ); ?></p>
121
122        <?php
123    }
124
125    /**
126     * Sanitize widget form values as they are saved.
127     *
128     * @see WP_Widget::update()
129     *
130     * @param array $new_instance Values just sent to be saved.
131     * @param array $old_instance Previously saved values from database.
132     *
133     * @return array Updated safe values to be saved.
134     */
135    public function update( $new_instance, $old_instance ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
136        $instance          = array();
137        $instance['title'] = wp_kses( $new_instance['title'], array() );
138        $instance['hits']  = wp_kses( $new_instance['hits'], array() );
139
140        return $instance;
141    }
142
143    /**
144     * Front-end display of widget.
145     *
146     * @see WP_Widget::widget()
147     *
148     * @param array $args     Widget arguments.
149     * @param array $instance Saved values from database.
150     */
151    public function widget( $args, $instance ) {
152        $instance = wp_parse_args( $instance, $this->defaults() );
153
154        /** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
155        $title = apply_filters( 'widget_title', $instance['title'] );
156
157        echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
158
159        if ( ! empty( $title ) ) {
160            echo $args['before_title'] . $title . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
161        }
162
163        // Get the Site Stats.
164        $views = $this->get_stats();
165
166        if ( 0 === $views ) {
167            esc_html_e( 'There is nothing to display yet', 'jetpack' );
168        } elseif ( $views ) {
169            printf(
170                '<ul><li>%1$s %2$s</li></ul>',
171                esc_html( number_format_i18n( $views ) ),
172                isset( $instance['hits'] ) ? esc_html( $instance['hits'] ) : ''
173            );
174        } else {
175            esc_html_e( 'There was an issue retrieving stats. Please try again later.', 'jetpack' );
176        }
177
178        echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
179
180        /** This action is already documented in modules/widgets/gravatar-profile.php */
181        do_action( 'jetpack_stats_extra', 'widget_view', 'blog_stats' );
182    }
183}
184
185/**
186 * If the Stats module is active in a recent version of Jetpack, register the widget.
187 *
188 * @since 4.5.0
189 */
190function jetpack_blog_stats_widget_init() {
191    if ( Jetpack::is_module_active( 'stats' ) ) {
192        register_widget( 'Jetpack_Blog_Stats_Widget' );
193    }
194}
195add_action( 'widgets_init', 'jetpack_blog_stats_widget_init' );