PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 6.4.4
Jetpack – WP Security, Backup, Speed, & Growth v6.4.4
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 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 All 501 releases
jetpack / modules / sharedaddy / sharing-sources.php

sharing-sources.php in Jetpack – WP Security, Backup, Speed, & Growth 6.4.4, at modules/sharedaddy/sharing-sources.php

1,804 lines 53.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 abstract class Sharing_Source {
4 public $button_style;
5 public $smart;
6 protected $open_link_in_new;
7 protected $id;
8
9 public function __construct( $id, array $settings ) {
10 $this->id = $id;
11 /**
12 * Filter the way sharing links open.
13 *
14 * By default, sharing links open in a new window.
15 *
16 * @module sharedaddy
17 *
18 * @since 3.4.0
19 *
20 * @param bool true Should Sharing links open in a new window. Default to true.
21 */
22 $this->open_link_in_new = apply_filters( 'jetpack_open_sharing_in_new_window', true );
23
24 if ( isset( $settings['button_style'] ) ) {
25 $this->button_style = $settings['button_style'];
26 }
27
28 if ( isset( $settings['smart'] ) ) {
29 $this->smart = $settings['smart'];
30 }
31 }
32
33 public function http() {
34 return is_ssl() ? 'https' : 'http';
35 }
36
37 public function get_id() {
38 return $this->id;
39 }
40
41 public function get_class() {
42 return $this->id;
43 }
44
45 public function get_share_url( $post_id ) {
46 /**
47 * Filter the sharing permalink.
48 *
49 * @module sharedaddy
50 *
51 * @since 1.2.0
52 *
53 * @param string get_permalink( $post_id ) Post Permalink.
54 * @param int $post_id Post ID.
55 * @param int $this->id Sharing ID.
56 */
57 return apply_filters( 'sharing_permalink', get_permalink( $post_id ), $post_id, $this->id );
58 }
59
60 public function get_share_title( $post_id ) {
61 $post = get_post( $post_id );
62 /**
63 * Filter the sharing title.
64 *
65 * @module sharedaddy
66 *
67 * @since 2.8.0
68 *
69 * @param string $post->post_title Post Title.
70 * @param int $post_id Post ID.
71 * @param int $this->id Sharing ID.
72 */
73 $title = apply_filters( 'sharing_title', $post->post_title, $post_id, $this->id );
74
75 return html_entity_decode( wp_kses( $title, null ) );
76 }
77
78 public function has_custom_button_style() {
79 return false;
80 }
81
82 public function get_link( $url, $text, $title, $query = '', $id = false ) {
83 $args = func_get_args();
84 $klasses = array( 'share-' . $this->get_class(), 'sd-button' );
85
86 if ( 'icon' == $this->button_style || 'icon-text' == $this->button_style ) {
87 $klasses[] = 'share-icon';
88 }
89
90 if ( 'icon' == $this->button_style ) {
91 $text = $title;
92 $klasses[] = 'no-text';
93
94 if ( true == $this->open_link_in_new ) {
95 $text .= __( ' (Opens in new window)', 'jetpack' );
96 }
97 }
98
99 /**
100 * Filter the sharing display ID.
101 *
102 * @module sharedaddy
103 *
104 * @since 3.4.0
105 *
106 * @param int|false $id Sharing ID.
107 * @param object $this Sharing service properties.
108 * @param array $args Array of sharing service options.
109 */
110 $id = apply_filters( 'jetpack_sharing_display_id', $id, $this, $args );
111 /**
112 * Filter the sharing display link.
113 *
114 * @module sharedaddy
115 *
116 * @since 2.8.0
117 *
118 * @param string $url Post URL.
119 * @param object $this Sharing service properties.
120 * @param int|false $id Sharing ID.
121 * @param array $args Array of sharing service options.
122 */
123 $url = apply_filters( 'sharing_display_link', $url, $this, $id, $args ); // backwards compatibility
124 /**
125 * Filter the sharing display link.
126 *
127 * @module sharedaddy
128 *
129 * @since 2.8.0
130 *
131 * @param string $url Post URL.
132 * @param object $this Sharing service properties.
133 * @param int|false $id Sharing ID.
134 * @param array $args Array of sharing service options.
135 */
136 $url = apply_filters( 'jetpack_sharing_display_link', $url, $this, $id, $args );
137 /**
138 * Filter the sharing display query.
139 *
140 * @module sharedaddy
141 *
142 * @since 2.8.0
143 *
144 * @param string $query Sharing service URL parameter.
145 * @param object $this Sharing service properties.
146 * @param int|false $id Sharing ID.
147 * @param array $args Array of sharing service options.
148 */
149 $query = apply_filters( 'jetpack_sharing_display_query', $query, $this, $id, $args );
150
151 if ( ! empty( $query ) ) {
152 if ( false === stripos( $url, '?' ) ) {
153 $url .= '?' . $query;
154 } else {
155 $url .= '&amp;' . $query;
156 }
157 }
158
159 if ( 'text' == $this->button_style ) {
160 $klasses[] = 'no-icon';
161 }
162
163 /**
164 * Filter the sharing display classes.
165 *
166 * @module sharedaddy
167 *
168 * @since 3.4.0
169 *
170 * @param array $klasses Sharing service classes.
171 * @param object $this Sharing service properties.
172 * @param int|false $id Sharing ID.
173 * @param array $args Array of sharing service options.
174 */
175 $klasses = apply_filters( 'jetpack_sharing_display_classes', $klasses, $this, $id, $args );
176 /**
177 * Filter the sharing display title.
178 *
179 * @module sharedaddy
180 *
181 * @since 3.4.0
182 *
183 * @param string $title Sharing service title.
184 * @param object $this Sharing service properties.
185 * @param int|false $id Sharing ID.
186 * @param array $args Array of sharing service options.
187 */
188 $title = apply_filters( 'jetpack_sharing_display_title', $title, $this, $id, $args );
189 /**
190 * Filter the sharing display text.
191 *
192 * @module sharedaddy
193 *
194 * @since 3.4.0
195 *
196 * @param string $text Sharing service text.
197 * @param object $this Sharing service properties.
198 * @param int|false $id Sharing ID.
199 * @param array $args Array of sharing service options.
200 */
201 $text = apply_filters( 'jetpack_sharing_display_text', $text, $this, $id, $args );
202
203 return sprintf(
204 '<a rel="nofollow" data-shared="%s" class="%s" href="%s"%s title="%s"><span%s>%s</span></a>',
205 ( $id ? esc_attr( $id ) : '' ),
206 implode( ' ', $klasses ),
207 $url,
208 ( true == $this->open_link_in_new ) ? ' rel="noopener noreferrer" target="_blank"' : '',
209 $title,
210 ( 'icon' == $this->button_style ) ? '></span><span class="sharing-screen-reader-text"' : '',
211 $text
212 );
213 }
214
215 /**
216 * Get an unfiltered post permalink to use when generating a sharing URL with get_link.
217 * Use instead of get_share_url for non-official styles as get_permalink ensures that process_request
218 * will be executed more reliably, in the case that the filtered URL uses a service that strips query parameters.
219 *
220 * @since 3.7.0
221 * @param int $post_id Post ID.
222 * @uses get_permalink
223 * @return string get_permalink( $post_id ) Post permalink.
224 */
225 public function get_process_request_url( $post_id ) {
226 return get_permalink( $post_id );
227 }
228
229 abstract public function get_name();
230 abstract public function get_display( $post );
231
232 public function display_header() {
233 }
234
235 public function display_footer() {
236 }
237
238 public function has_advanced_options() {
239 return false;
240 }
241
242 public function display_preview( $echo = true, $force_smart = false, $button_style = null ) {
243 $text = '&nbsp;';
244 $button_style = ( ! empty( $button_style ) ) ? $button_style : $this->button_style;
245 if ( ! $this->smart && ! $force_smart ) {
246 if ( $button_style != 'icon' ) {
247 $text = $this->get_name();
248 }
249 }
250
251 $klasses = array( 'share-' . $this->get_class(), 'sd-button' );
252
253 if ( $button_style == 'icon' || $button_style == 'icon-text' ) {
254 $klasses[] = 'share-icon';
255 }
256
257 if ( $button_style == 'icon' ) {
258 $klasses[] = 'no-text';
259 }
260
261 if ( $button_style == 'text' ) {
262 $klasses[] = 'no-icon';
263 }
264
265 $link = sprintf(
266 '<a rel="nofollow" class="%s" href="javascript:void(0)" title="%s"><span>%s</span></a>',
267 implode( ' ', $klasses ),
268 $this->get_name(),
269 $text
270 );
271
272 $smart = ( $this->smart || $force_smart ) ? 'on' : 'off';
273 $return = "<div class='option option-smart-$smart'>$link</div>";
274 if ( $echo ) {
275 echo $return;
276 }
277
278 return $return;
279 }
280
281 public function get_total( $post = false ) {
282 global $wpdb, $blog_id;
283
284 $name = strtolower( $this->get_id() );
285
286 if ( $post == false ) {
287 // get total number of shares for service
288 return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s', $blog_id, $name ) );
289 }
290
291 // get total shares for a post
292 return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT count FROM sharing_stats WHERE blog_id = %d AND post_id = %d AND share_service = %s', $blog_id, $post->ID, $name ) );
293 }
294
295 public function get_posts_total() {
296 global $wpdb, $blog_id;
297
298 $totals = array();
299 $name = strtolower( $this->get_id() );
300
301 $my_data = $wpdb->get_results( $wpdb->prepare( 'SELECT post_id as id, SUM( count ) as total FROM sharing_stats WHERE blog_id = %d AND share_service = %s GROUP BY post_id ORDER BY count DESC ', $blog_id, $name ) );
302
303 if ( ! empty( $my_data ) ) {
304 foreach ( $my_data as $row ) {
305 $totals[] = new Sharing_Post_Total( $row->id, $row->total );
306 }
307 }
308
309 usort( $totals, array( 'Sharing_Post_Total', 'cmp' ) );
310
311 return $totals;
312 }
313
314 public function process_request( $post, array $post_data ) {
315 /**
316 * Fires when a post is shared via one of the sharing buttons.
317 *
318 * @module sharedaddy
319 *
320 * @since 1.1.0
321 *
322 * @param array $args Aray of information about the sharing service.
323 */
324 do_action( 'sharing_bump_stats', array( 'service' => $this, 'post' => $post ) );
325 }
326
327 public function js_dialog( $name, $params = array() ) {
328 if ( true !== $this->open_link_in_new ) {
329 return;
330 }
331
332 $defaults = array(
333 'menubar' => 1,
334 'resizable' => 1,
335 'width' => 600,
336 'height' => 400,
337 );
338 $params = array_merge( $defaults, $params );
339 $opts = array();
340 foreach ( $params as $key => $val ) {
341 $opts[] = "$key=$val";
342 }
343 $opts = implode( ',', $opts );
344
345 // Add JS after sharing-js has been enqueued.
346 wp_add_inline_script( 'sharing-js',
347 "var windowOpen;
348 jQuery( document.body ).on( 'click', 'a.share-$name', function() {
349 // If there's another sharing window open, close it.
350 if ( 'undefined' !== typeof windowOpen ) {
351 windowOpen.close();
352 }
353 windowOpen = window.open( jQuery( this ).attr( 'href' ), 'wpcom$name', '$opts' );
354 return false;
355 });"
356 );
357 }
358 }
359
360 abstract class Sharing_Advanced_Source extends Sharing_Source {
361 public function has_advanced_options() {
362 return true;
363 }
364
365 abstract public function display_options();
366 abstract public function update_options( array $data );
367 abstract public function get_options();
368 }
369
370 class Share_Email extends Sharing_Source {
371 public $shortname = 'email';
372 public $icon = '\f410';
373 public function __construct( $id, array $settings ) {
374 parent::__construct( $id, $settings );
375
376 if ( 'official' == $this->button_style ) {
377 $this->smart = true;
378 } else {
379 $this->smart = false;
380 }
381 }
382
383 public function get_name() {
384 return _x( 'Email', 'as sharing source', 'jetpack' );
385 }
386
387 // Default does nothing
388 public function process_request( $post, array $post_data ) {
389 $ajax = false;
390 if ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) == 'xmlhttprequest' ) {
391 $ajax = true;
392 }
393
394 $source_email = $target_email = $source_name = false;
395
396 if ( isset( $post_data['source_email'] ) && is_email( $post_data['source_email'] ) ) {
397 $source_email = $post_data['source_email'];
398 }
399
400 if ( isset( $post_data['target_email'] ) && is_email( $post_data['target_email'] ) ) {
401 $target_email = $post_data['target_email'];
402 }
403
404 if ( isset( $post_data['source_name'] ) && strlen( $post_data['source_name'] ) < 200 ) {
405 $source_name = $post_data['source_name'];
406 } elseif ( isset( $post_data['source_name'] ) ) {
407 $source_name = substr( $post_data['source_name'], 0, 200 );
408 } else {
409 $source_name = '';
410 }
411
412 // Test email
413 $error = 1; // Failure in data
414 if ( empty( $post_data['source_f_name'] ) && $source_email && $target_email && $source_name ) {
415 /**
416 * Allow plugins to stop the email sharing button from running the shared message through Akismet.
417 *
418 * @module sharedaddy
419 *
420 * @since 1.1.0
421 *
422 * @param bool true Should we check if the message isn't spam?
423 * @param object $post Post information.
424 * @param array $post_data Information about the shared message.
425 */
426 if ( apply_filters( 'sharing_email_check', true, $post, $post_data ) ) {
427 $data = array(
428 'post' => $post,
429 'source' => $source_email,
430 'target' => $target_email,
431 'name' => $source_name,
432 'sharing_source' => $this,
433 );
434 // todo: implement an error message when email doesn't get sent.
435 /**
436 * Filter whether an email can be sent from the Email sharing button.
437 *
438 * @module sharedaddy
439 *
440 * @since 1.1.0
441 *
442 * @param array $data Array of information about the shared message.
443 */
444 if ( ( $data = apply_filters( 'sharing_email_can_send', $data ) ) !== false ) {
445 // Record stats
446 parent::process_request( $data['post'], $post_data );
447
448 /**
449 * Fires when an email is sent via the Email sharing button.
450 *
451 * @module sharedaddy
452 *
453 * @since 1.1.0
454 *
455 * @param array $data Array of information about the shared message.
456 */
457 do_action( 'sharing_email_send_post', $data );
458 }
459
460 // Return a positive regardless of whether the user is subscribed or not
461 if ( $ajax ) {
462 ?>
463 <div class="response">
464 <div class="response-title"><?php _e( 'This post has been shared!', 'jetpack' ); ?></div>
465 <div class="response-sub"><?php printf( __( 'You have shared this post with %s', 'jetpack' ), esc_html( $target_email ) ); ?></div>
466 <div class="response-close"><a href="#" class="sharing_cancel"><?php _e( 'Close', 'jetpack' ); ?></a></div>
467 </div>
468 <?php
469 } else {
470 wp_safe_redirect( get_permalink( $post->ID ) . '?shared=email' );
471 }
472
473 die();
474 } else {
475 $error = 2; // Email check failed
476 }
477 }
478
479 if ( $ajax ) {
480 echo $error;
481 } else {
482 wp_safe_redirect( get_permalink( $post->ID ) . '?shared=email&msg=fail' );
483 }
484
485 die();
486 }
487
488 public function get_display( $post ) {
489 return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Email', 'share to', 'jetpack' ), __( 'Click to email this to a friend', 'jetpack' ), 'share=email' );
490 }
491
492 /**
493 * Outputs the hidden email dialog
494 */
495 public function display_footer() {
496 global $current_user;
497
498 $visible = $status = false;
499 ?>
500 <div id="sharing_email" style="display: none;">
501 <form action="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" method="post">
502 <label for="target_email"><?php _e( 'Send to Email Address', 'jetpack' ) ?></label>
503 <input type="email" name="target_email" id="target_email" value="" />
504
505 <?php if ( is_user_logged_in() ) : ?>
506 <input type="hidden" name="source_name" value="<?php echo esc_attr( $current_user->display_name ); ?>" />
507 <input type="hidden" name="source_email" value="<?php echo esc_attr( $current_user->user_email ); ?>" />
508 <?php else : ?>
509
510 <label for="source_name"><?php _e( 'Your Name', 'jetpack' ) ?></label>
511 <input type="text" name="source_name" id="source_name" value="" />
512
513 <label for="source_email"><?php _e( 'Your Email Address', 'jetpack' ) ?></label>
514 <input type="email" name="source_email" id="source_email" value="" />
515
516 <?php endif; ?>
517 <input type="text" id="jetpack-source_f_name" name="source_f_name" class="input" value="" size="25" autocomplete="off" title="<?php esc_attr_e( 'This field is for validation and should not be changed', 'jetpack' ); ?>" />
518 <?php
519 /**
520 * Fires when the Email sharing dialog is loaded.
521 *
522 * @module sharedaddy
523 *
524 * @since 1.1.0
525 *
526 * @param string jetpack Eail sharing source.
527 */
528 do_action( 'sharing_email_dialog', 'jetpack' );
529 ?>
530
531 <img style="float: right; display: none" class="loading" src="<?php
532 /** This filter is documented in modules/stats.php */
533 echo apply_filters( 'jetpack_static_url', plugin_dir_url( __FILE__ ) . 'images/loading.gif' ); ?>" alt="loading" width="16" height="16" />
534 <input type="submit" value="<?php esc_attr_e( 'Send Email', 'jetpack' ); ?>" class="sharing_send" />
535 <a rel="nofollow" href="#cancel" class="sharing_cancel"><?php _e( 'Cancel', 'jetpack' ); ?></a>
536
537 <div class="errors errors-1" style="display: none;">
538 <?php _e( 'Post was not sent - check your email addresses!', 'jetpack' ); ?>
539 </div>
540
541 <div class="errors errors-2" style="display: none;">
542 <?php _e( 'Email check failed, please try again', 'jetpack' ); ?>
543 </div>
544
545 <div class="errors errors-3" style="display: none;">
546 <?php _e( 'Sorry, your blog cannot share posts by email.', 'jetpack' ); ?>
547 </div>
548 </form>
549 </div>
550 <?php
551 }
552 }
553
554 class Share_Twitter extends Sharing_Source {
555 public $shortname = 'twitter';
556 public $icon = '\f202';
557 // 'https://dev.twitter.com/rest/reference/get/help/configuration' ( 2015/02/06 ) short_url_length is 22, short_url_length_https is 23
558 public $short_url_length = 24;
559
560 public function __construct( $id, array $settings ) {
561 parent::__construct( $id, $settings );
562
563 if ( 'official' == $this->button_style ) {
564 $this->smart = true;
565 } else {
566 $this->smart = false;
567 }
568 }
569
570 public function get_name() {
571 return __( 'Twitter', 'jetpack' );
572 }
573
574 /**
575 * Determine the Twitter 'via' value for a post.
576 *
577 * @param WP_Post|int $post Post object or post ID.
578 * @return string Twitter handle without the preceding @.
579 **/
580 public static function sharing_twitter_via( $post ) {
581 $post = get_post( $post );
582 /**
583 * Allow third-party plugins to customize the Twitter username used as "twitter:site" Twitter Card Meta Tag.
584 *
585 * @module sharedaddy
586 *
587 * @since 3.0.0
588 *
589 * @param string $string Twitter Username.
590 * @param array $args Array of Open Graph Meta Tags and Twitter Cards tags.
591 */
592 $twitter_site_tag_value = apply_filters( 'jetpack_twitter_cards_site_tag', '', array() );
593
594 /*
595 * Hack to remove the unwanted behavior of adding 'via @jetpack' which
596 * was introduced with the adding of the Twitter cards.
597 * This should be a temporary solution until a better method is setup.
598 */
599 if ( 'jetpack' == $twitter_site_tag_value ) {
600 $twitter_site_tag_value = '';
601 }
602
603 /**
604 * Filters the Twitter username used as "via" in the Twitter sharing button.
605 *
606 * @module sharedaddy
607 *
608 * @since 1.7.0
609 *
610 * @param string $twitter_site_tag_value Twitter Username.
611 * @param int $post->ID Post ID.
612 */
613 $twitter_site_tag_value = apply_filters( 'jetpack_sharing_twitter_via', $twitter_site_tag_value, $post->ID );
614
615 // Strip out anything other than a letter, number, or underscore.
616 // This will prevent the inadvertent inclusion of an extra @, as well as normalizing the handle.
617 return preg_replace( '/[^\da-z_]+/i', '', $twitter_site_tag_value );
618 }
619
620 /**
621 * Determine the 'related' Twitter accounts for a post.
622 *
623 * @param WP_Post|int $post Post object or post ID.
624 * @return string Comma-separated list of Twitter handles.
625 **/
626 public static function get_related_accounts( $post ) {
627 $post = get_post( $post );
628 /**
629 * Filter the list of related Twitter accounts added to the Twitter sharing button.
630 *
631 * @module sharedaddy
632 *
633 * @since 1.7.0
634 *
635 * @param array $args Array of Twitter usernames. Format is 'username' => 'Optional description'
636 * @param int $post->ID Post ID.
637 */
638 $related_accounts = apply_filters( 'jetpack_sharing_twitter_related', array(), $post->ID );
639
640 // Example related string: account1,account2:Account 2 description,account3
641 $related = array();
642
643 foreach ( $related_accounts as $related_account_username => $related_account_description ) {
644 // Join the description onto the end of the username
645 if ( $related_account_description ) {
646 $related_account_username .= ':' . $related_account_description;
647 }
648
649 $related[] = $related_account_username;
650 }
651
652 return implode( ',', $related );
653 }
654
655 public function get_display( $post ) {
656 $via = $this->sharing_twitter_via( $post );
657
658 if ( $via ) {
659 $via = 'data-via="' . esc_attr( $via ) . '"';
660 } else {
661 $via = '';
662 }
663
664 $related = $this->get_related_accounts( $post );
665 if ( ! empty( $related ) && $related !== $via ) {
666 $related = 'data-related="' . esc_attr( $related ) . '"';
667 } else {
668 $related = '';
669 }
670
671 if ( $this->smart ) {
672 $share_url = $this->get_share_url( $post->ID );
673 $post_title = $this->get_share_title( $post->ID );
674 return sprintf(
675 '<a href="https://twitter.com/share" class="twitter-share-button" data-url="%1$s" data-text="%2$s" %3$s %4$s>Tweet</a>',
676 esc_url( $share_url ),
677 esc_attr( $post_title ),
678 $via,
679 $related
680 );
681 } else {
682 if (
683 /**
684 * Allow plugins to disable sharing counts for specific sharing services.
685 *
686 * @module sharedaddy
687 *
688 * @since 3.0.0
689 *
690 * @param bool true Should sharing counts be enabled for this specific service. Default to true.
691 * @param int $post->ID Post ID.
692 * @param string $str Sharing service name.
693 */
694 apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'twitter' )
695 ) {
696 sharing_register_post_for_share_counts( $post->ID );
697 }
698 return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Twitter', 'share to', 'jetpack' ), __( 'Click to share on Twitter', 'jetpack' ), 'share=twitter', 'sharing-twitter-' . $post->ID );
699 }
700 }
701
702 public function process_request( $post, array $post_data ) {
703 $post_title = $this->get_share_title( $post->ID );
704 $post_link = $this->get_share_url( $post->ID );
705
706 if ( function_exists( 'mb_stripos' ) ) {
707 $strlen = 'mb_strlen';
708 $substr = 'mb_substr';
709 } else {
710 $strlen = 'strlen';
711 $substr = 'substr';
712 }
713
714 $via = $this->sharing_twitter_via( $post );
715 $related = $this->get_related_accounts( $post );
716 if ( $via ) {
717 $sig = " via @$via";
718 if ( $related === $via ) {
719 $related = false;
720 }
721 } else {
722 $via = false;
723 $sig = '';
724 }
725
726 $suffix_length = $this->short_url_length + $strlen( $sig );
727 // $sig is handled by twitter in their 'via' argument.
728 // $post_link is handled by twitter in their 'url' argument.
729 if ( 280 < $strlen( $post_title ) + $suffix_length ) {
730 // The -1 is for "\xE2\x80\xA6", a UTF-8 ellipsis.
731 $text = $substr( $post_title, 0, 280 - $suffix_length - 1 ) . "\xE2\x80\xA6";
732 } else {
733 $text = $post_title;
734 }
735
736 // Record stats
737 parent::process_request( $post, $post_data );
738
739 $url = $post_link;
740 $twitter_url = add_query_arg(
741 rawurlencode_deep( array_filter( compact( 'via', 'related', 'text', 'url' ) ) ),
742 'https://twitter.com/intent/tweet'
743 );
744
745 // Redirect to Twitter
746 wp_redirect( $twitter_url );
747 die();
748 }
749
750 public function has_custom_button_style() {
751 return $this->smart;
752 }
753
754 public function display_footer() {
755 if ( $this->smart ) {
756 ?>
757 <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
758 <?php
759 } else {
760 $this->js_dialog( $this->shortname, array( 'height' => 350 ) );
761 }
762 }
763 }
764
765
766 class Share_Reddit extends Sharing_Source {
767 public $shortname = 'reddit';
768 public $icon = '\f222';
769 public function __construct( $id, array $settings ) {
770 parent::__construct( $id, $settings );
771
772 if ( 'official' == $this->button_style ) {
773 $this->smart = true;
774 } else {
775 $this->smart = false;
776 }
777 }
778
779 public function get_name() {
780 return __( 'Reddit', 'jetpack' );
781 }
782
783 public function get_display( $post ) {
784 if ( $this->smart ) {
785 return '<div class="reddit_button"><iframe src="' . $this->http() . '://www.reddit.com/static/button/button1.html?newwindow=true&width=120&amp;url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&amp;title=' . rawurlencode( $this->get_share_title( $post->ID ) ) . '" height="22" width="120" scrolling="no" frameborder="0"></iframe></div>';
786 } else {
787 return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Reddit', 'share to', 'jetpack' ), __( 'Click to share on Reddit', 'jetpack' ), 'share=reddit' );
788 }
789 }
790
791 public function process_request( $post, array $post_data ) {
792 $reddit_url = $this->http() . '://reddit.com/submit?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $this->get_share_title( $post->ID ) );
793
794 // Record stats
795 parent::process_request( $post, $post_data );
796
797 // Redirect to Reddit
798 wp_redirect( $reddit_url );
799 die();
800 }
801 }
802
803 class Share_LinkedIn extends Sharing_Source {
804 public $shortname = 'linkedin';
805 public $icon = '\f207';
806 public function __construct( $id, array $settings ) {
807 parent::__construct( $id, $settings );
808
809 if ( 'official' == $this->button_style ) {
810 $this->smart = true;
811 } else {
812 $this->smart = false;
813 }
814 }
815
816 public function get_name() {
817 return __( 'LinkedIn', 'jetpack' );
818 }
819
820 public function has_custom_button_style() {
821 return $this->smart;
822 }
823
824 public function get_display( $post ) {
825 $display = '';
826
827 if ( $this->smart ) {
828 $share_url = $this->get_share_url( $post->ID );
829 $display .= sprintf( '<div class="linkedin_button"><script type="in/share" data-url="%s" data-counter="right"></script></div>', esc_url( $share_url ) );
830 } else {
831 $display = $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'LinkedIn', 'share to', 'jetpack' ), __( 'Click to share on LinkedIn', 'jetpack' ), 'share=linkedin', 'sharing-linkedin-' . $post->ID );
832 }
833
834 /** This filter is already documented in modules/sharedaddy/sharing-sources.php */
835 if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'linkedin' ) ) {
836 sharing_register_post_for_share_counts( $post->ID );
837 }
838
839 return $display;
840 }
841
842 public function process_request( $post, array $post_data ) {
843
844 $post_link = $this->get_share_url( $post->ID );
845
846 // Using the same URL as the official button, which is *not* LinkedIn's documented sharing link
847 // https://www.linkedin.com/cws/share?url={url}&token=&isFramed=false
848 $linkedin_url = add_query_arg( array(
849 'url' => rawurlencode( $post_link ),
850 ), 'https://www.linkedin.com/cws/share?token=&isFramed=false' );
851
852 // Record stats
853 parent::process_request( $post, $post_data );
854
855 // Redirect to LinkedIn
856 wp_redirect( $linkedin_url );
857 die();
858 }
859
860 public function display_footer() {
861 if ( ! $this->smart ) {
862 $this->js_dialog( $this->shortname, array( 'width' => 580, 'height' => 450 ) );
863 } else {
864 ?><script type="text/javascript">
865 jQuery( document ).ready( function() {
866 jQuery.getScript( 'https://platform.linkedin.com/in.js?async=true', function success() {
867 IN.init();
868 });
869 });
870 jQuery( document.body ).on( 'post-load', function() {
871 if ( typeof IN != 'undefined' )
872 IN.parse();
873 });
874 </script><?php
875 }
876 }
877 }
878
879 class Share_Facebook extends Sharing_Source {
880 public $shortname = 'facebook';
881 public $icon = '\f204';
882 private $share_type = 'default';
883
884 public function __construct( $id, array $settings ) {
885 parent::__construct( $id, $settings );
886
887 if ( isset( $settings['share_type'] ) ) {
888 $this->share_type = $settings['share_type'];
889 }
890
891 if ( 'official' == $this->button_style ) {
892 $this->smart = true;
893 } else {
894 $this->smart = false;
895 }
896 }
897
898 public function get_name() {
899 return __( 'Facebook', 'jetpack' );
900 }
901
902 public function display_header() {
903 }
904
905 function guess_locale_from_lang( $lang ) {
906 if ( 'en' == $lang || 'en_US' == $lang || ! $lang ) {
907 return 'en_US';
908 }
909
910 if ( ! class_exists( 'GP_Locales' ) ) {
911 if ( ! defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) || ! file_exists( JETPACK__GLOTPRESS_LOCALES_PATH ) ) {
912 return false;
913 }
914
915 require JETPACK__GLOTPRESS_LOCALES_PATH;
916 }
917
918 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
919 // WP.com: get_locale() returns 'it'
920 $locale = GP_Locales::by_slug( $lang );
921 } else {
922 // Jetpack: get_locale() returns 'it_IT';
923 $locale = GP_Locales::by_field( 'wp_locale', $lang );
924 }
925
926 if ( ! $locale ) {
927 return false;
928 }
929
930 if ( empty( $locale->facebook_locale ) ) {
931 if ( empty( $locale->wp_locale ) ) {
932 return false;
933 } else {
934 // Facebook SDK is smart enough to fall back to en_US if a
935 // locale isn't supported. Since supported Facebook locales
936 // can fall out of sync, we'll attempt to use the known
937 // wp_locale value and rely on said fallback.
938 return $locale->wp_locale;
939 }
940 }
941
942 return $locale->facebook_locale;
943 }
944
945 public function get_display( $post ) {
946 if ( $this->smart ) {
947 $share_url = $this->get_share_url( $post->ID );
948 $fb_share_html = '<div class="fb-share-button" data-href="' . esc_attr( $share_url ) . '" data-layout="button_count"></div>';
949 /**
950 * Filter the output of the Facebook Sharing button.
951 *
952 * @module sharedaddy
953 *
954 * @since 3.6.0
955 *
956 * @param string $fb_share_html Facebook Sharing button HTML.
957 * @param string $share_url URL of the post to share.
958 */
959 return apply_filters( 'jetpack_sharing_facebook_official_button_output', $fb_share_html, $share_url );
960 }
961
962 /** This filter is already documented in modules/sharedaddy/sharing-sources.php */
963 if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'facebook' ) ) {
964 sharing_register_post_for_share_counts( $post->ID );
965 }
966 return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Facebook', 'share to', 'jetpack' ), __( 'Click to share on Facebook', 'jetpack' ), 'share=facebook', 'sharing-facebook-' . $post->ID );
967 }
968
969 public function process_request( $post, array $post_data ) {
970 $fb_url = $this->http() . '://www.facebook.com/sharer.php?u=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&t=' . rawurlencode( $this->get_share_title( $post->ID ) );
971
972 // Record stats
973 parent::process_request( $post, $post_data );
974
975 // Redirect to Facebook
976 wp_redirect( $fb_url );
977 die();
978 }
979
980 public function display_footer() {
981 $this->js_dialog( $this->shortname );
982 if ( $this->smart ) {
983 $locale = $this->guess_locale_from_lang( get_locale() );
984 if ( ! $locale ) {
985 $locale = 'en_US';
986 }
987 /**
988 * Filter the App ID used in the official Facebook Share button.
989 *
990 * @since 3.8.0
991 *
992 * @param int $fb_app_id Facebook App ID. Default to 249643311490 (WordPress.com's App ID).
993 */
994 $fb_app_id = apply_filters( 'jetpack_sharing_facebook_app_id', '249643311490' );
995 if ( is_numeric( $fb_app_id ) ) {
996 $fb_app_id = '&appId=' . $fb_app_id;
997 } else {
998 $fb_app_id = '';
999 }
1000 ?><div id="fb-root"></div>
1001 <script>(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = 'https://connect.facebook.net/<?php echo $locale; ?>/sdk.js#xfbml=1<?php echo $fb_app_id; ?>&version=v2.3'; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk'));</script>
1002 <script>
1003 jQuery( document.body ).on( 'post-load', function() {
1004 if ( 'undefined' !== typeof FB ) {
1005 FB.XFBML.parse();
1006 }
1007 } );
1008 </script>
1009 <?php
1010 }
1011 }
1012 }
1013
1014 class Share_Print extends Sharing_Source {
1015 public $shortname = 'print';
1016 public $icon = '\f469';
1017 public function __construct( $id, array $settings ) {
1018 parent::__construct( $id, $settings );
1019
1020 if ( 'official' == $this->button_style ) {
1021 $this->smart = true;
1022 } else {
1023 $this->smart = false;
1024 }
1025 }
1026
1027 public function get_name() {
1028 return __( 'Print', 'jetpack' );
1029 }
1030
1031 public function get_display( $post ) {
1032 return $this->get_link( $this->get_process_request_url( $post->ID ) . ( ( is_single() || is_page() ) ? '#print': '' ), _x( 'Print', 'share to', 'jetpack' ), __( 'Click to print', 'jetpack' ) );
1033 }
1034 }
1035
1036 class Share_PressThis extends Sharing_Source {
1037 public $shortname = 'pressthis';
1038 public $icon = '\f205';
1039 public function __construct( $id, array $settings ) {
1040 parent::__construct( $id, $settings );
1041
1042 if ( 'official' == $this->button_style ) {
1043 $this->smart = true;
1044 } else {
1045 $this->smart = false;
1046 }
1047 }
1048
1049 public function get_name() {
1050 return __( 'Press This', 'jetpack' );
1051 }
1052
1053 public function process_request( $post, array $post_data ) {
1054 global $current_user, $wp_version;
1055
1056 $primary_blog = (int) get_user_meta( $current_user->ID, 'primary_blog', true );
1057 if ( $primary_blog ) {
1058 $primary_blog_details = get_blog_details( $primary_blog );
1059 } else {
1060 $primary_blog_details = false;
1061 }
1062
1063 if ( $primary_blog_details ) {
1064 $blogs = array( $primary_blog_details );
1065 } elseif ( function_exists( 'get_active_blogs_for_user' ) ) {
1066 $blogs = get_active_blogs_for_user();
1067 if ( empty( $blogs ) ) {
1068 $blogs = get_blogs_of_user( $current_user->ID );
1069 }
1070 } else {
1071 $blogs = get_blogs_of_user( $current_user->ID );
1072 }
1073
1074 if ( empty( $blogs ) ) {
1075 wp_safe_redirect( get_permalink( $post->ID ) );
1076 die();
1077 }
1078
1079 $blog = current( $blogs );
1080
1081 $args = array(
1082 'u' => rawurlencode( $this->get_share_url( $post->ID ) ),
1083 );
1084
1085 if ( version_compare( $wp_version, '4.9-RC1-42107', '>=' ) ) {
1086 $args[ 'url-scan-submit' ] = 'Scan';
1087 $args[ '_wpnonce' ] = wp_create_nonce( 'scan-site' );
1088
1089 } else { // Remove once 4.9 is the minimum.
1090 $args['t'] = rawurlencode( $this->get_share_title( $post->ID ) );
1091 if ( isset( $_GET['sel'] ) ) {
1092 $args['s'] = rawurlencode( $_GET['sel'] );
1093 }
1094 }
1095
1096 $url = $blog->siteurl . '/wp-admin/press-this.php';
1097 $url = add_query_arg( $args, $url );
1098
1099 // Record stats
1100 parent::process_request( $post, $post_data );
1101
1102 // Redirect to Press This
1103 wp_redirect( $url );
1104 die();
1105 }
1106
1107 public function get_display( $post ) {
1108 return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Press This', 'share to', 'jetpack' ), __( 'Click to Press This!', 'jetpack' ), 'share=press-this' );
1109 }
1110 }
1111
1112 class Share_GooglePlus1 extends Sharing_Source {
1113 public $shortname = 'googleplus1';
1114 public $icon = '\f218';
1115 private $state = false;
1116
1117 public function __construct( $id, array $settings ) {
1118 parent::__construct( $id, $settings );
1119
1120 if ( 'official' == $this->button_style ) {
1121 $this->smart = true;
1122 } else {
1123 $this->smart = false;
1124 }
1125 }
1126
1127 public function get_name() {
1128 return __( 'Google', 'jetpack' );
1129 }
1130
1131 public function has_custom_button_style() {
1132 return $this->smart;
1133 }
1134
1135 public function get_display( $post ) {
1136
1137 if ( $this->smart ) {
1138 $share_url = $this->get_share_url( $post->ID );
1139 return '<div class="googleplus1_button"><div class="g-plus" data-action="share" data-annotation="bubble" data-href="' . esc_url( $share_url ) . '"></div></div>';
1140 } else {
1141 return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Google', 'share to', 'jetpack' ), __( 'Click to share on Google+', 'jetpack' ), 'share=google-plus-1', 'sharing-google-' . $post->ID );
1142 }
1143 }
1144
1145 public function get_state() {
1146 return $this->state;
1147 }
1148
1149 public function process_request( $post, array $post_data ) {
1150
1151 if ( isset( $post_data['state'] ) ) {
1152 $this->state = $post_data['state'];
1153 }
1154 // Record stats
1155 parent::process_request( $post, $post_data );
1156
1157 // Redirect to Google +'s sharing endpoint
1158 $url = 'https://plus.google.com/share?url=' . rawurlencode( $this->get_share_url( $post->ID ) );
1159 wp_redirect( $url );
1160 die();
1161 }
1162
1163 public function display_footer() {
1164 global $post;
1165
1166 if ( $this->smart ) { ?>
1167 <script>
1168 function renderGooglePlus1() {
1169 if ( 'undefined' === typeof gapi ) {
1170 return;
1171 }
1172
1173 jQuery( '.g-plus' ).each(function() {
1174 var $button = jQuery( this );
1175
1176 if ( ! $button.data( 'gplus-rendered' ) ) {
1177 gapi.plusone.render( this, {
1178 href: $button.attr( 'data-href' ),
1179 size: $button.attr( 'data-size' ),
1180 annotation: $button.attr( 'data-annotation' )
1181 });
1182
1183 $button.data( 'gplus-rendered', true );
1184 }
1185 });
1186 }
1187
1188 (function() {
1189 var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
1190 po.src = 'https://apis.google.com/js/platform.js';
1191 po.innerHTML = '{"parsetags": "explicit"}';
1192 po.onload = renderGooglePlus1;
1193 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
1194 })();
1195
1196 jQuery( document.body ).on( 'post-load', renderGooglePlus1 );
1197 </script>
1198 <?php
1199 } else {
1200 $this->js_dialog( 'google-plus-1', array( 'width' => 480, 'height' => 550 ) );
1201 }
1202 }
1203
1204 public function get_total( $post = false ) {
1205 global $wpdb, $blog_id;
1206
1207 $name = strtolower( $this->get_id() );
1208
1209 if ( $post == false ) {
1210 // get total number of shares for service
1211 return $wpdb->get_var( $wpdb->prepare( 'SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s', $blog_id, $name ) );
1212 }
1213
1214 // get total shares for a post
1215 return $wpdb->get_var( $wpdb->prepare( 'SELECT count FROM sharing_stats WHERE blog_id = %d AND post_id = %d AND share_service = %s', $blog_id, $post->ID, $name ) );
1216 }
1217 }
1218
1219 class Share_Custom extends Sharing_Advanced_Source {
1220 private $name;
1221 private $icon;
1222 private $url;
1223 public $smart = true;
1224 public $shortname;
1225
1226 public function get_class() {
1227 return 'custom share-custom-' . sanitize_html_class( strtolower( $this->name ) );
1228 }
1229
1230 public function __construct( $id, array $settings ) {
1231 parent::__construct( $id, $settings );
1232
1233 $opts = $this->get_options();
1234
1235 if ( isset( $settings['name'] ) ) {
1236 $this->name = $settings['name'];
1237 $this->shortname = preg_replace( '/[^a-z0-9]*/', '', $settings['name'] );
1238 }
1239
1240 if ( isset( $settings['icon'] ) ) {
1241 $this->icon = $settings['icon'];
1242
1243 $new_icon = esc_url_raw( wp_specialchars_decode( $this->icon, ENT_QUOTES ) );
1244 $i = 0;
1245 while ( $new_icon != $this->icon ) {
1246 if ( $i > 5 ) {
1247 $this->icon = false;
1248 break;
1249 } else {
1250 $this->icon = $new_icon;
1251 $new_icon = esc_url_raw( wp_specialchars_decode( $this->icon, ENT_QUOTES ) );
1252 }
1253 $i++;
1254 }
1255 }
1256
1257 if ( isset( $settings['url'] ) ) {
1258 $this->url = $settings['url'];
1259 }
1260 }
1261
1262 public function get_name() {
1263 return $this->name;
1264 }
1265
1266 public function get_display( $post ) {
1267 $str = $this->get_link( $this->get_process_request_url( $post->ID ), esc_html( $this->name ), sprintf( __( 'Click to share on %s', 'jetpack' ), esc_attr( $this->name ) ), 'share=' . $this->id );
1268 return str_replace( '<span>', '<span style="' . esc_attr( 'background-image:url("' . addcslashes( esc_url_raw( $this->icon ), '"' ) . '");' ) . '">', $str );
1269 }
1270
1271 public function process_request( $post, array $post_data ) {
1272 $url = str_replace( '&amp;', '&', $this->url );
1273 $url = str_replace( '%post_id%', rawurlencode( $post->ID ), $url );
1274 $url = str_replace( '%post_url%', rawurlencode( $this->get_share_url( $post->ID ) ), $url );
1275 $url = str_replace( '%post_full_url%', rawurlencode( get_permalink( $post->ID ) ), $url );
1276 $url = str_replace( '%post_title%', rawurlencode( $this->get_share_title( $post->ID ) ), $url );
1277 $url = str_replace( '%home_url%', rawurlencode( home_url() ), $url );
1278 $url = str_replace( '%post_slug%', rawurlencode( $post->post_name ), $url );
1279
1280 if ( strpos( $url, '%post_tags%' ) !== false ) {
1281 $tags = get_the_tags( $post->ID );
1282 $tagged = '';
1283
1284 if ( $tags ) {
1285 $tagged_raw = array();
1286 foreach ( $tags as $tag ) {
1287 $tagged_raw[] = rawurlencode( $tag->name );
1288 }
1289
1290 $tagged = implode( ',', $tagged_raw );
1291 }
1292
1293 $url = str_replace( '%post_tags%', $tagged, $url );
1294 }
1295
1296 if ( strpos( $url, '%post_excerpt%' ) !== false ) {
1297 $url_excerpt = $post->post_excerpt;
1298 if ( empty( $url_excerpt ) ) {
1299 $url_excerpt = $post->post_content;
1300 }
1301
1302 $url_excerpt = strip_tags( strip_shortcodes( $url_excerpt ) );
1303 $url_excerpt = wp_html_excerpt( $url_excerpt, 100 );
1304 $url_excerpt = rtrim( preg_replace( '/[^ .]*$/', '', $url_excerpt ) );
1305 $url = str_replace( '%post_excerpt%', rawurlencode( $url_excerpt ), $url );
1306 }
1307
1308 // Record stats
1309 parent::process_request( $post, $post_data );
1310
1311 // Redirect
1312 wp_redirect( $url );
1313 die();
1314 }
1315
1316 public function display_options() {
1317 ?>
1318 <div class="input">
1319 <table class="form-table">
1320 <tbody>
1321 <tr>
1322 <th scope="row"><?php _e( 'Label', 'jetpack' ); ?></th>
1323 <td><input type="text" name="name" value="<?php echo esc_attr( $this->name ); ?>" /></td>
1324 </tr>
1325
1326 <tr>
1327 <th scope="row"><?php _e( 'URL', 'jetpack' ); ?></th>
1328 <td><input type="text" name="url" value="<?php echo esc_attr( $this->url ); ?>" /></td>
1329 </tr>
1330
1331 <tr>
1332 <th scope="row"><?php _e( 'Icon', 'jetpack' ); ?></th>
1333 <td><input type="text" name="icon" value="<?php echo esc_attr( $this->icon ); ?>" /></td>
1334 </tr>
1335
1336 <tr>
1337 <th scope="row"></th>
1338 <td>
1339 <input class="button-secondary" type="submit" value="<?php esc_attr_e( 'Save', 'jetpack' ); ?>" />
1340 <a href="#" class="remove"><small><?php _e( 'Remove Service', 'jetpack' ); ?></small></a>
1341 </td>
1342 </tr>
1343 </tbody>
1344 </table>
1345 </div>
1346 <?php
1347 }
1348
1349 public function update_options( array $data ) {
1350 $name = trim( wp_html_excerpt( wp_kses( stripslashes( $data['name'] ), array() ), 30 ) );
1351 $url = trim( esc_url_raw( $data['url'] ) );
1352 $icon = trim( esc_url_raw( $data['icon'] ) );
1353
1354 if ( $name ) {
1355 $this->name = $name;
1356 }
1357
1358 if ( $url ) {
1359 $this->url = $url;
1360 }
1361
1362 if ( $icon ) {
1363 $this->icon = $icon;
1364 }
1365 }
1366
1367 public function get_options() {
1368 return array(
1369 'name' => $this->name,
1370 'icon' => $this->icon,
1371 'url' => $this->url,
1372 );
1373 }
1374
1375 public function display_preview( $echo = true, $force_smart = false, $button_style = null ) {
1376 $opts = $this->get_options();
1377
1378 $text = '&nbsp;';
1379 if ( ! $this->smart ) {
1380 if ( $this->button_style != 'icon' ) {
1381 $text = $this->get_name();
1382 }
1383 }
1384
1385 $klasses = array( 'share-' . $this->shortname );
1386
1387 if ( $this->button_style == 'icon' || $this->button_style == 'icon-text' ) {
1388 $klasses[] = 'share-icon';
1389 }
1390
1391 if ( $this->button_style == 'icon' ) {
1392 $text = '';
1393 $klasses[] = 'no-text';
1394 }
1395
1396 if ( $this->button_style == 'text' ) {
1397 $klasses[] = 'no-icon';
1398 }
1399
1400 $link = sprintf(
1401 '<a rel="nofollow" class="%s" href="javascript:void(0)" title="%s"><span style="background-image:url(&quot;%s&quot;) !important;background-position:left center;background-repeat:no-repeat;">%s</span></a>',
1402 implode( ' ', $klasses ),
1403 $this->get_name(),
1404 addcslashes( esc_url_raw( $opts['icon'] ), '"' ),
1405 $text
1406 );
1407 ?>
1408 <div class="option option-smart-off">
1409 <?php echo $link ; ?>
1410 </div><?php
1411 }
1412 }
1413
1414 class Share_Tumblr extends Sharing_Source {
1415 public $shortname = 'tumblr';
1416 public $icon = '\f214';
1417 public function __construct( $id, array $settings ) {
1418 parent::__construct( $id, $settings );
1419 if ( 'official' == $this->button_style ) {
1420 $this->smart = true;
1421 } else {
1422 $this->smart = false;
1423 }
1424 }
1425
1426 public function get_name() {
1427 return __( 'Tumblr', 'jetpack' );
1428 }
1429
1430 public function get_display( $post ) {
1431 if ( $this->smart ) {
1432 $target = '';
1433 if ( true == $this->open_link_in_new ) {
1434 $target = '_blank';
1435 }
1436
1437 return '<a target="' . $target . '" href="https://www.tumblr.com/share/link/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&name=' . rawurlencode( $this->get_share_title( $post->ID ) ) . '" title="' . __( 'Share on Tumblr', 'jetpack' ) . '" style="display:inline-block; text-indent:-9999px; overflow:hidden; width:62px; height:20px; background:url(\'https://platform.tumblr.com/v1/share_2.png\') top left no-repeat transparent;">' . __( 'Share on Tumblr', 'jetpack' ) . '</a>';
1438 } else {
1439 return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Tumblr', 'share to', 'jetpack' ), __( 'Click to share on Tumblr', 'jetpack' ), 'share=tumblr' );
1440 }
1441 }
1442
1443 public function process_request( $post, array $post_data ) {
1444 // Record stats
1445 parent::process_request( $post, $post_data );
1446
1447 // Redirect to Tumblr's sharing endpoint (a la their bookmarklet)
1448 $url = 'https://www.tumblr.com/share?v=3&u=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&t=' . rawurlencode( $this->get_share_title( $post->ID ) ) . '&s=';
1449 wp_redirect( $url );
1450 die();
1451 }
1452 // http://www.tumblr.com/share?v=3&u=URL&t=TITLE&s=
1453 public function display_footer() {
1454 if ( $this->smart ) {
1455 ?><script type="text/javascript" src="https://platform.tumblr.com/v1/share.js"></script><?php
1456 } else {
1457 $this->js_dialog( $this->shortname, array( 'width' => 450, 'height' => 450 ) );
1458 }
1459 }
1460 }
1461
1462 class Share_Pinterest extends Sharing_Source {
1463 public $shortname = 'pinterest';
1464 public $icon = '\f209';
1465
1466 public function __construct( $id, array $settings ) {
1467 parent::__construct( $id, $settings );
1468 if ( 'official' == $this->button_style ) {
1469 $this->smart = true;
1470 } else {
1471 $this->smart = false;
1472 }
1473 }
1474
1475 public function get_name() {
1476 return __( 'Pinterest', 'jetpack' );
1477 }
1478
1479 public function get_image( $post ) {
1480 if ( class_exists( 'Jetpack_PostImages' ) ) {
1481 $image = Jetpack_PostImages::get_image( $post->ID, array( 'fallback_to_avatars' => true ) );
1482 if ( ! empty( $image ) ) {
1483 return $image['src'];
1484 }
1485 }
1486
1487 /**
1488 * Filters the default image used by the Pinterest Pin It share button.
1489 *
1490 * @module sharedaddy
1491 *
1492 * @since 3.6.0
1493 *
1494 * @param string $url Default image URL.
1495 */
1496 return apply_filters( 'jetpack_sharing_pinterest_default_image', 'https://s0.wp.com/i/blank.jpg' );
1497 }
1498
1499 public function get_external_url( $post ) {
1500 $url = 'https://www.pinterest.com/pin/create/button/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&media=' . rawurlencode( $this->get_image( $post ) ) . '&description=' . rawurlencode( $post->post_title );
1501
1502 /**
1503 * Filters the Pinterest share URL used in sharing button output.
1504 *
1505 * @module sharedaddy
1506 *
1507 * @since 3.6.0
1508 *
1509 * @param string $url Pinterest share URL.
1510 */
1511 return apply_filters( 'jetpack_sharing_pinterest_share_url', $url );
1512 }
1513
1514 public function get_widget_type() {
1515 /**
1516 * Filters the Pinterest widget type.
1517 *
1518 * @see https://business.pinterest.com/en/widget-builder
1519 *
1520 * @module sharedaddy
1521 *
1522 * @since 3.6.0
1523 *
1524 * @param string $type Pinterest widget type. Default of 'buttonPin' for single-image selection. 'buttonBookmark' for multi-image modal.
1525 */
1526 return apply_filters( 'jetpack_sharing_pinterest_widget_type', 'buttonPin' );
1527 }
1528
1529 public function get_display( $post ) {
1530 $display = '';
1531
1532 if ( $this->smart ) {
1533 $display = sprintf(
1534 '<div class="pinterest_button"><a href="%s" data-pin-do="%s" data-pin-config="beside"><img src="//assets.pinterest.com/images/pidgets/pinit_fg_en_rect_gray_20.png" /></a></div>',
1535 esc_url( $this->get_external_url( $post ) ),
1536 esc_attr( $this->get_widget_type() )
1537 );
1538 } else {
1539 $display = $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Pinterest', 'share to', 'jetpack' ), __( 'Click to share on Pinterest', 'jetpack' ), 'share=pinterest', 'sharing-pinterest-' . $post->ID );
1540 }
1541
1542 /** This filter is already documented in modules/sharedaddy/sharing-sources.php */
1543 if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'linkedin' ) ) {
1544 sharing_register_post_for_share_counts( $post->ID );
1545 }
1546
1547 return $display;
1548 }
1549
1550 public function process_request( $post, array $post_data ) {
1551 // Record stats
1552 parent::process_request( $post, $post_data );
1553 // If we're triggering the multi-select panel, then we don't need to redirect to Pinterest
1554 if ( ! isset( $_GET['js_only'] ) ) {
1555 $pinterest_url = esc_url_raw( $this->get_external_url( $post ) );
1556 wp_redirect( $pinterest_url );
1557 } else {
1558 echo '// share count bumped';
1559 }
1560 die();
1561 }
1562
1563 public function display_footer() {
1564 /**
1565 * Filter the Pin it button appearing when hovering over images when using the official button style.
1566 *
1567 * @module sharedaddy
1568 *
1569 * @since 3.6.0
1570 *
1571 * @param bool $jetpack_pinit_over True by default, displays the Pin it button when hovering over images.
1572 */
1573 $jetpack_pinit_over = apply_filters( 'jetpack_pinit_over_button', true );
1574 ?>
1575 <?php if ( $this->smart ) : ?>
1576 <script type="text/javascript">
1577 // Pinterest shared resources
1578 var s = document.createElement("script");
1579 s.type = "text/javascript";
1580 s.async = true;
1581 <?php if ( $jetpack_pinit_over ) {
1582 echo "s.setAttribute('data-pin-hover', true);";
1583 } ?>
1584 s.src = window.location.protocol + "//assets.pinterest.com/js/pinit.js";
1585 var x = document.getElementsByTagName("script")[0];
1586 x.parentNode.insertBefore(s, x);
1587 // if 'Pin it' button has 'counts' make container wider
1588 jQuery(window).load( function(){ jQuery( 'li.share-pinterest a span:visible' ).closest( '.share-pinterest' ).width( '80px' ); } );
1589 </script>
1590 <?php elseif ( 'buttonPin' != $this->get_widget_type() ) : ?>
1591 <script type="text/javascript">
1592 jQuery(document).ready( function(){
1593 jQuery('body').on('click', 'a.share-pinterest', function(e){
1594 e.preventDefault();
1595 // Load Pinterest Bookmarklet code
1596 var s = document.createElement("script");
1597 s.type = "text/javascript";
1598 s.src = window.location.protocol + "//assets.pinterest.com/js/pinmarklet.js?r=" + ( Math.random() * 99999999 );
1599 var x = document.getElementsByTagName("script")[0];
1600 x.parentNode.insertBefore(s, x);
1601 // Trigger Stats
1602 var s = document.createElement("script");
1603 s.type = "text/javascript";
1604 s.src = this + ( this.toString().indexOf( '?' ) ? '&' : '?' ) + 'js_only=1';
1605 var x = document.getElementsByTagName("script")[0];
1606 x.parentNode.insertBefore(s, x);
1607 });
1608 });
1609 </script>
1610 <?php endif;
1611 }
1612 }
1613
1614 class Share_Pocket extends Sharing_Source {
1615 public $shortname = 'pocket';
1616 public $icon = '\f224';
1617
1618 public function __construct( $id, array $settings ) {
1619 parent::__construct( $id, $settings );
1620
1621 if ( 'official' == $this->button_style ) {
1622 $this->smart = true;
1623 } else {
1624 $this->smart = false;
1625 }
1626 }
1627
1628 public function get_name() {
1629 return __( 'Pocket', 'jetpack' );
1630 }
1631
1632 public function process_request( $post, array $post_data ) {
1633 // Record stats
1634 parent::process_request( $post, $post_data );
1635
1636 $pocket_url = esc_url_raw( 'https://getpocket.com/save/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $this->get_share_title( $post->ID ) ) );
1637 wp_redirect( $pocket_url );
1638 exit;
1639 }
1640
1641 public function get_display( $post ) {
1642 if ( $this->smart ) {
1643 $post_count = 'horizontal';
1644
1645 $button = '';
1646 $button .= '<div class="pocket_button">';
1647 $button .= sprintf( '<a href="https://getpocket.com/save" class="pocket-btn" data-lang="%s" data-save-url="%s" data-pocket-count="%s" >%s</a>', 'en', esc_attr( $this->get_share_url( $post->ID ) ), $post_count, esc_attr__( 'Pocket', 'jetpack' ) );
1648 $button .= '</div>';
1649
1650 return $button;
1651 } else {
1652 return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Pocket', 'share to', 'jetpack' ), __( 'Click to share on Pocket', 'jetpack' ), 'share=pocket' );
1653 }
1654
1655 }
1656
1657 function display_footer() {
1658 if ( $this->smart ) :
1659 ?>
1660 <script>
1661 // Don't use Pocket's default JS as it we need to force init new Pocket share buttons loaded via JS.
1662 function jetpack_sharing_pocket_init() {
1663 jQuery.getScript( 'https://widgets.getpocket.com/v1/j/btn.js?v=1' );
1664 }
1665 jQuery( document ).ready( jetpack_sharing_pocket_init );
1666 jQuery( document.body ).on( 'post-load', jetpack_sharing_pocket_init );
1667 </script>
1668 <?php
1669 else :
1670 $this->js_dialog( $this->shortname, array( 'width' => 450, 'height' => 450 ) );
1671 endif;
1672
1673 }
1674
1675 }
1676
1677 class Share_Telegram extends Sharing_Source {
1678 public $shortname = 'telegram';
1679
1680 public function __construct( $id, array $settings ) {
1681 parent::__construct( $id, $settings );
1682 }
1683
1684 public function get_name() {
1685 return __( 'Telegram', 'jetpack' );
1686 }
1687 public function process_request( $post, array $post_data ) {
1688 // Record stats
1689 parent::process_request( $post, $post_data );
1690 $telegram_url = esc_url_raw( 'https://telegram.me/share/url?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&text=' . rawurlencode( $this->get_share_title( $post->ID ) ) );
1691 wp_redirect( $telegram_url );
1692 exit;
1693 }
1694
1695 public function get_display( $post ) {
1696 return $this->get_link( $this->get_process_request_url( $post->ID ), _x( 'Telegram', 'share to', 'jetpack' ), __( 'Click to share on Telegram', 'jetpack' ), 'share=telegram' );
1697 }
1698
1699 function display_footer() {
1700 $this->js_dialog( $this->shortname, array( 'width' => 450, 'height' => 450 ) );
1701 }
1702 }
1703
1704 class Jetpack_Share_WhatsApp extends Sharing_Source {
1705 public $shortname = 'jetpack-whatsapp';
1706
1707 public function __construct( $id, array $settings ) {
1708 parent::__construct( $id, $settings );
1709 }
1710
1711 public function get_name() {
1712 return __( 'WhatsApp', 'jetpack' );
1713 }
1714
1715 public function get_display( $post ) {
1716 return $this->get_link( 'https://api.whatsapp.com/send?text=' . rawurlencode( $this->get_share_title( $post->ID ) . ' ' . $this->get_share_url( $post->ID ) ), _x( 'WhatsApp', 'share to', 'jetpack' ), __( 'Click to share on WhatsApp', 'jetpack' ) );
1717 }
1718 }
1719
1720 class Share_Skype extends Sharing_Source {
1721 public $shortname = 'skype';
1722 public $icon = '\f220';
1723 private $share_type = 'default';
1724
1725 public function __construct( $id, array $settings ) {
1726 parent::__construct( $id, $settings );
1727
1728 if ( isset( $settings['share_type'] ) ) {
1729 $this->share_type = $settings['share_type'];
1730 }
1731
1732 if ( 'official' == $this->button_style ) {
1733 $this->smart = true;
1734 } else {
1735 $this->smart = false;
1736 }
1737
1738 }
1739
1740 public function get_name() {
1741 return __( 'Skype', 'jetpack' );
1742 }
1743
1744 public function get_display( $post ) {
1745 if ( $this->smart ) {
1746 $skype_share_html = sprintf(
1747 '<div class="skype-share" data-href="%1$s" data-lang="%2$s" data-style="small" data-source="jetpack" ></div>',
1748 esc_attr( $this->get_share_url( $post->ID ) ),
1749 'en-US'
1750 );
1751 return $skype_share_html;
1752 }
1753
1754 /** This filter is already documented in modules/sharedaddy/sharing-sources.php */
1755 if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'skype' ) ) {
1756 sharing_register_post_for_share_counts( $post->ID );
1757 }
1758 return $this->get_link(
1759 $this->get_process_request_url( $post->ID ), _x( 'Skype', 'share to', 'jetpack' ), __( 'Click to share on Skype', 'jetpack' ), 'share=skype', 'sharing-skype-' . $post->ID );
1760 }
1761
1762 public function process_request( $post, array $post_data ) {
1763 $skype_url = sprintf(
1764 'https://web.skype.com/share?url=%1$s&lang=%2$s=&source=jetpack',
1765 rawurlencode( $this->get_share_url( $post->ID ) ),
1766 'en-US'
1767 );
1768
1769 // Record stats
1770 parent::process_request( $post, $post_data );
1771
1772 // Redirect to Skype
1773 wp_redirect( $skype_url );
1774 die();
1775 }
1776
1777 public function display_footer() {
1778 if ( $this->smart ) :
1779 ?>
1780 <script>
1781 (function(r, d, s) {
1782 r.loadSkypeWebSdkAsync = r.loadSkypeWebSdkAsync || function(p) {
1783 var js, sjs = d.getElementsByTagName(s)[0];
1784 if (d.getElementById(p.id)) { return; }
1785 js = d.createElement(s);
1786 js.id = p.id;
1787 js.src = p.scriptToLoad;
1788 js.onload = p.callback
1789 sjs.parentNode.insertBefore(js, sjs);
1790 };
1791 var p = {
1792 scriptToLoad: 'https://swx.cdn.skype.com/shared/v/latest/skypewebsdk.js',
1793 id: 'skype_web_sdk'
1794 };
1795 r.loadSkypeWebSdkAsync(p);
1796 })(window, document, 'script');
1797 </script>
1798 <?php
1799 else :
1800 $this->js_dialog( $this->shortname, array( 'width' => 305, 'height' => 665 ) );
1801 endif;
1802 }
1803 }
1804