Completed
Push — update/synced-options-minileve... ( e27c34...006016 )
by Jeremy
09:45 queued 02:35
created

Jetpack_Twitter_Timeline_Widget::update()   D

Complexity

Conditions 12
Paths 288

Size

Total Lines 81

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
nc 288
nop 2
dl 0
loc 81
rs 4.4412
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * Based on Evolution Twitter Timeline
5
 * (https://wordpress.org/extend/plugins/evolution-twitter-timeline/)
6
 * For details on Twitter Timelines see:
7
 *  - https://twitter.com/settings/widgets
8
 *  - https://dev.twitter.com/docs/embedded-timelines
9
 */
10
11
use Automattic\Jetpack\Assets;
12
13
/**
14
 * Register the widget for use in Appearance -> Widgets
15
 */
16
add_action( 'widgets_init', 'jetpack_twitter_timeline_widget_init' );
17
18
function jetpack_twitter_timeline_widget_init() {
19
	register_widget( 'Jetpack_Twitter_Timeline_Widget' );
20
}
21
22
class Jetpack_Twitter_Timeline_Widget extends WP_Widget {
23
	/**
24
	 * Register widget with WordPress.
25
	 */
26
	public function __construct() {
27
		parent::__construct(
28
			'twitter_timeline',
29
			/** This filter is documented in modules/widgets/facebook-likebox.php */
30
			apply_filters( 'jetpack_widget_name', esc_html__( 'Twitter Timeline', 'jetpack' ) ),
31
			array(
32
				'classname'                   => 'widget_twitter_timeline',
33
				'description'                 => __( 'Display an official Twitter Embedded Timeline widget.', 'jetpack' ),
34
				'customize_selective_refresh' => true,
35
			)
36
		);
37
38 View Code Duplication
		if ( is_active_widget( false, false, $this->id_base ) || is_active_widget( false, false, 'monster' ) || is_customize_preview() ) {
39
			add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
40
		}
41
42
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
43
	}
44
45
	/**
46
	 * Enqueue scripts.
47
	 */
48
	public function enqueue_scripts() {
49
		wp_enqueue_script( 'jetpack-twitter-timeline' );
50
	}
51
52
	/**
53
	 * Enqueue Twitter's widget library.
54
	 *
55
	 * @deprecated
56
	 */
57
	public function library() {
58
		_deprecated_function( __METHOD__, '4.0.0' );
59
		wp_print_scripts( array( 'jetpack-twitter-timeline' ) );
60
	}
61
62
	/**
63
	 * Enqueue script to improve admin UI
64
	 */
65
	public function admin_scripts( $hook ) {
66
		// This is still 'widgets.php' when managing widgets via the Customizer.
67
		if ( 'widgets.php' === $hook ) {
68
			wp_enqueue_script(
69
				'twitter-timeline-admin',
70
				Assets::get_file_url_for_environment(
71
					'_inc/build/widgets/twitter-timeline-admin.min.js',
72
					'modules/widgets/twitter-timeline-admin.js'
73
				)
74
			);
75
		}
76
	}
77
78
	/**
79
	 * Front-end display of widget.
80
	 *
81
	 * @see WP_Widget::widget()
82
	 *
83
	 * @param array $args     Widget arguments.
84
	 * @param array $instance Saved values from database.
85
	 */
86
	public function widget( $args, $instance ) {
87
		// Twitter deprecated `data-widget-id` on 2018-05-25,
88
		// with cease support deadline on 2018-07-27.
89
		if ( isset( $instance['type'] ) && 'widget-id' === $instance['type'] ) {
90
			if ( current_user_can( 'edit_theme_options' ) ) {
91
				echo $args['before_widget'];
92
				echo $args['before_title'] . esc_html__( 'Twitter Timeline', 'jetpack' ) . $args['after_title'];
93
				echo '<p>' . esc_html__( "The Twitter Timeline widget can't display tweets based on searches or hashtags. To display a simple list of tweets instead, change the Widget ID to a Twitter username. Otherwise, delete this widget.", 'jetpack' ) . '</p>';
94
				echo '<p>' . esc_html__( '(Only administrators will see this message.)', 'jetpack' ) . '</p>';
95
				echo $args['after_widget'];
96
			}
97
			return;
98
		}
99
100
		$instance['lang'] = substr( strtoupper( get_locale() ), 0, 2 );
101
102
		echo $args['before_widget'];
103
104
		$title = isset( $instance['title'] ) ? $instance['title'] : '';
105
106
		/** This filter is documented in core/src/wp-includes/default-widgets.php */
107
		$title = apply_filters( 'widget_title', $title );
108
		if ( ! empty( $title ) ) {
109
			echo $args['before_title'] . $title . $args['after_title'];
110
		}
111
112
		if ( isset( $instance['type'] ) && 'widget-id' === $instance['type'] && current_user_can( 'edit_theme_options' ) ) {
113
			echo '<p>' . esc_html__( 'As of July 27, 2018, the Twitter Timeline widget will no longer display tweets based on searches or hashtags. To display a simple list of tweets instead, change the Widget ID to a Twitter username.', 'jetpack' ) . '</p>';
114
			echo '<p>' . esc_html__( '(Only administrators will see this message.)', 'jetpack' ) . '</p>';
115
		}
116
117
		// Start tag output
118
		// This tag is transformed into the widget markup by Twitter's
119
		// widgets.js code
120
		echo '<a class="twitter-timeline"';
121
122
		$data_attribs = array(
123
			'width',
124
			'height',
125
			'theme',
126
			'link-color',
127
			'border-color',
128
			'tweet-limit',
129
			'lang',
130
		);
131
		foreach ( $data_attribs as $att ) {
132
			if ( ! empty( $instance[ $att ] ) && ! is_array( $instance[ $att ] ) ) {
133
				echo ' data-' . esc_attr( $att ) . '="' . esc_attr( $instance[ $att ] ) . '"';
134
			}
135
		}
136
137
		/** This filter is documented in modules/shortcodes/tweet.php */
138
		$partner = apply_filters( 'jetpack_twitter_partner_id', 'jetpack' );
139
		if ( ! empty( $partner ) ) {
140
			echo ' data-partner="' . esc_attr( $partner ) . '"';
141
		}
142
143
		/**
144
		 * Allow the activation of Do Not Track for the Twitter Timeline Widget.
145
		 *
146
		 * @see https://developer.twitter.com/en/docs/twitter-for-websites/timelines/guides/parameter-reference.html
147
		 *
148
		 * @module widgets
149
		 *
150
		 * @since 6.9.0
151
		 *
152
		 * @param bool false Should the Twitter Timeline use the DNT attribute? Default to false.
153
		 */
154
		$dnt = apply_filters( 'jetpack_twitter_timeline_default_dnt', false );
155
		if ( true === $dnt ) {
156
			echo ' data-dnt="true"';
157
		}
158
159
		if ( ! empty( $instance['chrome'] ) && is_array( $instance['chrome'] ) ) {
160
			echo ' data-chrome="' . esc_attr( join( ' ', $instance['chrome'] ) ) . '"';
161
		}
162
163
		$type      = ( isset( $instance['type'] ) ? $instance['type'] : '' );
164
		$widget_id = ( isset( $instance['widget-id'] ) ? $instance['widget-id'] : '' );
165
		switch ( $type ) {
166
			case 'profile':
167
				echo ' href="https://twitter.com/' . esc_attr( $widget_id ) . '"';
168
				break;
169
			case 'widget-id':
170
			default:
171
				echo ' data-widget-id="' . esc_attr( $widget_id ) . '"';
172
				break;
173
		}
174
		echo ' href="https://twitter.com/' . esc_attr( $widget_id ) . '"';
175
176
		// End tag output
177
		echo '>';
178
179
		$timeline_placeholder = __( 'My Tweets', 'jetpack' );
180
181
		/**
182
		 * Filter the Timeline placeholder text.
183
		 *
184
		 * @module widgets
185
		 *
186
		 * @since 3.4.0
187
		 *
188
		 * @param string $timeline_placeholder Timeline placeholder text.
189
		 */
190
		$timeline_placeholder = apply_filters( 'jetpack_twitter_timeline_placeholder', $timeline_placeholder );
191
192
		echo esc_html( $timeline_placeholder ) . '</a>';
193
194
		// End tag output
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', 'twitter_timeline' );
200
	}
201
202
203
	/**
204
	 * Sanitize widget form values as they are saved.
205
	 *
206
	 * @see WP_Widget::update()
207
	 *
208
	 * @param array $new_instance Values just sent to be saved.
209
	 * @param array $old_instance Previously saved values from database.
210
	 *
211
	 * @return array Updated safe values to be saved.
212
	 */
213
	public function update( $new_instance, $old_instance ) {
214
		$instance = array();
215
216
		$instance['title'] = sanitize_text_field( $new_instance['title'] );
217
218
		$width = (int) $new_instance['width'];
219
		if ( $width ) {
220
			// From publish.twitter.com: 220 <= width <= 1200
221
			$instance['width'] = min( max( $width, 220 ), 1200 );
222
		} else {
223
			$instance['width'] = '';
224
		}
225
226
		$height = (int) $new_instance['height'];
227
		if ( $height ) {
228
			// From publish.twitter.com: height >= 200
229
			$instance['height'] = max( $height, 200 );
230
		} else {
231
			$instance['height'] = '';
232
		}
233
234
		$tweet_limit = (int) $new_instance['tweet-limit'];
235
		if ( $tweet_limit ) {
236
			$instance['tweet-limit'] = min( max( $tweet_limit, 1 ), 20 );
237
			/**
238
			 * A timeline with a specified limit is expanded to the height of those Tweets.
239
			 * The specified height value no longer applies, so reject the height value
240
			 * when a valid limit is set: a widget attempting to save both limit 5 and
241
			 * height 400 would be saved with just limit 5.
242
			 */
243
			$instance['height'] = '';
244
		} else {
245
			$instance['tweet-limit'] = null;
246
		}
247
248
		// If they entered something that might be a full URL, try to parse it out
249
		if ( is_string( $new_instance['widget-id'] ) ) {
250
			if ( preg_match(
251
				'#https?://twitter\.com/settings/widgets/(\d+)#s',
252
				$new_instance['widget-id'],
253
				$matches
254
			) ) {
255
				$new_instance['widget-id'] = $matches[1];
256
			}
257
		}
258
259
		$instance['widget-id'] = sanitize_text_field( $new_instance['widget-id'] );
260
261
		$hex_regex = '/#([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?\b/';
262
		foreach ( array( 'link-color', 'border-color' ) as $color ) {
263
			$new_color = sanitize_text_field( $new_instance[ $color ] );
264
			if ( preg_match( $hex_regex, $new_color ) ) {
265
				$instance[ $color ] = $new_color;
266
			}
267
		}
268
269
		$instance['type'] = 'profile';
270
271
		$instance['theme'] = 'light';
272
		if ( in_array( $new_instance['theme'], array( 'light', 'dark' ) ) ) {
273
			$instance['theme'] = $new_instance['theme'];
274
		}
275
276
		$instance['chrome'] = array();
277
		$chrome_settings    = array(
278
			'noheader',
279
			'nofooter',
280
			'noborders',
281
			'transparent',
282
			'noscrollbar',
283
		);
284
		if ( isset( $new_instance['chrome'] ) ) {
285
			foreach ( $new_instance['chrome'] as $chrome ) {
286
				if ( in_array( $chrome, $chrome_settings ) ) {
287
					$instance['chrome'][] = $chrome;
288
				}
289
			}
290
		}
291
292
		return $instance;
293
	}
294
295
	/**
296
	 * Returns a link to the documentation for a feature of this widget on
297
	 * Jetpack or WordPress.com.
298
	 */
299
	public function get_docs_link( $hash = '' ) {
300
		if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
301
			$base_url = 'https://support.wordpress.com/widgets/twitter-timeline-widget/';
302
		} else {
303
			$base_url = 'https://jetpack.com/support/extra-sidebar-widgets/twitter-timeline-widget/';
304
		}
305
		return '<a href="' . $base_url . $hash . '" target="_blank">( ? )</a>';
306
	}
307
308
	/**
309
	 * Back end widget form.
310
	 *
311
	 * @see WP_Widget::form()
312
	 *
313
	 * @param array $instance Previously saved values from database.
314
	 */
315
	public function form( $instance ) {
316
		$defaults = array(
317
			'title'        => esc_html__( 'Follow me on Twitter', 'jetpack' ),
318
			'width'        => '',
319
			'height'       => '400',
320
			'type'         => 'profile',
321
			'widget-id'    => '',
322
			'link-color'   => '#f96e5b',
323
			'border-color' => '#e8e8e8',
324
			'theme'        => 'light',
325
			'chrome'       => array(),
326
			'tweet-limit'  => null,
327
		);
328
329
		$instance = wp_parse_args( (array) $instance, $defaults );
330
331
		if ( 'widget-id' === $instance['type'] ) {
332
			$instance['widget-id'] = '';
333
		}
334
335
		$instance['type'] = 'profile';
336
		?>
337
338
		<p>
339
			<label for="<?php echo $this->get_field_id( 'title' ); ?>">
340
				<?php esc_html_e( 'Title:', 'jetpack' ); ?>
341
			</label>
342
			<input
343
				class="widefat"
344
				id="<?php echo $this->get_field_id( 'title' ); ?>"
345
				name="<?php echo $this->get_field_name( 'title' ); ?>"
346
				type="text"
347
				value="<?php echo esc_attr( $instance['title'] ); ?>"
348
			/>
349
		</p>
350
351
		<p>
352
			<label for="<?php echo $this->get_field_id( 'width' ); ?>">
353
				<?php esc_html_e( 'Maximum Width (px; 220 to 1200):', 'jetpack' ); ?>
354
			</label>
355
			<input
356
				class="widefat"
357
				id="<?php echo $this->get_field_id( 'width' ); ?>"
358
				name="<?php echo $this->get_field_name( 'width' ); ?>"
359
				type="number" min="220" max="1200"
360
				value="<?php echo esc_attr( $instance['width'] ); ?>"
361
			/>
362
		</p>
363
364
		<p>
365
			<label for="<?php echo $this->get_field_id( 'height' ); ?>">
366
				<?php esc_html_e( 'Height (px; at least 200):', 'jetpack' ); ?>
367
			</label>
368
			<input
369
				class="widefat"
370
				id="<?php echo $this->get_field_id( 'height' ); ?>"
371
				name="<?php echo $this->get_field_name( 'height' ); ?>"
372
				type="number" min="200"
373
				value="<?php echo esc_attr( $instance['height'] ); ?>"
374
			/>
375
		</p>
376
377
		<p>
378
			<label for="<?php echo $this->get_field_id( 'tweet-limit' ); ?>">
379
				<?php esc_html_e( '# of Tweets Shown (1 to 20):', 'jetpack' ); ?>
380
			</label>
381
			<input
382
				class="widefat"
383
				id="<?php echo $this->get_field_id( 'tweet-limit' ); ?>"
384
				name="<?php echo $this->get_field_name( 'tweet-limit' ); ?>"
385
				type="number" min="1" max="20"
386
				value="<?php echo esc_attr( $instance['tweet-limit'] ); ?>"
387
			/>
388
		</p>
389
390
		<p class="jetpack-twitter-timeline-widget-id-container">
391
			<label for="<?php echo $this->get_field_id( 'widget-id' ); ?>">
392
				<?php esc_html_e( 'Twitter Username:', 'jetpack' ); ?>
393
				<?php echo $this->get_docs_link( '#twitter-username' ); ?>
394
			</label>
395
			<input
396
				class="widefat"
397
				id="<?php echo $this->get_field_id( 'widget-id' ); ?>"
398
				name="<?php echo $this->get_field_name( 'widget-id' ); ?>"
399
				type="text"
400
				value="<?php echo esc_attr( $instance['widget-id'] ); ?>"
401
			/>
402
		</p>
403
404
		<p>
405
			<label for="<?php echo $this->get_field_id( 'chrome-noheader' ); ?>">
406
				<?php esc_html_e( 'Layout Options:', 'jetpack' ); ?>
407
			</label>
408
			<br />
409
			<input
410
				type="checkbox"<?php checked( in_array( 'noheader', $instance['chrome'] ) ); ?>
411
				id="<?php echo $this->get_field_id( 'chrome-noheader' ); ?>"
412
				name="<?php echo $this->get_field_name( 'chrome' ); ?>[]"
413
				value="noheader"
414
			/>
415
			<label for="<?php echo $this->get_field_id( 'chrome-noheader' ); ?>">
416
				<?php esc_html_e( 'No Header', 'jetpack' ); ?>
417
			</label>
418
			<br />
419
			<input
420
				type="checkbox"<?php checked( in_array( 'nofooter', $instance['chrome'] ) ); ?>
421
				id="<?php echo $this->get_field_id( 'chrome-nofooter' ); ?>"
422
				name="<?php echo $this->get_field_name( 'chrome' ); ?>[]"
423
				value="nofooter"
424
			/>
425
			<label for="<?php echo $this->get_field_id( 'chrome-nofooter' ); ?>">
426
				<?php esc_html_e( 'No Footer', 'jetpack' ); ?>
427
			</label>
428
			<br />
429
			<input
430
				type="checkbox"<?php checked( in_array( 'noborders', $instance['chrome'] ) ); ?>
431
				id="<?php echo $this->get_field_id( 'chrome-noborders' ); ?>"
432
				name="<?php echo $this->get_field_name( 'chrome' ); ?>[]"
433
				value="noborders"
434
			/>
435
			<label for="<?php echo $this->get_field_id( 'chrome-noborders' ); ?>">
436
				<?php esc_html_e( 'No Borders', 'jetpack' ); ?>
437
			</label>
438
			<br />
439
			<input
440
				type="checkbox"<?php checked( in_array( 'noscrollbar', $instance['chrome'] ) ); ?>
441
				id="<?php echo $this->get_field_id( 'chrome-noscrollbar' ); ?>"
442
				name="<?php echo $this->get_field_name( 'chrome' ); ?>[]"
443
				value="noscrollbar"
444
			/>
445
			<label for="<?php echo $this->get_field_id( 'chrome-noscrollbar' ); ?>">
446
				<?php esc_html_e( 'No Scrollbar', 'jetpack' ); ?>
447
			</label>
448
			<br />
449
			<input
450
				type="checkbox"<?php checked( in_array( 'transparent', $instance['chrome'] ) ); ?>
451
				id="<?php echo $this->get_field_id( 'chrome-transparent' ); ?>"
452
				name="<?php echo $this->get_field_name( 'chrome' ); ?>[]"
453
				value="transparent"
454
			/>
455
			<label for="<?php echo $this->get_field_id( 'chrome-transparent' ); ?>">
456
				<?php esc_html_e( 'Transparent Background', 'jetpack' ); ?>
457
			</label>
458
		</p>
459
460
		<p>
461
			<label for="<?php echo $this->get_field_id( 'link-color' ); ?>">
462
				<?php _e( 'Link Color (hex):', 'jetpack' ); ?>
463
			</label>
464
			<input
465
				class="widefat"
466
				id="<?php echo $this->get_field_id( 'link-color' ); ?>"
467
				name="<?php echo $this->get_field_name( 'link-color' ); ?>"
468
				type="text"
469
				value="<?php echo esc_attr( $instance['link-color'] ); ?>"
470
			/>
471
		</p>
472
473
		<p>
474
			<label for="<?php echo $this->get_field_id( 'border-color' ); ?>">
475
				<?php _e( 'Border Color (hex):', 'jetpack' ); ?>
476
			</label>
477
			<input
478
				class="widefat"
479
				id="<?php echo $this->get_field_id( 'border-color' ); ?>"
480
				name="<?php echo $this->get_field_name( 'border-color' ); ?>"
481
				type="text"
482
				value="<?php echo esc_attr( $instance['border-color'] ); ?>"
483
			/>
484
		</p>
485
486
		<p>
487
			<label for="<?php echo $this->get_field_id( 'theme' ); ?>">
488
				<?php _e( 'Timeline Theme:', 'jetpack' ); ?>
489
			</label>
490
			<select
491
				name="<?php echo $this->get_field_name( 'theme' ); ?>"
492
				id="<?php echo $this->get_field_id( 'theme' ); ?>"
493
				class="widefat"
494
			>
495
				<option value="light"<?php selected( $instance['theme'], 'light' ); ?>>
496
					<?php esc_html_e( 'Light', 'jetpack' ); ?>
497
				</option>
498
				<option value="dark"<?php selected( $instance['theme'], 'dark' ); ?>>
499
					<?php esc_html_e( 'Dark', 'jetpack' ); ?>
500
				</option>
501
			</select>
502
		</p>
503
	<?php
504
	}
505
}
506