PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 7.7
Jetpack – WP Security, Backup, Speed, & Growth v7.7
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 7.7, at modules/sharedaddy/sharing-sources.php

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