Completed
Push — update/community-wording ( c646d8...a8d204 )
by Jeremy
80:28 queued 73:19
created

Jetpack_My_Community_Widget   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 263
Duplicated Lines 6.46 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 17
loc 263
rs 10
c 0
b 0
f 0
wmc 28
lcom 1
cbo 1

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 17 17 4
A enqueue_style() 0 4 1
C form() 0 52 8
A update() 0 20 3
B widget() 0 41 4
B get_community() 0 30 5
B fetch_remote_community() 0 26 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * Disable direct access/execution to/of the widget code.
4
 */
5
if ( ! defined( 'ABSPATH' ) ) {
6
	exit;
7
}
8
9
/**
10
 * Jetpack_My_Community_Widget displays community members of this site.
11
 *
12
 * A community member is a WordPress.com user that liked or commented on an entry or subscribed to the site.
13
 * Requires WordPress.com connection to work. Otherwise it won't be visible in Widgets screen in admin.
14
 */
15
class Jetpack_My_Community_Widget extends WP_Widget {
16
	/**
17
	 * Transient expiration time.
18
	 *
19
	 * @var int $expiration
20
	 */
21
	static $expiration = 600;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $expiration.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
22
23
	/**
24
	 * Default widget title.
25
	 *
26
	 * @var string $default_title
27
	 */
28
	var $default_title;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $default_title.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
29
30
	/**
31
	 * Registers the widget with WordPress.
32
	 */
33 View Code Duplication
	function __construct() {
34
		parent::__construct(
35
			'jetpack_my_community', // Base ID
36
			/** This filter is documented in modules/widgets/facebook-likebox.php */
37
			apply_filters( 'jetpack_widget_name', esc_html__( 'My Community', 'jetpack' ) ),
38
			array(
39
				'description' => esc_html__( 'A sampling of users from your blog.', 'jetpack' ),
40
				'customize_selective_refresh' => true,
41
			)
42
		);
43
44
		if ( is_active_widget( false, false, $this->id_base ) || is_active_widget( false, false, 'monster' ) || is_customize_preview() ) {
45
			add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_style' ) );
46
		}
47
48
		$this->default_title = esc_html__( 'Community', 'jetpack' );
49
	}
50
51
	/**
52
	 * Enqueue stylesheet for grid layout.
53
	 */
54
	function enqueue_style() {
55
		wp_register_style( 'jetpack-my-community-widget', plugins_url( 'my-community/style.css', __FILE__ ), array(), '20160129' );
56
		wp_enqueue_style( 'jetpack-my-community-widget' );
57
	}
58
59
	/**
60
	 * Back-end widget form.
61
	 *
62
	 * @see WP_Widget::form()
63
	 *
64
	 * @param array $instance Previously saved values from database.
65
	 *
66
	 * @return string|void
67
	 */
68
	function form( $instance ) {
69
		$title = isset( $instance['title' ] ) ? $instance['title'] : false;
70
		if ( false === $title ) {
71
			$title = $this->default_title;
72
		}
73
74
		$number = isset( $instance['number'] ) ? $instance['number'] : 10;
75
		if ( ! in_array( $number, array( 10, 50 ) ) ) {
76
			$number = 10;
77
		}
78
79
		$include_likers     = isset( $instance['include_likers'] )     ? (bool) $instance['include_likers']     : true;
80
		$include_followers  = isset( $instance['include_followers'] )  ? (bool) $instance['include_followers']  : true;
81
		$include_commenters = isset( $instance['include_commenters'] ) ? (bool) $instance['include_commenters'] : true;
82
		?>
83
84
		<p>
85
			<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php esc_html_e( 'Title:', 'jetpack' ); ?></label>
86
			<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
87
		</p>
88
89
		<p>
90
			<label><?php esc_html_e( 'Show a maximum of', 'jetpack' ); ?></label>
91
		</p>
92
		<ul>
93
			<li><label><input id="<?php echo $this->get_field_id( 'number' ); ?>-few"  name="<?php echo $this->get_field_name( 'number' ); ?>" type="radio" value="10" <?php checked( '10', $number ); ?> /> <?php esc_html_e( '10 community members', 'jetpack' ); ?></label></li>
94
			<li><label><input id="<?php echo $this->get_field_id( 'number' ); ?>-lots" name="<?php echo $this->get_field_name( 'number' ); ?>" type="radio" value="50" <?php checked( '50', $number ); ?> /> <?php esc_html_e( '50 community members', 'jetpack' ); ?></label></li>
95
		</ul>
96
97
		<p>
98
			<label for="<?php echo $this->get_field_id( 'include_likers' ); ?>">
99
				<input type="checkbox" class="checkbox"  id="<?php echo $this->get_field_id( 'include_likers' ); ?>" name="<?php echo $this->get_field_name( 'include_likers' ); ?>" value="1" <?php checked( $include_likers, 1 ); ?> />
100
				<?php esc_html_e( 'Include activity from likers', 'jetpack' ); ?>
101
			</label>
102
		</p>
103
104
		<p>
105
			<label for="<?php echo $this->get_field_id( 'include_followers' ); ?>">
106
				<input type="checkbox" class="checkbox"  id="<?php echo $this->get_field_id( 'include_followers' ); ?>" name="<?php echo $this->get_field_name( 'include_followers' ); ?>" value="1" <?php checked( $include_followers, 1 ); ?> />
107
				<?php esc_html_e( 'Include activity from followers', 'jetpack' ); ?>
108
			</label>
109
		</p>
110
111
		<p>
112
			<label for="<?php echo $this->get_field_id( 'include_commenters' ); ?>">
113
				<input type="checkbox" class="checkbox"  id="<?php echo $this->get_field_id( 'include_commenters' ); ?>" name="<?php echo $this->get_field_name( 'include_commenters' ); ?>" value="1" <?php checked( $include_commenters, 1 ); ?> />
114
				<?php esc_html_e( 'Include activity from commenters', 'jetpack' ); ?>
115
			</label>
116
		</p>
117
118
		<?php
119
	}
120
121
	/**
122
	 * Sanitize widget form values as they are saved.
123
	 *
124
	 * @see WP_Widget::update()
125
	 *
126
	 * @param array $new_instance Values just sent to be saved.
127
	 * @param array $old_instance Previously saved values from database.
128
	 *
129
	 * @return array Updated safe values to be saved.
130
	 */
131
	function update( $new_instance, $old_instance ) {
132
		$instance = array();
133
		$instance['title'] = wp_kses( $new_instance['title'], array() );
134
		if ( $instance['title'] === $this->default_title ) {
135
			$instance['title'] = false; // Store as false in case of language change
136
		}
137
138
		$instance['number'] = (int) $new_instance['number'];
139
		if ( !in_array( $instance['number'], array( 10, 50 ) ) ) {
140
			$instance['number'] = 10;
141
		}
142
143
		$instance['include_likers']     = (bool) $new_instance['include_likers'];
144
		$instance['include_followers']  = (bool) $new_instance['include_followers'];
145
		$instance['include_commenters'] = (bool) $new_instance['include_commenters'];
146
147
		delete_transient( "$this->id-{$instance['number']}" . (int) $instance['include_likers'] . (int) $instance['include_followers'] . (int) $instance['include_commenters'] );
148
149
		return $instance;
150
	}
151
152
	/**
153
	 * Front-end display of widget.
154
	 *
155
	 * @see WP_Widget::widget()
156
	 *
157
	 * @param array $args     Widget arguments.
158
	 * @param array $instance Saved values from database.
159
	 */
160
	function widget( $args, $instance ) {
161
		$instance = wp_parse_args( $instance, array(
162
			'title'              => false,
163
			'number'             => true,
164
			'include_likers'     => true,
165
			'include_followers'  => true,
166
			'include_commenters' => true,
167
		) );
168
169
		$title = $instance['title'];
170
171
		if ( false === $title ) {
172
			$title = $this->default_title;
173
		}
174
175
		/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
176
		$title = apply_filters( 'widget_title', $title );
177
178
		echo $args['before_widget'];
179
180
		if ( ! empty( $title ) ) {
181
			echo $args['before_title'] . $title . $args['after_title'];
182
		}
183
184
		$transient_name = "$this->id-{$instance['number']}" . (int) $instance['include_likers'] . (int) $instance['include_followers'] . (int) $instance['include_commenters'];
185
186
		$my_community = get_transient( $transient_name );
187
188
		if ( empty( $my_community ) ) {
189
			$my_community = $this->get_community( $instance );
190
191
			set_transient( $transient_name, $my_community, self::$expiration );
192
		}
193
194
		echo $my_community;
195
196
		echo $args['after_widget'];
197
198
		/** This action is documented in modules/widgets/gravatar-profile.php */
199
		do_action( 'jetpack_stats_extra', 'widget_view', 'my_community' );
200
	}
201
202
	/**
203
	 * Initiate request and render the response.
204
	 *
205
	 * @since 4.0
206
	 *
207
	 * @param array $query
208
	 *
209
	 * @return string
210
	 */
211
	function get_community( $query ) {
212
		$members = $this->fetch_remote_community( $query );
213
214
		if ( ! empty( $members ) ) {
215
216
			$my_community = '<div class="widgets-multi-column-grid"><ul>';
217
218
			foreach ( $members as $member ) {
219
				$my_community .= sprintf( '<li><a href="%s" %s><img alt="" src="%s" class="avatar avatar-240" height="48" width="48" originals="240" scale="1" /></a></li>',
220
					$member->profile_URL,
221
					empty( $member->name ) ? '' : 'title="' . $member->name . '"',
222
					$member->avatar_URL
223
				);
224
			}
225
226
			$my_community .= '</ul></div>';
227
228
		} else {
229
			if ( current_user_can( 'edit_theme_options' ) ) {
230
				$my_community = '<p>' . wp_kses( sprintf( __( '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' ),
231
						admin_url( 'widgets.php' ),
232
						'http://en.support.wordpress.com/getting-more-site-traffic/'
233
					), array( 'a' => array( 'href' => true ) ) ) . '</p>';
234
			} else {
235
				$my_community = '<p>' . esc_html__( "I'm just starting out; leave me a comment or a like :)", 'jetpack' ) . '</p>';
236
			}
237
		}
238
239
		return $my_community;
240
	}
241
242
	/**
243
	 * Request community members to WordPress.com endpoint.
244
	 *
245
	 * @since 4.0
246
	 *
247
	 * @param $query
248
	 *
249
	 * @return array
250
	 */
251
	function fetch_remote_community( $query ) {
252
		$jetpack_blog_id = Jetpack_Options::get_option( 'id' );
253
		$url = add_query_arg(
254
			array(
255
				'number'     => $query['number'],
256
				'likers'     => (int) $query['include_likers'],
257
				'followers'  => (int) $query['include_followers'],
258
				'commenters' => (int) $query['include_commenters'],
259
			),
260
			"https://public-api.wordpress.com/rest/v1.1/sites/$jetpack_blog_id/community"
261
		);
262
		$response = wp_remote_get( $url );
263
		$response_body = wp_remote_retrieve_body( $response );
264
265
		if ( empty( $response_body ) ) {
266
			return array();
267
		}
268
269
		$response_body = json_decode( $response_body );
270
271
		if ( isset( $response_body->users ) ) {
272
			return $response_body->users;
273
		}
274
275
		return array();
276
	}
277
}
278
279
/**
280
 * If site is connected to WordPress.com, register the widget.
281
 *
282
 * @since 4.0
283
 */
284
function jetpack_my_community_init() {
285
	if ( Jetpack::is_active() ) {
286
		register_widget( 'Jetpack_My_Community_Widget' );
287
	}
288
}
289
290
add_action( 'widgets_init', 'jetpack_my_community_init' );
291