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

1,259 lines 38.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_links;
7 protected $id;
8
9 public function __construct( $id, array $settings ) {
10 $this->id = $id;
11
12 if ( isset( $settings['button_style'] ) )
13 $this->button_style = $settings['button_style'];
14
15 if ( isset( $settings['open_links'] ) )
16 $this->open_links = $settings['open_links'];
17
18 if ( isset( $settings['smart'] ) )
19 $this->smart = $settings['smart'];
20 }
21
22 public function http() {
23 return is_ssl() ? 'https' : 'http';
24 }
25
26 public function get_id() {
27 return $this->id;
28 }
29
30 public function get_class() {
31 return $this->id;
32 }
33
34 public function get_share_url( $post_id ) {
35 return apply_filters( 'sharing_permalink', get_permalink( $post_id ), $post_id, $this->id );
36 }
37
38 public function get_share_title( $post_id ) {
39 $post = get_post( $post_id );
40 $title = apply_filters( 'sharing_title', $post->post_title, $post_id, $this->id );
41
42 return html_entity_decode( wp_kses( $title, null ) );
43 }
44
45 public function has_custom_button_style() {
46 return false;
47 }
48
49 public function get_link( $url, $text, $title, $query = '', $id = false ) {
50 $klasses = array( 'share-'.$this->get_class(), 'sd-button' );
51
52 if ( $this->button_style == 'icon' || $this->button_style == 'icon-text' )
53 $klasses[] = 'share-icon';
54
55 if ( $this->button_style == 'icon' ) {
56 $text = $title;
57 $klasses[] = 'no-text';
58
59 if ( $this->open_links == 'new' )
60 $text .= __( ' (Opens in new window)', 'jetpack' );
61 }
62
63 $url = apply_filters( 'sharing_display_link', $url );
64 if ( !empty( $query ) ) {
65 if ( stripos( $url, '?' ) === false )
66 $url .= '?'.$query;
67 else
68 $url .= '&amp;'.$query;
69 }
70
71 if ( $this->button_style == 'text' )
72 $klasses[] = 'no-icon';
73
74 return sprintf(
75 '<a rel="nofollow" class="%s" href="%s"%s title="%s"%s><span%s>%s</span></a>',
76 implode( ' ', $klasses ),
77 $url,
78 ( $this->open_links == 'new' ) ? ' target="_blank"' : '',
79 $title,
80 ( $id ? ' id="' . esc_attr( $id ) . '"' : '' ),
81 ( $this->button_style == 'icon' ) ? '></span><span class="sharing-screen-reader-text"' : '',
82
83 $text
84 );
85 }
86
87 abstract public function get_name();
88 abstract public function get_display( $post );
89
90 public function display_header() {
91 }
92
93 public function display_footer() {
94 }
95
96 public function has_advanced_options() {
97 return false;
98 }
99
100 public function display_preview() {
101 $text = '&nbsp;';
102 if ( !$this->smart )
103 if ( $this->button_style != 'icon' )
104 $text = $this->get_name();
105
106 $klasses = array( 'share-'.$this->get_class(), 'sd-button' );
107
108 if ( $this->button_style == 'icon' || $this->button_style == 'icon-text' )
109 $klasses[] = 'share-icon';
110
111 if ( $this->button_style == 'icon' )
112 $klasses[] = 'no-text';
113
114 if ( $this->button_style == 'text' )
115 $klasses[] = 'no-icon';
116
117 $link = sprintf(
118 '<a rel="nofollow" class="%s" href="javascript:void(0);return false;" title="%s"><span>%s</span></a>',
119 implode( ' ', $klasses ),
120 $this->get_name(),
121 $text
122 );
123 ?>
124 <div class="option option-smart-<?php echo $this->smart ? 'on' : 'off'; ?>">
125 <?php echo $link; ?>
126 </div><?php
127 }
128
129 public function get_total( $post = false ) {
130 global $wpdb, $blog_id;
131
132 $name = strtolower( $this->get_id() );
133
134 if ( $post == false ) {
135 // get total number of shares for service
136 return (int) $wpdb->get_var( $wpdb->prepare( "SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s", $blog_id, $name ) );
137 }
138
139 // get total shares for a post
140 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 ) );
141 }
142
143 public function get_posts_total() {
144 global $wpdb, $blog_id;
145
146 $totals = array();
147 $name = strtolower( $this->get_id() );
148
149 $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 ) );
150
151 if ( !empty( $my_data ) )
152 foreach( $my_data as $row )
153 $totals[] = new Sharing_Post_Total( $row->id, $row->total );
154
155 usort( $totals, array( 'Sharing_Post_Total', 'cmp' ) );
156
157 return $totals;
158 }
159
160 public function process_request( $post, array $post_data ) {
161 do_action( 'sharing_bump_stats', array( 'service' => $this, 'post' => $post ) );
162 }
163
164 public function js_dialog( $name, $params = array() ) {
165 $defaults = array(
166 'menubar' => 1,
167 'resizable' => 1,
168 'width' => 600,
169 'height' => 400,
170 );
171 $params = array_merge( $defaults, $params );
172 $opts = array();
173 foreach( $params as $key => $val ) {
174 $opts[] = "$key=$val";
175 }
176 $opts = implode( ',', $opts );
177 ?>
178 <script type="text/javascript">
179 jQuery(document).on( 'ready post-load', function(){
180 jQuery( 'a.share-<?php echo $name; ?>' ).on( 'click', function() {
181 window.open( jQuery(this).attr( 'href' ), 'wpcom<?php echo $name; ?>', '<?php echo $opts; ?>' );
182 return false;
183 });
184 });
185 </script>
186 <?php
187 }
188 }
189
190 abstract class Sharing_Advanced_Source extends Sharing_Source {
191 public function has_advanced_options() {
192 return true;
193 }
194
195 abstract public function display_options();
196 abstract public function update_options( array $data );
197 abstract public function get_options();
198 }
199
200
201 class Share_Email extends Sharing_Source {
202 var $shortname = 'email';
203 public function __construct( $id, array $settings ) {
204 parent::__construct( $id, $settings );
205
206 if ( 'official' == $this->button_style )
207 $this->smart = true;
208 else
209 $this->smart = false;
210 }
211
212 public function get_name() {
213 return _x( 'Email', 'as sharing source', 'jetpack' );
214 }
215
216 // Default does nothing
217 public function process_request( $post, array $post_data ) {
218 $ajax = false;
219 if ( isset( $_SERVER['HTTP_X_REQUESTED_WITH'] ) && strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ) == 'xmlhttprequest' )
220 $ajax = true;
221
222 $source_email = $target_email = $source_name = false;
223
224 if ( isset( $post_data['source_email'] ) && is_email( $post_data['source_email'] ) )
225 $source_email = $post_data['source_email'];
226
227 if ( isset( $post_data['target_email'] ) && is_email( $post_data['target_email'] ) )
228 $target_email = $post_data['target_email'];
229
230 if ( isset( $post_data['source_name'] ) )
231 $source_name = $post_data['source_name'];
232
233 // Test email
234 $error = 1; // Failure in data
235 if ( $source_email && $target_email && $source_name ) {
236 if ( apply_filters( 'sharing_email_check', true, $post, $post_data ) ) {
237 $data = array(
238 'post' => $post,
239 'source' => $source_email,
240 'target' => $target_email,
241 'name' => $source_name
242 );
243
244 if ( ( $data = apply_filters( 'sharing_email_can_send', $data ) ) !== false ) {
245 // Record stats
246 parent::process_request( $data['post'], $post_data );
247
248 do_action( 'sharing_email_send_post', $data );
249 }
250
251 // Return a positive regardless of whether the user is subscribed or not
252 if ( $ajax ) {
253 ?>
254 <div class="response">
255 <div class="response-title"><?php _e( 'This post has been shared!', 'jetpack' ); ?></div>
256 <div class="response-sub"><?php printf( __( 'You have shared this post with %s', 'jetpack' ), esc_html( $target_email ) ); ?></div>
257 <div class="response-close"><a href="#" class="sharing_cancel"><?php _e( 'Close', 'jetpack' ); ?></a></div>
258 </div>
259 <?php
260 }
261 else
262 wp_safe_redirect( get_permalink( $post->ID ).'?shared=email' );
263
264 die();
265 }
266 else
267 $error = 2; // Email check failed
268 }
269
270 if ( $ajax )
271 echo $error;
272 else
273 wp_safe_redirect( get_permalink( $post->ID ).'?shared=email&msg=fail' );
274
275 die();
276 }
277
278 public function get_display( $post ) {
279 return $this->get_link( get_permalink( $post->ID ), _x( 'Email', 'share to', 'jetpack' ), __( 'Click to email this to a friend', 'jetpack' ), 'share=email' );
280 }
281
282 /**
283 * Outputs the hidden email dialog
284 */
285 public function display_footer() {
286 global $current_user;
287
288 $visible = $status = false;
289 ?>
290 <div id="sharing_email" style="display: none;">
291 <form action="<?php echo esc_url( $_SERVER['REQUEST_URI'] ); ?>" method="post">
292 <label for="target_email"><?php _e( 'Send to Email Address', 'jetpack' ) ?></label>
293 <input type="email" name="target_email" id="target_email" value="" />
294
295 <?php if ( is_user_logged_in() ) : ?>
296 <input type="hidden" name="source_name" value="<?php echo esc_attr( $current_user->display_name ); ?>" />
297 <input type="hidden" name="source_email" value="<?php echo esc_attr( $current_user->user_email ); ?>" />
298 <?php else : ?>
299
300 <label for="source_name"><?php _e( 'Your Name', 'jetpack' ) ?></label>
301 <input type="text" name="source_name" id="source_name" value="" />
302
303 <label for="source_email"><?php _e( 'Your Email Address', 'jetpack' ) ?></label>
304 <input type="email" name="source_email" id="source_email" value="" />
305
306 <?php endif; ?>
307
308 <?php do_action( 'sharing_email_dialog', 'jetpack' ); ?>
309
310 <img style="float: right; display: none" class="loading" src="<?php echo apply_filters( 'jetpack_static_url', plugin_dir_url( __FILE__ ) . 'images/loading.gif' ); ?>" alt="loading" width="16" height="16" />
311 <input type="submit" value="<?php esc_attr_e( 'Send Email', 'jetpack' ); ?>" class="sharing_send" />
312 <a href="#cancel" class="sharing_cancel"><?php _e( 'Cancel', 'jetpack' ); ?></a>
313
314 <div class="errors errors-1" style="display: none;">
315 <?php _e( 'Post was not sent - check your email addresses!', 'jetpack' ); ?>
316 </div>
317
318 <div class="errors errors-2" style="display: none;">
319 <?php _e( 'Email check failed, please try again', 'jetpack' ); ?>
320 </div>
321
322 <div class="errors errors-3" style="display: none;">
323 <?php _e( 'Sorry, your blog cannot share posts by email.', 'jetpack' ); ?>
324 </div>
325 </form>
326 </div>
327 <?php
328 }
329 }
330
331 class Share_Twitter extends Sharing_Source {
332 var $shortname = 'twitter';
333 // 'https://dev.twitter.com/docs/api/1.1/get/help/configuration' ( 2013/06/24 ) short_url_length is 22
334 var $short_url_length = 24;
335
336 public function __construct( $id, array $settings ) {
337 parent::__construct( $id, $settings );
338
339 if ( 'official' == $this->button_style )
340 $this->smart = true;
341 else
342 $this->smart = false;
343 }
344
345 public function get_name() {
346 return __( 'Twitter', 'jetpack' );
347 }
348
349 function sharing_twitter_via( $post ) {
350 // Allow themes to customize the via
351 $twitter_site_tag_value = apply_filters( 'jetpack_twitter_cards_site_tag', '', array() );
352
353 /*
354 * Hack to remove the unwanted behavior of adding 'via @jetpack' which
355 * was introduced with the adding of the Twitter cards.
356 * This should be a temporary solution until a better method is setup.
357 */
358 if( 'jetpack' == $twitter_site_tag_value ) {
359 $twitter_site_tag_value = '';
360 }
361
362 // Strip out anything other than a letter, number, or underscore.
363 // This will prevent the inadvertent inclusion of an extra @, as well as normalizing the handle.
364 $twitter_site_tag_value = preg_replace( '/[^\da-z_]+/i', '', $twitter_site_tag_value );
365 return apply_filters( 'jetpack_sharing_twitter_via', $twitter_site_tag_value, $post->ID );
366 }
367
368 public function get_related_accounts( $post ) {
369 // Format is 'username' => 'Optional description'
370 $related_accounts = apply_filters( 'jetpack_sharing_twitter_related', array(), $post->ID );
371
372 // Example related string: account1,account2:Account 2 description,account3
373 $related = array();
374
375 foreach ( $related_accounts as $related_account_username => $related_account_description ) {
376 // Join the description onto the end of the username
377 if ( $related_account_description )
378 $related_account_username .= ':' . $related_account_description;
379
380 $related[] = $related_account_username;
381 }
382
383 return implode( ',', $related );
384 }
385
386 public function get_display( $post ) {
387 $via = $this->sharing_twitter_via( $post );
388
389 if ( $via ) {
390 $via = '&via=' . rawurlencode( $via );
391
392 $related = $this->get_related_accounts( $post );
393 if ( ! empty( $related ) && $related !== $via )
394 $via .= '&related=' . rawurlencode( $related );
395 } else {
396 $via = '';
397 }
398
399 $share_url = $this->get_share_url( $post->ID );
400 $post_title = $this->get_share_title( $post->ID );
401
402 if ( $this->smart ) {
403 return '<div class="twitter_button"><iframe allowtransparency="true" frameborder="0" scrolling="no" src="' . esc_url( $this->http() . '://platform.twitter.com/widgets/tweet_button.html?url=' . rawurlencode( $share_url ) . '&counturl=' . rawurlencode( str_replace( 'https://', 'http://', get_permalink( $post->ID ) ) ) . '&count=horizontal&text=' . rawurlencode( $post_title . ':' ) . $via ) . '" style="width:101px; height:20px;"></iframe></div>';
404 } else {
405 if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'twitter' ) ) {
406 sharing_register_post_for_share_counts( $post->ID );
407 }
408 return $this->get_link( get_permalink( $post->ID ), _x( 'Twitter', 'share to', 'jetpack' ), __( 'Click to share on Twitter', 'jetpack' ), 'share=twitter', 'sharing-twitter-' . $post->ID );
409 }
410 }
411
412 public function process_request( $post, array $post_data ) {
413 $post_title = $this->get_share_title( $post->ID );
414 $post_link = $this->get_share_url( $post->ID );
415
416 if ( function_exists( 'mb_stripos' ) ) {
417 $strlen = 'mb_strlen';
418 $substr = 'mb_substr';
419 } else {
420 $strlen = 'strlen';
421 $substr = 'substr';
422 }
423
424 $via = $this->sharing_twitter_via( $post );
425 if ( $via ) {
426 $related = $this->get_related_accounts( $post );
427 if ( $related === $via )
428 $related = false;
429
430 $sig = " via @$via";
431 } else {
432 $via = false;
433 $related = false;
434 $sig = '';
435 }
436
437
438 $suffix_length = $this->short_url_length + $strlen( " {$sig}" );
439 // $sig is handled by twitter in their 'via' argument.
440 // $post_link is handled by twitter in their 'url' argument.
441 if ( 140 < $strlen( $post_title ) + $suffix_length ) {
442 // The -1 is for "\xE2\x80\xA6", a UTF-8 ellipsis.
443 $text = $substr( $post_title, 0, 140 - $suffix_length - 1 ) . "\xE2\x80\xA6";
444 } else {
445 $text = $post_title;
446 }
447
448 // Record stats
449 parent::process_request( $post, $post_data );
450
451 $url = $post_link;
452 $twitter_url = add_query_arg(
453 urlencode_deep( array_filter( compact( 'via', 'related', 'text', 'url' ) ) ),
454 sprintf( '%s://twitter.com/intent/tweet', $this->http() )
455 );
456
457 // Redirect to Twitter
458 wp_redirect( $twitter_url );
459 die();
460 }
461
462 public function has_custom_button_style() {
463 return $this->smart;
464 }
465
466 public function display_footer() {
467 $this->js_dialog( $this->shortname, array( 'height' => 350 ) );
468 }
469 }
470
471 class Share_Stumbleupon extends Sharing_Source {
472 var $shortname = 'stumbleupon';
473 public function __construct( $id, array $settings ) {
474 parent::__construct( $id, $settings );
475
476 if ( 'official' == $this->button_style )
477 $this->smart = true;
478 else
479 $this->smart = false;
480 }
481
482 public function get_name() {
483 return __( 'StumbleUpon', 'jetpack' );
484 }
485
486 public function has_custom_button_style() {
487 return $this->smart;
488 }
489
490 public function get_display( $post ) {
491 if ( $this->smart )
492 return '<div class="stumbleupon_button"><iframe src="http://www.stumbleupon.com/badge/embed/1/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&amp;title=' . rawurlencode( $this->get_share_title( $post->ID ) ) . '" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:74px; height: 18px;" allowTransparency="true"></iframe></div>';
493 else
494 return $this->get_link( get_permalink( $post->ID ), _x( 'StumbleUpon', 'share to', 'jetpack' ), __( 'Click to share on StumbleUpon', 'jetpack' ), 'share=stumbleupon' );
495 }
496
497 public function process_request( $post, array $post_data ) {
498 $stumbleupon_url = $this->http() . '://www.stumbleupon.com/submit?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $this->get_share_title( $post->ID ) );
499
500 // Record stats
501 parent::process_request( $post, $post_data );
502
503 // Redirect to Stumbleupon
504 wp_redirect( $stumbleupon_url );
505 die();
506 }
507 }
508
509 class Share_Reddit extends Sharing_Source {
510 var $shortname = 'reddit';
511 public function __construct( $id, array $settings ) {
512 parent::__construct( $id, $settings );
513
514 if ( 'official' == $this->button_style )
515 $this->smart = true;
516 else
517 $this->smart = false;
518 }
519
520 public function get_name() {
521 return __( 'Reddit', 'jetpack' );
522 }
523
524 public function get_display( $post ) {
525 if ( $this->smart )
526 return '<div class="reddit_button"><iframe src="' . $this->http() . '://www.reddit.com/static/button/button1.html?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>';
527 else
528 return $this->get_link( get_permalink( $post->ID ), _x( 'Reddit', 'share to', 'jetpack' ), __( 'Click to share on Reddit', 'jetpack' ), 'share=reddit' );
529 }
530
531 public function process_request( $post, array $post_data ) {
532 $reddit_url = $this->http() . '://reddit.com/submit?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&title=' . rawurlencode( $this->get_share_title( $post->ID ) );
533
534 // Record stats
535 parent::process_request( $post, $post_data );
536
537 // Redirect to Reddit
538 wp_redirect( $reddit_url );
539 die();
540 }
541 }
542
543 class Share_LinkedIn extends Sharing_Source {
544 var $shortname = 'linkedin';
545 public function __construct( $id, array $settings ) {
546 parent::__construct( $id, $settings );
547
548 if ( 'official' == $this->button_style )
549 $this->smart = true;
550 else
551 $this->smart = false;
552 }
553
554 public function get_name() {
555 return __( 'LinkedIn', 'jetpack' );
556 }
557
558 public function has_custom_button_style() {
559 return $this->smart;
560 }
561
562 public function get_display( $post ) {
563 $share_url = $this->get_share_url( $post->ID );
564 $display = '';
565
566 if ( $this->smart )
567 $display .= sprintf( '<div class="linkedin_button"><script type="in/share" data-url="%s" data-counter="right"></script></div>', esc_url( $share_url ) );
568 else
569 $display = $this->get_link( get_permalink( $post->ID ), _x( 'LinkedIn', 'share to', 'jetpack' ), __( 'Click to share on LinkedIn', 'jetpack' ), 'share=linkedin', 'sharing-linkedin-' . $post->ID );
570
571 if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'linkedin' ) ) {
572 sharing_register_post_for_share_counts( $post->ID );
573 }
574
575 return $display;
576 }
577
578 public function process_request( $post, array $post_data ) {
579
580 $post_link = $this->get_share_url( $post->ID );
581
582 // Using the same URL as the official button, which is *not* LinkedIn's documented sharing link
583 // https://www.linkedin.com/cws/share?url={url}&token=&isFramed=false
584
585 $linkedin_url = add_query_arg( array(
586 'url' => rawurlencode( $post_link ),
587 ), 'https://www.linkedin.com/cws/share?token=&isFramed=false' );
588
589 // Record stats
590 parent::process_request( $post, $post_data );
591
592 // Redirect to LinkedIn
593 wp_redirect( $linkedin_url );
594 die();
595 }
596
597 public function display_footer() {
598 if ( !$this->smart ) {
599 $this->js_dialog( $this->shortname, array( 'width' => 580, 'height' => 450 ) );
600 } else {
601 ?><script type="text/javascript">
602 jQuery( document ).ready( function() {
603 jQuery.getScript( '//platform.linkedin.com/in.js?async=true', function success() {
604 IN.init();
605 });
606 });
607 jQuery( document.body ).on( 'post-load', function() {
608 if ( typeof IN != 'undefined' )
609 IN.parse();
610 });
611 </script><?php
612 }
613 }
614 }
615
616 class Share_Facebook extends Sharing_Source {
617 var $shortname = 'facebook';
618 private $share_type = 'default';
619
620 public function __construct( $id, array $settings ) {
621 parent::__construct( $id, $settings );
622
623 if ( isset( $settings['share_type'] ) )
624 $this->share_type = $settings['share_type'];
625
626 if ( 'official' == $this->button_style )
627 $this->smart = true;
628 else
629 $this->smart = false;
630 }
631
632 public function get_name() {
633 return __( 'Facebook', 'jetpack' );
634 }
635
636 public function display_header() {
637 }
638
639 function guess_locale_from_lang( $lang ) {
640 if ( 'en' == $lang || 'en_US' == $lang || !$lang ) {
641 return 'en_US';
642 }
643
644 if ( !class_exists( 'GP_Locales' ) ) {
645 if ( !defined( 'JETPACK__GLOTPRESS_LOCALES_PATH' ) || !file_exists( JETPACK__GLOTPRESS_LOCALES_PATH ) ) {
646 return false;
647 }
648
649 require JETPACK__GLOTPRESS_LOCALES_PATH;
650 }
651
652 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
653 // WP.com: get_locale() returns 'it'
654 $locale = GP_Locales::by_slug( $lang );
655 } else {
656 // Jetpack: get_locale() returns 'it_IT';
657 $locale = GP_Locales::by_field( 'wp_locale', $lang );
658 }
659
660 if ( !$locale || empty( $locale->facebook_locale ) ) {
661 return false;
662 }
663
664 return $locale->facebook_locale;
665 }
666
667 public function get_display( $post ) {
668 $share_url = $this->get_share_url( $post->ID );
669 if ( $this->smart ) {
670 $url = $this->http() . '://www.facebook.com/plugins/like.php?href=' . rawurlencode( $share_url ) . '&amp;layout=button_count&amp;show_faces=false&amp;action=like&amp;colorscheme=light&amp;height=21';
671
672 // Default widths to suit English
673 $inner_w = 90;
674
675 // Locale-specific widths/overrides
676 $widths = array(
677 'bg_BG' => 120,
678 'bn_IN' => 100,
679 'cs_CZ' => 135,
680 'de_DE' => 120,
681 'da_DK' => 120,
682 'es_ES' => 122,
683 'es_LA' => 110,
684 'fi_FI' => 100,
685 'it_IT' => 100,
686 'ja_JP' => 100,
687 'pl_PL' => 100,
688 'nl_NL' => 130,
689 'ro_RO' => 100,
690 'ru_RU' => 128,
691 );
692
693 $widths = apply_filters( 'sharing_facebook_like_widths', $widths );
694
695 $locale = $this->guess_locale_from_lang( get_locale() );
696 if ( $locale ) {
697 $url .= '&amp;locale=' . $locale;
698
699 if ( isset( $widths[$locale] ) ) {
700 $inner_w = $widths[$locale];
701 }
702 }
703
704 $url .= '&amp;width='.$inner_w;
705 return '<div class="like_button"><iframe src="'.$url.'" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:'.( $inner_w + 6 ).'px; height:21px;" allowTransparency="true"></iframe></div>';
706 }
707
708 if ( apply_filters( 'jetpack_register_post_for_share_counts', true, $post->ID, 'facebook' ) ) {
709 sharing_register_post_for_share_counts( $post->ID );
710 }
711 return $this->get_link( get_permalink( $post->ID ), _x( 'Facebook', 'share to', 'jetpack' ), __( 'Share on Facebook', 'jetpack' ), 'share=facebook', 'sharing-facebook-' . $post->ID );
712 }
713
714 public function process_request( $post, array $post_data ) {
715 $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 ) );
716
717 // Record stats
718 parent::process_request( $post, $post_data );
719
720 // Redirect to Facebook
721 wp_redirect( $fb_url );
722 die();
723 }
724
725 public function display_footer() {
726 $this->js_dialog( $this->shortname );
727 }
728 }
729
730 class Share_Print extends Sharing_Source {
731 var $shortname = 'print';
732 public function __construct( $id, array $settings ) {
733 parent::__construct( $id, $settings );
734
735 if ( 'official' == $this->button_style )
736 $this->smart = true;
737 else
738 $this->smart = false;
739 }
740
741 public function get_name() {
742 return __( 'Print', 'jetpack' );
743 }
744
745 public function get_display( $post ) {
746 return $this->get_link( get_permalink( $post->ID ) . ( ( is_single() || is_page() ) ? '#print': '' ), _x( 'Print', 'share to', 'jetpack' ), __( 'Click to print', 'jetpack' ) );
747 }
748 }
749
750 class Share_PressThis extends Sharing_Source {
751 var $shortname = 'pressthis';
752 public function __construct( $id, array $settings ) {
753 parent::__construct( $id, $settings );
754
755 if ( 'official' == $this->button_style )
756 $this->smart = true;
757 else
758 $this->smart = false;
759 }
760
761 public function get_name() {
762 return __( 'Press This', 'jetpack' );
763 }
764
765 public function process_request( $post, array $post_data ) {
766 global $current_user;
767
768 $primary_blog = (int) get_user_meta( $current_user->ID, 'primary_blog', true );
769 if ( $primary_blog ) {
770 $primary_blog_details = get_blog_details( $primary_blog );
771 } else {
772 $primary_blog_details = false;
773 }
774
775 if ( $primary_blog_details ) {
776 $blogs = array( $primary_blog_details );
777 } elseif ( function_exists( 'get_active_blogs_for_user' ) ) {
778 $blogs = get_active_blogs_for_user();
779 if ( empty( $blogs ) ) {
780 $blogs = get_blogs_of_user( $current_user->ID );
781 }
782 } else {
783 $blogs = get_blogs_of_user( $current_user->ID );
784 }
785
786 if ( empty( $blogs ) ) {
787 wp_safe_redirect( get_permalink( $post->ID ) );
788 die();
789 }
790
791 $blog = current( $blogs );
792
793 $url = $blog->siteurl.'/wp-admin/press-this.php?u='.rawurlencode( $this->get_share_url( $post->ID ) ).'&t='.rawurlencode( $this->get_share_title( $post->ID ) ).'&v=4';
794
795 if ( isset( $_GET['sel'] ) )
796 $url .= '&s='.rawurlencode( $_GET['sel'] );
797
798 // Record stats
799 parent::process_request( $post, $post_data );
800
801 // Redirect to Press This
802 wp_safe_redirect( $url );
803 die();
804 }
805
806 public function get_display( $post ) {
807 return $this->get_link( get_permalink( $post->ID ), _x( 'Press This', 'share to', 'jetpack' ), __( 'Click to Press This!', 'jetpack' ), 'share=press-this' );
808 }
809 }
810
811 class Share_GooglePlus1 extends Sharing_Source {
812 var $shortname = 'googleplus1';
813 private $state = false;
814
815 public function __construct( $id, array $settings ) {
816 parent::__construct( $id, $settings );
817
818 if ( 'official' == $this->button_style )
819 $this->smart = true;
820 else
821 $this->smart = false;
822 }
823
824 public function get_name() {
825 return __( 'Google', 'jetpack' );
826 }
827
828 public function has_custom_button_style() {
829 return $this->smart;
830 }
831
832 public function get_display( $post ) {
833 $share_url = $this->get_share_url( $post->ID );
834
835 if ( $this->smart ) {
836 return '<div class="googleplus1_button"><div class="g-plus" data-action="share" data-annotation="bubble" data-href="' . esc_url( $share_url ) . '"></div></div>';
837 } else {
838 return $this->get_link( get_permalink( $post->ID ), _x( 'Google', 'share to', 'jetpack' ), __( 'Click to share on Google+', 'jetpack' ), 'share=google-plus-1', 'sharing-google-' . $post->ID );
839 }
840 }
841
842 public function get_state() {
843 return $this->state;
844 }
845
846 public function process_request( $post, array $post_data ) {
847
848 if ( isset( $post_data['state'] ) ) {
849 $this->state = $post_data['state'];
850 }
851 // Record stats
852 parent::process_request( $post, $post_data );
853
854 // Redirect to Google +'s sharing endpoint
855 $url = 'https://plus.google.com/share?url=' . rawurlencode( $this->get_share_url( $post->ID ) );
856 wp_redirect( $url );
857 die();
858 }
859
860 public function display_footer() {
861 global $post;
862
863 if ( $this->smart ) { ?>
864 <script type="text/javascript">
865 (function() {
866 var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
867 po.src = 'https://apis.google.com/js/plusone.js';
868 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
869 })();
870 </script>
871 <?php
872 } else {
873 $this->js_dialog( 'google-plus-1', array( 'width' => 480, 'height' => 550 ) );
874 }
875 }
876
877 public function get_total( $post = false ) {
878 global $wpdb, $blog_id;
879
880 $name = strtolower( $this->get_id() );
881
882 if ( $post == false ) {
883 // get total number of shares for service
884 return $wpdb->get_var( $wpdb->prepare( "SELECT SUM( count ) FROM sharing_stats WHERE blog_id = %d AND share_service = %s", $blog_id, $name ) );
885 }
886
887 //get total shares for a post
888 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 ) );
889 }
890 }
891
892 class Share_Custom extends Sharing_Advanced_Source {
893 private $name;
894 private $icon;
895 private $url;
896 public $smart = true;
897 var $shortname;
898
899 public function get_class() {
900 return 'custom';
901 }
902
903 public function __construct( $id, array $settings ) {
904 parent::__construct( $id, $settings );
905
906 $opts = $this->get_options();
907
908 if ( isset( $settings['name'] ) ) {
909 $this->name = $settings['name'];
910 $this->shortname = preg_replace( '/[^a-z0-9]*/', '', $settings['name'] );
911 }
912
913 if ( isset( $settings['icon'] ) ) {
914 $this->icon = $settings['icon'];
915
916 $new_icon = esc_url_raw( wp_specialchars_decode( $this->icon, ENT_QUOTES ) );
917 $i = 0;
918 while ( $new_icon != $this->icon ) {
919 if ( $i > 5 ) {
920 $this->icon = false;
921 break;
922 } else {
923 $this->icon = $new_icon;
924 $new_icon = esc_url_raw( wp_specialchars_decode( $this->icon, ENT_QUOTES ) );
925 }
926 $i++;
927 }
928 }
929
930 if ( isset( $settings['url'] ) )
931 $this->url = $settings['url'];
932 }
933
934 public function get_name() {
935 return $this->name;
936 }
937
938 public function get_display( $post ) {
939 $str = $this->get_link( get_permalink( $post->ID ), esc_html( $this->name ), __( 'Click to share', 'jetpack' ), 'share='.$this->id );
940 return str_replace( '<span>', '<span style="' . esc_attr( 'background-image:url("' . addcslashes( esc_url_raw( $this->icon ), '"' ) . '");' ) . '">', $str );
941 }
942
943 public function process_request( $post, array $post_data ) {
944 $url = str_replace( '&amp;', '&', $this->url );
945 $url = str_replace( '%post_url%', rawurlencode( $this->get_share_url( $post->ID ) ), $url );
946 $url = str_replace( '%post_full_url%', rawurlencode( get_permalink( $post->ID ) ), $url );
947 $url = str_replace( '%post_title%', rawurlencode( $this->get_share_title( $post->ID ) ), $url );
948
949 if ( strpos( $url, '%post_tags%' ) !== false ) {
950 $tags = get_the_tags( $post->ID );
951 $tagged = '';
952
953 if ( $tags ) {
954 foreach ( $tags AS $tag ) {
955 $tagged[] = rawurlencode( $tag->name );
956 }
957
958 $tagged = implode( ',', $tagged );
959 }
960
961 $url = str_replace( '%post_tags%', $tagged, $url );
962 }
963
964 if ( strpos( $url, '%post_excerpt%' ) !== false ) {
965 $url_excerpt = $post->post_excerpt;
966 if ( empty( $url_excerpt ) )
967 $url_excerpt = $post->post_content;
968
969 $url_excerpt = strip_tags( strip_shortcodes( $url_excerpt ) );
970 $url_excerpt = wp_html_excerpt( $url_excerpt, 100 );
971 $url_excerpt = rtrim( preg_replace( '/[^ .]*$/', '', $url_excerpt ) );
972 $url = str_replace( '%post_excerpt%', rawurlencode( $url_excerpt ), $url );
973 }
974
975 // Record stats
976 parent::process_request( $post, $post_data );
977
978 // Redirect
979 wp_redirect( $url );
980 die();
981 }
982
983 public function display_options() {
984 ?>
985 <div class="input">
986 <table class="form-table">
987 <tbody>
988 <tr>
989 <th scope="row"><?php _e( 'Label', 'jetpack' ); ?></th>
990 <td><input type="text" name="name" value="<?php echo esc_attr( $this->name ); ?>" /></td>
991 </tr>
992
993 <tr>
994 <th scope="row"><?php _e( 'URL', 'jetpack' ); ?></th>
995 <td><input type="text" name="url" value="<?php echo esc_attr( $this->url ); ?>" /></td>
996 </tr>
997
998 <tr>
999 <th scope="row"><?php _e( 'Icon', 'jetpack' ); ?></th>
1000 <td><input type="text" name="icon" value="<?php echo esc_attr( $this->icon ); ?>" /></td>
1001 </tr>
1002
1003 <tr>
1004 <th scope="row"></th>
1005 <td>
1006 <input class="button-secondary" type="submit" value="<?php esc_attr_e( 'Save', 'jetpack' ); ?>" />
1007 <a href="#" class="remove"><small><?php _e( 'Remove Service', 'jetpack' ); ?></small></a>
1008 </td>
1009 </tr>
1010 </tbody>
1011 </table>
1012 </div>
1013 <?php
1014 }
1015
1016 public function update_options( array $data ) {
1017 $name = trim( wp_html_excerpt( wp_kses( stripslashes( $data['name'] ), array() ), 30 ) );
1018 $url = trim( esc_url_raw( $data['url'] ) );
1019 $icon = trim( esc_url_raw( $data['icon'] ) );
1020
1021 if ( $name )
1022 $this->name = $name;
1023
1024 if ( $url )
1025 $this->url = $url;
1026
1027 if ( $icon )
1028 $this->icon = $icon;
1029 }
1030
1031 public function get_options() {
1032 return array(
1033 'name' => $this->name,
1034 'icon' => $this->icon,
1035 'url' => $this->url,
1036 );
1037 }
1038
1039 public function display_preview() {
1040 $opts = $this->get_options();
1041
1042 $text = '&nbsp;';
1043 if ( !$this->smart )
1044 if ( $this->button_style != 'icon' )
1045 $text = $this->get_name();
1046
1047 $klasses = array( 'share-'.$this->shortname );
1048
1049 if ( $this->button_style == 'icon' || $this->button_style == 'icon-text' )
1050 $klasses[] = 'share-icon';
1051
1052 if ( $this->button_style == 'icon' ) {
1053 $text = '';
1054 $klasses[] = 'no-text';
1055 }
1056
1057 if ( $this->button_style == 'text' )
1058 $klasses[] = 'no-icon';
1059
1060 $link = sprintf(
1061 '<a rel="nofollow" class="%s" href="javascript:void(0);return false;" title="%s"><span style="background-image:url(&quot;%s&quot;) !important;background-position:left center;background-repeat:no-repeat;">%s</span></a>',
1062 implode( ' ', $klasses ),
1063 $this->get_name(),
1064 addcslashes( esc_url_raw( $opts['icon'] ), '"' ),
1065 $text
1066 );
1067 ?>
1068 <div class="option option-smart-off">
1069 <?php echo $link ; ?>
1070 </div><?php
1071 }
1072 }
1073
1074
1075 class Share_Tumblr extends Sharing_Source {
1076 var $shortname = 'tumblr';
1077 public function __construct( $id, array $settings ) {
1078 parent::__construct( $id, $settings );
1079 if ( 'official' == $this->button_style )
1080 $this->smart = true;
1081 else
1082 $this->smart = false;
1083 }
1084
1085 public function get_name() {
1086 return __( 'Tumblr', 'jetpack' );
1087 }
1088
1089 public function get_display( $post ) {
1090 if ( $this->smart ) {
1091 $target = '';
1092 if ( 'new' == $this->open_links )
1093 $target = '_blank';
1094
1095 return '<a target="' . $target . '" href="http://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(\'//platform.tumblr.com/v1/share_2.png\') top left no-repeat transparent;">' . __( 'Share on Tumblr', 'jetpack' ) . '</a>';
1096 } else {
1097 return $this->get_link( get_permalink( $post->ID ), _x( 'Tumblr', 'share to', 'jetpack' ), __( 'Click to share on Tumblr', 'jetpack' ), 'share=tumblr' );
1098 }
1099 }
1100
1101 public function process_request( $post, array $post_data ) {
1102 // Record stats
1103 parent::process_request( $post, $post_data );
1104
1105 // Redirect to Tumblr's sharing endpoint (a la their bookmarklet)
1106 $url = 'http://www.tumblr.com/share?v=3&u=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&t=' . rawurlencode( $this->get_share_title( $post->ID ) ) . '&s=';
1107 wp_redirect( $url );
1108 die();
1109 }
1110 // http://www.tumblr.com/share?v=3&u=URL&t=TITLE&s=
1111 public function display_footer() {
1112 if ( $this->smart ) {
1113 ?><script type="text/javascript" src="//platform.tumblr.com/v1/share.js"></script><?php
1114 } else {
1115 $this->js_dialog( $this->shortname, array( 'width' => 450, 'height' => 450 ) );
1116 }
1117 }
1118 }
1119
1120 class Share_Pinterest extends Sharing_Source {
1121 var $shortname = 'pinterest';
1122
1123 public function __construct( $id, array $settings ) {
1124 parent::__construct( $id, $settings );
1125
1126 if ( 'official' == $this->button_style )
1127 $this->smart = true;
1128 else
1129 $this->smart = false;
1130 }
1131
1132 public function get_name() {
1133 return __( 'Pinterest', 'jetpack' );
1134 }
1135
1136 public function get_display( $post ) {
1137 if ( $this->smart )
1138 return '<div class="pinterest_button"><a href="' . esc_url( 'http://pinterest.com/pin/create/button/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&description=' . rawurlencode( $post->post_title ) ) .'" data-pin-do="buttonBookmark" data-pin-config="beside"><img src="//assets.pinterest.com/images/pidgets/pinit_fg_en_rect_gray_20.png" /></a></div>';
1139 else
1140 return $this->get_link( get_permalink( $post->ID ), _x( 'Pinterest', 'share to', 'jetpack' ), __( 'Click to share on Pinterest', 'jetpack' ), 'share=pinterest' );
1141 }
1142
1143 public function process_request( $post, array $post_data ) {
1144 // Record stats
1145 parent::process_request( $post, $post_data );
1146
1147 // If we're triggering the multi-select panel, then we don't need to redirect to Pinterest
1148 if ( !isset( $_GET['js_only'] ) ) {
1149 $pinterest_url = esc_url_raw( 'http://pinterest.com/pin/create/button/?url=' . rawurlencode( $this->get_share_url( $post->ID ) ) . '&description=' . rawurlencode( $this->get_share_title( $post->ID ) ) );
1150 wp_redirect( $pinterest_url );
1151 } else {
1152 echo '// share count bumped';
1153 }
1154
1155 die();
1156 }
1157
1158 public function display_footer() {
1159 ?>
1160 <?php if ( $this->smart ) : ?>
1161 <script type="text/javascript">
1162 // Pinterest shared resources
1163 var s = document.createElement("script");
1164 s.type = "text/javascript";
1165 s.async = true;
1166 s.src = window.location.protocol + "//assets.pinterest.com/js/pinit.js";
1167 var x = document.getElementsByTagName("script")[0];
1168 x.parentNode.insertBefore(s, x);
1169 // if 'Pin it' button has 'counts' make container wider
1170 jQuery(window).load( function(){ jQuery( 'li.share-pinterest a span:visible' ).closest( '.share-pinterest' ).width( '80px' ); } );
1171 </script>
1172 <?php else : ?>
1173 <script type="text/javascript">
1174 jQuery(document).on('ready', function(){
1175 jQuery('body').on('click', 'a.share-pinterest', function(e){
1176 e.preventDefault();
1177
1178 // Load Pinterest Bookmarklet code
1179 var s = document.createElement("script");
1180 s.type = "text/javascript";
1181 s.src = window.location.protocol + "//assets.pinterest.com/js/pinmarklet.js?r=" + ( Math.random() * 99999999 );
1182 var x = document.getElementsByTagName("script")[0];
1183 x.parentNode.insertBefore(s, x);
1184
1185 // Trigger Stats
1186 var s = document.createElement("script");
1187 s.type = "text/javascript";
1188 s.src = this + ( this.toString().indexOf( '?' ) ? '&' : '?' ) + 'js_only=1';
1189 var x = document.getElementsByTagName("script")[0];
1190 x.parentNode.insertBefore(s, x);
1191 });
1192 });
1193 </script>
1194 <?php endif;
1195 }
1196 }
1197
1198 class Share_Pocket extends Sharing_Source {
1199 var $shortname = 'pocket';
1200
1201 public function __construct( $id, array $settings ) {
1202 parent::__construct( $id, $settings );
1203
1204 if ( 'official' == $this->button_style )
1205 $this->smart = true;
1206 else
1207 $this->smart = false;
1208 }
1209
1210 public function get_name() {
1211 return __( 'Pocket', 'jetpack' );
1212 }
1213
1214 public function process_request( $post, array $post_data ) {
1215 // Record stats
1216 parent::process_request( $post, $post_data );
1217
1218 $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 ) ) );
1219 wp_redirect( $pocket_url );
1220 exit;
1221 }
1222
1223 public function get_display( $post ) {
1224 if ( $this->smart ) {
1225 $post_count = 'horizontal';
1226
1227 $button = '';
1228 $button .= '<div class="pocket_button">';
1229 $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' ) );
1230 $button .= '</div>';
1231
1232 return $button;
1233 } else {
1234 return $this->get_link( get_permalink( $post->ID ), _x( 'Pocket', 'share to', 'jetpack' ), __( 'Click to share on Pocket', 'jetpack' ), 'share=pocket' );
1235 }
1236
1237 }
1238
1239 function display_footer() {
1240 if ( $this->smart ) :
1241 ?>
1242 <script>
1243 // Don't use Pocket's default JS as it we need to force init new Pocket share buttons loaded via JS.
1244 function jetpack_sharing_pocket_init() {
1245 jQuery.getScript( 'https://widgets.getpocket.com/v1/j/btn.js?v=1' );
1246 }
1247 jQuery( document ).on( 'ready', jetpack_sharing_pocket_init );
1248 jQuery( document.body ).on( 'post-load', jetpack_sharing_pocket_init );
1249 </script>
1250 <?php
1251 else :
1252 $this->js_dialog( $this->shortname, array( 'width' => 450, 'height' => 450 ) );
1253 endif;
1254
1255 }
1256
1257 }
1258
1259