Completed
Push — social-icons-widget ( 62f89e )
by
unknown
24:17 queued 12:56
created

social-icons.php ➔ jetpack_widget_social_icons_load()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
class Jetpack_Widget_Social_Icons extends WP_Widget {
3
	/**
4
	 * @var array Default widget options.
5
	 */
6
	protected $defaults;
7
8
	/**
9
	 * @var array protocols that are allowed in esc_url validation function.
10
	 */
11
	protected $protocols = array( 'http', 'https', 'mailto', 'skype' );
12
13
	/**
14
	 * Widget constructor.
15
	 */
16
	public function __construct() {
17
		$widget_ops = array(
18
			'classname'                   => 'jetpack_widget_social_icons',
19
			'description'                 => esc_html__( 'Add social-media icons to your site.', 'jetpack' ),
20
			'customize_selective_refresh' => true,
21
		);
22
23
		parent::__construct( 'jetpack_widget_social_icons', esc_html__( 'Social Icons', 'jetpack' ), $widget_ops );
24
25
		$this->defaults = array(
26
			'title'     => esc_html__( 'Follow Us', 'jetpack' ),
27
			'icon-size' => 'medium',
28
			'icons'     => array(
29
				array(
30
					'url'   => '',
31
				),
32
			),
33
		);
34
35
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
36
		add_action( 'admin_print_footer_scripts', array( $this, 'render_admin_js' ) );
37
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_icon_scripts' ) );
38
		add_action( 'wp_footer', array( $this, 'jetpack_social_menu_include_svg_icons' ), 9999 );
39
	}
40
41
	/**
42
	 * Script & styles for admin widget form.
43
	 */
44
	public function enqueue_admin_scripts() {
45
		wp_enqueue_script( 'jetpack-widget-social-icons-script', plugins_url( 'social-icons/social-icons-admin.js', __FILE__ ), array( 'jquery-ui-sortable' ), '20170506' );
46
		wp_enqueue_style( 'jetpack-widget-social-icons-admin', plugins_url( 'social-icons/social-icons-admin.css', __FILE__ ), array(), '20170506' );
47
	}
48
49
	/**
50
	 * Styles for front-end widget.
51
	 */
52
	public function enqueue_icon_scripts() {
53
		wp_enqueue_style( 'jetpack-widget-social-icons-styles', plugins_url( 'social-icons/social-icons.css', __FILE__ ), array(), '20170506' );
54
	}
55
56
	/**
57
	 * JavaScript for admin widget form.
58
	 */
59
	public function render_admin_js() {
60
	?>
61
		<script type="text/html" id="tmpl-jetpack-widget-social-icons-template">
62
			<?php self::render_icons_template(); ?>
63
		</script>
64
	<?php
65
	}
66
67
	/**
68
	 * Add SVG definitions to the footer.
69
	 */
70
	public function jetpack_social_menu_include_svg_icons() {
71
		// Define SVG sprite file.
72
		$svg_icons = dirname( dirname( __FILE__ ) ) . '/theme-tools/social-menu/social-menu.svg';
73
74
		// If it exists, include it.
75
		if ( file_exists( $svg_icons ) ) {
76
			require_once( $svg_icons );
77
		}
78
	}
79
80
	/**
81
	 * Front-end display of widget.
82
	 *
83
	 * @see WP_Widget::widget()
84
	 *
85
	 * @param array $args Widget arguments.
86
	 * @param array $instance Saved values from database.
87
	 */
88
	public function widget( $args, $instance ) {
89
		$instance = wp_parse_args( (array) $instance, $this->defaults );
90
91
		/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
92
		$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );
93
94
		echo $args['before_widget'];
95
96 View Code Duplication
		if ( ! empty( $title ) ) {
97
			echo $args['before_title'] . esc_html( $title ) . $args['after_title'];
98
		}
99
100
		if ( ! empty( $instance['icons'] ) ) :
101
102
			// Get supported social icons.
103
			$social_labels = jetpack_social_menu_social_links_labels();
104
			$social_icons  = jetpack_social_menu_social_links_icons();
105
		?>
106
107
			<ul class="jetpack-social-widget-list size-<?php echo esc_attr( $instance['icon-size'] ); ?>">
108
109
				<?php foreach ( $instance['icons'] as $icon ) : ?>
110
111
					<?php if ( ! empty( $icon['url'] ) ) : ?>
112
						<li class="jetpack-social-widget-item">
113
							<a href="<?php echo esc_url( $icon['url'], $this->protocols ); ?>">
114
								<?php
115
									// Add a label if there is supported URL.
116
									foreach ( $social_labels as $attr => $value ) {
117
										if ( false !== strpos( $icon['url'], $attr ) ) {
118
											echo '<span class="screen-reader-text">' . esc_attr( $value ) . '</span>';
119
										}
120
									}
121
122
									$icon_output = jetpack_social_menu_get_svg( array( 'icon' => 'chain' ) );
123
124
									// Change SVG icon inside social links menu if there is supported URL.
125
									foreach ( $social_icons as $attr => $value ) {
126
										if ( false !== strpos( $icon['url'], $attr ) ) {
127
											$icon_output = jetpack_social_menu_get_svg( array( 'icon' => esc_attr( $value ) ) );
128
										}
129
									}
130
131
									echo $icon_output;
132
								?>
133
							</a>
134
						</li>
135
					<?php endif; ?>
136
137
				<?php endforeach; ?>
138
139
			</ul>
140
141
		<?php
142
		endif;
143
144
		echo $args['after_widget'];
145
	}
146
147
	/**
148
	 * Sanitize widget form values as they are saved.
149
	 *
150
	 * @see WP_Widget::update()
151
	 *
152
	 * @param array $new_instance Values just sent to be saved.
153
	 * @param array $old_instance Previously saved values from database.
154
	 *
155
	 * @return array Updated safe values to be saved.
156
	 */
157
	public function update( $new_instance, $old_instance ) {
158
		$instance['title']     = sanitize_text_field( $new_instance['title'] );
0 ignored issues
show
Coding Style Comprehensibility introduced by
$instance was never initialized. Although not strictly required by PHP, it is generally a good practice to add $instance = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
159
		$instance['icon-size'] = $this->defaults['icon-size'];
160
161
		if ( in_array( $new_instance['icon-size'], array( 'small', 'medium', 'large' ) ) ) {
162
			$instance['icon-size'] = $new_instance['icon-size'];
163
		}
164
165
		$icon_count        = count( $new_instance['url-icons'] );
166
		$instance['icons'] = array();
167
168
		for ( $i = 0; $i < $icon_count; $i++ ) {
169
			$url = filter_var( $new_instance['url-icons'][ $i ], FILTER_SANITIZE_URL );
170
171
			if ( ! empty( $url ) ) {
172
				$instance['icons'][] = array(
173
					'url' => $url,
174
				);
175
			}
176
		}
177
178
		return $instance;
179
	}
180
181
	/**
182
	 * Back-end widget form.
183
	 *
184
	 * @see WP_Widget::form()
185
	 *
186
	 * @param array $instance Previously saved values from database.
187
	 *
188
	 * @return string|void
189
	 */
190
	public function form( $instance ) {
191
		$instance = wp_parse_args( (array) $instance, $this->defaults );
192
		$title    = sanitize_text_field( $instance['title'] );
193
		$sizes    = array(
194
			'small'  => esc_html__( 'Small', 'jetpack' ),
195
			'medium' => esc_html__( 'Medium', 'jetpack' ),
196
			'large'  => esc_html__( 'Large', 'jetpack' ),
197
		);
198
		?>
199
200
		<p>
201
			<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php esc_html_e( 'Title:', 'jetpack' ); ?></label>
202
			<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 ); ?>" />
203
		</p>
204
205
		<p>
206
			<label for="<?php echo $this->get_field_id( 'icon-size' ); ?>"><?php esc_html_e( 'Size:', 'jetpack' ); ?></label>
207
			<select class="widefat" name="<?php echo $this->get_field_name( 'icon-size' ); ?>">
208
				<?php foreach ( $sizes as $value => $label ) : ?>
209
					<option value="<?php echo esc_attr( $value ); ?>" <?php selected( $value, $instance['icon-size'] ); ?>><?php echo esc_attr( $label ); ?></option>
210
				<?php endforeach; ?>
211
			</select>
212
		</p>
213
214
		<div class="jetpack-social-icons-widget-list"
215
			data-url-icon-id="<?php echo $this->get_field_id( 'url-icons' ); ?>"
216
			data-url-icon-name="<?php echo $this->get_field_name( 'url-icons' ); ?>"
217
		>
218
219
			<?php
220
				foreach ( $instance['icons'] as $icon ) {
221
					self::render_icons_template( array(
222
						'url-icon-id'   => $this->get_field_id( 'url-icons' ),
223
						'url-icon-name' => $this->get_field_name( 'url-icons' ),
224
						'url-value'     => $icon['url'],
225
					) );
226
				}
227
			?>
228
229
		</div>
230
231
		<p class="jetpack-social-icons-widget add-button">
232
			<button type="button" class="button jetpack-social-icons-add-button">
233
				<?php esc_html_e( 'Add an icon', 'jetpack' ); ?>
234
			</button>
235
		</p>
236
237
		<?php
238
			$support     = 'https://en.support.wordpress.com/widgets/social-media-icons-widget/#available-icons';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned correctly; expected 1 space but found 5 spaces

This check looks for improperly formatted assignments.

Every assignment must have exactly one space before and one space after the equals operator.

To illustrate:

$a = "a";
$ab = "ab";
$abc = "abc";

will have no issues, while

$a   = "a";
$ab  = "ab";
$abc = "abc";

will report issues in lines 1 and 2.

Loading history...
239
			if ( 'es' === get_locale() ) {
240
				$support = 'https://es.support.wordpress.com/social-media-icons-widget/#iconos-disponibles';
241
			}
242
			if ( 'pt-br' === get_locale() ) {
243
				$support = 'https://br.support.wordpress.com/widgets/widget-de-icones-sociais/#ícones-disponíveis';
244
			}
245
		?>
246
247
		<p>
248
			<em><a href="<?php echo esc_url( $support ); ?>" target="_blank">
249
				<?php esc_html_e( 'View available icons', 'jetpack' ); ?>
250
			</a></em>
251
		</p>
252
253
	<?php
254
	}
255
256
	/**
257
	 * Generates template to add icons.
258
	 *
259
	 * @param array $args Template arguments
260
	 */
261
	static function render_icons_template( $args = array() ) {
262
		$defaults = array(
263
			'url-icon-id'   => '',
264
			'url-icon-name' => '',
265
			'url-value'     => '',
266
		);
267
268
		$args = wp_parse_args( $args, $defaults );
269
		?>
270
271
		<div class="jetpack-social-icons-widget-item">
272
			<div class="jetpack-social-icons-widget-item-wrapper">
273
				<div class="handle"></div>
274
275
				<p class="jetpack-widget-social-icons-url">
276
					<?php
277
						printf( '<input class="widefat id="%1$s" name="%2$s[]" type="text" placeholder="%3$s" value="%4$s"/>',
278
							esc_attr( $args['url-icon-id'] ),
279
							esc_attr( $args['url-icon-name'] ),
280
							esc_attr__( 'Account URL', 'jetpack' ),
281
							esc_url( $args['url-value'] )
282
						);
283
					?>
284
				</p>
285
286
				<p class="jetpack-widget-social-icons-remove-item">
287
					<a class="jetpack-widget-social-icons-remove-item-button" href="javascript:;">
288
						<?php esc_html_e( 'Remove', 'jetpack' ); ?>
289
					</a>
290
				</p>
291
			</div>
292
		</div>
293
294
		<?php
295
	}
296
} // Jetpack_Widget_Social_Icons
297
298
/**
299
 * Register and load the widget.
300
 *
301
 * @access public
302
 * @return void
303
 */
304
function jetpack_widget_social_icons_load() {
305
	register_widget( 'Jetpack_Widget_Social_Icons' );
306
}
307
add_action( 'widgets_init', 'jetpack_widget_social_icons_load' );
308
309 View Code Duplication
if ( ! function_exists( 'jetpack_social_menu_get_svg' ) ) :
310
/**
311
 * Return SVG markup.
312
 *
313
 * @param array $args {
314
 *     Parameters needed to display an SVG.
315
 *
316
 *     @type string $icon  Required SVG icon filename.
317
 * }
318
 * @return string SVG markup.
319
 */
320
function jetpack_social_menu_get_svg( $args = array() ) {
0 ignored issues
show
Best Practice introduced by
The function jetpack_social_menu_get_svg() has been defined more than once; this definition is ignored, only the first definition in modules/theme-tools/social-menu/icon-functions.php (L33-76) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
321
	// Make sure $args are an array.
322
	if ( empty( $args ) ) {
323
		return esc_html__( 'Please define default parameters in the form of an array.', 'jetpack' );
324
	}
325
326
	// Set defaults.
327
	$defaults = array(
328
		'icon'     => '',
329
		'fallback' => false,
330
	);
331
332
	// Parse args.
333
	$args = wp_parse_args( $args, $defaults );
334
335
	// Define an icon.
336
	if ( false === array_key_exists( 'icon', $args ) ) {
337
		return esc_html__( 'Please define an SVG icon filename.', 'jetpack' );
338
	}
339
340
	// Set aria hidden.
341
	$aria_hidden = ' aria-hidden="true"';
342
343
	// Begin SVG markup.
344
	$svg = '<svg class="icon icon-' . esc_attr( $args['icon'] ) . '"' . $aria_hidden . ' role="img">';
345
346
	/*
347
	 * Display the icon.
348
	 *
349
	 * The whitespace around `<use>` is intentional - it is a work around to a keyboard navigation bug in Safari 10.
350
	 *
351
	 * See https://core.trac.wordpress.org/ticket/38387.
352
	 */
353
	$svg .= ' <use href="#icon-' . esc_html( $args['icon'] ) . '" xlink:href="#icon-' . esc_html( $args['icon'] ) . '"></use> ';
354
355
	// Add some markup to use as a fallback for browsers that do not support SVGs.
356
	if ( $args['fallback'] ) {
357
		$svg .= '<span class="svg-fallback icon-' . esc_attr( $args['icon'] ) . '"></span>';
358
	}
359
360
	$svg .= '</svg>';
361
362
	return $svg;
363
}
364
endif;
365
366 View Code Duplication
if ( ! function_exists( 'jetpack_social_menu_social_links_icons' ) ) :
367
/**
368
 * Returns an array of supported social links (URL and icon name).
369
 *
370
 * @return array $social_links_icons
371
 */
372
function jetpack_social_menu_social_links_icons() {
0 ignored issues
show
Best Practice introduced by
The function jetpack_social_menu_social_links_icons() has been defined more than once; this definition is ignored, only the first definition in modules/theme-tools/social-menu/icon-functions.php (L113-172) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
373
	// Supported social links icons.
374
	$social_links_icons = array(
375
		'500px.com'       => '500px',
376
		'amazon.cn'       => 'amazon',
377
		'amazon.in'       => 'amazon',
378
		'amazon.fr'       => 'amazon',
379
		'amazon.de'       => 'amazon',
380
		'amazon.it'       => 'amazon',
381
		'amazon.nl'       => 'amazon',
382
		'amazon.es'       => 'amazon',
383
		'amazon.co'       => 'amazon',
384
		'amazon.ca'       => 'amazon',
385
		'amazon.com'      => 'amazon',
386
		'apple.com'       => 'apple',
387
		'itunes.com'      => 'apple',
388
		'bandcamp.com'    => 'bandcamp',
389
		'behance.net'     => 'behance',
390
		'codepen.io'      => 'codepen',
391
		'deviantart.com'  => 'deviantart',
392
		'digg.com'        => 'digg',
393
		'dribbble.com'    => 'dribbble',
394
		'dropbox.com'     => 'dropbox',
395
		'etsy.com'        => 'etsy',
396
		'facebook.com'    => 'facebook',
397
		'/feed/'          => 'feed',
398
		'flickr.com'      => 'flickr',
399
		'foursquare.com'  => 'foursquare',
400
		'goodreads.com'   => 'goodreads',
401
		'google.com'      => 'google',
402
		'plus.google.com' => 'google-plus',
403
		'github.com'      => 'github',
404
		'instagram.com'   => 'instagram',
405
		'linkedin.com'    => 'linkedin',
406
		'mailto:'         => 'mail',
407
		'meetup.com'      => 'meetup',
408
		'medium.com'      => 'medium',
409
		'pinterest.com'   => 'pinterest',
410
		'getpocket.com'   => 'pocket',
411
		'reddit.com'      => 'reddit',
412
		'skype.com'       => 'skype',
413
		'skype:'          => 'skype',
414
		'slideshare.net'  => 'slideshare',
415
		'snapchat.com'    => 'snapchat',
416
		'soundcloud.com'  => 'soundcloud',
417
		'spotify.com'     => 'spotify',
418
		'stumbleupon.com' => 'stumbleupon',
419
		'tumblr.com'      => 'tumblr',
420
		'twitch.tv'       => 'twitch',
421
		'twitter.com'     => 'twitter',
422
		'vimeo.com'       => 'vimeo',
423
		'vk.com'          => 'vk',
424
		'wordpress.org'   => 'wordpress',
425
		'wordpress.com'   => 'wordpress',
426
		'yelp.com'        => 'yelp',
427
		'youtube.com'     => 'youtube',
428
	);
429
430
	return $social_links_icons;
431
}
432
endif;
433
434 View Code Duplication
if ( ! function_exists( 'jetpack_social_menu_social_links_labels' ) ) :
435
/**
436
 * Returns an array of supported social links (URL and label).
437
 *
438
 * @return array $social_links_labels
439
 */
440
function jetpack_social_menu_social_links_labels() {
441
	// Supported social links icons.
442
	$social_links_labels = array(
443
		'500px.com'       => '500px',
444
		'amazon.cn'       => 'Amazon',
445
		'amazon.in'       => 'Amazon',
446
		'amazon.fr'       => 'Amazon',
447
		'amazon.de'       => 'Amazon',
448
		'amazon.it'       => 'Amazon',
449
		'amazon.nl'       => 'Amazon',
450
		'amazon.es'       => 'Amazon',
451
		'amazon.co'       => 'Amazon',
452
		'amazon.ca'       => 'Amazon',
453
		'amazon.com'      => 'Amazon',
454
		'apple.com'       => 'Apple',
455
		'itunes.com'      => 'Apple',
456
		'bandcamp.com'    => 'Bandcamp',
457
		'behance.net'     => 'Behance',
458
		'codepen.io'      => 'CodePen',
459
		'deviantart.com'  => 'DeviantArt',
460
		'digg.com'        => 'Digg',
461
		'dribbble.com'    => 'Dribbble',
462
		'dropbox.com'     => 'Dropbox',
463
		'etsy.com'        => 'Etsy',
464
		'facebook.com'    => 'Facebook',
465
		'/feed/'          => 'RSS',
466
		'flickr.com'      => 'Flickr',
467
		'foursquare.com'  => 'Foursquare',
468
		'goodreads.com'   => 'Goodreads',
469
		'google.com'      => 'Google',
470
		'plus.google.com' => 'Google Plus',
471
		'github.com'      => 'GitHub',
472
		'instagram.com'   => 'Instagram',
473
		'linkedin.com'    => 'LinkedIn',
474
		'mailto:'         => 'Email',
475
		'meetup.com'      => 'Meetup',
476
		'medium.com'      => 'Medium',
477
		'pinterest.com'   => 'Pinterest',
478
		'getpocket.com'   => 'Pocket',
479
		'reddit.com'      => 'Reddit',
480
		'skype.com'       => 'Skype',
481
		'skype:'          => 'Skype',
482
		'slideshare.net'  => 'SlideShare',
483
		'snapchat.com'    => 'Snapchat',
484
		'soundcloud.com'  => 'SoundCloud',
485
		'spotify.com'     => 'Spotify',
486
		'stumbleupon.com' => 'StumbleUpon',
487
		'tumblr.com'      => 'Tumblr',
488
		'twitch.tv'       => 'Twitch',
489
		'twitter.com'     => 'Twitter',
490
		'vimeo.com'       => 'Vimeo',
491
		'vk.com'          => 'VK',
492
		'wordpress.org'   => 'WordPress',
493
		'wordpress.com'   => 'WordPress',
494
		'yelp.com'        => 'Yelp',
495
		'youtube.com'     => 'YouTube',
496
	);
497
498
	return $social_links_labels;
499
}
500
endif;