PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3
Jetpack – WP Security, Backup, Speed, & Growth v16.3
16.3 16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 All 508 releases
← All changes | modules/widgets/my-community.php +320 -0 16.2-beta → 16.3 View file →
@@ -1,0 +1,320 @@
1 +<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2 +
3 +// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move classes to appropriately-named class files.
4 +
5 +use Automattic\Jetpack\Redirect;
6 +
7 +// Disable direct access/execution to/of the widget code.
8 +if ( ! defined( 'ABSPATH' ) ) {
9 + exit( 0 );
10 +}
11 +
12 +/**
13 + * Jetpack_My_Community_Widget displays community members of this site.
14 + *
15 + * A community member is a WordPress.com user that liked or commented on an entry or subscribed to the site.
16 + * Requires WordPress.com connection to work. Otherwise it won't be visible in Widgets screen in admin.
17 + */
18 +class Jetpack_My_Community_Widget extends WP_Widget {
19 + /**
20 + * Transient expiration time.
21 + *
22 + * @var int $expiration
23 + */
24 + public static $expiration = 600;
25 +
26 + /**
27 + * Default widget title.
28 + *
29 + * @var string $default_title
30 + */
31 + public $default_title;
32 +
33 + /**
34 + * Registers the widget with WordPress.
35 + */
36 + public function __construct() {
37 + parent::__construct(
38 + 'jetpack_my_community', // Base ID.
39 + /** This filter is documented in modules/widgets/facebook-likebox.php */
40 + apply_filters( 'jetpack_widget_name', esc_html__( 'My Community', 'jetpack' ) ),
41 + array(
42 + 'description' => esc_html__( "Display members of your site's community.", 'jetpack' ),
43 + 'customize_selective_refresh' => true,
44 + )
45 + );
46 +
47 + $this->default_title = esc_html__( 'Community', 'jetpack' );
48 +
49 + add_filter( 'widget_types_to_hide_from_legacy_widget_block', array( $this, 'hide_widget_in_block_editor' ) );
50 + }
51 +
52 + /**
53 + * Remove the "My Community" widget from the Legacy Widget block
54 + *
55 + * @param array $widget_types List of widgets that are currently removed from the Legacy Widget block.
56 + * @return array $widget_types New list of widgets that will be removed.
57 + */
58 + public function hide_widget_in_block_editor( $widget_types ) {
59 + $widget_types[] = 'jetpack_my_community';
60 + return $widget_types;
61 + }
62 +
63 + /**
64 + * Enqueue stylesheet for grid layout.
65 + */
66 + public function enqueue_style() {
67 + wp_register_style( 'jetpack-my-community-widget', plugins_url( 'my-community/style.css', __FILE__ ), array(), '20160129' );
68 + wp_enqueue_style( 'jetpack-my-community-widget' );
69 + }
70 +
71 + /**
72 + * Back end widget form.
73 + *
74 + * @see WP_Widget::form()
75 + *
76 + * @param array $instance Previously saved values from database.
77 + *
78 + * @return string|void
79 + */
80 + public function form( $instance ) {
81 + $title = $instance['title'] ?? false;
82 + if ( false === $title ) {
83 + $title = $this->default_title;
84 + }
85 +
86 + $number = isset( $instance['number'] ) ? (int) $instance['number'] : 10;
87 + if ( ! in_array( $number, array( 10, 50 ), true ) ) {
88 + $number = 10;
89 + }
90 +
91 + $include_likers = isset( $instance['include_likers'] ) ? (bool) $instance['include_likers'] : true;
92 + $include_followers = isset( $instance['include_followers'] ) ? (bool) $instance['include_followers'] : true;
93 + $include_commenters = isset( $instance['include_commenters'] ) ? (bool) $instance['include_commenters'] : true;
94 + ?>
95 +
96 + <p>
97 + <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Title:', 'jetpack' ); ?></label>
98 + <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( $title ); ?>" />
99 + </p>
100 +
101 + <p>
102 + <label><?php esc_html_e( 'Show a maximum of', 'jetpack' ); ?></label>
103 + </p>
104 + <ul>
105 + <li><label><input id="<?php echo esc_attr( $this->get_field_id( 'number' ) ); ?>-few" name="<?php echo esc_attr( $this->get_field_name( 'number' ) ); ?>" type="radio" value="10" <?php checked( '10', $number ); ?> /> <?php esc_html_e( '10 community members', 'jetpack' ); ?></label></li>
106 + <li><label><input id="<?php echo esc_attr( $this->get_field_id( 'number' ) ); ?>-lots" name="<?php echo esc_attr( $this->get_field_name( 'number' ) ); ?>" type="radio" value="50" <?php checked( '50', $number ); ?> /> <?php esc_html_e( '50 community members', 'jetpack' ); ?></label></li>
107 + </ul>
108 +
109 + <p>
110 + <label for="<?php echo esc_attr( $this->get_field_id( 'include_likers' ) ); ?>">
111 + <input type="checkbox" class="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'include_likers' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'include_likers' ) ); ?>" value="1" <?php checked( $include_likers, 1 ); ?> />
112 + <?php esc_html_e( 'Include activity from likers', 'jetpack' ); ?>
113 + </label>
114 + </p>
115 +
116 + <p>
117 + <label for="<?php echo esc_attr( $this->get_field_id( 'include_followers' ) ); ?>">
118 + <input type="checkbox" class="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'include_followers' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'include_followers' ) ); ?>" value="1" <?php checked( $include_followers, 1 ); ?> />
119 + <?php esc_html_e( 'Include activity from followers', 'jetpack' ); ?>
120 + </label>
121 + </p>
122 +
123 + <p>
124 + <label for="<?php echo esc_attr( $this->get_field_id( 'include_commenters' ) ); ?>">
125 + <input type="checkbox" class="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'include_commenters' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'include_commenters' ) ); ?>" value="1" <?php checked( $include_commenters, 1 ); ?> />
126 + <?php esc_html_e( 'Include activity from commenters', 'jetpack' ); ?>
127 + </label>
128 + </p>
129 +
130 + <?php
131 + }
132 +
133 + /**
134 + * Sanitize widget form values as they are saved.
135 + *
136 + * @see WP_Widget::update()
137 + *
138 + * @param array $new_instance Values just sent to be saved.
139 + * @param array $old_instance Previously saved values from database.
140 + *
141 + * @return array Updated safe values to be saved.
142 + */
143 + public function update( $new_instance, $old_instance ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
144 + $instance = array();
145 + $instance['title'] = wp_kses( $new_instance['title'] ?? '', array() );
146 + if ( $instance['title'] === $this->default_title ) {
147 + $instance['title'] = false; // Store as false in case of language change.
148 + }
149 +
150 + $instance['number'] = (int) ( $new_instance['number'] ?? 0 );
151 + if ( ! in_array( $instance['number'], array( 10, 50 ), true ) ) {
152 + $instance['number'] = 10;
153 + }
154 +
155 + $instance['include_likers'] = ! empty( $new_instance['include_likers'] );
156 + $instance['include_followers'] = ! empty( $new_instance['include_followers'] );
157 + $instance['include_commenters'] = ! empty( $new_instance['include_commenters'] );
158 +
159 + delete_transient( "$this->id-v2-{$instance['number']}" . (int) $instance['include_likers'] . (int) $instance['include_followers'] . (int) $instance['include_commenters'] );
160 +
161 + return $instance;
162 + }
163 +
164 + /**
165 + * Front-end display of widget.
166 + *
167 + * @see WP_Widget::widget()
168 + *
169 + * @param array $args Widget arguments.
170 + * @param array $instance Saved values from database.
171 + */
172 + public function widget( $args, $instance ) {
173 + $args = wp_parse_args(
174 + $args,
175 + array(
176 + 'before_widget' => '',
177 + 'after_widget' => '',
178 + 'before_title' => '',
179 + 'after_title' => '',
180 + )
181 + );
182 + $instance = wp_parse_args(
183 + $instance,
184 + array(
185 + 'title' => false,
186 + 'number' => true,
187 + 'include_likers' => true,
188 + 'include_followers' => true,
189 + 'include_commenters' => true,
190 + )
191 + );
192 +
193 + $title = $instance['title'];
194 +
195 + if ( false === $title ) {
196 + $title = $this->default_title;
197 + }
198 +
199 + // Enqueue front end assets.
200 + $this->enqueue_style();
201 +
202 + echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
203 +
204 + /** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
205 + $title = apply_filters( 'widget_title', $title );
206 + if ( ! empty( $title ) ) {
207 + echo $args['before_title'] . $title . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
208 + }
209 +
210 + $transient_name = "$this->id-v2-{$instance['number']}" . (int) $instance['include_likers'] . (int) $instance['include_followers'] . (int) $instance['include_commenters'];
211 +
212 + $my_community = get_transient( $transient_name );
213 +
214 + if ( empty( $my_community ) ) {
215 + $my_community = $this->get_community( $instance );
216 +
217 + set_transient( $transient_name, $my_community, self::$expiration );
218 + }
219 +
220 + echo $my_community; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
221 +
222 + echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
223 +
224 + /** This action is documented in modules/widgets/gravatar-profile.php */
225 + do_action( 'jetpack_stats_extra', 'widget_view', 'my_community' );
226 + }
227 +
228 + /**
229 + * Initiate request and render the response.
230 + *
231 + * @since 4.0
232 + *
233 + * @param array $query Saved widget values from database.
234 + *
235 + * @return string
236 + */
237 + private function get_community( $query ) {
238 + $members = $this->fetch_remote_community( $query );
239 +
240 + if ( ! empty( $members ) ) {
241 +
242 + $my_community = '<div class="widgets-multi-column-grid"><ul>';
243 +
244 + foreach ( $members as $member ) {
245 + $my_community .= sprintf(
246 + '<li><a href="%s" title="%s"><img alt="%s" src="%s" class="avatar avatar-48" height="48" width="48"></a></li>',
247 + esc_url( $member->profile_URL ), // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
248 + esc_attr( $member->name ),
249 + esc_attr( $member->name ),
250 + esc_url( $member->avatar_URL ) // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
251 + );
252 + }
253 +
254 + $my_community .= '</ul></div>';
255 +
256 + } elseif ( current_user_can( 'edit_theme_options' ) ) {
257 + $my_community = '<p>' . wp_kses(
258 + sprintf(
259 + /* Translators: 1. link to the widgets settings screen. 2. link to support document. */
260 + __( 'There are no users to display in this <a href="%1$s">My Community widget</a>. <a href="%2$s">Want more traffic?</a>', 'jetpack' ),
261 + admin_url( 'widgets.php' ),
262 + esc_url( Redirect::get_url( 'jetpack-support-getting-more-views-and-traffic' ) )
263 + ),
264 + array( 'a' => array( 'href' => true ) )
265 + ) . '</p>';
266 + } else {
267 + $my_community = '<p>' . esc_html__( "I'm just starting out; leave me a comment or a like :)", 'jetpack' ) . '</p>';
268 + }
269 +
270 + return $my_community;
271 + }
272 +
273 + /**
274 + * Request community members to WordPress.com endpoint.
275 + *
276 + * @since 4.0
277 + *
278 + * @param array $query Saved widget values from database.
279 + *
280 + * @return array
281 + */
282 + private function fetch_remote_community( $query ) {
283 + $jetpack_blog_id = Jetpack_Options::get_option( 'id' );
284 + $url = add_query_arg(
285 + array(
286 + 'number' => $query['number'],
287 + 'likers' => (int) $query['include_likers'],
288 + 'followers' => (int) $query['include_followers'],
289 + 'commenters' => (int) $query['include_commenters'],
290 + ),
291 + "https://public-api.wordpress.com/rest/v1.1/sites/$jetpack_blog_id/community"
292 + );
293 + $response = wp_remote_get( $url );
294 + $response_body = wp_remote_retrieve_body( $response );
295 +
296 + if ( empty( $response_body ) ) {
297 + return array();
298 + }
299 +
300 + $response_body = json_decode( $response_body );
301 +
302 + if ( isset( $response_body->users ) ) {
303 + return $response_body->users;
304 + }
305 +
306 + return array();
307 + }
308 +}
309 +
310 +/**
311 + * If site is connected to WordPress.com, register the widget.
312 + *
313 + * @since 4.0
314 + */
315 +function jetpack_my_community_init() {
316 + if ( Jetpack::is_connection_ready() ) {
317 + register_widget( 'Jetpack_My_Community_Widget' );
318 + }
319 +}
320 +add_action( 'widgets_init', 'jetpack_my_community_init' );