Jetpack by WordPress.com - Version 4.2

Version Description

  • Release date: August 10th, 2016

Performance Enhancements:

  • Weve improved Jetpacks performance by making calls to the database more efficient; essentially, Jetpack is doing less on each page load, making things faster. #4281, #4316
  • Weve ensured that every feature uses information that is up to date by completely refactoring the way information was synchronized between your site and WordPress.com.
  • We've improved the way Jetpack queries for information about features, which results in less overall queries.

Exciting Feature and UI Improvements:

  • We now track your visitor views of Carousel images in stats.
  • You can now customize advanced typographic settings like ligatures in the Custom CSS editor with new support for the font-feature-settings property.
  • Weve improved the experience when you dont actually have enough posts to Infinitely Scroll.
  • Our Contact Info Widget allows you to enter a Google Maps API Key which is now required by Google if you want to display a map.

Security:

  • Were continuing our efforts to harden Jetpack security, by implementing the hash_equals() function to avoid timing attacks when comparing strings. We also improved security on CSVs exported from your contact form.

Slightly Less Exciting Feature Improvements:

  • The Cartodb shortcode has been changed to match the new product name, Carto.
  • The YouTube shortcode now uses the content width defined by the theme when available, even if an embed size was defined in an old version of WordPress.
  • Breadcrumbs now support hierarchical post types and taxonomies.
  • Weve added the Portfolio Post Type to the WordPress.com REST API whitelist.
  • There are a few new parameters for the Dailymotion shortcode.

Improved Compatibility:

  • We now work well with WP Stagecoach staging sites, so you should not see any future impact on production sites.
  • We had some PHP notices popping up in the WooCommerce plugin wizard screen, these are gone.

Bug Fixes:

  • We stopped loading compatibility stylesheets on the default theme's singular views for Infinite Scroll.
  • Debug tests forwarded through the contact form in the Jetpack Debug menu are now successfully sent to the support team.
  • Weve removed the PHP notices you might have seen when moderating comments.
  • There are no longer PHP notices cropping up when publishing via Cron.
  • Weve fixed the official Sharing buttons so they now line up just right.
  • The PHP warnings of Sitemaps stylesheets have been eliminated.
  • Weve done away with the warnings that appeared when Tonesque processes a file which claims to be one filetype, but is actually another.
  • Weve exterminated PHP notices that appeared when using Random Redirect, as well as when the author wasn't set.
Download this release

Release Info

Developer samhotchkiss
Plugin Icon 128x128 Jetpack by WordPress.com
Version 4.2
Comparing to
See all releases

Code changes from version 4.1.1 to 4.2

Files changed (151) hide show
  1. 3rd-party/3rd-party.php +3 -1
  2. 3rd-party/bitly.php +2 -2
  3. 3rd-party/polldaddy.php +7 -0
  4. 3rd-party/vaultpress.php +0 -13
  5. _inc/jquery.jetpack-sync.js +0 -68
  6. _inc/lib/tonesque.php +1 -21
  7. changelog.txt +6 -6
  8. class.jetpack-admin.php +1 -2
  9. class.jetpack-bbpress-json-api-compat.php +0 -10
  10. class.jetpack-cli.php +4 -4
  11. class.jetpack-client-server.php +18 -16
  12. class.jetpack-debugger.php +68 -34
  13. class.jetpack-heartbeat.php +4 -0
  14. class.jetpack-modules-list-table.php +3 -0
  15. class.jetpack-options.php +21 -11
  16. class.jetpack-signature.php +3 -3
  17. class.jetpack-sync.php +0 -1104
  18. class.jetpack-twitter-cards.php +1 -1
  19. class.jetpack-user-agent.php +70 -15
  20. class.jetpack-xmlrpc-server.php +1 -53
  21. class.jetpack.php +166 -569
  22. css/jetpack-admin.css.map +1 -1
  23. css/jetpack-rtl.css +1 -1
  24. css/jetpack.css +1 -1
  25. functions.opengraph.php +2 -2
  26. jetpack.php +3 -4
  27. json-endpoints.php +125 -2
  28. json-endpoints/class.wpcom-json-api-comment-endpoint.php +2 -0
  29. json-endpoints/class.wpcom-json-api-get-site-endpoint.php +3 -2
  30. json-endpoints/class.wpcom-json-api-post-endpoint.php +0 -1
  31. json-endpoints/class.wpcom-json-api-site-settings-endpoint.php +2 -2
  32. json-endpoints/class.wpcom-json-api-update-comment-endpoint.php +1 -1
  33. json-endpoints/jetpack/class.jetpack-json-api-plugins-endpoint.php +2 -1
  34. json-endpoints/jetpack/class.jetpack-json-api-plugins-install-endpoint.php +2 -1
  35. json-endpoints/jetpack/class.jetpack-json-api-sync-endpoint.php +168 -5
  36. json-endpoints/jetpack/json-api-jetpack-endpoints.php +114 -0
  37. modules/after-the-deadline.php +1 -1
  38. modules/carousel/jetpack-carousel.js +8 -0
  39. modules/carousel/jetpack-carousel.php +22 -4
  40. modules/comments.php +0 -9
  41. modules/contact-form/grunion-contact-form.php +36 -8
  42. modules/custom-css/csstidy/class.csstidy.php +1 -1
  43. modules/custom-css/csstidy/class.csstidy_optimise.php +1 -1
  44. modules/custom-css/csstidy/class.csstidy_print.php +1 -1
  45. modules/custom-css/csstidy/data-wp.inc.php +1 -0
  46. modules/custom-css/custom-css.php +4 -7
  47. modules/custom-post-types/portfolios.php +13 -1
  48. modules/custom-post-types/testimonial.php +1 -1
  49. modules/enhanced-distribution.php +21 -3
  50. modules/gravatar-hovercards.php +1 -1
  51. modules/infinite-scroll.php +1 -1
  52. modules/infinite-scroll/infinity.js +4 -8
  53. modules/infinite-scroll/infinity.php +19 -6
  54. modules/infinite-scroll/themes/twentyeleven.php +4 -2
  55. modules/infinite-scroll/themes/twentyfifteen.php +4 -2
  56. modules/infinite-scroll/themes/twentyfourteen.php +3 -1
  57. modules/infinite-scroll/themes/twentysixteen.php +4 -2
  58. modules/infinite-scroll/themes/twentyten.php +4 -2
  59. modules/infinite-scroll/themes/twentythirteen.php +3 -1
  60. modules/infinite-scroll/themes/twentytwelve.php +4 -2
  61. modules/json-api.php +1 -4
  62. modules/likes.php +45 -99
  63. modules/manage.php +0 -13
  64. modules/markdown/easy-markdown.php +3 -3
  65. modules/minileven.php +1 -1
  66. modules/minileven/minileven.php +1 -1
  67. modules/minileven/theme/pub/minileven/footer.php +1 -1
  68. modules/monitor.php +0 -3
  69. modules/notes.php +0 -23
  70. modules/post-by-email.php +0 -7
  71. modules/protect.php +6 -4
  72. modules/publicize.php +0 -33
  73. modules/publicize/publicize-jetpack.php +34 -4
  74. modules/publicize/publicize.php +5 -1
  75. modules/related-posts.php +0 -16
  76. modules/related-posts/jetpack-related-posts.php +2 -2
  77. modules/sharedaddy/sharedaddy.php +1 -1
  78. modules/sharedaddy/sharing-sources.php +10 -12
  79. modules/sharedaddy/sharing.css +1 -2
  80. modules/sharedaddy/sharing.js +1 -1
  81. modules/shortcodes.php +4 -3
  82. modules/shortcodes/cartodb.php +12 -9
  83. modules/shortcodes/dailymotion.php +97 -17
  84. modules/shortcodes/slideshow.php +1 -1
  85. modules/shortcodes/soundcloud.php +1 -1
  86. modules/shortcodes/vimeo.php +3 -5
  87. modules/shortcodes/wufoo.php +1 -1
  88. modules/shortcodes/youtube.php +12 -11
  89. modules/site-icon.php +0 -2
  90. modules/site-icon/jetpack-site-icon.php +1 -1
  91. modules/sitemaps/sitemap-xsl.php +30 -2
  92. modules/sso.php +2 -2
  93. modules/sso/jetpack-sso-login-rtl.css +6 -0
  94. modules/sso/jetpack-sso-login-rtl.min.css +1 -1
  95. modules/sso/jetpack-sso-login.css +6 -0
  96. modules/sso/jetpack-sso-login.js +1 -1
  97. modules/sso/jetpack-sso-login.min.css +1 -1
  98. modules/stats.php +0 -23
  99. modules/subscriptions.php +0 -18
  100. modules/theme-tools/random-redirect.php +4 -2
  101. modules/theme-tools/site-breadcrumbs.php +56 -14
  102. modules/tiled-gallery/tiled-gallery.php +1 -1
  103. modules/verification-tools/blog-verification-tools.php +1 -1
  104. modules/videopress/js/videopress-admin.js +1 -1
  105. modules/widgets/contact-info.php +35 -37
  106. modules/widgets/contact-info/contact-info-admin.js +8 -0
  107. modules/widgets/contact-info/contact-info-map.css +4 -11
  108. modules/widgets/contact-info/contact-info-map.js +0 -41
  109. modules/widgets/gravatar-profile.php +1 -1
  110. modules/widgets/social-media-icons.php +1 -1
  111. modules/widgets/top-posts.php +1 -1
  112. modules/widgets/top-posts/style.css +1 -1
  113. modules/widgets/twitter-timeline.php +1 -1
  114. readme.txt +48 -3
  115. sal/class.json-api-links.php +4 -4
  116. sal/class.json-api-post-base.php +0 -1
  117. sal/class.json-api-site-base.php +1 -1
  118. sal/class.json-api-site-jetpack-base.php +26 -13
  119. sal/class.json-api-site-jetpack.php +29 -4
  120. sync/class.jetpack-sync-actions.php +248 -0
  121. sync/class.jetpack-sync-defaults.php +256 -0
  122. sync/class.jetpack-sync-functions.php +157 -0
  123. sync/class.jetpack-sync-json-deflate-codec.php +58 -0
  124. sync/class.jetpack-sync-listener.php +154 -0
  125. sync/class.jetpack-sync-module-attachments.php +28 -0
  126. sync/class.jetpack-sync-module-callables.php +144 -0
  127. sync/class.jetpack-sync-module-comments.php +129 -0
  128. sync/class.jetpack-sync-module-constants.php +123 -0
  129. sync/class.jetpack-sync-module-full-sync.php +241 -0
  130. sync/class.jetpack-sync-module-meta.php +34 -0
  131. sync/class.jetpack-sync-module-network-options.php +112 -0
  132. sync/class.jetpack-sync-module-options.php +141 -0
  133. sync/class.jetpack-sync-module-plugins.php +14 -0
  134. sync/class.jetpack-sync-module-posts.php +132 -0
  135. sync/class.jetpack-sync-module-protect.php +16 -0
  136. sync/class.jetpack-sync-module-terms.php +112 -0
  137. sync/class.jetpack-sync-module-themes.php +71 -0
  138. sync/class.jetpack-sync-module-updates.php +85 -0
  139. sync/class.jetpack-sync-module-users.php +197 -0
  140. sync/class.jetpack-sync-module.php +115 -0
  141. sync/class.jetpack-sync-modules.php +90 -0
  142. sync/class.jetpack-sync-queue.php +415 -0
  143. sync/class.jetpack-sync-sender.php +322 -0
  144. sync/class.jetpack-sync-server.php +106 -0
  145. sync/class.jetpack-sync-settings.php +75 -0
  146. sync/class.jetpack-sync-users.php +81 -0
  147. sync/class.jetpack-sync-wp-replicastore.php +694 -0
  148. sync/interface.jetpack-sync-codec.php +14 -0
  149. sync/interface.jetpack-sync-replicastore.php +125 -0
  150. uninstall.php +8 -2
  151. views/admin/my-jetpack-page.php +1 -0
3rd-party/3rd-party.php CHANGED
@@ -10,4 +10,6 @@ require_once( JETPACK__PLUGIN_DIR . '3rd-party/wpml.php' );
10
  require_once( JETPACK__PLUGIN_DIR . '3rd-party/bitly.php' );
11
  require_once( JETPACK__PLUGIN_DIR . '3rd-party/bbpress.php' );
12
  require_once( JETPACK__PLUGIN_DIR . '3rd-party/woocommerce.php' );
13
- require_once( JETPACK__PLUGIN_DIR . '3rd-party/vaultpress.php' );
 
 
10
  require_once( JETPACK__PLUGIN_DIR . '3rd-party/bitly.php' );
11
  require_once( JETPACK__PLUGIN_DIR . '3rd-party/bbpress.php' );
12
  require_once( JETPACK__PLUGIN_DIR . '3rd-party/woocommerce.php' );
13
+
14
+ // We can't load this conditionally since polldaddy add the call in class constuctor.
15
+ require_once( JETPACK__PLUGIN_DIR . '3rd-party/polldaddy.php' );
3rd-party/bitly.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  /*
4
  * Fixes issues with the Official Bitly for WordPress
5
- * http://wordpress.org/plugins/bitly/
6
  */
7
  if( class_exists( 'Bitly' ) ) {
8
 
@@ -10,7 +10,7 @@ if( class_exists( 'Bitly' ) ) {
10
  if ( method_exists( $GLOBALS['bitly'], 'og_tags' ) ) {
11
  remove_action( 'wp_head', array( $GLOBALS['bitly'], 'og_tags' ) );
12
  }
13
-
14
  add_action( 'wp_head', 'jetpack_bitly_og_tag', 100 );
15
  }
16
 
2
 
3
  /*
4
  * Fixes issues with the Official Bitly for WordPress
5
+ * https://wordpress.org/plugins/bitly/
6
  */
7
  if( class_exists( 'Bitly' ) ) {
8
 
10
  if ( method_exists( $GLOBALS['bitly'], 'og_tags' ) ) {
11
  remove_action( 'wp_head', array( $GLOBALS['bitly'], 'og_tags' ) );
12
  }
13
+
14
  add_action( 'wp_head', 'jetpack_bitly_og_tag', 100 );
15
  }
16
 
3rd-party/polldaddy.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Jetpack_Sync {
4
+ static function sync_options() {
5
+ _deprecated_function( __METHOD__, 'jetpack-4.2', 'jetpack_options_whitelist filter' );
6
+ }
7
+ }
3rd-party/vaultpress.php DELETED
@@ -1,13 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * For backward compatibility with VaultPress 1.8.3 to play nicely with Jetpack 4.1
5
- */
6
- add_action( 'init', 'jetpack_vaultpress_sync_options' );
7
- function jetpack_vaultpress_sync_options() {
8
- if ( ! class_exists( 'VaultPress' ) ) {
9
- return;
10
- }
11
- $vaultpress = VaultPress::init();
12
- Jetpack_Sync::sync_options( __FILE__, $vaultpress->auto_register_option, $vaultpress->option_name );
13
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
_inc/jquery.jetpack-sync.js DELETED
@@ -1,68 +0,0 @@
1
- /* global ajaxurl */
2
- jQuery( document ).ready( function($) {
3
- var update = function( cooldown ) {
4
- var self = $( '.jetpack_sync_reindex_control' ),
5
- data;
6
-
7
- self
8
- .find( '.jetpack_sync_reindex_control_action' )
9
- .attr( 'disabled', true );
10
-
11
- self
12
- .find( '.jetpack_sync_reindex_control_status' )
13
- .html( '&hellip;' );
14
-
15
- if ( 'DONE' === self.data( 'status' ) ) {
16
- data = { action:'jetpack-sync-reindex-trigger' };
17
- } else {
18
- data = { action:'jetpack-sync-reindex-status' };
19
- }
20
-
21
- $.getJSON(
22
- ajaxurl,
23
- data,
24
- function( response ) {
25
- var self = $( '.jetpack_sync_reindex_control' ),
26
- strings,
27
- status;
28
-
29
- if ( 0 === self.length ) {
30
- return;
31
- }
32
-
33
- strings = self.data( 'strings' );
34
- status = strings[response.status].status;
35
-
36
- if ( 'INDEXING' === response.status ) {
37
- status += ' (' + Math.floor( 100 * response.posts.imported / response.posts.total ) + '%)';
38
- }
39
-
40
- self
41
- .data( 'status', response.status );
42
-
43
- self
44
- .find( '.jetpack_sync_reindex_control_action' )
45
- .val( strings[response.status].action );
46
-
47
- self
48
- .find( '.jetpack_sync_reindex_control_status' )
49
- .text( status );
50
-
51
- setTimeout( function() {
52
- $( '.jetpack_sync_reindex_control' )
53
- .find( '.jetpack_sync_reindex_control_action' )
54
- .attr( 'disabled', false );
55
- }, cooldown );
56
- }
57
- );
58
- };
59
-
60
- $( '.jetpack_sync_reindex_control' )
61
- .find( '.jetpack_sync_reindex_control_action' )
62
- .live( 'click', function( event ) {
63
- event.preventDefault();
64
- update( 5000 );
65
- } );
66
-
67
- update( 1000 );
68
- } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
_inc/lib/tonesque.php CHANGED
@@ -37,27 +37,7 @@ class Tonesque {
37
  }
38
 
39
  public static function imagecreatefromurl( $image_url ) {
40
- // Grab the extension
41
- $file = strtolower( pathinfo( $image_url, PATHINFO_EXTENSION ) );
42
- $file = explode( '?', $file );
43
- $file = $file[ 0 ];
44
-
45
- switch ( $file ) {
46
- case 'gif' :
47
- $image_obj = imagecreatefromgif( $image_url );
48
- break;
49
- case 'png' :
50
- $image_obj = imagecreatefrompng( $image_url );
51
- break;
52
- case 'jpg' :
53
- case 'jpeg' :
54
- $image_obj = imagecreatefromjpeg( $image_url );
55
- break;
56
- default:
57
- return false;
58
- }
59
-
60
- return $image_obj;
61
  }
62
 
63
  /**
37
  }
38
 
39
  public static function imagecreatefromurl( $image_url ) {
40
+ return imagecreatefromstring( file_get_contents( $image_url ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  }
42
 
43
  /**
changelog.txt CHANGED
@@ -103,7 +103,7 @@ Bug Fixes:
103
  * We accidentally removed the ability for Open Graph to select images from slideshows, it’s up and running again.
104
  * There was an issue where Open Graph meta tags weren’t being set when your homepage is a “Static Front Page”, it’s working again.
105
  * In rare cases when developers were customizing Photon they were seeing a PHP notice when arguments were passed as a string rather than an array. This has been fixed.
106
- * We’ve fixed an issue where Protect’s backup math form wasn’t showing on custom frontend login forms.
107
  * When setting up WooCommerce you might have seen a Related Posts notice which didn’t belong. We’ve eliminated them.
108
  * If you’ve been using our sharing tool with unofficial sharing buttons you might have noticed your sharing numbers were missing. They’re now back.
109
  * In unique situations where special characters were used in sitemap stylesheets an error would occur; that has been remedied.
@@ -1282,7 +1282,7 @@ Release Post: http://wp.me/p1moTy-oR
1282
  * Bug Fix: Contact Form - RTL styles
1283
  * Bug Fix: Contact Form - Better handle MP6 icons
1284
  * Bug Fix: Custom CSS - array_shift() took a variable by reference, so avoid passing it the result of a function
1285
- * Bug Fix: Custom CSS - Allow case-insensitive CSS properties (<a href="http://wordpress.org/support/topic/two-issues-with-jetpack-css-module?replies=9">ref</a>)
1286
  * Bug Fix: Infinite Scroll - Maintain main query's `post__not_in` values when querying posts for IS
1287
  * Bug Fix: Infinite Scroll - Ensure that IS's `pre_get_posts` method isn't applied in the admin. Also fixes an incorrect use of `add_filter()` where `add_action()` was meant. Fixes #1696-plugins
1288
  * Bug Fix: Infinite Scroll - CSS update - IS footer was too large in Firefox
@@ -1475,7 +1475,7 @@ Release Post: http://wp.me/p1moTy-lT
1475
  Release Date: December 14, 2012
1476
  Release Post: http://wp.me/p1moTy-lJ
1477
 
1478
- * Enhancement: Infinite Scroll: support [VideoPress](http://wordpress.org/extend/plugins/video/) plugin.
1479
  * Enhancement: Photon: Apply to all images retrieved from the Media Library.
1480
  * Enhancement: Photon: Retina image support.
1481
  * Enhancement: Custom CSS: Refined editor interface.
@@ -1495,7 +1495,7 @@ Release Post: http://wp.me/p1moTy-lu
1495
  Release Date: November 21, 2012
1496
  Release Post: http://wp.me/p1moTy-lc
1497
 
1498
- * Enhancement: Photon: Support for the [Lazy Load](http://wordpress.org/extend/plugins/lazy-load/) plugin.
1499
  * Bug Fix: Photon: Fix warped images with un- or under-specified dimensions.
1500
  * Bug Fix: Photon: Fix warped images with pre-photonized URLs; don't try to photonize them twice.
1501
  * Bug Fix: Infinite Scroll: Check a child theme's parent theme for infinite scroll support.
@@ -1552,7 +1552,7 @@ Release Post: http://wp.me/p1moTy-hC
1552
  * Enhancement: Contact Form: Overhaul of the contact form code to fix incompatibilites with other plugins.
1553
  * Bug Fix: Only allow users with manage_options permission to enable/disable modules
1554
  * Bug Fix: Custom CSS: allow '/' in media query units; e.g. (-o-min-device-pixel-ratio: 3/2)
1555
- * Bug Fix: Custom CSS: leave comments alone in CSS when editing but minify on the frontend
1556
  * Bug Fix: Sharing: Keep "more" pane open so Google+ Button isn't obscured
1557
  * Bug Fix: Carousel: Make sure the original size is used, even when it is exceedingly large.
1558
  * Bug Fix: Exclude iPad from Twitter on iPhone mobile browsing
@@ -1788,7 +1788,7 @@ Release Post: http://wp.me/p1moTy-8x
1788
  * Enhancement: Stats: More responsive stats dashboard.
1789
  * Enhancement: Shortcodes: Google Maps, VideoPress
1790
  * Enhancement: Sharing: Google+, LinkedIn
1791
- * Enhancement: Enhanced Distribution: Added Jetpack blogs to http://en.wordpress.com/firehose/
1792
  * Bug Fix: Spelling and Grammar: WordPress 3.3 compatibility.
1793
  * Bug Fix: Translatable module names/descriptinos.
1794
  * Bug Fix: Correctly detect host's ability to make outgoing HTTPS requests.
103
  * We accidentally removed the ability for Open Graph to select images from slideshows, it’s up and running again.
104
  * There was an issue where Open Graph meta tags weren’t being set when your homepage is a “Static Front Page”, it’s working again.
105
  * In rare cases when developers were customizing Photon they were seeing a PHP notice when arguments were passed as a string rather than an array. This has been fixed.
106
+ * We’ve fixed an issue where Protect’s backup math form wasn’t showing on custom front end login forms.
107
  * When setting up WooCommerce you might have seen a Related Posts notice which didn’t belong. We’ve eliminated them.
108
  * If you’ve been using our sharing tool with unofficial sharing buttons you might have noticed your sharing numbers were missing. They’re now back.
109
  * In unique situations where special characters were used in sitemap stylesheets an error would occur; that has been remedied.
1282
  * Bug Fix: Contact Form - RTL styles
1283
  * Bug Fix: Contact Form - Better handle MP6 icons
1284
  * Bug Fix: Custom CSS - array_shift() took a variable by reference, so avoid passing it the result of a function
1285
+ * Bug Fix: Custom CSS - Allow case-insensitive CSS properties (<a href="https://wordpress.org/support/topic/two-issues-with-jetpack-css-module?replies=9">ref</a>)
1286
  * Bug Fix: Infinite Scroll - Maintain main query's `post__not_in` values when querying posts for IS
1287
  * Bug Fix: Infinite Scroll - Ensure that IS's `pre_get_posts` method isn't applied in the admin. Also fixes an incorrect use of `add_filter()` where `add_action()` was meant. Fixes #1696-plugins
1288
  * Bug Fix: Infinite Scroll - CSS update - IS footer was too large in Firefox
1475
  Release Date: December 14, 2012
1476
  Release Post: http://wp.me/p1moTy-lJ
1477
 
1478
+ * Enhancement: Infinite Scroll: support [VideoPress](https://wordpress.org/plugins/video/) plugin.
1479
  * Enhancement: Photon: Apply to all images retrieved from the Media Library.
1480
  * Enhancement: Photon: Retina image support.
1481
  * Enhancement: Custom CSS: Refined editor interface.
1495
  Release Date: November 21, 2012
1496
  Release Post: http://wp.me/p1moTy-lc
1497
 
1498
+ * Enhancement: Photon: Support for the [Lazy Load](https://wordpress.org/plugins/lazy-load/) plugin.
1499
  * Bug Fix: Photon: Fix warped images with un- or under-specified dimensions.
1500
  * Bug Fix: Photon: Fix warped images with pre-photonized URLs; don't try to photonize them twice.
1501
  * Bug Fix: Infinite Scroll: Check a child theme's parent theme for infinite scroll support.
1552
  * Enhancement: Contact Form: Overhaul of the contact form code to fix incompatibilites with other plugins.
1553
  * Bug Fix: Only allow users with manage_options permission to enable/disable modules
1554
  * Bug Fix: Custom CSS: allow '/' in media query units; e.g. (-o-min-device-pixel-ratio: 3/2)
1555
+ * Bug Fix: Custom CSS: leave comments alone in CSS when editing but minify on the front end
1556
  * Bug Fix: Sharing: Keep "more" pane open so Google+ Button isn't obscured
1557
  * Bug Fix: Carousel: Make sure the original size is used, even when it is exceedingly large.
1558
  * Bug Fix: Exclude iPad from Twitter on iPhone mobile browsing
1788
  * Enhancement: Stats: More responsive stats dashboard.
1789
  * Enhancement: Shortcodes: Google Maps, VideoPress
1790
  * Enhancement: Sharing: Google+, LinkedIn
1791
+ * Enhancement: Enhanced Distribution: Added Jetpack blogs to https://en.wordpress.com/firehose/
1792
  * Bug Fix: Spelling and Grammar: WordPress 3.3 compatibility.
1793
  * Bug Fix: Translatable module names/descriptinos.
1794
  * Bug Fix: Correctly detect host's ability to make outgoing HTTPS requests.
class.jetpack-admin.php CHANGED
@@ -36,14 +36,13 @@ class Jetpack_Admin {
36
  if ( isset( $_POST['jetpack-set-master-user'] ) ) {
37
  add_action( 'init', array( $this->my_jetpack_page, 'jetpack_my_jetpack_change_user' ) );
38
  }
39
-
40
  // Add hooks for admin menus
41
  add_action( 'admin_menu', array( $this->landing_page, 'add_actions' ), 998 );
42
  add_action( 'jetpack_admin_menu', array( $this, 'admin_menu_debugger' ) );
43
  add_action( 'jetpack_admin_menu', array( $this->settings_page, 'add_actions' ) );
44
  add_action( 'jetpack_admin_menu', array( $this->my_jetpack_page, 'add_actions' ) );
45
 
46
-
47
  // Add redirect to current page for activation/deactivation of modules
48
  add_action( 'jetpack_pre_activate_module', array( $this, 'fix_redirect' ), 10, 2 );
49
  add_action( 'jetpack_pre_deactivate_module', array( $this, 'fix_redirect' ) );
36
  if ( isset( $_POST['jetpack-set-master-user'] ) ) {
37
  add_action( 'init', array( $this->my_jetpack_page, 'jetpack_my_jetpack_change_user' ) );
38
  }
39
+
40
  // Add hooks for admin menus
41
  add_action( 'admin_menu', array( $this->landing_page, 'add_actions' ), 998 );
42
  add_action( 'jetpack_admin_menu', array( $this, 'admin_menu_debugger' ) );
43
  add_action( 'jetpack_admin_menu', array( $this->settings_page, 'add_actions' ) );
44
  add_action( 'jetpack_admin_menu', array( $this->my_jetpack_page, 'add_actions' ) );
45
 
 
46
  // Add redirect to current page for activation/deactivation of modules
47
  add_action( 'jetpack_pre_activate_module', array( $this, 'fix_redirect' ), 10, 2 );
48
  add_action( 'jetpack_pre_deactivate_module', array( $this, 'fix_redirect' ) );
class.jetpack-bbpress-json-api-compat.php CHANGED
@@ -21,11 +21,6 @@ class bbPress_Jetpack_REST_API {
21
  }
22
 
23
  function allow_bbpress_post_types( $allowed_post_types ) {
24
-
25
- // only run for REST API requests
26
- if ( ! defined( 'REST_API_REQUEST' ) || ! REST_API_REQUEST )
27
- return $allowed_post_types;
28
-
29
  $allowed_post_types[] = 'forum';
30
  $allowed_post_types[] = 'topic';
31
  $allowed_post_types[] = 'reply';
@@ -33,11 +28,6 @@ class bbPress_Jetpack_REST_API {
33
  }
34
 
35
  function allow_bbpress_public_metadata( $allowed_meta_keys ) {
36
-
37
- // only run for REST API requests
38
- if ( ! defined( 'REST_API_REQUEST' ) || ! REST_API_REQUEST )
39
- return $allowed_meta_keys;
40
-
41
  $allowed_meta_keys[] = '_bbp_forum_id';
42
  $allowed_meta_keys[] = '_bbp_topic_id';
43
  $allowed_meta_keys[] = '_bbp_status';
21
  }
22
 
23
  function allow_bbpress_post_types( $allowed_post_types ) {
 
 
 
 
 
24
  $allowed_post_types[] = 'forum';
25
  $allowed_post_types[] = 'topic';
26
  $allowed_post_types[] = 'reply';
28
  }
29
 
30
  function allow_bbpress_public_metadata( $allowed_meta_keys ) {
 
 
 
 
 
31
  $allowed_meta_keys[] = '_bbp_forum_id';
32
  $allowed_meta_keys[] = '_bbp_topic_id';
33
  $allowed_meta_keys[] = '_bbp_status';
class.jetpack-cli.php CHANGED
@@ -215,7 +215,7 @@ class Jetpack_CLI extends WP_CLI_Command {
215
  _e( "Resetting default modules...\n", "jetpack" );
216
  usleep( 500000 ); // Take a breath
217
  $default_modules = Jetpack::get_default_modules();
218
- Jetpack_Options::update_option( 'active_modules', $default_modules );
219
  WP_CLI::success( __( 'Modules reset to default.', 'jetpack' ) );
220
 
221
  // Jumpstart option is special
@@ -224,7 +224,7 @@ class Jetpack_CLI extends WP_CLI_Command {
224
  break;
225
  case 'modules':
226
  $default_modules = Jetpack::get_default_modules();
227
- Jetpack_Options::update_option( 'active_modules', $default_modules );
228
  WP_CLI::success( __( 'Modules reset to default.', 'jetpack' ) );
229
  break;
230
  case 'prompt':
@@ -306,7 +306,7 @@ class Jetpack_CLI extends WP_CLI_Command {
306
  break;
307
  case 'activate_all':
308
  $modules = Jetpack::get_available_modules();
309
- Jetpack_Options::update_option( 'active_modules', $modules );
310
  WP_CLI::success( __( 'All modules activated!', 'jetpack' ) );
311
  break;
312
  case 'deactivate':
@@ -316,7 +316,7 @@ class Jetpack_CLI extends WP_CLI_Command {
316
  WP_CLI::success( sprintf( __( '%s has been deactivated.', 'jetpack' ), $module['name'] ) );
317
  break;
318
  case 'deactivate_all':
319
- Jetpack_Options::update_option( 'active_modules', '' );
320
  WP_CLI::success( __( 'All modules deactivated!', 'jetpack' ) );
321
  break;
322
  case 'toggle':
215
  _e( "Resetting default modules...\n", "jetpack" );
216
  usleep( 500000 ); // Take a breath
217
  $default_modules = Jetpack::get_default_modules();
218
+ Jetpack::update_active_modules( $default_modules );
219
  WP_CLI::success( __( 'Modules reset to default.', 'jetpack' ) );
220
 
221
  // Jumpstart option is special
224
  break;
225
  case 'modules':
226
  $default_modules = Jetpack::get_default_modules();
227
+ Jetpack::update_active_modules( $default_modules );
228
  WP_CLI::success( __( 'Modules reset to default.', 'jetpack' ) );
229
  break;
230
  case 'prompt':
306
  break;
307
  case 'activate_all':
308
  $modules = Jetpack::get_available_modules();
309
+ Jetpack::update_active_modules( $modules );
310
  WP_CLI::success( __( 'All modules activated!', 'jetpack' ) );
311
  break;
312
  case 'deactivate':
316
  WP_CLI::success( sprintf( __( '%s has been deactivated.', 'jetpack' ), $module['name'] ) );
317
  break;
318
  case 'deactivate_all':
319
+ Jetpack::delete_active_modules();
320
  WP_CLI::success( __( 'All modules deactivated!', 'jetpack' ) );
321
  break;
322
  case 'toggle':
class.jetpack-client-server.php CHANGED
@@ -12,8 +12,7 @@ class Jetpack_Client_Server {
12
  function client_authorize() {
13
  $data = stripslashes_deep( $_GET );
14
  $data['auth_type'] = 'client';
15
- $jetpack = $this->get_jetpack();
16
- $role = $jetpack->translate_current_user_to_role();
17
  $redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
18
 
19
  $this->check_admin_referer( "jetpack-authorize_{$role}_{$redirect}" );
@@ -29,6 +28,15 @@ class Jetpack_Client_Server {
29
  $this->wp_safe_redirect( Jetpack::admin_url() );
30
  }
31
 
 
 
 
 
 
 
 
 
 
32
  $this->do_exit();
33
  }
34
 
@@ -48,7 +56,7 @@ class Jetpack_Client_Server {
48
  update_option( 'jetpack_unique_connection', $jetpack_unique_connection );
49
 
50
  //track unique connection
51
- $jetpack = Jetpack::init();
52
 
53
  $jetpack->stat( 'connections', 'unique-connection' );
54
  $jetpack->do_stats( 'server_side' );
@@ -58,14 +66,13 @@ class Jetpack_Client_Server {
58
  $jetpack_unique_connection['connected'] += 1;
59
  Jetpack_Options::update_option( 'unique_connection', $jetpack_unique_connection );
60
 
61
- $jetpack = $this->get_jetpack();
62
- $role = $jetpack->translate_current_user_to_role();
63
 
64
  if ( ! $role ) {
65
  return new Jetpack_Error( 'no_role', 'Invalid request.', 400 );
66
  }
67
 
68
- $cap = $jetpack->translate_role_to_cap( $role );
69
  if ( ! $cap ) {
70
  return new Jetpack_Error( 'no_cap', 'Invalid request.', 400 );
71
  }
@@ -116,17 +123,13 @@ class Jetpack_Client_Server {
116
 
117
  $redirect_on_activation_error = ( 'client' === $data['auth_type'] ) ? true : false;
118
  if ( $active_modules = Jetpack_Options::get_option( 'active_modules' ) ) {
119
- Jetpack_Options::delete_option( 'active_modules' );
120
 
121
  Jetpack::activate_default_modules( 999, 1, $active_modules, $redirect_on_activation_error );
122
  } else {
123
  Jetpack::activate_default_modules( false, false, array(), $redirect_on_activation_error );
124
  }
125
-
126
- // Sync all registers options and constants
127
- /** This action is documented in class.jetpack.php */
128
- do_action( 'jetpack_sync_all_registered_options' );
129
-
130
  // Start nonce cleaner
131
  wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
132
  wp_schedule_event( time(), 'hourly', 'jetpack_clean_nonces' );
@@ -158,8 +161,7 @@ class Jetpack_Client_Server {
158
  * @return object|WP_Error
159
  */
160
  function get_token( $data ) {
161
- $jetpack = $this->get_jetpack();
162
- $role = $jetpack->translate_current_user_to_role();
163
 
164
  if ( ! $role ) {
165
  return new Jetpack_Error( 'role', __( 'An administrator for this blog must set up the Jetpack connection.', 'jetpack' ) );
@@ -236,11 +238,11 @@ class Jetpack_Client_Server {
236
  return new Jetpack_Error( 'scope', 'Malformed Scope', $code );
237
  }
238
 
239
- if ( $jetpack->sign_role( $role ) !== $json->scope ) {
240
  return new Jetpack_Error( 'scope', 'Invalid Scope', $code );
241
  }
242
 
243
- if ( ! $cap = $jetpack->translate_role_to_cap( $role ) ) {
244
  return new Jetpack_Error( 'scope', 'No Cap', $code );
245
  }
246
 
12
  function client_authorize() {
13
  $data = stripslashes_deep( $_GET );
14
  $data['auth_type'] = 'client';
15
+ $role = Jetpack::translate_current_user_to_role();
 
16
  $redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
17
 
18
  $this->check_admin_referer( "jetpack-authorize_{$role}_{$redirect}" );
28
  $this->wp_safe_redirect( Jetpack::admin_url() );
29
  }
30
 
31
+ /**
32
+ * Fires after the Jetpack client is authorized to communicate with WordPress.com.
33
+ *
34
+ * @since 4.2.0
35
+ *
36
+ * @param int Jetpack Blog ID.
37
+ */
38
+ do_action( 'jetpack_client_authorized', Jetpack_Options::get_option( 'id' ) );
39
+
40
  $this->do_exit();
41
  }
42
 
56
  update_option( 'jetpack_unique_connection', $jetpack_unique_connection );
57
 
58
  //track unique connection
59
+ $jetpack = $this->get_jetpack();;
60
 
61
  $jetpack->stat( 'connections', 'unique-connection' );
62
  $jetpack->do_stats( 'server_side' );
66
  $jetpack_unique_connection['connected'] += 1;
67
  Jetpack_Options::update_option( 'unique_connection', $jetpack_unique_connection );
68
 
69
+ $role = Jetpack::translate_current_user_to_role();
 
70
 
71
  if ( ! $role ) {
72
  return new Jetpack_Error( 'no_role', 'Invalid request.', 400 );
73
  }
74
 
75
+ $cap = Jetpack::translate_role_to_cap( $role );
76
  if ( ! $cap ) {
77
  return new Jetpack_Error( 'no_cap', 'Invalid request.', 400 );
78
  }
123
 
124
  $redirect_on_activation_error = ( 'client' === $data['auth_type'] ) ? true : false;
125
  if ( $active_modules = Jetpack_Options::get_option( 'active_modules' ) ) {
126
+ Jetpack::delete_active_modules();
127
 
128
  Jetpack::activate_default_modules( 999, 1, $active_modules, $redirect_on_activation_error );
129
  } else {
130
  Jetpack::activate_default_modules( false, false, array(), $redirect_on_activation_error );
131
  }
132
+
 
 
 
 
133
  // Start nonce cleaner
134
  wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
135
  wp_schedule_event( time(), 'hourly', 'jetpack_clean_nonces' );
161
  * @return object|WP_Error
162
  */
163
  function get_token( $data ) {
164
+ $role = Jetpack::translate_current_user_to_role();
 
165
 
166
  if ( ! $role ) {
167
  return new Jetpack_Error( 'role', __( 'An administrator for this blog must set up the Jetpack connection.', 'jetpack' ) );
238
  return new Jetpack_Error( 'scope', 'Malformed Scope', $code );
239
  }
240
 
241
+ if ( Jetpack::sign_role( $role ) !== $json->scope ) {
242
  return new Jetpack_Error( 'scope', 'Invalid Scope', $code );
243
  }
244
 
245
+ if ( ! $cap = Jetpack::translate_role_to_cap( $role ) ) {
246
  return new Jetpack_Error( 'scope', 'No Cap', $code );
247
  }
248
 
class.jetpack-debugger.php CHANGED
@@ -18,6 +18,27 @@ class Jetpack_Debugger {
18
  }
19
  }
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  public static function jetpack_increase_timeout() {
22
  return 30; // seconds
23
  }
@@ -60,6 +81,40 @@ class Jetpack_Debugger {
60
  $debug_info .= "\r\n" . esc_html( "SITE_URL: " . site_url() );
61
  $debug_info .= "\r\n" . esc_html( "HOME_URL: " . home_url() );
62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  foreach ( array (
64
  'HTTP_HOST',
65
  'SERVER_PORT',
@@ -172,7 +227,7 @@ class Jetpack_Debugger {
172
  <h3><?php esc_html_e( 'Trouble with Jetpack?', 'jetpack' ); ?></h3>
173
  <h4><?php esc_html_e( 'It may be caused by one of these issues, which you can diagnose yourself:', 'jetpack' ); ?></h4>
174
  <ol>
175
- <li><b><em><?php esc_html_e( 'A known issue.', 'jetpack' ); ?></em></b> <?php echo sprintf( __( 'Some themes and plugins have <a href="%1$s" target="_blank">known conflicts</a> with Jetpack – check the <a href="%2$s" target="_blank">list</a>. (You can also browse the <a href="%3$s" target="_blank">Jetpack support pages</a> or <a href="%4$s" target="_blank">Jetpack support forum</a> to see if others have experienced and solved the problem.)', 'jetpack' ), 'http://jetpack.com/support/getting-started-with-jetpack/known-issues/', 'http://jetpack.com/support/getting-started-with-jetpack/known-issues/', 'http://jetpack.com/support/', 'http://wordpress.org/support/plugin/jetpack' ); ?></li>
176
  <li><b><em><?php esc_html_e( 'An incompatible plugin.', 'jetpack' ); ?></em></b> <?php esc_html_e( "Find out by disabling all plugins except Jetpack. If the problem persists, it's not a plugin issue. If the problem is solved, turn your plugins on one by one until the problem pops up again – there's the culprit! Let us know, and we'll try to help.", 'jetpack' ); ?></li>
177
  <li>
178
  <b><em><?php esc_html_e( 'A theme conflict.', 'jetpack' ); ?></em></b>
@@ -203,11 +258,6 @@ class Jetpack_Debugger {
203
  <div id="connected-user-details">
204
  <p><?php printf( __( 'The primary connection is owned by <strong>%s</strong>\'s WordPress.com account.', 'jetpack' ), esc_html( Jetpack::get_master_user_email() ) ); ?></p>
205
  </div>
206
- <hr />
207
- <div id="sync-related-posts">
208
- <p><?php echo esc_html__( 'Some features of Jetpack use the WordPress.com infrastructure and require that your public content be mirrored there. If you see intermittent issues only affecting certain posts, please try requesting a reindex of your posts.', 'jetpack' ); ?></p>
209
- <?php echo Jetpack::init()->sync->reindex_ui() ?>
210
- </div>
211
  <?php endif; ?>
212
  </div>
213
  <div id="contact-message" <?php if( ! isset( $_GET['contact'] ) ) {?> style="display:none" <?php } ?>>
@@ -236,7 +286,7 @@ class Jetpack_Debugger {
236
  ?>
237
  <div class="formbox">
238
  <label for="message" class="h"><?php esc_html_e( 'Please describe the problem you are having.', 'jetpack' ); ?></label>
239
- <textarea name="message" cols="40" rows="7" id="did"></textarea>
240
  </div>
241
 
242
  <div id="name_div" class="formbox">
@@ -264,7 +314,7 @@ class Jetpack_Debugger {
264
 
265
  <div id="blog_div" class="formbox">
266
  <div id="submit_div" class="contact-support">
267
- <input type="submit" name="submit" value="<?php esc_html_e( 'Submit &#187;', 'jetpack' ); ?>">
268
  </div>
269
  </div>
270
  <div style="clear: both;"></div>
@@ -274,7 +324,7 @@ class Jetpack_Debugger {
274
  <div id="toggle_debug_info"><a href="#"><?php _e( 'View Advanced Debug Results', 'jetpack' ); ?></a></div>
275
  <div id="debug_info_div" style="display:none">
276
  <h4><?php esc_html_e( 'Debug Info', 'jetpack' ); ?></h4>
277
- <div id="debug_info"><?php echo wpautop( esc_html( $debug_info ) ); ?></div>
278
  </div>
279
  </div>
280
  <?php
@@ -326,13 +376,11 @@ class Jetpack_Debugger {
326
 
327
  form#contactme {
328
  border: 1px solid #dfdfdf;
329
- background: #eaf3fa;
330
  padding: 20px;
331
  margin: 10px;
332
- background-color: #eaf3fa;
333
- border-radius: 5px;
334
  font-size: 15px;
335
- font-family: "Open Sans", "Helvetica Neue", sans-serif;
336
  }
337
 
338
  form#contactme label.h {
@@ -349,31 +397,17 @@ class Jetpack_Debugger {
349
 
350
  .formbox input[type="text"], .formbox input[type="email"], .formbox input[type="url"], .formbox textarea, #debug_info_div {
351
  border: 1px solid #e5e5e5;
352
- border-radius: 11px;
353
  box-shadow: inset 0 1px 1px rgba(0,0,0,0.1);
354
  color: #666;
355
  font-size: 14px;
356
  padding: 10px;
357
  width: 97%;
358
  }
359
- .formbox .contact-support input[type="submit"] {
360
- float: right;
361
- margin: 0 !important;
362
- border-radius: 20px !important;
363
- cursor: pointer;
364
- font-size: 13pt !important;
365
- height: auto !important;
366
- margin: 0 0 2em 10px !important;
367
- padding: 8px 16px !important;
368
- background-color: #ddd;
369
- border: 1px solid rgba(0,0,0,0.05);
370
- border-top-color: rgba(255,255,255,0.1);
371
- border-bottom-color: rgba(0,0,0,0.15);
372
- color: #333;
373
- font-weight: 400;
374
- display: inline-block;
375
- text-align: center;
376
- text-decoration: none;
377
  }
378
 
379
  .formbox span.errormsg {
@@ -397,7 +431,7 @@ class Jetpack_Debugger {
397
  }
398
 
399
  #debug_info_div, #toggle_debug_info, #debug_info_div p {
400
- font-size: smaller;
401
  }
402
 
403
  </style>
@@ -444,7 +478,7 @@ class Jetpack_Debugger {
444
  if ( validation_error ) {
445
  return false;
446
  }
447
- message.val( message.val() + "\r\n\r\n----------------------------------------------\r\n\r\nDEBUG INFO:\r\n" + $('#debug_info').val() );
448
  return true;
449
  });
450
 
18
  }
19
  }
20
 
21
+ static function seconds_to_time( $seconds ) {
22
+ $units = array(
23
+ "week" => 7*24*3600,
24
+ "day" => 24*3600,
25
+ "hour" => 3600,
26
+ "minute" => 60,
27
+ "second" => 1,
28
+ );
29
+ // specifically handle zero
30
+ if ( $seconds == 0 ) return "0 seconds";
31
+ $human_readable = "";
32
+ foreach ( $units as $name => $divisor ) {
33
+ if ( $quot = intval( $seconds / $divisor) ) {
34
+ $human_readable .= "$quot $name";
35
+ $human_readable .= ( abs( $quot ) > 1 ? "s" : "" ) . ", ";
36
+ $seconds -= $quot * $divisor;
37
+ }
38
+ }
39
+ return substr( $human_readable, 0, -2 );
40
+ }
41
+
42
  public static function jetpack_increase_timeout() {
43
  return 30; // seconds
44
  }
81
  $debug_info .= "\r\n" . esc_html( "SITE_URL: " . site_url() );
82
  $debug_info .= "\r\n" . esc_html( "HOME_URL: " . home_url() );
83
 
84
+ $debug_info .= "\r\n";
85
+ require_once JETPACK__PLUGIN_DIR . 'sync/class.jetpack-sync-modules.php';
86
+ $sync_module = Jetpack_Sync_Modules::get_module( 'full-sync' );
87
+ $sync_statuses = $sync_module->get_status();
88
+ $human_readable_sync_status = array();
89
+ foreach( $sync_statuses as $sync_status => $sync_status_value ) {
90
+ $human_readable_sync_status[ $sync_status ] =
91
+ in_array( $sync_status, array( 'started', 'queue_finished', 'sent_started', 'finished' ) )
92
+ ? date( 'r', $sync_status_value ) : $sync_status_value ;
93
+ }
94
+
95
+ $debug_info .= "\r\n". sprintf( esc_html__( 'Jetpack Sync Full Status: `%1$s`', 'jetpack' ), print_r( $human_readable_sync_status, 1 ) );
96
+
97
+ $next_schedules = wp_next_scheduled( 'jetpack_sync_full' );
98
+ if( $next_schedules ) {
99
+ $debug_info .= "\r\n". sprintf( esc_html__( 'Next Jetpack Full Sync Schedule: `%1$s`', 'jetpack' ), date( 'r', $next_schedules ) );
100
+ } else {
101
+ $debug_info .= "\r\n". esc_html__( "Next Jetpack Full Sync Schedule: Not Scheduled", 'jetpack' );
102
+ }
103
+
104
+ require_once JETPACK__PLUGIN_DIR. 'sync/class.jetpack-sync-sender.php';
105
+
106
+ $queue = Jetpack_Sync_Sender::get_instance()->get_sync_queue();
107
+
108
+ $debug_info .= "\r\n". sprintf( esc_html__( 'Sync Queue size: %1$s', 'jetpack' ), $queue->size() );
109
+ $debug_info .= "\r\n". sprintf( esc_html__( 'Sync Queue lag: %1$s', 'jetpack' ), self::seconds_to_time( $queue->lag() ) );
110
+
111
+ $full_sync_queue = Jetpack_Sync_Sender::get_instance()->get_full_sync_queue();
112
+
113
+ $debug_info .= "\r\n". sprintf( esc_html__( 'Full Sync Queue size: %1$s', 'jetpack' ), $full_sync_queue->size() );
114
+ $debug_info .= "\r\n". sprintf( esc_html__( 'Full Sync Queue lag: %1$s', 'jetpack' ), self::seconds_to_time( $full_sync_queue->lag() ) );
115
+
116
+ $debug_info .= "\r\n";
117
+
118
  foreach ( array (
119
  'HTTP_HOST',
120
  'SERVER_PORT',
227
  <h3><?php esc_html_e( 'Trouble with Jetpack?', 'jetpack' ); ?></h3>
228
  <h4><?php esc_html_e( 'It may be caused by one of these issues, which you can diagnose yourself:', 'jetpack' ); ?></h4>
229
  <ol>
230
+ <li><b><em><?php esc_html_e( 'A known issue.', 'jetpack' ); ?></em></b> <?php echo sprintf( __( 'Some themes and plugins have <a href="%1$s" target="_blank">known conflicts</a> with Jetpack – check the <a href="%2$s" target="_blank">list</a>. (You can also browse the <a href="%3$s" target="_blank">Jetpack support pages</a> or <a href="%4$s" target="_blank">Jetpack support forum</a> to see if others have experienced and solved the problem.)', 'jetpack' ), 'http://jetpack.com/support/getting-started-with-jetpack/known-issues/', 'http://jetpack.com/support/getting-started-with-jetpack/known-issues/', 'http://jetpack.com/support/', 'https://wordpress.org/support/plugin/jetpack' ); ?></li>
231
  <li><b><em><?php esc_html_e( 'An incompatible plugin.', 'jetpack' ); ?></em></b> <?php esc_html_e( "Find out by disabling all plugins except Jetpack. If the problem persists, it's not a plugin issue. If the problem is solved, turn your plugins on one by one until the problem pops up again – there's the culprit! Let us know, and we'll try to help.", 'jetpack' ); ?></li>
232
  <li>
233
  <b><em><?php esc_html_e( 'A theme conflict.', 'jetpack' ); ?></em></b>
258
  <div id="connected-user-details">
259
  <p><?php printf( __( 'The primary connection is owned by <strong>%s</strong>\'s WordPress.com account.', 'jetpack' ), esc_html( Jetpack::get_master_user_email() ) ); ?></p>
260
  </div>
 
 
 
 
 
261
  <?php endif; ?>
262
  </div>
263
  <div id="contact-message" <?php if( ! isset( $_GET['contact'] ) ) {?> style="display:none" <?php } ?>>
286
  ?>
287
  <div class="formbox">
288
  <label for="message" class="h"><?php esc_html_e( 'Please describe the problem you are having.', 'jetpack' ); ?></label>
289
+ <textarea name="message" cols="40" rows="7" id="did"><?php echo ( isset( $_GET['note'] ) ? esc_textarea( $_GET['note'] ) : '' ); ?></textarea>
290
  </div>
291
 
292
  <div id="name_div" class="formbox">
314
 
315
  <div id="blog_div" class="formbox">
316
  <div id="submit_div" class="contact-support">
317
+ <input type="submit" name="submit" class="button button-primary button-large" value="<?php esc_html_e( 'Submit &#187;', 'jetpack' ); ?>">
318
  </div>
319
  </div>
320
  <div style="clear: both;"></div>
324
  <div id="toggle_debug_info"><a href="#"><?php _e( 'View Advanced Debug Results', 'jetpack' ); ?></a></div>
325
  <div id="debug_info_div" style="display:none">
326
  <h4><?php esc_html_e( 'Debug Info', 'jetpack' ); ?></h4>
327
+ <div id="debug_info"><pre><?php echo esc_html( $debug_info ) ; ?></pre></div>
328
  </div>
329
  </div>
330
  <?php
376
 
377
  form#contactme {
378
  border: 1px solid #dfdfdf;
379
+ background: #FFF;
380
  padding: 20px;
381
  margin: 10px;
382
+ background-color: #F3F6F8;
 
383
  font-size: 15px;
 
384
  }
385
 
386
  form#contactme label.h {
397
 
398
  .formbox input[type="text"], .formbox input[type="email"], .formbox input[type="url"], .formbox textarea, #debug_info_div {
399
  border: 1px solid #e5e5e5;
 
400
  box-shadow: inset 0 1px 1px rgba(0,0,0,0.1);
401
  color: #666;
402
  font-size: 14px;
403
  padding: 10px;
404
  width: 97%;
405
  }
406
+ #debug_info_div {
407
+ border-radius: 0;
408
+ margin-top: 16px;
409
+ background: #FFF;
410
+ padding: 16px;
 
 
 
 
 
 
 
 
 
 
 
 
 
411
  }
412
 
413
  .formbox span.errormsg {
431
  }
432
 
433
  #debug_info_div, #toggle_debug_info, #debug_info_div p {
434
+ font-size: 12px;
435
  }
436
 
437
  </style>
478
  if ( validation_error ) {
479
  return false;
480
  }
481
+ message.val( message.val() + "\r\n\r\n----------------------------------------------\r\n\r\nDEBUG INFO:\r\n" + $('#debug_form_info').val() );
482
  return true;
483
  });
484
 
class.jetpack-heartbeat.php CHANGED
@@ -139,6 +139,10 @@ class Jetpack_Heartbeat {
139
  $return["{$prefix}module-{$slug}"] = Jetpack::is_module_active( $slug ) ? 'on' : 'off';
140
  }
141
 
 
 
 
 
142
  return $return;
143
  }
144
 
139
  $return["{$prefix}module-{$slug}"] = Jetpack::is_module_active( $slug ) ? 'on' : 'off';
140
  }
141
 
142
+ require_once dirname(__FILE__).'/sync/class.jetpack-sync-wp-replicastore.php';
143
+ $store = new Jetpack_Sync_WP_Replicastore();
144
+ $return["{$prefix}sync-checksum"] = json_encode( $store->checksum_all() );
145
+
146
  return $return;
147
  }
148
 
class.jetpack-modules-list-table.php CHANGED
@@ -150,6 +150,9 @@ class Jetpack_Modules_List_Table extends WP_List_Table {
150
  continue;
151
  }
152
  $key = sanitize_title( $title );
 
 
 
153
  $display_title = esc_html( wptexturize( $title ) );
154
  $url = esc_url( add_query_arg( 'module_tag', urlencode( $title ) ) );
155
  $current = '';
150
  continue;
151
  }
152
  $key = sanitize_title( $title );
153
+ if ( 'centralized-management' === $key && Jetpack::is_module_active( 'manage' ) ) {
154
+ continue;
155
+ }
156
  $display_title = esc_html( wptexturize( $title ) );
157
  $url = esc_url( add_query_arg( 'module_tag', urlencode( $title ) ) );
158
  $current = '';
class.jetpack-options.php CHANGED
@@ -23,7 +23,6 @@ class Jetpack_Options {
23
  'wpcc_options',
24
  'relatedposts',
25
  'file_data',
26
- 'security_report',
27
  'autoupdate_plugins', // (array) An array of plugin ids ( eg. jetpack/jetpack ) that should be autoupdated
28
  'autoupdate_themes', // (array) An array of theme ids ( eg. twentyfourteen ) that should be autoupdated
29
  'autoupdate_core', // (bool) Whether or not to autoupdate core
@@ -63,8 +62,6 @@ class Jetpack_Options {
63
  'identity_crisis_whitelist', // (array) An array of options, each having an array of the values whitelisted for it.
64
  'gplus_authors', // (array) The Google+ authorship information for connected users.
65
  'last_heartbeat', // (int) The timestamp of the last heartbeat that fired.
66
- 'last_security_report', // (int) The timestamp of the last security report that was run.
67
- 'sync_bulk_reindexing', // (bool) If a bulk reindex is currently underway.
68
  'jumpstart', // (string) A flag for whether or not to show the Jump Start. Accepts: new_connection, jumpstart_activated, jetpack_action_taken, jumpstart_dismissed.
69
  'hide_jitm' // (array) A list of just in time messages that we should not show because they have been dismissed by the user
70
  );
@@ -121,6 +118,26 @@ class Jetpack_Options {
121
  return $default;
122
  }
123
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  private static function update_grouped_option( $group, $name, $value ) {
125
  $options = get_option( self::$grouped_options[ $group ] );
126
  if ( ! is_array( $options ) ) {
@@ -149,14 +166,7 @@ class Jetpack_Options {
149
  */
150
  do_action( 'pre_update_jetpack_option_' . $name, $name, $value );
151
  if ( self::is_valid( $name, 'non_compact' ) ) {
152
- /**
153
- * Allowing update_option to change autoload status only shipped in WordPress v4.2
154
- * @link https://github.com/WordPress/WordPress/commit/305cf8b95
155
- */
156
- if ( version_compare( $GLOBALS['wp_version'], '4.2', '>=' ) ) {
157
- return update_option( "jetpack_$name", $value, $autoload );
158
- }
159
- return update_option( "jetpack_$name", $value );
160
  }
161
 
162
  foreach ( array_keys( self::$grouped_options ) as $group ) {
23
  'wpcc_options',
24
  'relatedposts',
25
  'file_data',
 
26
  'autoupdate_plugins', // (array) An array of plugin ids ( eg. jetpack/jetpack ) that should be autoupdated
27
  'autoupdate_themes', // (array) An array of theme ids ( eg. twentyfourteen ) that should be autoupdated
28
  'autoupdate_core', // (bool) Whether or not to autoupdate core
62
  'identity_crisis_whitelist', // (array) An array of options, each having an array of the values whitelisted for it.
63
  'gplus_authors', // (array) The Google+ authorship information for connected users.
64
  'last_heartbeat', // (int) The timestamp of the last heartbeat that fired.
 
 
65
  'jumpstart', // (string) A flag for whether or not to show the Jump Start. Accepts: new_connection, jumpstart_activated, jetpack_action_taken, jumpstart_dismissed.
66
  'hide_jitm' // (array) A list of just in time messages that we should not show because they have been dismissed by the user
67
  );
118
  return $default;
119
  }
120
 
121
+ /**
122
+ * Returns the requested option, and ensures it's autoloaded in the future.
123
+ * This does _not_ adjust the prefix in any way (does not prefix jetpack_%)
124
+ *
125
+ * @param string $name Option name
126
+ * @param mixed $default (optional)
127
+ *
128
+ * @return mixed|void
129
+ */
130
+ public static function get_option_and_ensure_autoload( $name, $default ) {
131
+ $value = get_option( $name );
132
+
133
+ if ( $value === false && $default !== false ) {
134
+ update_option( $name, $default );
135
+ $value = $default;
136
+ }
137
+
138
+ return $value;
139
+ }
140
+
141
  private static function update_grouped_option( $group, $name, $value ) {
142
  $options = get_option( self::$grouped_options[ $group ] );
143
  if ( ! is_array( $options ) ) {
166
  */
167
  do_action( 'pre_update_jetpack_option_' . $name, $name, $value );
168
  if ( self::is_valid( $name, 'non_compact' ) ) {
169
+ return update_option( "jetpack_$name", $value, $autoload );
 
 
 
 
 
 
 
170
  }
171
 
172
  foreach ( array_keys( self::$grouped_options ) as $group ) {
class.jetpack-signature.php CHANGED
@@ -43,14 +43,14 @@ class Jetpack_Signature {
43
  // with SSL termination proxies (self-served, Cloudflare, etc.) don't need to fiddle with
44
  // the JETPACK_SIGNATURE__HTTPS_PORT constant. The code also implies we can't talk to a
45
  // site at https://example.com:80/ (which would be a strange configuration).
46
- // JETPACK_SIGNATURE__HTTPS_PORT: Set this constant in wp-config.php to the backend webserver's port
47
  // if the site is behind a proxy running on port 443 without
48
- // X-Forwarded-Port and the backend's port is *not* 80. It's better,
49
  // though, to configure the proxy to send X-Forwarded-Port.
50
  $port = in_array( $host_port, array( 443, 80, JETPACK_SIGNATURE__HTTPS_PORT ) ) ? '' : $host_port;
51
  } else {
52
  // 80: Standard Port
53
- // JETPACK_SIGNATURE__HTTPS_PORT: Set this constant in wp-config.php to the backend webserver's port
54
  // if the site is behind a proxy running on port 80 without
55
  // X-Forwarded-Port. It's better, though, to configure the proxy to
56
  // send X-Forwarded-Port.
43
  // with SSL termination proxies (self-served, Cloudflare, etc.) don't need to fiddle with
44
  // the JETPACK_SIGNATURE__HTTPS_PORT constant. The code also implies we can't talk to a
45
  // site at https://example.com:80/ (which would be a strange configuration).
46
+ // JETPACK_SIGNATURE__HTTPS_PORT: Set this constant in wp-config.php to the back end webserver's port
47
  // if the site is behind a proxy running on port 443 without
48
+ // X-Forwarded-Port and the back end's port is *not* 80. It's better,
49
  // though, to configure the proxy to send X-Forwarded-Port.
50
  $port = in_array( $host_port, array( 443, 80, JETPACK_SIGNATURE__HTTPS_PORT ) ) ? '' : $host_port;
51
  } else {
52
  // 80: Standard Port
53
+ // JETPACK_SIGNATURE__HTTPS_PORT: Set this constant in wp-config.php to the back end webserver's port
54
  // if the site is behind a proxy running on port 80 without
55
  // X-Forwarded-Port. It's better, though, to configure the proxy to
56
  // send X-Forwarded-Port.
class.jetpack-sync.php DELETED
@@ -1,1104 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Request that a piece of data on this WordPress install be synced back to the
5
- * Jetpack server for remote processing/notifications/etc
6
- */
7
- class Jetpack_Sync {
8
- // What modules want to sync what content
9
- public $sync_conditions = array( 'posts' => array(), 'comments' => array() );
10
-
11
- // We keep track of all the options registered for sync so that we can sync them all if needed
12
- public $sync_options = array();
13
-
14
- public $sync_constants = array();
15
-
16
- // Keep trac of status transitions, which we wouldn't always know about on the Jetpack Servers but are important when deciding what to do with the sync.
17
- public $post_transitions = array();
18
- public $comment_transitions = array();
19
-
20
- // Objects to sync
21
- public $sync = array();
22
-
23
- function __construct() {
24
- // WP Cron action. Only used on upgrade
25
- add_action( 'jetpack_sync_all_registered_options', array( $this, 'sync_all_registered_options' ) );
26
- add_action( 'jetpack_heartbeat', array( $this, 'sync_all_registered_options' ) );
27
-
28
- // Sync constants on heartbeat and plugin upgrade and connects
29
- add_action( 'init', array( $this, 'register_constants_as_options' ) );
30
- add_action( 'jetpack_sync_all_registered_options', array( $this, 'sync_all_constants' ) );
31
- add_action( 'jetpack_heartbeat', array( $this, 'sync_all_constants' ) );
32
-
33
- add_action( 'jetpack_activate_module', array( $this, 'sync_module_constants' ), 10, 1 );
34
- }
35
-
36
- /* Static Methods for Modules */
37
-
38
- /**
39
- * @param string $file __FILE__
40
- * @param array settings:
41
- * post_types => array( post_type slugs ): The post types to sync. Default: post, page
42
- * post_stati => array( post_status slugs ): The post stati to sync. Default: publish
43
- */
44
- static function sync_posts( $file, array $settings = null ) {
45
- if ( is_network_admin() ) return;
46
- $jetpack = Jetpack::init();
47
- $args = func_get_args();
48
- return call_user_func_array( array( $jetpack->sync, 'posts' ), $args );
49
- }
50
-
51
- /**
52
- * @param string $file __FILE__
53
- * @param array settings:
54
- * post_types => array( post_type slugs ): The post types to sync. Default: post, page
55
- * post_stati => array( post_status slugs ): The post stati to sync. Default: publish
56
- * comment_types => array( comment_type slugs ): The comment types to sync. Default: '', comment, trackback, pingback
57
- * comment_stati => array( comment_status slugs ): The comment stati to sync. Default: approved
58
- */
59
- static function sync_comments( $file, array $settings = null ) {
60
- if ( is_network_admin() ) return;
61
- $jetpack = Jetpack::init();
62
- $args = func_get_args();
63
- return call_user_func_array( array( $jetpack->sync, 'comments' ), $args );
64
- }
65
-
66
- /**
67
- * @param string $file __FILE__
68
- * @param string $option, Option name to sync
69
- * @param string $option ...
70
- */
71
- static function sync_options( $file, $option /*, $option, ... */ ) {
72
- if ( is_network_admin() ) return;
73
- $jetpack = Jetpack::init();
74
- $args = func_get_args();
75
- return call_user_func_array( array( $jetpack->sync, 'options' ), $args );
76
- }
77
- /**
78
- * @param string $file __FILE__
79
- * @param string $option, Option name to sync
80
- * @param string $option ...
81
- */
82
- static function sync_constant( $file, $constant ) {
83
- if ( is_network_admin() ) return;
84
- $jetpack = Jetpack::init();
85
- $args = func_get_args();
86
- return call_user_func_array( array( $jetpack->sync, 'constant' ), $args );
87
- }
88
-
89
- /* Internal Methods */
90
-
91
- /**
92
- * Create a sync object/request
93
- *
94
- * @param string $object Type of object to sync -- [ post | comment | option ]
95
- * @param int $id Unique identifier
96
- * @param array $settings
97
- */
98
- function register( $object, $id = false, array $settings = null ) {
99
- // Since we've registered something for sync, hook it up to execute on shutdown if we haven't already
100
- if ( !$this->sync ) {
101
- if ( function_exists( 'ignore_user_abort' ) ) {
102
- ignore_user_abort( true );
103
- }
104
- add_action( 'shutdown', array( $this, 'sync' ), 9 ); // Right before async XML-RPC
105
- }
106
-
107
- $defaults = array(
108
- 'on_behalf_of' => array(), // What modules want this data
109
- );
110
- $settings = wp_parse_args( $settings, $defaults );
111
-
112
- if ( !isset( $this->sync[$object] ) ) {
113
- $this->sync[$object] = array();
114
- }
115
-
116
- // Store the settings for this object
117
- if (
118
- // First time for this object
119
- !isset( $this->sync[$object][$id] )
120
- ) {
121
- // Easy: store the current settings
122
- $this->sync[$object][$id] = $settings;
123
- } else {
124
- // Not as easy: we have to manually merge the settings from previous runs for this object with the settings for this run
125
-
126
- $this->sync[$object][$id]['on_behalf_of'] = array_unique( array_merge( $this->sync[$object][$id]['on_behalf_of'], $settings['on_behalf_of'] ) );
127
- }
128
-
129
- $delete_prefix = 'delete_';
130
- if ( 0 === strpos( $object, $delete_prefix ) ) {
131
- $unset_object = substr( $object, strlen( $delete_prefix ) );
132
- } else {
133
- $unset_object = "{$delete_prefix}{$object}";
134
- }
135
-
136
- // Ensure post ... delete_post yields a delete operation
137
- // Ensure delete_post ... post yields a sync post operation
138
- // Ensure update_option() ... delete_option() ends up as a delete
139
- // Ensure delete_option() ... update_option() ends up as an update
140
- // Etc.
141
- unset( $this->sync[$unset_object][$id] );
142
-
143
- return true;
144
- }
145
-
146
- function get_common_sync_data() {
147
- $available_modules = Jetpack::get_available_modules();
148
- $active_modules = Jetpack::get_active_modules();
149
- $modules = array();
150
- foreach ( $available_modules as $available_module ) {
151
- $modules[$available_module] = in_array( $available_module, $active_modules );
152
- }
153
- $modules['vaultpress'] = class_exists( 'VaultPress' ) || function_exists( 'vaultpress_contact_service' );
154
-
155
- $sync_data = array(
156
- 'modules' => $modules,
157
- 'version' => JETPACK__VERSION,
158
- 'is_multisite' => is_multisite(),
159
- );
160
-
161
- return $sync_data;
162
- }
163
-
164
- /**
165
- * Set up all the data and queue it for the outgoing XML-RPC request
166
- */
167
- function sync() {
168
- if ( !$this->sync ) {
169
- return false;
170
- }
171
-
172
- // Don't sync anything from a staging site.
173
- if ( Jetpack::is_development_mode() || Jetpack::is_staging_site() ) {
174
- return false;
175
- }
176
-
177
- $sync_data = $this->get_common_sync_data();
178
-
179
- $wp_importing = defined( 'WP_IMPORTING' ) && WP_IMPORTING;
180
-
181
- foreach ( $this->sync as $sync_operation_type => $sync_operations ) {
182
- switch ( $sync_operation_type ) {
183
- case 'post':
184
- if ( $wp_importing ) {
185
- break;
186
- }
187
-
188
- $global_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null;
189
- $GLOBALS['post'] = null;
190
- foreach ( $sync_operations as $post_id => $settings ) {
191
- $sync_data['post'][$post_id] = $this->get_post( $post_id );
192
- if ( isset( $this->post_transitions[$post_id] ) ) {
193
- $sync_data['post'][$post_id]['transitions'] = $this->post_transitions[$post_id];
194
- } else {
195
- $sync_data['post'][$post_id]['transitions'] = array( false, false );
196
- }
197
- $sync_data['post'][$post_id]['on_behalf_of'] = $settings['on_behalf_of'];
198
- }
199
- $GLOBALS['post'] = $global_post;
200
- unset( $global_post );
201
- break;
202
- case 'comment':
203
- if ( $wp_importing ) {
204
- break;
205
- }
206
-
207
- $global_comment = isset( $GLOBALS['comment'] ) ? $GLOBALS['comment'] : null;
208
- unset( $GLOBALS['comment'] );
209
- foreach ( $sync_operations as $comment_id => $settings ) {
210
- $sync_data['comment'][$comment_id] = $this->get_comment( $comment_id );
211
- if ( isset( $this->comment_transitions[$comment_id] ) ) {
212
- $sync_data['comment'][$comment_id]['transitions'] = $this->comment_transitions[$comment_id];
213
- } else {
214
- $sync_data['comment'][$comment_id]['transitions'] = array( false, false );
215
- }
216
- $sync_data['comment'][$comment_id]['on_behalf_of'] = $settings['on_behalf_of'];
217
- }
218
- $GLOBALS['comment'] = $global_comment;
219
- unset( $global_comment );
220
- break;
221
- case 'option' :
222
- foreach ( $sync_operations as $option => $settings ) {
223
- $sync_data['option'][ $option ] = array( 'value' => get_option( $option ) );
224
- }
225
- break;
226
-
227
- case 'constant' :
228
- foreach( $sync_operations as $constant => $settings ) {
229
- $sync_data['constant'][ $constant ] = array( 'value' => $this->get_constant( $constant ) );
230
- }
231
- break;
232
-
233
- case 'delete_post':
234
- case 'delete_comment':
235
- foreach ( $sync_operations as $object_id => $settings ) {
236
- $sync_data[$sync_operation_type][$object_id] = array( 'on_behalf_of' => $settings['on_behalf_of'] );
237
- }
238
- break;
239
- case 'delete_option' :
240
- foreach ( $sync_operations as $object_id => $settings ) {
241
- $sync_data[$sync_operation_type][$object_id] = true;
242
- }
243
- break;
244
- }
245
- }
246
- Jetpack::xmlrpc_async_call( 'jetpack.syncContent', $sync_data );
247
- }
248
-
249
- /**
250
- * Format and return content data from a direct xmlrpc request for it.
251
- *
252
- * @param array $content_ids: array( 'posts' => array of ids, 'comments' => array of ids, 'options' => array of options )
253
- */
254
- function get_content( $content_ids ) {
255
- $sync_data = $this->get_common_sync_data();
256
-
257
- if ( isset( $content_ids['posts'] ) ) {
258
- foreach ( $content_ids['posts'] as $id ) {
259
- $sync_data['post'][$id] = $this->get_post( $id );
260
- }
261
- }
262
-
263
- if ( isset( $content_ids['comments'] ) ) {
264
- foreach ( $content_ids['comments'] as $id ) {
265
- $sync_data['comment'][$id] = $this->get_post( $id );
266
- }
267
- }
268
-
269
- if ( isset( $content_ids['options'] ) ) {
270
- foreach ( $content_ids['options'] as $option ) {
271
- $sync_data['option'][$option] = array( 'value' => get_option( $option ) );
272
- }
273
- }
274
-
275
- return $sync_data;
276
- }
277
-
278
- /**
279
- * Helper method for registering a post for sync
280
- *
281
- * @param int $id wp_posts.ID
282
- * @param array $settings Sync data
283
- */
284
- function register_post( $id, array $settings = null ) {
285
- $id = (int) $id;
286
- if ( !$id ) {
287
- return false;
288
- }
289
-
290
- $post = get_post( $id );
291
- if ( !$post ) {
292
- return false;
293
- }
294
-
295
- $settings = wp_parse_args( $settings, array(
296
- 'on_behalf_of' => array(),
297
- ) );
298
-
299
- return $this->register( 'post', $id, $settings );
300
- }
301
-
302
- /**
303
- * Helper method for registering a comment for sync
304
- *
305
- * @param int $id wp_comments.comment_ID
306
- * @param array $settings Sync data
307
- */
308
- function register_comment( $id, array $settings = null ) {
309
- $id = (int) $id;
310
- if ( !$id ) {
311
- return false;
312
- }
313
-
314
- $comment = get_comment( $id );
315
- if ( !$comment || empty( $comment->comment_post_ID ) ) {
316
- return false;
317
- }
318
-
319
- $post = get_post( $comment->comment_post_ID );
320
- if ( !$post ) {
321
- return false;
322
- }
323
-
324
- $settings = wp_parse_args( $settings, array(
325
- 'on_behalf_of' => array(),
326
- ) );
327
-
328
- return $this->register( 'comment', $id, $settings );
329
- }
330
-
331
- /* Posts Sync */
332
-
333
- function posts( $file, array $settings = null ) {
334
- $module_slug = Jetpack::get_module_slug( $file );
335
-
336
- $defaults = array(
337
- 'post_types' => array( 'post', 'page' ),
338
- 'post_stati' => array( 'publish' ),
339
- );
340
-
341
- $this->sync_conditions['posts'][$module_slug] = wp_parse_args( $settings, $defaults );
342
-
343
- add_action( 'transition_post_status', array( $this, 'transition_post_status_action' ), 10, 3 );
344
- add_action( 'delete_post', array( $this, 'delete_post_action' ) );
345
- }
346
-
347
- function delete_post_action( $post_id ) {
348
- $post = get_post( $post_id );
349
- if ( !$post ) {
350
- return $this->register( 'delete_post', (int) $post_id );
351
- }
352
-
353
- $this->transition_post_status_action( 'delete', $post->post_status, $post );
354
- }
355
-
356
- function transition_post_status_action( $new_status, $old_status, $post ) {
357
- $sync = $this->get_post_sync_operation( $new_status, $old_status, $post, $this->sync_conditions['posts'] );
358
- if ( !$sync ) {
359
- // No module wants to sync this post
360
- return false;
361
- }
362
-
363
- // Track post transitions
364
- if ( isset( $this->post_transitions[$post->ID] ) ) {
365
- // status changed more than once - keep tha most recent $new_status
366
- $this->post_transitions[$post->ID][0] = $new_status;
367
- } else {
368
- $this->post_transitions[$post->ID] = array( $new_status, $old_status );
369
- }
370
-
371
- $operation = $sync['operation'];
372
- unset( $sync['operation'] );
373
-
374
- switch ( $operation ) {
375
- case 'delete' :
376
- return $this->register( 'delete_post', (int) $post->ID, $sync );
377
- case 'submit' :
378
- return $this->register_post( (int) $post->ID, $sync );
379
- }
380
- }
381
-
382
- function get_post_sync_operation( $new_status, $old_status, $post, $module_conditions ) {
383
- $delete_on_behalf_of = array();
384
- $submit_on_behalf_of = array();
385
- $delete_stati = array( 'delete' );
386
- $cache_cleared = false;
387
-
388
- foreach ( $module_conditions as $module => $conditions ) {
389
- if ( !in_array( $post->post_type, $conditions['post_types'] ) ) {
390
- continue;
391
- }
392
-
393
- $deleted_post = in_array( $new_status, $delete_stati );
394
-
395
- if ( $deleted_post ) {
396
- $delete_on_behalf_of[] = $module;
397
- } else {
398
- if ( ! $cache_cleared ) {
399
- // inefficient to clear cache more than once
400
- clean_post_cache( $post->ID );
401
- $cache_cleared = true;
402
- }
403
- $new_status = get_post_status( $post->ID ); // Inherited status is resolved here
404
- }
405
-
406
- $old_status_in_stati = in_array( $old_status, $conditions['post_stati'] );
407
- $new_status_in_stati = in_array( $new_status, $conditions['post_stati'] );
408
-
409
- if ( $old_status_in_stati && !$new_status_in_stati ) {
410
- // Jetpack no longer needs the post
411
- if ( !$deleted_post ) {
412
- $delete_on_behalf_of[] = $module;
413
- } // else, we've already flagged it above
414
- continue;
415
- }
416
-
417
- if ( !$new_status_in_stati ) {
418
- continue;
419
- }
420
-
421
- // At this point, we know we want to sync the post, not delete it
422
- $submit_on_behalf_of[] = $module;
423
- }
424
-
425
- if ( !empty( $submit_on_behalf_of ) ) {
426
- return array( 'operation' => 'submit', 'on_behalf_of' => $submit_on_behalf_of );
427
- }
428
-
429
- if ( !empty( $delete_on_behalf_of ) ) {
430
- return array( 'operation' => 'delete', 'on_behalf_of' => $delete_on_behalf_of );
431
- }
432
-
433
- return false;
434
- }
435
-
436
- /**
437
- * Get a post and associated data in the standard JP format.
438
- * Cannot be called statically
439
- *
440
- * @param int $id Post ID
441
- * @return Array containing full post details
442
- */
443
- function get_post( $id ) {
444
- $post_obj = get_post( $id );
445
- if ( !$post_obj )
446
- return false;
447
-
448
- if ( is_callable( $post_obj, 'to_array' ) ) {
449
- // WP >= 3.5
450
- $post = $post_obj->to_array();
451
- } else {
452
- // WP < 3.5
453
- $post = get_object_vars( $post_obj );
454
- }
455
-
456
- if ( 0 < strlen( $post['post_password'] ) ) {
457
- $post['post_password'] = 'auto-' . wp_generate_password( 10, false ); // We don't want the real password. Just pass something random.
458
- }
459
-
460
- // local optimizations
461
- unset(
462
- $post['filter'],
463
- $post['ancestors'],
464
- $post['post_content_filtered'],
465
- $post['to_ping'],
466
- $post['pinged']
467
- );
468
-
469
- if ( $this->is_post_public( $post ) ) {
470
- $post['post_is_public'] = Jetpack_Options::get_option( 'public' );
471
- } else {
472
- //obscure content
473
- $post['post_content'] = '';
474
- $post['post_excerpt'] = '';
475
- $post['post_is_public'] = false;
476
- }
477
- $post_type_obj = get_post_type_object( $post['post_type'] );
478
- $post['post_is_excluded_from_search'] = $post_type_obj->exclude_from_search;
479
-
480
- $post['tax'] = array();
481
- $taxonomies = get_object_taxonomies( $post_obj );
482
- foreach ( $taxonomies as $taxonomy ) {
483
- $terms = get_object_term_cache( $post_obj->ID, $taxonomy );
484
- if ( empty( $terms ) )
485
- $terms = wp_get_object_terms( $post_obj->ID, $taxonomy );
486
- $term_names = array();
487
- foreach ( $terms as $term ) {
488
- $term_names[] = $term->name;
489
- }
490
- $post['tax'][$taxonomy] = $term_names;
491
- }
492
-
493
- $meta = get_post_meta( $post_obj->ID, false );
494
- $post['meta'] = array();
495
- foreach ( $meta as $key => $value ) {
496
- $post['meta'][$key] = array_map( 'maybe_unserialize', $value );
497
- }
498
-
499
- $post['extra'] = array(
500
- 'author' => get_the_author_meta( 'display_name', $post_obj->post_author ),
501
- 'author_email' => get_the_author_meta( 'email', $post_obj->post_author ),
502
- 'dont_email_post_to_subs' => get_post_meta( $post_obj->ID, '_jetpack_dont_email_post_to_subs', true ),
503
- );
504
-
505
- if ( $fid = get_post_thumbnail_id( $id ) ) {
506
- $feature = wp_get_attachment_image_src( $fid, 'large' );
507
- if ( ! empty( $feature[0] ) ) {
508
- $post['extra']['featured_image'] = $feature[0];
509
- }
510
-
511
- $attachment = get_post( $fid );
512
- if ( ! empty( $attachment ) ) {
513
- $metadata = wp_get_attachment_metadata( $fid );
514
-
515
- $post['extra']['post_thumbnail'] = array(
516
- 'ID' => (int) $fid,
517
- 'URL' => (string) wp_get_attachment_url( $fid ),
518
- 'guid' => (string) $attachment->guid,
519
- 'mime_type' => (string) $attachment->post_mime_type,
520
- 'width' => (int) isset( $metadata['width'] ) ? $metadata['width'] : 0,
521
- 'height' => (int) isset( $metadata['height'] ) ? $metadata['height'] : 0,
522
- );
523
-
524
- if ( isset( $metadata['duration'] ) ) {
525
- $post['extra']['post_thumbnail'] = (int) $metadata['duration'];
526
- }
527
-
528
- /**
529
- * Filters the Post Thumbnail information returned for a specific post.
530
- *
531
- * @since 3.3.0
532
- *
533
- * @param array $post['extra']['post_thumbnail'] {
534
- * Array of details about the Post Thumbnail.
535
- * @param int ID Post Thumbnail ID.
536
- * @param string URL Post thumbnail URL.
537
- * @param string guid Post thumbnail guid.
538
- * @param string mime_type Post thumbnail mime type.
539
- * @param int width Post thumbnail width.
540
- * @param int height Post thumbnail height.
541
- * }
542
- */
543
- $post['extra']['post_thumbnail'] = (object) apply_filters( 'get_attachment', $post['extra']['post_thumbnail'] );
544
- }
545
- }
546
-
547
- $post['permalink'] = get_permalink( $post_obj->ID );
548
- $post['shortlink'] = wp_get_shortlink( $post_obj->ID );
549
- /**
550
- * Allow modules to send extra info on the sync post process.
551
- *
552
- * @since 2.8.0
553
- *
554
- * @param array $args Array of custom data to attach to a post.
555
- * @param Object $post_obj Object returned by get_post() for a given post ID.
556
- */
557
- $post['module_custom_data'] = apply_filters( 'jetpack_sync_post_module_custom_data', array(), $post_obj );
558
- return $post;
559
- }
560
-
561
- /**
562
- * Decide whether a post/page/attachment is visible to the public.
563
- *
564
- * @param array $post
565
- * @return bool
566
- */
567
- function is_post_public( $post ) {
568
- if ( !is_array( $post ) ) {
569
- $post = (array) $post;
570
- }
571
-
572
- if ( 0 < strlen( $post['post_password'] ) )
573
- return false;
574
- if ( ! in_array( $post['post_type'], get_post_types( array( 'public' => true ) ) ) )
575
- return false;
576
- $post_status = get_post_status( $post['ID'] ); // Inherited status is resolved here.
577
- if ( ! in_array( $post_status, get_post_stati( array( 'public' => true ) ) ) )
578
- return false;
579
- return true;
580
- }
581
-
582
- /* Comments Sync */
583
-
584
- function comments( $file, array $settings = null ) {
585
- $module_slug = Jetpack::get_module_slug( $file );
586
-
587
- $defaults = array(
588
- 'post_types' => array( 'post', 'page' ), // For what post types will we sync comments?
589
- 'post_stati' => array( 'publish' ), // For what post stati will we sync comments?
590
- 'comment_types' => array( '', 'comment', 'trackback', 'pingback' ), // What comment types will we sync?
591
- 'comment_stati' => array( 'approved' ), // What comment stati will we sync?
592
- );
593
-
594
- $settings = wp_parse_args( $settings, $defaults );
595
-
596
- $this->sync_conditions['comments'][$module_slug] = $settings;
597
-
598
- add_action( 'wp_insert_comment', array( $this, 'wp_insert_comment_action' ), 10, 2 );
599
- add_action( 'transition_comment_status', array( $this, 'transition_comment_status_action' ), 10, 3 );
600
- add_action( 'edit_comment', array( $this, 'edit_comment_action' ) );
601
- }
602
-
603
- /*
604
- * This is really annoying. If you edit a comment, but don't change the status, WordPress doesn't fire the transition_comment_status hook.
605
- * That means we have to catch these comments on the edit_comment hook, but ignore comments on that hook when the transition_comment_status does fire.
606
- */
607
- function edit_comment_action( $comment_id ) {
608
- $comment = get_comment( $comment_id );
609
- $new_status = $this->translate_comment_status( $comment->comment_approved );
610
- add_action( "comment_{$new_status}_{$comment->comment_type}", array( $this, 'transition_comment_status_for_comments_whose_status_does_not_change' ), 10, 2 );
611
- }
612
-
613
- function wp_insert_comment_action( $comment_id, $comment ) {
614
- $this->transition_comment_status_action( $comment->comment_approved, 'new', $comment );
615
- }
616
-
617
- function transition_comment_status_for_comments_whose_status_does_not_change( $comment_id, $comment ) {
618
- if ( isset( $this->comment_transitions[$comment_id] ) ) {
619
- return $this->transition_comment_status_action( $comment->comment_approved, $this->comment_transitions[$comment_id][1], $comment );
620
- }
621
-
622
- return $this->transition_comment_status_action( $comment->comment_approved, $comment->comment_approved, $comment );
623
- }
624
-
625
- function translate_comment_status( $status ) {
626
- switch ( (string) $status ) {
627
- case '0' :
628
- case 'hold' :
629
- return 'unapproved';
630
- case '1' :
631
- case 'approve' :
632
- return 'approved';
633
- }
634
-
635
- return $status;
636
- }
637
-
638
- function transition_comment_status_action( $new_status, $old_status, $comment ) {
639
- $post = get_post( $comment->comment_post_ID );
640
- if ( !$post ) {
641
- return false;
642
- }
643
-
644
- foreach ( array( 'new_status', 'old_status' ) as $_status ) {
645
- $$_status = $this->translate_comment_status( $$_status );
646
- }
647
-
648
- // Track comment transitions
649
- if ( isset( $this->comment_transitions[$comment->comment_ID] ) ) {
650
- // status changed more than once - keep tha most recent $new_status
651
- $this->comment_transitions[$comment->comment_ID][0] = $new_status;
652
- } else {
653
- $this->comment_transitions[$comment->comment_ID] = array( $new_status, $old_status );
654
- }
655
-
656
- $post_sync = $this->get_post_sync_operation( $post->post_status, '_jetpack_test_sync', $post, $this->sync_conditions['comments'] );
657
-
658
- if ( !$post_sync ) {
659
- // No module wants to sync this comment because its post doesn't match any sync conditions
660
- return false;
661
- }
662
-
663
- if ( 'delete' == $post_sync['operation'] ) {
664
- // Had we been looking at post sync operations (instead of comment sync operations),
665
- // this comment's post would have been deleted. Don't sync the comment.
666
- return false;
667
- }
668
-
669
- $delete_on_behalf_of = array();
670
- $submit_on_behalf_of = array();
671
- $delete_stati = array( 'delete' );
672
-
673
- foreach ( $this->sync_conditions['comments'] as $module => $conditions ) {
674
- if ( !in_array( $comment->comment_type, $conditions['comment_types'] ) ) {
675
- continue;
676
- }
677
-
678
- $deleted_comment = in_array( $new_status, $delete_stati );
679
-
680
- if ( $deleted_comment ) {
681
- $delete_on_behalf_of[] = $module;
682
- }
683
-
684
- $old_status_in_stati = in_array( $old_status, $conditions['comment_stati'] );
685
- $new_status_in_stati = in_array( $new_status, $conditions['comment_stati'] );
686
-
687
- if ( $old_status_in_stati && !$new_status_in_stati ) {
688
- // Jetpack no longer needs the comment
689
- if ( !$deleted_comment ) {
690
- $delete_on_behalf_of[] = $module;
691
- } // else, we've already flagged it above
692
- continue;
693
- }
694
-
695
- if ( !$new_status_in_stati ) {
696
- continue;
697
- }
698
-
699
- // At this point, we know we want to sync the comment, not delete it
700
- $submit_on_behalf_of[] = $module;
701
- }
702
-
703
- if ( ! empty( $submit_on_behalf_of ) ) {
704
- $this->register_post( $comment->comment_post_ID, array( 'on_behalf_of' => $submit_on_behalf_of ) );
705
- return $this->register_comment( $comment->comment_ID, array( 'on_behalf_of' => $submit_on_behalf_of ) );
706
- }
707
-
708
- if ( !empty( $delete_on_behalf_of ) ) {
709
- return $this->register( 'delete_comment', $comment->comment_ID, array( 'on_behalf_of' => $delete_on_behalf_of ) );
710
- }
711
-
712
- return false;
713
- }
714
-
715
- /**
716
- * Get a comment and associated data in the standard JP format.
717
- * Cannot be called statically
718
- *
719
- * @param int $id Comment ID
720
- * @return Array containing full comment details
721
- */
722
- function get_comment( $id ) {
723
- $comment_obj = get_comment( $id );
724
- if ( !$comment_obj )
725
- return false;
726
- $comment = get_object_vars( $comment_obj );
727
-
728
- $meta = get_comment_meta( $id, false );
729
- $comment['meta'] = array();
730
- foreach ( $meta as $key => $value ) {
731
- $comment['meta'][$key] = array_map( 'maybe_unserialize', $value );
732
- }
733
-
734
- return $comment;
735
- }
736
-
737
- /* Options Sync */
738
-
739
- /* Ah... so much simpler than Posts and Comments :) */
740
- function options( $file, $option /*, $option, ... */ ) {
741
- $options = func_get_args();
742
- $file = array_shift( $options );
743
-
744
- $module_slug = Jetpack::get_module_slug( $file );
745
-
746
- if ( !isset( $this->sync_options[$module_slug] ) ) {
747
- $this->sync_options[$module_slug] = array();
748
- }
749
-
750
- foreach ( $options as $option ) {
751
- $this->sync_options[$module_slug][] = $option;
752
- add_action( "delete_option_{$option}", array( $this, 'deleted_option_action' ) );
753
- add_action( "update_option_{$option}", array( $this, 'updated_option_action' ) );
754
- add_action( "add_option_{$option}", array( $this, 'added_option_action' ) );
755
- }
756
-
757
- $this->sync_options[$module_slug] = array_unique( $this->sync_options[$module_slug] );
758
- }
759
-
760
- function deleted_option_action( $option ) {
761
- $this->register( 'delete_option', $option );
762
- }
763
-
764
- function updated_option_action() {
765
- // The value of $option isn't passed to the filter
766
- // Calculate it
767
- $option = current_filter();
768
- $prefix = 'update_option_';
769
- if ( 0 !== strpos( $option, $prefix ) ) {
770
- return;
771
- }
772
- $option = substr( $option, strlen( $prefix ) );
773
-
774
- $this->added_option_action( $option );
775
- }
776
-
777
- function added_option_action( $option ) {
778
- $this->register( 'option', $option );
779
- }
780
-
781
- function sync_all_module_options( $module_slug ) {
782
- if ( empty( $this->sync_options[$module_slug] ) ) {
783
- return;
784
- }
785
-
786
- foreach ( $this->sync_options[$module_slug] as $option ) {
787
- $this->added_option_action( $option );
788
- }
789
- }
790
-
791
- function sync_all_registered_options() {
792
- if ( 'jetpack_sync_all_registered_options' == current_filter() ) {
793
- add_action( 'shutdown', array( $this, 'register_all_options' ), 8 );
794
- } else {
795
- wp_schedule_single_event( time(), 'jetpack_sync_all_registered_options', array( $this->sync_options ) );
796
- }
797
- }
798
-
799
- /**
800
- * All the options that are defined in modules as well as class.jetpack.php will get synced.
801
- * Registers all options to be synced.
802
- */
803
- function register_all_options() {
804
- $all_registered_options = array_unique( call_user_func_array( 'array_merge', $this->sync_options ) );
805
- foreach ( $all_registered_options as $option ) {
806
- $this->added_option_action( $option );
807
- }
808
- }
809
-
810
- /* Constants Sync */
811
-
812
- function get_all_constants() {
813
- return array(
814
- 'EMPTY_TRASH_DAYS',
815
- 'WP_POST_REVISIONS',
816
- 'AUTOMATIC_UPDATER_DISABLED',
817
- 'ABSPATH',
818
- 'WP_CONTENT_DIR',
819
- 'FS_METHOD',
820
- 'DISALLOW_FILE_EDIT',
821
- 'DISALLOW_FILE_MODS',
822
- 'WP_AUTO_UPDATE_CORE',
823
- 'WP_HTTP_BLOCK_EXTERNAL',
824
- 'WP_ACCESSIBLE_HOSTS',
825
- );
826
- }
827
- /**
828
- * This lets us get the constant value like get_option( 'jetpack_constant_CONSTANT' );
829
- * Not the best way to get the constant value but necessery in some cases like in the API.
830
- */
831
- function register_constants_as_options() {
832
- foreach( $this->get_all_constants() as $constant ) {
833
- add_filter( 'pre_option_jetpack_constant_'. $constant, array( $this, 'get_default_constant' ) );
834
- }
835
- }
836
-
837
- function sync_all_constants() {
838
- // add the constant to sync.
839
- foreach( $this->get_all_constants() as $constant ) {
840
- $this->register_constant( $constant );
841
- }
842
- add_action( 'shutdown', array( $this, 'register_all_module_constants' ), 8 );
843
- }
844
-
845
- /**
846
- * Returns default values of Constants
847
- */
848
- function default_constant( $constant ) {
849
- switch( $constant ) {
850
- case 'WP_AUTO_UPDATE_CORE':
851
- return 'minor';
852
- break;
853
-
854
- default:
855
- return null;
856
- break;
857
- }
858
- }
859
-
860
- function register_all_module_constants() {
861
- // also add the contstants from each module to be synced.
862
- foreach( $this->sync_constants as $module ) {
863
- foreach( $module as $constant ) {
864
- $this->register_constant( $constant );
865
- }
866
- }
867
- }
868
-
869
- /**
870
- * Sync constants required by the module that was just activated.
871
- * If you add Jetpack_Sync::sync_constant( __FILE__, 'HELLO_WORLD' );
872
- * to the module it will start syncing the constant after the constant has been updated.
873
- *
874
- * This function gets called on module activation.
875
- */
876
- function sync_module_constants( $module ) {
877
-
878
- if ( isset( $this->sync_constants[ $module ] ) && is_array( $this->sync_constants[ $module ] ) ) {
879
- // also add the contstants from each module to be synced.
880
- foreach( $this->sync_constants[ $module ] as $constant ) {
881
- $this->register_constant( $constant );
882
- }
883
- }
884
- }
885
-
886
- public function reindex_needed() {
887
- return ( $this->_get_post_count_local() != $this->_get_post_count_cloud() );
888
- }
889
-
890
- public function reindex_trigger() {
891
- $response = array( 'status' => 'ERROR' );
892
-
893
- // Force a privacy check
894
- Jetpack::check_privacy( JETPACK__PLUGIN_FILE );
895
-
896
- Jetpack::load_xml_rpc_client();
897
- $client = new Jetpack_IXR_Client( array(
898
- 'user_id' => JETPACK_MASTER_USER,
899
- ) );
900
-
901
- $client->query( 'jetpack.reindexTrigger' );
902
-
903
- if ( !$client->isError() ) {
904
- $response = $client->getResponse();
905
- Jetpack_Options::update_option( 'sync_bulk_reindexing', true );
906
- }
907
-
908
- return $response;
909
- }
910
-
911
- public function reindex_status() {
912
- $response = array( 'status' => 'ERROR' );
913
-
914
- // Assume reindexing is done if it was not triggered in the first place
915
- if ( false === Jetpack_Options::get_option( 'sync_bulk_reindexing' ) ) {
916
- return array( 'status' => 'DONE' );
917
- }
918
-
919
- Jetpack::load_xml_rpc_client();
920
- $client = new Jetpack_IXR_Client( array(
921
- 'user_id' => JETPACK_MASTER_USER,
922
- ) );
923
-
924
- $client->query( 'jetpack.reindexStatus' );
925
-
926
- if ( !$client->isError() ) {
927
- $response = $client->getResponse();
928
- if ( 'DONE' == $response['status'] ) {
929
- Jetpack_Options::delete_option( 'sync_bulk_reindexing' );
930
- }
931
- }
932
-
933
- return $response;
934
- }
935
-
936
- public function reindex_ui() {
937
- $strings = json_encode( array(
938
- 'WAITING' => array(
939
- 'action' => __( 'Refresh Status', 'jetpack' ),
940
- 'status' => __( 'Indexing request queued and waiting&hellip;', 'jetpack' ),
941
- ),
942
- 'INDEXING' => array(
943
- 'action' => __( 'Refresh Status', 'jetpack' ),
944
- 'status' => __( 'Indexing posts', 'jetpack' ),
945
- ),
946
- 'DONE' => array(
947
- 'action' => __( 'Reindex Posts', 'jetpack' ),
948
- 'status' => __( 'Posts indexed.', 'jetpack' ),
949
- ),
950
- 'ERROR' => array(
951
- 'action' => __( 'Refresh Status', 'jetpack' ),
952
- 'status' => __( 'Status unknown.', 'jetpack' ),
953
- ),
954
- 'ERROR:LARGE' => array(
955
- 'action' => __( 'Refresh Status', 'jetpack' ),
956
- 'status' => __( 'This site is too large, please contact Jetpack support to sync.', 'jetpack' ),
957
- ),
958
- ) );
959
-
960
- wp_enqueue_script(
961
- 'jetpack_sync_reindex_control',
962
- plugins_url( '_inc/jquery.jetpack-sync.js', JETPACK__PLUGIN_FILE ),
963
- array( 'jquery' ),
964
- JETPACK__VERSION
965
- );
966
-
967
- $template = <<<EOT
968
- <p class="jetpack_sync_reindex_control" id="jetpack_sync_reindex_control" data-strings="%s">
969
- <input type="submit" class="jetpack_sync_reindex_control_action button" value="%s" disabled />
970
- <span class="jetpack_sync_reindex_control_status">&hellip;</span>
971
- </p>
972
- EOT;
973
-
974
- return sprintf(
975
- $template,
976
- esc_attr( $strings ),
977
- esc_attr__( 'Refresh Status', 'jetpack' )
978
- );
979
- }
980
-
981
- private function _get_post_count_local() {
982
- global $wpdb;
983
- return (int) $wpdb->get_var(
984
- "SELECT count(*)
985
- FROM {$wpdb->posts}
986
- WHERE post_status = 'publish' AND post_password = ''"
987
- );
988
- }
989
-
990
- private function _get_post_count_cloud() {
991
- $blog_id = Jetpack::init()->get_option( 'id' );
992
-
993
- $body = array(
994
- 'size' => 1,
995
- );
996
-
997
- $response = wp_remote_post(
998
- "https://public-api.wordpress.com/rest/v1/sites/$blog_id/search",
999
- array(
1000
- 'timeout' => 10,
1001
- 'user-agent' => 'jetpack_related_posts',
1002
- 'sslverify' => true,
1003
- 'body' => $body,
1004
- )
1005
- );
1006
-
1007
- if ( is_wp_error( $response ) ) {
1008
- return 0;
1009
- }
1010
-
1011
- $results = json_decode( wp_remote_retrieve_body( $response ), true );
1012
-
1013
- return isset( $results['results'] ) && isset( $results['results']['total'] ) ? (int) $results['results']['total'] : 0;
1014
- }
1015
-
1016
- /**
1017
- * Sometimes we need to fake options to be able to sync data with .com
1018
- * This is a helper function. That will make it easier to do just that.
1019
- *
1020
- * It will make sure that the options are synced when do_action( 'jetpack_sync_all_registered_options' );
1021
- *
1022
- * Which should happen everytime we update Jetpack to a new version or daily by Jetpack_Heartbeat.
1023
- *
1024
- * $callback is a function that is passed into a filter that returns the value of the option.
1025
- * This value should never be false. Since we want to short circuit the get_option function
1026
- * to return the value of the our callback.
1027
- *
1028
- * You can also trigger an update when a something else changes by calling the
1029
- * do_action( 'add_option_jetpack_' . $option, 'jetpack_'.$option, $callback_function );
1030
- * on the action that should that would trigger the update.
1031
- *
1032
- *
1033
- * @param string $option Option will always be prefixed with Jetpack and be saved on .com side
1034
- * @param string or array $callback
1035
- */
1036
- function mock_option( $option , $callback ) {
1037
- add_filter( 'pre_option_jetpack_'. $option, $callback );
1038
- // This shouldn't happen but if it does we return the same as before.
1039
- add_filter( 'option_jetpack_'. $option, $callback );
1040
- // Instead of passing a file we just pass in a string.
1041
- $this->options( 'mock-option' , 'jetpack_' . $option );
1042
-
1043
- }
1044
- /**
1045
- * Sometimes you need to sync constants to .com
1046
- * Using the function will allow you to do just that.
1047
- *
1048
- * @param 'string' $constant Constants defined in code.
1049
- *
1050
- */
1051
- function register_constant( $constant ) {
1052
- $this->register( 'constant', $constant );
1053
- }
1054
-
1055
- function get_default_constant() {
1056
- $filter = current_filter();
1057
- // We don't know what the constant is so we get it from the current filter.
1058
- if ( 'pre_option_jetpack_constant_' === substr( $filter, 0, 28 ) ) {
1059
- $constant = substr( $filter, 28 );
1060
- if ( defined( $constant ) ) {
1061
- // If constant is set to false we will not shortcut the get_option function and will return the default value.
1062
- // Hance we set it to null. Which in most cases would produce the same result.
1063
- return false === constant( $constant ) ? null : constant( $constant );
1064
- }
1065
- return $this->default_constant( $constant );
1066
- }
1067
- }
1068
- /**
1069
- * Simular to $this->options() function.
1070
- * Add the constant to be synced to .com when we activate the module.
1071
- * As well as on heartbeat and plugin upgrade and connection to .com.
1072
- *
1073
- * @param string $file
1074
- * @param string $constant
1075
- */
1076
- function constant( $file, $constant ) {
1077
- $constants = func_get_args();
1078
- $file = array_shift( $constants );
1079
-
1080
- $module_slug = Jetpack::get_module_slug( $file );
1081
-
1082
- if ( ! isset( $this->sync_constants[ $module_slug ] ) ) {
1083
- $this->sync_constants[ $module_slug ] = array();
1084
- }
1085
-
1086
- foreach ( $constants as $constant ) {
1087
- $this->sync_constants[ $module_slug ][] = $constant;
1088
- }
1089
- }
1090
-
1091
- /**
1092
- * Helper function to return the constants value.
1093
- *
1094
- * @param string $constant
1095
- * @return value of the constant or null if the constant is set to false or doesn't exits.
1096
- */
1097
- static function get_constant( $constant ) {
1098
- if ( defined( $constant ) ) {
1099
- return constant( $constant );
1100
- }
1101
-
1102
- return null;
1103
- }
1104
- }