Jetpack by WordPress.com - Version 3.4.4

Version Description

Release Date: May 26, 2016

  • Important security update. Please upgrade immediately.
Download this release

Release Info

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

Code changes from version 3.3.4 to 3.4.4

Files changed (88) hide show
  1. _inc/footer.php +33 -37
  2. _inc/header.php +2 -2
  3. _inc/jp.js +166 -196
  4. _inc/lib/admin-pages/class.jetpack-admin-page.php +10 -1
  5. _inc/lib/admin-pages/class.jetpack-landing-page.php +145 -4
  6. _inc/lib/admin-pages/class.jetpack-settings-page.php +2 -2
  7. _inc/lib/tonesque.php +7 -0
  8. class.jetpack-admin.php +8 -1
  9. class.jetpack-autoupdate.php +227 -5
  10. class.jetpack-client-server.php +3 -1
  11. class.jetpack-client.php +6 -1
  12. class.jetpack-heartbeat.php +1 -19
  13. class.jetpack-modules-list-table.php +4 -1
  14. class.jetpack-options.php +115 -54
  15. class.jetpack-post-images.php +18 -10
  16. class.jetpack-sync.php +165 -9
  17. class.jetpack-twitter-cards.php +2 -2
  18. class.jetpack-user-agent.php +4 -0
  19. class.jetpack.php +755 -70
  20. class.json-api-endpoints.php +77 -12
  21. class.json-api.php +25 -2
  22. class.media-extractor.php +1 -1
  23. class.photon.php +9 -6
  24. css/dashboard-widget-rtl.css +108 -0
  25. css/dashboard-widget-rtl.min.css +3 -0
  26. css/dashboard-widget.css +105 -0
  27. css/dashboard-widget.css.map +1 -0
  28. css/dashboard-widget.min.css +3 -0
  29. css/dashboard-widget.min.css.map +1 -0
  30. css/jetpack-admin-rtl.css +706 -33
  31. css/jetpack-admin-rtl.min.css +1 -1
  32. css/jetpack-admin.css +705 -32
  33. css/jetpack-admin.css.map +1 -1
  34. css/jetpack-admin.min.css +1 -1
  35. css/jetpack-admin.min.css.map +1 -1
  36. css/jetpack-rtl.css +1 -1
  37. css/jetpack.css +1 -1
  38. css/jp-benefits.css +2 -0
  39. css/jp-benefits.css.map +1 -0
  40. functions.opengraph.php +25 -2
  41. images/jetpack-protect-shield.svg +30 -0
  42. images/screenshots/beautifulmath.png +0 -0
  43. images/screenshots/carousel.png +0 -0
  44. images/screenshots/comments.png +0 -0
  45. images/screenshots/contactform.png +0 -0
  46. images/screenshots/custom-content-types.png +0 -0
  47. images/screenshots/custom-css.png +0 -0
  48. images/screenshots/google-plus.png +0 -0
  49. images/screenshots/hovercards.png +0 -0
  50. images/screenshots/likes.png +0 -0
  51. images/screenshots/manage-sm.png +0 -0
  52. images/screenshots/manage.png +0 -0
  53. images/screenshots/mobile-push-notifications.jpg +0 -0
  54. images/screenshots/mobile-theme.png +0 -0
  55. images/screenshots/notes.png +0 -0
  56. images/screenshots/post-by-email.png +0 -0
  57. images/screenshots/publicize.png +0 -0
  58. images/screenshots/sharing.png +0 -0
  59. images/screenshots/shortcodes.png +0 -0
  60. images/screenshots/shortlinks.png +0 -0
  61. images/screenshots/site-icon.png +0 -0
  62. images/screenshots/spelling.png +0 -0
  63. images/screenshots/stats.png +0 -0
  64. images/screenshots/subscriptions.png +0 -0
  65. images/screenshots/tiled-gallery.png +0 -0
  66. images/screenshots/vaultpress.png +0 -0
  67. images/screenshots/widgets.png +0 -0
  68. images/the-footcloud.svg +5 -6
  69. jetpack.php +6 -4
  70. json-api-config.php +13 -0
  71. json-endpoints.php +482 -441
  72. json-endpoints/class.wpcom-json-api-get-site-endpoint.php +19 -12
  73. json-endpoints/class.wpcom-json-api-list-media-v1-1-endpoint.php +194 -3
  74. json-endpoints/class.wpcom-json-api-list-posts-endpoint.php +78 -15
  75. json-endpoints/class.wpcom-json-api-list-posts-v1-1-endpoint.php +86 -23
  76. json-endpoints/class.wpcom-json-api-post-endpoint.php +62 -28
  77. json-endpoints/class.wpcom-json-api-post-v1-1-endpoint.php +110 -71
  78. json-endpoints/class.wpcom-json-api-sharing-buttons-endpoint.php +250 -135
  79. json-endpoints/class.wpcom-json-api-site-settings-endpoint.php +25 -3
  80. json-endpoints/class.wpcom-json-api-update-comment-endpoint.php +1 -1
  81. json-endpoints/class.wpcom-json-api-update-media-v1-1-endpoint.php +38 -3
  82. json-endpoints/class.wpcom-json-api-update-taxonomy-endpoint.php +2 -2
  83. json-endpoints/class.wpcom-json-api-upload-media-endpoint.php +1 -1
  84. json-endpoints/jetpack/class.jetpack-json-api-endpoint.php +3 -6
  85. json-endpoints/jetpack/class.jetpack-json-api-sync-endpoint.php +13 -0
  86. json-endpoints/jetpack/json-api-jetpack-endpoints.php +15 -0
  87. languages/jetpack-ar.mo +0 -0
  88. languages/jetpack-ar.po +1096 -1666
_inc/footer.php CHANGED
@@ -5,43 +5,39 @@ $user_token = Jetpack_Data::get_access_token( $current_user->ID );
5
  $is_user_connected = $user_token && ! is_wp_error( $user_token );
6
  $is_master_user = $current_user->ID == Jetpack_Options::get_option( 'master_user' );
7
  ?>
8
- <div class="footer">
9
- <?php if ( ! $is_active && current_user_can( 'jetpack_connect' ) ) : ?>
10
- <a href="<?php echo $this->jetpack->build_connect_url() ?>" class="download-jetpack"><?php esc_html_e( 'Connect to Get Started', 'jetpack' ); ?></a>
11
- <?php elseif ( $is_active && ! $is_user_connected && current_user_can( 'jetpack_connect_user' ) ) : ?>
12
- <a href="<?php echo $this->jetpack->build_connect_url() ?>" class="download-jetpack"><?php esc_html_e( 'Link your account to WordPress.com', 'jetpack' ); ?></a>
13
- <?php endif; ?>
14
-
15
- <nav class="primary nav-horizontal">
16
- <div class="a8c-attribution">
17
- <span>
18
- <?php echo sprintf( __( 'An %s Airline', 'jetpack' ),
19
- '<a href="http://automattic.com/" class="a8c-logo">Automattic</a>'
20
- ); ?>
21
- </span>
22
- </div>
23
- </nav><!-- .primary -->
24
-
25
- <nav class="secondary nav-horizontal">
26
- <div class="secondary-footer">
27
- <a href="http://jetpack.me">Jetpack <?php echo JETPACK__VERSION; ?></a>
28
- <a href="http://wordpress.com/tos/"><?php esc_html_e( 'Terms', 'jetpack' ); ?></a>
29
- <a href="http://automattic.com/privacy/"><?php esc_html_e( 'Privacy', 'jetpack' ); ?></a>
30
- <a href="<?php echo esc_url( Jetpack::admin_url( 'page=jetpack-debugger' ) ); ?>" title="<?php esc_attr_e( 'Test your site&#8217;s compatibility with Jetpack.', 'jetpack' ); ?>"><?php _e( 'Debug', 'jetpack' ); ?></a>
31
- <a href="http://jetpack.me/contact-support/" title="<?php esc_attr_e( 'Contact the Jetpack Happiness Squad.', 'jetpack' ); ?>"><?php _e( 'Support', 'jetpack' ); ?></a>
32
- <a href="http://jetpack.me/survey/?rel=<?php echo JETPACK__VERSION; ?>" title="<?php esc_attr_e( 'Take a survey. Tell us how we&#8217;re doing.', 'jetpack' ); ?>"><?php _e( 'Give Us Feedback', 'jetpack' ); ?></a>
33
-
34
- <?php if ( $is_active && current_user_can( 'jetpack_disconnect' ) ) : ?>
35
- <a href="<?php echo wp_nonce_url( Jetpack::admin_url( 'action=disconnect' ), 'jetpack-disconnect' ); ?>"><?php esc_html_e( 'Disconnect from WordPress.com', 'jetpack' ); ?></a>
36
- <?php endif; ?>
37
- <?php if ( $is_active && $is_user_connected && ! $is_master_user ) : ?>
38
- <a href="<?php echo wp_nonce_url( Jetpack::admin_url( 'action=unlink' ), 'jetpack-unlink' ); ?>"><?php esc_html_e( 'Unlink your user account', 'jetpack' ); ?></a>
39
- <?php endif; ?>
40
-
41
- </div>
42
- </nav><!-- .secondary -->
43
- </div><!-- .footer -->
44
  </div><!-- .wrapper -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  <div class="modal" aria-labelledby="modal-label">
47
  <header>
@@ -53,7 +49,7 @@ $is_master_user = $current_user->ID == Jetpack_Options::get_option( 'master_u
53
  </header>
54
  <div class="content-container"><div class="content"></div></div>
55
  </div>
56
- <div class="shade" />
57
 
58
  </div><!-- .jp-frame -->
59
  </div><!-- .jp-content -->
5
  $is_user_connected = $user_token && ! is_wp_error( $user_token );
6
  $is_master_user = $current_user->ID == Jetpack_Options::get_option( 'master_user' );
7
  ?>
8
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  </div><!-- .wrapper -->
10
+ <div class="footer">
11
+
12
+ <nav class="primary nav-horizontal">
13
+ <div class="a8c-attribution">
14
+ <span>
15
+ <?php echo sprintf( __( 'An %s Airline', 'jetpack' ),
16
+ '<a href="http://automattic.com/" class="a8c-logo">Automattic</a>'
17
+ ); ?>
18
+ </span>
19
+ </div>
20
+ </nav><!-- .primary -->
21
+
22
+ <nav class="secondary nav-horizontal">
23
+ <div class="secondary-footer">
24
+ <a href="http://jetpack.me">Jetpack <?php echo JETPACK__VERSION; ?></a>
25
+ <a href="http://wordpress.com/tos/"><?php esc_html_e( 'Terms', 'jetpack' ); ?></a>
26
+ <a href="http://automattic.com/privacy/"><?php esc_html_e( 'Privacy', 'jetpack' ); ?></a>
27
+ <a href="<?php echo esc_url( Jetpack::admin_url( 'page=jetpack-debugger' ) ); ?>" title="<?php esc_attr_e( 'Test your site&#8217;s compatibility with Jetpack.', 'jetpack' ); ?>"><?php _e( 'Debug', 'jetpack' ); ?></a>
28
+ <a href="http://jetpack.me/contact-support/" title="<?php esc_attr_e( 'Contact the Jetpack Happiness Squad.', 'jetpack' ); ?>"><?php _e( 'Support', 'jetpack' ); ?></a>
29
+ <a href="http://jetpack.me/survey/?rel=<?php echo JETPACK__VERSION; ?>" title="<?php esc_attr_e( 'Take a survey. Tell us how we&#8217;re doing.', 'jetpack' ); ?>"><?php _e( 'Give Us Feedback', 'jetpack' ); ?></a>
30
+
31
+ <?php if ( $is_active && current_user_can( 'jetpack_disconnect' ) ) : ?>
32
+ <a href="<?php echo wp_nonce_url( Jetpack::admin_url( 'action=disconnect' ), 'jetpack-disconnect' ); ?>" onclick="return confirm('<?php echo htmlspecialchars( __('Are you sure you want to disconnect from WordPress.com?', 'jetpack'), ENT_QUOTES ); ?>');"><?php esc_html_e( 'Disconnect from WordPress.com', 'jetpack' ); ?></a>
33
+ <?php endif; ?>
34
+ <?php if ( $is_active && $is_user_connected && ! $is_master_user ) : ?>
35
+ <a href="<?php echo wp_nonce_url( Jetpack::admin_url( 'action=unlink' ), 'jetpack-unlink' ); ?>"><?php esc_html_e( 'Unlink your user account', 'jetpack' ); ?></a>
36
+ <?php endif; ?>
37
+
38
+ </div>
39
+ </nav><!-- .secondary -->
40
+ </div><!-- .footer -->
41
 
42
  <div class="modal" aria-labelledby="modal-label">
43
  <header>
49
  </header>
50
  <div class="content-container"><div class="content"></div></div>
51
  </div>
52
+ <div class="shade"></div>
53
 
54
  </div><!-- .jp-frame -->
55
  </div><!-- .jp-content -->
_inc/header.php CHANGED
@@ -5,14 +5,14 @@
5
  <nav role="navigation" class="header-nav drawer-nav nav-horizontal">
6
 
7
  <ul class="main-nav">
8
- <li class="jetpack-logo"><a href="<?php echo Jetpack::admin_url(); ?>" title="<?php esc_attr_e( 'Home', 'jetpack' ); ?>" <?php if ( 'jetpack' == $current ) { echo 'class="current"'; } ?>><span><?php esc_html_e( 'Jetpack', 'jetpack' ); ?></span></a></li>
9
  <?php if ( ( Jetpack::is_active() || Jetpack::is_development_mode() )
10
  && current_user_can( 'jetpack_manage_modules' )
11
  ) : ?>
12
  <li class="jetpack-modules">
13
  <a href="<?php echo Jetpack::admin_url( 'page=jetpack_modules' ); ?>" class="jp-button--settings <?php if ( 'jetpack_modules' == $current ) { echo 'current'; } ?>"><?php esc_html_e( 'Settings', 'jetpack' ); ?></a>
14
  </li>
15
- <li class="jetpack-modules" style="margin-left:15px">
16
  <a href="http://jetpack.me/survey/?rel=<?php echo JETPACK__VERSION; ?>" class="jp-button--settings"><?php esc_html_e( 'Feedback', 'jetpack' ); ?></a>
17
  </li>
18
  <?php endif; ?>
5
  <nav role="navigation" class="header-nav drawer-nav nav-horizontal">
6
 
7
  <ul class="main-nav">
8
+ <li class="jetpack-logo"><a href="<?php echo Jetpack::admin_url(); ?>" title="<?php esc_attr_e( 'Jetpack', 'jetpack' ); ?>" <?php if ( 'jetpack' == $current ) { echo 'class="current"'; } ?>><span><?php esc_html_e( 'Jetpack', 'jetpack' ); ?></span></a></li>
9
  <?php if ( ( Jetpack::is_active() || Jetpack::is_development_mode() )
10
  && current_user_can( 'jetpack_manage_modules' )
11
  ) : ?>
12
  <li class="jetpack-modules">
13
  <a href="<?php echo Jetpack::admin_url( 'page=jetpack_modules' ); ?>" class="jp-button--settings <?php if ( 'jetpack_modules' == $current ) { echo 'current'; } ?>"><?php esc_html_e( 'Settings', 'jetpack' ); ?></a>
14
  </li>
15
+ <li class="jetpack-modules">
16
  <a href="http://jetpack.me/survey/?rel=<?php echo JETPACK__VERSION; ?>" class="jp-button--settings"><?php esc_html_e( 'Feedback', 'jetpack' ); ?></a>
17
  </li>
18
  <?php endif; ?>
_inc/jp.js CHANGED
@@ -6,13 +6,26 @@
6
  // INIT
7
  ///////////////////////////////////////
8
 
9
- var originPoint;
 
10
 
11
  $( document ).ready(function () {
 
 
 
 
 
 
 
 
 
 
12
  initEvents();
13
- filterModules( 'introduced' );
14
- loadModules();
15
- updateModuleCount();
 
 
16
  });
17
 
18
  ///////////////////////////////////////
@@ -40,128 +53,20 @@
40
  });
41
  }
42
 
43
- function filterModules( prop ) {
44
-
45
- // Mapping prior to sorting improves performance by over 50%
46
- var map = [],
47
- result = [],
48
- val = '',
49
- i,
50
- length;
51
-
52
- // create the map
53
- for ( i = 0, length = modules.length; i < length; i++ ) {
54
-
55
- // Prep value
56
- if ( 'name' === prop ) {
57
- val = modules[i][prop].toLowerCase();
58
- } else {
59
- val = parseInt( modules[i][prop].replace( '0:', '' ) * 10, 10 );
60
- }
61
-
62
- map.push( {
63
- index: i,
64
- value: val
65
- });
66
- }
67
-
68
- // sort the map
69
- map.sort(function( a, b ) {
70
- if ( 'name' === prop ) {
71
- return a.value > b.value ? 1 : -1;
72
- } else {
73
- return b.value > a.value ? 1 : -1;
74
- }
75
- });
76
-
77
- // copy values in right order
78
- for ( i = 0, length = map.length; i < length; i++ ) {
79
- result.push( modules[map[i].index] );
80
- result[i].index = i; // make sure we set the index to the right order
81
- }
82
-
83
- // Replace old object, with newly sorted object
84
- modules = result;
85
-
86
- // If all modules are already showing, make sure they stay expanded
87
- if ( ! $( '.load-more' ).is( ':visible' ) ) {
88
- $( '.module' ).fadeIn();
89
- }
90
- }
91
-
92
- function filterModulesByCategory() {
93
- var categories,
94
- c, i, catId;
95
-
96
- // First alphabatize the modules
97
- filterModules( 'name' );
98
-
99
- // Add category containers
100
- $( '.modules' ).html( wp.template( 'category' )( {} ) );
101
-
102
- // Loop through adding sections for each category
103
- for ( i = 0; i < modules.length; i++ ) {
104
- // Get categories
105
- categories = modules[i].module_tags;
106
-
107
- // Loop through each individual category
108
- for ( c = 0; c < categories.length; c++ ) {
109
- // Add modules to the correct categories
110
- catId = 'category-' + categories[c].toLowerCase().replace( '.', '' ).replace( / /g, '-' );
111
- $( '.' + catId + ' .clear' ).before( wp.template( 'mod' )( modules[i] ) );
112
- }
113
- }
114
-
115
- recalculateModuleHeights();
116
- initModalEvents();
117
- }
118
-
119
  function initEvents () {
120
- // DOPS toggle
121
- $( '#a8c-service-toggle, .dops-close' ).click(function() {
122
- $( '.a8c-dops' ).toggleClass( 'show' );
123
- $( '#a8c-service-toggle .genericon' ).toggleClass( 'genericon-downarrow' ).toggleClass( 'genericon-uparrow' );
124
- return false;
125
- });
126
-
127
- // Load more
128
- $( '.load-more' ).click(function() {
129
- showAllModules();
130
- return false;
131
- });
132
-
133
- // Module filtering
134
- $( '#newest, #category, #alphabetical' ).on( 'click', function () {
135
- var $this = $( this ),
136
- prop = $this.data( 'filter' );
137
 
138
- // Reset selected filter
139
- $( '.jp-filter a' ).removeClass( 'selected' );
140
- $this.addClass( 'selected' );
141
 
142
- if ( 'cat' === prop ) {
143
- filterModulesByCategory();
144
- } else {
145
- // Rearrange modules
146
- filterModules( prop );
147
-
148
- // Reload the DOM based on this new sort order
149
- loadModules();
150
- }
151
-
152
- showAllModules();
153
- return false;
154
  });
155
 
156
- // Search modules
157
- $( '#jetpack-search' ).on( 'keyup search', function() {
158
- var term = $( this ).val();
159
- searchModules( term );
160
- });
161
- // prevent the form from
162
- $( '#module-search' ).on( 'submit', function( event ) {
163
- event.preventDefault();
164
- });
165
 
166
  // Modal events
167
  $( document ).ready(function () {
@@ -179,24 +84,11 @@
179
  }, 100 );
180
  }
181
  };
182
-
183
- // Close shade toggle
184
- closeShadeToggle();
185
-
186
- // Show specific category of modules
187
- $( '.showFilter a' ).on( 'click', function () {
188
- $( '.showFilter a' ).removeClass( 'active' );
189
- $( this ).addClass( 'active' );
190
-
191
- // TODO Do sorting here
192
-
193
- return false;
194
- });
195
  }
196
 
197
  function initModalEvents() {
198
  var $modal = $( '.modal' );
199
- $( '.module, .feature a, .configs a' ).on( 'click keypress', function (e) {
200
  // Only show modal on enter when keypress recorded (accessibility)
201
  if ( e.keyCode && 13 !== e.keyCode ) {
202
  return;
@@ -208,14 +100,12 @@
208
 
209
  // Show loading message on init
210
  $modal.html( wp.template( 'modalLoading' )( {} ) ).fadeIn();
211
-
212
  // Load & populate with content
213
- var $this = $( this ),
214
  index = $this.data( 'index' ),
215
  name = $this.data( 'name' );
216
-
217
  $modal.empty().html( wp.template( 'modal' )( $.extend( modules[index], { name: name } ) ) );
218
-
219
  // Save the focused element, then shift focus to the modal window.
220
  originPoint = this;
221
  $modal[0].setAttribute( 'tabindex', '0' );
@@ -232,53 +122,68 @@
232
  });
233
  }
234
 
235
- function loadModules() {
 
 
 
 
 
 
 
 
236
  var html = '',
237
- featuredModules = [],
238
- featuredModulesIndex,
239
- i;
240
-
241
- if ( $( '.configure' ).length !== 0 ) {
242
- // Config page
243
- for ( i = 0; i < modules.length; i++ ) {
244
- html += wp.template( 'modconfig' )( modules[i] );
245
- }
246
 
247
- $( 'table tbody' ).html( html );
248
- } else {
249
- // Array of featured modules
250
- $( '.feature a.f-img' ).each(function() {
251
- featuredModules.push($( this ).data( 'module' ));
252
- });
 
 
 
 
 
253
 
254
- // About page
255
- for ( i = 0; i < modules.length; i++ ) {
256
- if ( currentVersion.indexOf( modules[i].introduced ) === 0 ) {
257
- modules[i]['new'] = true;
258
- }
 
 
259
 
260
- // Add data-index to featured modules
261
- featuredModulesIndex = featuredModules.indexOf( modules[i].module );
262
- if ( featuredModulesIndex > -1 ) {
263
- $( '.feature' ).eq( featuredModulesIndex ).find( 'a' ).data( 'index', i );
264
- }
265
 
266
- modules[i].index = i;
267
 
268
- html += wp.template( 'mod' )( modules[i] );
269
- }
 
 
270
 
271
- $( '.modules' ).html( html );
272
 
273
- recalculateModuleHeights();
274
- initModalEvents();
 
275
  }
 
 
 
276
  }
277
 
278
  function recalculateModuleHeights () {
279
-
280
  // Resize module heights based on screen resolution
281
- var module = $( '.module, .jp-support-column-left .widget-text' ),
282
  tallest = 0,
283
  thisHeight;
284
 
@@ -299,31 +204,96 @@
299
  module.css( 'height', tallest + 'px' );
300
  }
301
 
302
- function searchModules( term ) {
303
- var html = '', i, lowercaseDesc, lowercaseName, lowercaseTerm;
304
- for ( i = 0; i < modules.length; i++ ) {
305
- lowercaseDesc = modules[i].description.toLowerCase();
306
- lowercaseName = modules[i].name.toLowerCase();
307
- lowercaseTerm = term.toLowerCase();
308
- if ( lowercaseName.indexOf( lowercaseTerm ) !== -1 || lowercaseDesc.indexOf( lowercaseTerm ) !== -1 ) {
309
- html += wp.template( 'mod' )( modules[i] );
310
- }
311
- $( '.modules' ).html( html );
312
- }
313
- if ( '' === html ) {
314
- $( '.modules' ).text( jetpackL10n.no_modules_found.replace( '{term}', term ) );
315
- }
316
- recalculateModuleHeights();
317
- initModalEvents();
318
- }
319
 
320
- function showAllModules() {
321
- $( '.module' ).fadeIn();
322
- $( '.load-more' ).hide();
323
- }
 
 
 
 
 
 
 
 
324
 
325
- function updateModuleCount () {
326
- $( '.load-more' ).text( jetpackL10n.view_all_features );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
327
  }
328
 
329
  })( jQuery, jetpackL10n.modules, jetpackL10n.currentVersion, jetpackL10n );
6
  // INIT
7
  ///////////////////////////////////////
8
 
9
+ var originPoint,
10
+ data;
11
 
12
  $( document ).ready(function () {
13
+
14
+ data = {
15
+ 'action' : 'jetpack_admin_ajax',
16
+ 'jumpstartModules' : jetpackL10n.jumpstart_modules,
17
+ 'jumpstartModSlug' : jetpackL10n.jumpstart_modules,
18
+ 'jumpstartNonce' : jetpackL10n.activate_nonce,
19
+ 'jumpstartStatsURLS' : jetpackL10n.jumpstart_stats_urls,
20
+ 'showJumpstart' : jetpackL10n.show_jumpstart
21
+ };
22
+
23
  initEvents();
24
+ loadModules( 'Recommended', 'mod-recommended', '.modules' );
25
+ if('1' === data.showJumpstart) {
26
+ loadModules( 'Jumpstart', 'mod-jumpstart', '#jp-config-list' );
27
+ }
28
+ jumpStartAJAX();
29
  });
30
 
31
  ///////////////////////////////////////
53
  });
54
  }
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  function initEvents () {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
+ // Show preconfigured list of features to enable via "Jump-start"
59
+ $( '.jp-config-list-btn' ).click(function(){
60
+ $( '#jp-config-list' ).toggle();
61
 
62
+ //Log Jump Start event "learn more" in MC Stats
63
+ new Image().src = data.jumpstartStatsURLS.learnmore;
 
 
 
 
 
 
 
 
 
 
64
  });
65
 
66
+ // Hide the successful connection message after a little bit
67
+ setTimeout( function(){
68
+ jQuery( '.jetpack-message' ).hide( 600 );
69
+ }, 6000);
 
 
 
 
 
70
 
71
  // Modal events
72
  $( document ).ready(function () {
84
  }, 100 );
85
  }
86
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  }
88
 
89
  function initModalEvents() {
90
  var $modal = $( '.modal' );
91
+ $( '.module h3, .feature a, .configs a, .more-info' ).on( 'click keypress', function (e) {
92
  // Only show modal on enter when keypress recorded (accessibility)
93
  if ( e.keyCode && 13 !== e.keyCode ) {
94
  return;
100
 
101
  // Show loading message on init
102
  $modal.html( wp.template( 'modalLoading' )( {} ) ).fadeIn();
 
103
  // Load & populate with content
104
+ var $this = $( this ).parent(),
105
  index = $this.data( 'index' ),
106
  name = $this.data( 'name' );
107
+
108
  $modal.empty().html( wp.template( 'modal' )( $.extend( modules[index], { name: name } ) ) );
 
109
  // Save the focused element, then shift focus to the modal window.
110
  originPoint = this;
111
  $modal[0].setAttribute( 'tabindex', '0' );
122
  });
123
  }
124
 
125
+
126
+ /*
127
+ Load Modules for a template
128
+ @param string: The module tag you'd like to filter by
129
+ @param string: The template name
130
+ @param string: The target element to display the template
131
+ */
132
+ function loadModules( prop, template, location ) {
133
+ // Mapping prior to sorting improves performance by over 50%
134
  var html = '',
135
+ result = [],
136
+ val = '',
137
+ i,
138
+ length,
139
+ renderingmodules = [];
 
 
 
 
140
 
141
+ // create the map
142
+ for ( i = 0, length = modules.length; i < length; i++ ) {
143
+ if( modules[i].feature.indexOf(prop) !== -1 ) {
144
+ val = modules[i].name.toLowerCase();
145
+ result.push( {
146
+ index: i,
147
+ value: val,
148
+ order: modules[i].recommendation_order
149
+ });
150
+ }
151
+ }
152
 
153
+ // Sort modules by recommendation order
154
+ result.sort(function( a, b ) {
155
+ if (a.order === b.order ) {
156
+ return 0;
157
+ }
158
+ return ( a.order < b.order ) ? -1 : 1;
159
+ });
160
 
161
+ // copy values in right order
162
+ for ( i = 0, length = result.length; i < length; i++ ) {
163
+ renderingmodules.push( modules[result[i].index] );
164
+ renderingmodules[i].index = result[i].index; // make sure we set the index to the right order*/
165
+ }
166
 
 
167
 
168
+ // Render modules
169
+ for ( i = 0; i < renderingmodules.length; i++ ) {
170
+ html += wp.template( template )( renderingmodules[i] );
171
+ }
172
 
173
+ $( location ).append( html );
174
 
175
+ // track Jump Start views
176
+ if('Jumpstart' === prop) {
177
+ new Image().src = data.jumpstartStatsURLS.viewed;
178
  }
179
+
180
+ recalculateModuleHeights();
181
+ initModalEvents();
182
  }
183
 
184
  function recalculateModuleHeights () {
 
185
  // Resize module heights based on screen resolution
186
+ var module = $( '.jp-jumpstart, .module, .jp-support-column-left .widget-text' ),
187
  tallest = 0,
188
  thisHeight;
189
 
204
  module.css( 'height', tallest + 'px' );
205
  }
206
 
207
+ /*
208
+ Handles the jump start ajax requests.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
 
210
+ Dismissing the Jump Start area will set an option, so it will never be seen again
211
+ Initiating Jump Start will activate all modules that are recommended and set a sharing options while doing so.
212
+ For either request, if update_option has failed, look for an error in the console.
213
+ @todo delete the "reset everything" call - meant for testing only.
214
+ */
215
+ function jumpStartAJAX() {
216
+
217
+ // Will dismiss the Jump Start area, and set wp option in callback
218
+ $( '.dismiss-jumpstart' ).click(function(){
219
+ $( '#jump-start-area' ).hide( 600 );
220
+
221
+ data.disableJumpStart = true;
222
 
223
+ $.post( jetpackL10n.ajaxurl, data, function (response) {
224
+ // If there's no response, something bad happened
225
+ if ( ! response ) {
226
+ //console.log( 'Option "jetpack_dismiss_jumpstart" not updated.' );
227
+ }
228
+ });
229
+
230
+ // Log Jump Start event in MC Stats
231
+ new Image().src = data.jumpstartStatsURLS.dismiss;
232
+
233
+ return false;
234
+ });
235
+
236
+ // Activate all Jump-start modules
237
+ $( '#jump-start' ).click(function () {
238
+
239
+ var module, dataName, configURL;
240
+
241
+ $( '.spinner' ).show();
242
+
243
+ data.jumpStartActivate = 'jump-start-activate';
244
+
245
+ $( '#jp-config-list' ).hide();
246
+
247
+ $.post( jetpackL10n.ajaxurl, data, function (response) {
248
+ // If there's no response, option 'sharing-services' was not updated.
249
+ if ( ! response ) {
250
+ //console.log( 'Option "sharing-services" not updated. Either you already had sharing buttons enabled, or something is broken.' );
251
+ }
252
+
253
+ module = data.jumpstartModules;
254
+
255
+ // Only target Jump Start modules
256
+ _.each( module, function( mod ) {
257
+ dataName = $( 'div[data-name="' + mod.module_name + '"]' );
258
+ configURL = mod.configure_url;
259
+
260
+ // Replace inactive content with active, provide config url
261
+ _.find( dataName, function( div ) {
262
+ $( div.children ).find( '.notconfigurable ').hide();
263
+ $( div.children ).find( '.configurable ' ).replaceWith( '<a class="button alignright" data-name="' + mod.module_name + '" title="Configure" href="' + configURL + '">Configure</a>' );
264
+ div.className += ' active';
265
+ });
266
+ });
267
+
268
+ $( '.spinner, .jstart, #jumpstart-cta' ).hide();
269
+ $( '.jumpstart-message, .miguel' ).toggle();
270
+
271
+ // Log Jump Start event in MC Stats
272
+ new Image().src = data.jumpstartStatsURLS.jumpstarted;
273
+
274
+ });
275
+
276
+ return false;
277
+ });
278
+
279
+ /*
280
+ RESET EVERYTHING (for testing only)
281
+ @todo remove
282
+ */
283
+
284
+ $( '#jump-start-deactivate' ).click(function () {
285
+ $( '.spinner' ).show();
286
+
287
+ data.jumpStartDeactivate = 'jump-start-deactivate';
288
+
289
+ $.post( jetpackL10n.ajaxurl, data, function ( response ) {
290
+ //$('#jumpstart-cta').html(response);
291
+ $( '#deactivate-success' ).html( response );
292
+ $( '.spinner' ).hide();
293
+ });
294
+
295
+ return false;
296
+ });
297
  }
298
 
299
  })( jQuery, jetpackL10n.modules, jetpackL10n.currentVersion, jetpackL10n );
_inc/lib/admin-pages/class.jetpack-admin-page.php CHANGED
@@ -46,6 +46,16 @@ abstract class Jetpack_Admin_Page {
46
 
47
  function admin_head() {
48
  if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) {
 
 
 
 
 
 
 
 
 
 
49
  do_action( 'jetpack_module_configuration_head_' . $_GET['configure'] );
50
  }
51
  }
@@ -97,4 +107,3 @@ abstract class Jetpack_Admin_Page {
97
  wp_style_add_data( 'jetpack-admin', 'suffix', $min );
98
  }
99
  }
100
- ?>
46
 
47
  function admin_head() {
48
  if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) {
49
+ /**
50
+ * Fires in the <head> of a particular Jetpack configuation page.
51
+ *
52
+ * The dynamic portion of the hook name, `$_GET['configure']`,
53
+ * refers to the slug of module, such as 'stats', 'sso', etc.
54
+ * A complete hook for the latter would be
55
+ * 'jetpack_module_configuation_head_sso'.
56
+ *
57
+ * @since 3.0.0
58
+ */
59
  do_action( 'jetpack_module_configuration_head_' . $_GET['configure'] );
60
  }
61
  }
107
  wp_style_add_data( 'jetpack-admin', 'suffix', $min );
108
  }
109
  }
 
_inc/lib/admin-pages/class.jetpack-landing-page.php CHANGED
@@ -35,19 +35,92 @@ class Jetpack_Landing_Page extends Jetpack_Admin_Page {
35
  // Add the main admin Jetpack menu with possible information about new
36
  // modules
37
  add_menu_page( 'Jetpack', $title, 'jetpack_admin_page', 'jetpack', array( $this, 'render' ), 'div' );
38
- // also create the submenu
39
  return add_submenu_page( 'jetpack', $title, $title, 'jetpack_admin_page', 'jetpack' );
40
  }
41
 
42
  function add_page_actions( $hook ) {
43
  // Add landing page specific underscore templates
44
  add_action( "admin_footer-$hook", array( $this, 'js_templates' ) );
 
45
  do_action( 'jetpack_admin_menu', $hook );
46
 
47
  // Place the Jetpack menu item on top and others in the order they
48
  // appear
49
  add_filter( 'custom_menu_order', '__return_true' );
50
  add_filter( 'menu_order', array( $this, 'jetpack_menu_order' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
 
53
  function jetpack_menu_order( $menu_order ) {
@@ -89,13 +162,58 @@ class Jetpack_Landing_Page extends Jetpack_Admin_Page {
89
 
90
  // Set template data for the admin page template
91
  $data = array(
92
- 'is_connected' => $is_connected,
93
  'is_user_connected' => $is_user_connected,
94
- 'is_master_user' => $is_master_user
 
 
 
95
  );
96
  Jetpack::init()->load_view( 'admin/admin-page.php', $data );
97
  }
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  // Render the configuration page for the module if it exists and an error
100
  // screen if the module is not configurable
101
  function render_nojs_configurable() {
@@ -112,6 +230,24 @@ class Jetpack_Landing_Page extends Jetpack_Admin_Page {
112
  echo '</div><!-- /wrap -->';
113
  }
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  function page_admin_scripts() {
116
  // Enqueue jp.js and localize it
117
  wp_enqueue_script( 'jetpack-js', plugins_url( '_inc/jp.js', JETPACK__PLUGIN_FILE ),
@@ -127,8 +263,13 @@ class Jetpack_Landing_Page extends Jetpack_Admin_Page {
127
  'no_modules_found' => sprintf( __( 'Sorry, no modules were found for the search term "%s"', 'jetpack' ), '{term}' ),
128
  'modules' => array_values( Jetpack_Admin::init()->get_modules() ),
129
  'currentVersion' => JETPACK__VERSION,
 
 
 
 
 
 
130
  )
131
  );
132
  }
133
  }
134
- ?>
35
  // Add the main admin Jetpack menu with possible information about new
36
  // modules
37
  add_menu_page( 'Jetpack', $title, 'jetpack_admin_page', 'jetpack', array( $this, 'render' ), 'div' );
38
+ // also create the submenu
39
  return add_submenu_page( 'jetpack', $title, $title, 'jetpack_admin_page', 'jetpack' );
40
  }
41
 
42
  function add_page_actions( $hook ) {
43
  // Add landing page specific underscore templates
44
  add_action( "admin_footer-$hook", array( $this, 'js_templates' ) );
45
+ /** This action is documented in class.jetpack.php */
46
  do_action( 'jetpack_admin_menu', $hook );
47
 
48
  // Place the Jetpack menu item on top and others in the order they
49
  // appear
50
  add_filter( 'custom_menu_order', '__return_true' );
51
  add_filter( 'menu_order', array( $this, 'jetpack_menu_order' ) );
52
+
53
+ add_action( 'jetpack_notices_update_settings', array( $this, 'show_notices_update_settings' ), 10, 1 );
54
+ }
55
+
56
+ /*
57
+ * Build an array of a specific module tag.
58
+ *
59
+ * @param string Name of the module tag
60
+ * @return array The module slug, config url, and name of each Jump Start module
61
+ */
62
+ function jumpstart_module_tag( $tag ) {
63
+ $modules = Jetpack_Admin::init()->get_modules();
64
+
65
+ $module_info = array();
66
+ foreach ( $modules as $module => $value ) {
67
+ if ( in_array( $tag, $value['feature'] ) ) {
68
+ $module_info[] = array(
69
+ 'module_slug' => $value['module'],
70
+ 'module_name' => $value['name'],
71
+ 'configure_url' => $value['configure_url'],
72
+ );
73
+ }
74
+ }
75
+ return $module_info;
76
+ }
77
+
78
+ /*
79
+ * Only show Jump Start on first activation.
80
+ * Any option 'jumpstart' other than 'new connection' will hide it.
81
+ *
82
+ * The option can be of 4 things, and will be stored as such:
83
+ * new_connection : Brand new connection - Show
84
+ * jumpstart_activated : Jump Start has been activated - dismiss
85
+ * jetpack_action_taken: Manual activation of a module already happened - dismiss
86
+ * jumpstart_dismissed : Manual dismissal of Jump Start - dismiss
87
+ *
88
+ * @return bool | show or hide
89
+ */
90
+ function jetpack_show_jumpstart() {
91
+ $jumpstart_option = Jetpack_Options::get_option( 'jumpstart' );
92
+
93
+ $hide_options = array(
94
+ 'jumpstart_activated',
95
+ 'jetpack_action_taken',
96
+ 'jumpstart_dismissed'
97
+ );
98
+
99
+ if ( ! $jumpstart_option || in_array( $jumpstart_option, $hide_options ) ) {
100
+ return false;
101
+ }
102
+
103
+ return true;
104
+ }
105
+
106
+ /*
107
+ * List of recommended modules for the Jump Start paragraph text.
108
+ * Will only show up in the paragraph if they are not active.
109
+ *
110
+ * @return string | comma-separated recommended modules that are not active
111
+ */
112
+ function jumpstart_list_modules() {
113
+ $jumpstart_recommended = $this->jumpstart_module_tag( 'Jumpstart' );
114
+
115
+ $module_name = array();
116
+ foreach ( $jumpstart_recommended as $module => $val ) {
117
+ if ( ! Jetpack::is_module_active( $val['module_slug'] ) ) {
118
+ $module_name[] = $val['module_name'];
119
+ }
120
+ }
121
+ $jumpstart_module_list = implode( $module_name, ', ' );
122
+
123
+ return $jumpstart_module_list;
124
  }
125
 
126
  function jetpack_menu_order( $menu_order ) {
162
 
163
  // Set template data for the admin page template
164
  $data = array(
165
+ 'is_connected' => $is_connected,
166
  'is_user_connected' => $is_user_connected,
167
+ 'is_master_user' => $is_master_user,
168
+ 'show_jumpstart' => $this->jetpack_show_jumpstart(),
169
+ 'jumpstart_list' => $this->jumpstart_list_modules(),
170
+ 'recommended_list' => $this->jumpstart_module_tag( 'Recommended' ),
171
  );
172
  Jetpack::init()->load_view( 'admin/admin-page.php', $data );
173
  }
174
 
175
+ /**
176
+ * Shows a notice message to users after they save Module config settings
177
+ * @param string $module_id
178
+ * @return null
179
+ */
180
+ function show_notices_update_settings( $module_id ) {
181
+ $state = Jetpack::state( 'message' );
182
+
183
+ switch( $state ) {
184
+ case 'module_activated' :
185
+ if ( $module = Jetpack::get_module( Jetpack::state( 'module' ) ) ) {
186
+ $message = sprintf( __( '<strong>%s Activated!</strong> You can change the setting of it here.', 'jetpack' ), $module['name'] );
187
+ }
188
+ break;
189
+ case 'module_configured':
190
+ $message = __( '<strong>Module settings were saved.</strong> ', 'jetpack' );
191
+ break;
192
+ case 'no_message' :
193
+ break;
194
+ }
195
+
196
+ if ( isset( $message ) ) {
197
+ ?>
198
+ <div id="message" class="jetpack-message">
199
+ <div class="squeezer">
200
+ <h4><?php echo wp_kses( $message, array( 'strong' => array(), 'a' => array( 'href' => true ), 'br' => true ) ); ?></h4>
201
+ <?php
202
+ /**
203
+ * Fires within the displayed message when a feature configuation is updated.
204
+ *
205
+ * This is a dynamic hook with `$module_id` being the slug of the module being updated.
206
+ *
207
+ * @since 3.4.0
208
+ */
209
+ do_action( 'jetpack_notices_update_settings_' . $module_id ); ?>
210
+ </div>
211
+ </div>
212
+ <?php
213
+ }
214
+ add_action( 'jetpack_notices', array( Jetpack::init(), 'admin_notices' ) );
215
+ }
216
+
217
  // Render the configuration page for the module if it exists and an error
218
  // screen if the module is not configurable
219
  function render_nojs_configurable() {
230
  echo '</div><!-- /wrap -->';
231
  }
232
 
233
+ /*
234
+ * Build an array of Jump Start stats urls.
235
+ * requires the build URL args passed as an array
236
+ *
237
+ * @param array $jumpstart_stats
238
+ * @return (array) of built stats urls
239
+ */
240
+ function build_jumpstart_stats_urls( $jumpstart_stats ) {
241
+ $jumpstart_urls = array();
242
+
243
+ foreach ( $jumpstart_stats as $value) {
244
+ $jumpstart_urls[$value] = Jetpack::build_stats_url( array( 'x_jetpack-jumpstart' => $value ) );
245
+ }
246
+
247
+ return $jumpstart_urls;
248
+
249
+ }
250
+
251
  function page_admin_scripts() {
252
  // Enqueue jp.js and localize it
253
  wp_enqueue_script( 'jetpack-js', plugins_url( '_inc/jp.js', JETPACK__PLUGIN_FILE ),
263
  'no_modules_found' => sprintf( __( 'Sorry, no modules were found for the search term "%s"', 'jetpack' ), '{term}' ),
264
  'modules' => array_values( Jetpack_Admin::init()->get_modules() ),
265
  'currentVersion' => JETPACK__VERSION,
266
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
267
+ 'jumpstart_modules' => $this->jumpstart_module_tag( 'Jumpstart' ),
268
+ 'show_jumpstart' => $this->jetpack_show_jumpstart(),
269
+ 'activate_nonce' => wp_create_nonce( 'jetpack-jumpstart-nonce' ),
270
+ 'jumpstart_stats_urls' => $this->build_jumpstart_stats_urls( array( 'dismiss', 'jumpstarted', 'learnmore', 'viewed', 'manual' ) ),
271
+ 'site_url_manage' => Jetpack::build_raw_urls( get_site_url() ),
272
  )
273
  );
274
  }
275
  }
 
_inc/lib/admin-pages/class.jetpack-settings-page.php CHANGED
@@ -19,7 +19,8 @@ class Jetpack_Settings_Page extends Jetpack_Admin_Page {
19
  $list_table = new Jetpack_Modules_List_Table;
20
  ?>
21
  <div class="clouds-sm"></div>
22
- <?php do_action( 'jetpack_notices' ) ?>
 
23
  <div class="page-content configure">
24
  <div class="frame top hide-if-no-js">
25
  <div class="wrap">
@@ -84,4 +85,3 @@ class Jetpack_Settings_Page extends Jetpack_Admin_Page {
84
  wp_enqueue_script( 'jetpack-admin-js', plugins_url( '_inc/jetpack-admin.js', JETPACK__PLUGIN_FILE ), array( 'jquery' ), JETPACK__VERSION . '-20121111' );
85
  }
86
  }
87
- ?>
19
  $list_table = new Jetpack_Modules_List_Table;
20
  ?>
21
  <div class="clouds-sm"></div>
22
+ <?php /** This action is documented in class.jetpack.php */
23
+ do_action( 'jetpack_notices' ) ?>
24
  <div class="page-content configure">
25
  <div class="frame top hide-if-no-js">
26
  <div class="wrap">
85
  wp_enqueue_script( 'jetpack-admin-js', plugins_url( '_inc/jetpack-admin.js', JETPACK__PLUGIN_FILE ), array( 'jquery' ), JETPACK__VERSION . '-20121111' );
86
  }
87
  }
 
_inc/lib/tonesque.php CHANGED
@@ -22,6 +22,13 @@ class Tonesque {
22
 
23
  $this->image_url = esc_url_raw( $image_url );
24
  $this->image_url = trim( $this->image_url );
 
 
 
 
 
 
 
25
  $this->image_url = apply_filters( 'tonesque_image_url', $this->image_url );
26
 
27
  $this->image_obj = self::imagecreatefromurl( $this->image_url );
22
 
23
  $this->image_url = esc_url_raw( $image_url );
24
  $this->image_url = trim( $this->image_url );
25
+ /**
26
+ * Allows any image URL to be passed in for $this->image_url.
27
+ *
28
+ * @since 2.5.0
29
+ *
30
+ * @param string $image_url The URL to any image
31
+ */
32
  $this->image_url = apply_filters( 'tonesque_image_url', $this->image_url );
33
 
34
  $this->image_obj = self::imagecreatefromurl( $this->image_url );
class.jetpack-admin.php CHANGED
@@ -66,7 +66,14 @@ class Jetpack_Admin {
66
  foreach ( $available_modules as $module ) {
67
  if ( $module_array = $this->jetpack->get_module( $module ) ) {
68
  $short_desc = apply_filters( 'jetpack_short_module_description', $module_array['description'], $module );
69
- $short_desc_trunc = ( strlen( $short_desc ) > 143 ) ? substr( $short_desc, 0, 140 ) . '...' : $short_desc;
 
 
 
 
 
 
 
70
 
71
  $module_array['module'] = $module;
72
  $module_array['activated'] = ( $jetpack_active ? in_array( $module, $active_modules ) : false );
66
  foreach ( $available_modules as $module ) {
67
  if ( $module_array = $this->jetpack->get_module( $module ) ) {
68
  $short_desc = apply_filters( 'jetpack_short_module_description', $module_array['description'], $module );
69
+ // Fix: correct multibyte strings truncate with checking for mbstring extension
70
+ $short_desc_trunc = ( function_exists( 'mb_strlen' ) )
71
+ ? ( ( mb_strlen( $short_desc ) > 143 )
72
+ ? mb_substr( $short_desc, 0, 140 ) . '...'
73
+ : $short_desc )
74
+ : ( ( strlen( $short_desc ) > 143 )
75
+ ? substr( $short_desc, 0, 140 ) . '...'
76
+ : $short_desc );
77
 
78
  $module_array['module'] = $module;
79
  $module_array['activated'] = ( $jetpack_active ? in_array( $module, $active_modules ) : false );
class.jetpack-autoupdate.php CHANGED
@@ -1,11 +1,27 @@
1
  <?php
2
 
3
- // Update any plugins that have been flagged for automatic updates
4
- // TODO: update themes and core
 
 
5
  class Jetpack_Autoupdate {
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  private static $instance = null;
8
- protected $updates_allowed;
9
 
10
  static function init() {
11
  if ( is_null( self::$instance ) ) {
@@ -15,19 +31,31 @@ class Jetpack_Autoupdate {
15
  }
16
 
17
  private function __construct() {
18
- $this->updates_allowed = Jetpack_Options::get_option( 'json_api_full_management', false );
19
 
 
20
  if ( $this->updates_allowed ) {
21
  add_filter( 'auto_update_plugin', array( $this, 'autoupdate_plugin' ), 10, 2 );
22
  add_filter( 'auto_update_theme', array( $this, 'autoupdate_theme' ), 10, 2 );
23
  add_filter( 'auto_update_core', array( $this, 'autoupdate_core' ), 10, 2 );
 
 
24
  }
 
 
 
 
 
 
 
 
25
  }
26
 
27
  function autoupdate_plugin( $update, $item ) {
28
  $autoupdate_plugin_list = Jetpack_Options::get_option( 'autoupdate_plugins', array() );
29
  if ( in_array( $item->plugin, $autoupdate_plugin_list ) ) {
30
- return true;
 
31
  }
32
 
33
  return $update;
@@ -36,6 +64,7 @@ class Jetpack_Autoupdate {
36
  function autoupdate_theme( $update, $item ) {
37
  $autoupdate_theme_list = Jetpack_Options::get_option( 'autoupdate_themes', array() );
38
  if ( in_array( $item->theme , $autoupdate_theme_list) ) {
 
39
  return true;
40
  }
41
  return $update;
@@ -48,5 +77,198 @@ class Jetpack_Autoupdate {
48
  }
49
  return $update;
50
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
  Jetpack_Autoupdate::init();
1
  <?php
2
 
3
+ /**
4
+ * Handles items that have been selected for automatic updates.
5
+ * Hooks into WP_Automatic_Updater
6
+ */
7
  class Jetpack_Autoupdate {
8
 
9
+ public $updates_allowed;
10
+ public $jetpack;
11
+ public $autoupdate_results;
12
+ public $is_updating = false;
13
+
14
+ public $autoupdate_expected = array(
15
+ 'plugin'=> array(),
16
+ 'theme' => array(),
17
+ );
18
+
19
+ public $log = array(
20
+ 'plugin' => array(),
21
+ 'theme' => array(),
22
+ );
23
+
24
  private static $instance = null;
 
25
 
26
  static function init() {
27
  if ( is_null( self::$instance ) ) {
31
  }
32
 
33
  private function __construct() {
34
+ $this->updates_allowed = Jetpack::is_module_active( 'manage' );
35
 
36
+ // Only run automatic updates if a user as opted in by activating the manage module.
37
  if ( $this->updates_allowed ) {
38
  add_filter( 'auto_update_plugin', array( $this, 'autoupdate_plugin' ), 10, 2 );
39
  add_filter( 'auto_update_theme', array( $this, 'autoupdate_theme' ), 10, 2 );
40
  add_filter( 'auto_update_core', array( $this, 'autoupdate_core' ), 10, 2 );
41
+ add_action( 'automatic_updates_complete', array( $this, 'automatic_updates_complete' ), 10, 1 );
42
+ add_action( 'shutdown', array( $this, 'log_results' ) );
43
  }
44
+
45
+ // Anytime WordPress saves update data, we'll want to update our Jetpack option as well.
46
+ if ( is_main_site() ) {
47
+ add_action( 'set_site_transient_update_plugins', array( $this, 'save_update_data' ) );
48
+ add_action( 'set_site_transient_update_themes', array( $this, 'save_update_data' ) );
49
+ add_action( 'set_site_transient_update_core', array( $this, 'save_update_data' ) );
50
+ }
51
+
52
  }
53
 
54
  function autoupdate_plugin( $update, $item ) {
55
  $autoupdate_plugin_list = Jetpack_Options::get_option( 'autoupdate_plugins', array() );
56
  if ( in_array( $item->plugin, $autoupdate_plugin_list ) ) {
57
+ $this->expect( $item->plugin );
58
+ return true;
59
  }
60
 
61
  return $update;
64
  function autoupdate_theme( $update, $item ) {
65
  $autoupdate_theme_list = Jetpack_Options::get_option( 'autoupdate_themes', array() );
66
  if ( in_array( $item->theme , $autoupdate_theme_list) ) {
67
+ $this->expect( $item->theme, $type = 'theme' );
68
  return true;
69
  }
70
  return $update;
77
  }
78
  return $update;
79
  }
80
+
81
+ /**
82
+ * Stores the an item identifier to the autoupdate_expected array.
83
+ *
84
+ * @param string $item Example: 'jetpack/jetpack.php' for type 'plugin' or 'twentyfifteen' for type 'theme'
85
+ * @param string $type 'plugin' or 'theme'
86
+ */
87
+ function expect( $item, $type='plugin' ) {
88
+ $this->is_updating = true;
89
+ $this->autoupdate_expected[ $type ][] = $item;
90
+ }
91
+
92
+ /**
93
+ * Calculates available updates and saves them to a Jetpack Option
94
+ * Update data is saved in the following schema:
95
+ *
96
+ * array (
97
+ * 'plugins' => (int) number of plugin updates available
98
+ * 'themes' => (int) number of theme updates available
99
+ * 'wordpress' => (int) number of wordpress core updates available
100
+ * 'translations' => (int) number of translation updates available
101
+ * 'total' => (int) total of all available updates
102
+ * 'wp_version' => (string) the current version of WordPress that is running
103
+ * 'wp_update_version' => (string) the latest available version of WordPress, only present if a WordPress update is needed
104
+ * 'site_is_version_controlled' => (bool) is the site under version control
105
+ * )
106
+ */
107
+ function save_update_data() {
108
+ global $wp_version;
109
+
110
+ $update_data = wp_get_update_data();
111
+
112
+ // Stores the individual update counts as well as the total count.
113
+ if ( isset( $update_data['counts'] ) ) {
114
+ $updates = $update_data['counts'];
115
+ }
116
+
117
+ // Stores the current version of WordPress.
118
+ $updates['wp_version'] = $wp_version;
119
+
120
+ // If we need to update WordPress core, let's find the latest version number.
121
+ if ( ! empty( $updates['wordpress'] ) ) {
122
+ $cur = get_preferred_from_update_core();
123
+ if ( isset( $cur->response ) && 'upgrade' === $cur->response ) {
124
+ $updates['wp_update_version'] = $cur->current;
125
+ }
126
+ }
127
+
128
+ $updates['site_is_version_controlled'] = (bool) $this->is_version_controlled();
129
+ Jetpack_Options::update_option( 'updates', $updates );
130
+ }
131
+
132
+ /**
133
+ * Finds out if a site is using a version control system.
134
+ * We'll store that information as a transient with a 24 expiration.
135
+ * We only need to check once per day.
136
+ *
137
+ * @return string ( '1' | '0' )
138
+ */
139
+ function is_version_controlled() {
140
+ $is_version_controlled = get_transient( 'jetpack_site_is_vcs' );
141
+
142
+ if ( false === $is_version_controlled ) {
143
+ include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
144
+ $updater = new WP_Automatic_Updater();
145
+ $is_version_controlled = strval( $updater->is_vcs_checkout( $context = ABSPATH ) );
146
+ // transients should not be empty
147
+ if ( empty( $is_version_controlled ) ) {
148
+ $is_version_controlled = '0';
149
+ }
150
+ set_transient( 'jetpack_site_is_vcs', $is_version_controlled, DAY_IN_SECONDS );
151
+ }
152
+
153
+ return $is_version_controlled;
154
+ }
155
+
156
+ /**
157
+ * On completion of an automatic update, let's store the results.
158
+ *
159
+ * @param $results - Sent by WP_Automatic_Updater after it completes an autoupdate action. Results may be empty.
160
+ */
161
+ function automatic_updates_complete( $results ) {
162
+ $this->autoupdate_results = $results;
163
+ }
164
+
165
+ /**
166
+ * On shutdown, let's check to see if we've preformed an automatic update.
167
+ * If so, let's compare the expected results to the actual results, and log our findings.
168
+ *
169
+ * Results are logged locally via Jetpack::log(), and globally via Jetpack::do_stats()
170
+ */
171
+ function log_results() {
172
+
173
+ if ( $this->is_updating ) {
174
+
175
+ $this->jetpack = Jetpack::init();
176
+ $items_to_log = array( 'plugin', 'theme' );
177
+
178
+ foreach( $items_to_log as $items ) {
179
+ $this->log_items( $items );
180
+ }
181
+
182
+ $this->jetpack->do_stats( 'server_side' );
183
+ $this->jetpack->log( 'autoupdates', $this->log );
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Iterates through expected items ( plugins or themes ) and compares them to actual results.
189
+ *
190
+ * @param $items 'plugin' or 'theme'
191
+ */
192
+ function log_items( $items ) {
193
+ $items_updated = 0;
194
+ $items_failed = 0;
195
+ $item_results = $this->get_successful_updates( $items );
196
+
197
+ foreach( $this->autoupdate_expected[ $items ] as $item ) {
198
+ if ( in_array( $item, $item_results ) ) {
199
+ $items_updated++;
200
+ $this->log[ $items ][ $item ] = true;
201
+ } else {
202
+ $items_failed++;
203
+ $this->log[ $items ][ $item ] = new WP_Error( "$items-fail", $this->get_error_message( $item, $type = $items ) );
204
+ }
205
+ }
206
+
207
+ if ( $items_updated ) {
208
+ $this->jetpack->stat( "autoupdates/$items-success", $items_updated );
209
+ }
210
+
211
+ if ( $items_failed ) {
212
+ $this->jetpack->stat( "autoupdates/$items-fail", $items_failed );
213
+ }
214
+
215
+ }
216
+
217
+ /**
218
+ * Parses the autoupdate results generated by WP_Automatic_Updater and returns a simple array of successful items
219
+ *
220
+ * @param string $type 'plugin' or 'theme'
221
+ *
222
+ * @return array
223
+ */
224
+ private function get_successful_updates( $type = 'plugin' ) {
225
+ $successful_updates = array();
226
+
227
+ if ( ! isset( $this->autoupdate_results[ $type ] ) ) {
228
+ return $successful_updates;
229
+ }
230
+
231
+ foreach( $this->autoupdate_results[ $type ] as $result ) {
232
+ if ( $result->result ) {
233
+ switch( $type ) {
234
+ case 'theme':
235
+ $successful_updates[] = $result->item->theme;
236
+ break;
237
+ default:
238
+ $successful_updates[] = $result->item->plugin;
239
+ }
240
+ }
241
+ }
242
+
243
+ return $successful_updates;
244
+ }
245
+
246
+ /**
247
+ * Cycles through results generated by WP_Automatic_Updater to find the messages for the given item and item type.
248
+ *
249
+ * @param $item Example: 'jetpack/jetpack.php' for type 'plugin' or 'twentyfifteen' for type 'theme'
250
+ * @param string $type 'plugin' or 'theme'
251
+ *
252
+ * @return bool|string
253
+ */
254
+ private function get_error_message( $item, $type = 'plugin' ) {
255
+ if ( ! isset( $this->autoupdate_results[ $type ] ) ) {
256
+ return false;
257
+ }
258
+ foreach( $this->autoupdate_results[ $type ] as $result ) {
259
+ switch( $type ) {
260
+ case 'theme':
261
+ $id = $result->item->theme;
262
+ break;
263
+ default:
264
+ $id = $result->item->plugin;
265
+ }
266
+ if ( $id == $item && isset( $result->messages ) ) {
267
+ return implode( ', ', $result->messages );
268
+ }
269
+ }
270
+ return false;
271
+ }
272
+
273
  }
274
  Jetpack_Autoupdate::init();
class.jetpack-client-server.php CHANGED
@@ -91,7 +91,8 @@ class Jetpack_Client_Server {
91
  Jetpack::activate_default_modules();
92
  }
93
 
94
- $jetpack->sync->register( 'noop' ); // Spawn a sync to make sure the Jetpack Servers know what modules are active.
 
95
 
96
  // Start nonce cleaner
97
  wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
@@ -108,6 +109,7 @@ class Jetpack_Client_Server {
108
  }
109
 
110
  public static function deactivate_plugin( $probable_file, $probable_title ) {
 
111
  if ( is_plugin_active( $probable_file ) ) {
112
  deactivate_plugins( $probable_file );
113
  return 1;
91
  Jetpack::activate_default_modules();
92
  }
93
 
94
+ // Sync all registers options and constants
95
+ do_action( 'jetpack_sync_all_registered_options' );
96
 
97
  // Start nonce cleaner
98
  wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
109
  }
110
 
111
  public static function deactivate_plugin( $probable_file, $probable_title ) {
112
+ include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
113
  if ( is_plugin_active( $probable_file ) ) {
114
  deactivate_plugins( $probable_file );
115
  return 1;
class.jetpack-client.php CHANGED
@@ -51,7 +51,12 @@ class Jetpack_Client {
51
  $jetpack_signature = new Jetpack_Signature( $token->secret, $time_diff );
52
 
53
  $timestamp = time() + $time_diff;
54
- $nonce = wp_generate_password( 10, false );
 
 
 
 
 
55
 
56
  // Kind of annoying. Maybe refactor Jetpack_Signature to handle body-hashing
57
  if ( is_null( $body ) ) {
51
  $jetpack_signature = new Jetpack_Signature( $token->secret, $time_diff );
52
 
53
  $timestamp = time() + $time_diff;
54
+
55
+ if( function_exists( 'wp_generate_password' ) ) {
56
+ $nonce = wp_generate_password( 10, false );
57
+ } else {
58
+ $nonce = substr( sha1( rand( 0, 1000000 ) ), 0, 10);
59
+ }
60
 
61
  // Kind of annoying. Maybe refactor Jetpack_Signature to handle body-hashing
62
  if ( is_null( $body ) ) {
class.jetpack-heartbeat.php CHANGED
@@ -111,24 +111,7 @@ class Jetpack_Heartbeat {
111
  $return["{$prefix}identitycrisis"] = Jetpack::check_identity_crisis( 1 ) ? 'yes' : 'no';
112
  $return["{$prefix}plugins"] = implode( ',', Jetpack::get_active_plugins() );
113
 
114
- switch ( Jetpack_Options::get_option( 'json_api_full_management', null ) ) {
115
- case null:
116
- $return["{$prefix}full_manage"] = 'unset';
117
- break;
118
- case false:
119
- $return["{$prefix}full_manage"] = 'false';
120
- break;
121
- case true:
122
- $return["{$prefix}full_manage"] = 'true';
123
- break;
124
- default:
125
- $return["{$prefix}full_manage"] = Jetpack_Options::get_option( 'json_api_full_management', null );
126
- }
127
-
128
- if ( ! Jetpack_Options::get_option( 'public' ) ) {
129
- // Also flag things as private since we don't provide the user with option to easy opt into if the site is private
130
- $return["{$prefix}full_manage"] = 'private-' . $return["{$prefix}full_manage"];
131
- }
132
 
133
  // is-multi-network can have three values, `single-site`, `single-network`, and `multi-network`
134
  $return["{$prefix}is-multi-network"] = 'single-site';
@@ -141,7 +124,6 @@ class Jetpack_Heartbeat {
141
  $ip_arr = array_map( 'intval', explode( '.', $ip ) );
142
  if ( 4 == count( $ip_arr ) ) {
143
  $return["{$prefix}ip-2-octets"] = implode( '.', array_slice( $ip_arr, 0, 2 ) );
144
- $return["{$prefix}ip-3-octets"] = implode( '.', array_slice( $ip_arr, 0, 3 ) );
145
  }
146
  }
147
 
111
  $return["{$prefix}identitycrisis"] = Jetpack::check_identity_crisis( 1 ) ? 'yes' : 'no';
112
  $return["{$prefix}plugins"] = implode( ',', Jetpack::get_active_plugins() );
113
 
114
+ $return["{$prefix}manage-enabled"] = Jetpack::is_module_active( 'manage' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
  // is-multi-network can have three values, `single-site`, `single-network`, and `multi-network`
117
  $return["{$prefix}is-multi-network"] = 'single-site';
124
  $ip_arr = array_map( 'intval', explode( '.', $ip ) );
125
  if ( 4 == count( $ip_arr ) ) {
126
  $return["{$prefix}ip-2-octets"] = implode( '.', array_slice( $ip_arr, 0, 2 ) );
 
127
  }
128
  }
129
 
class.jetpack-modules-list-table.php CHANGED
@@ -12,7 +12,7 @@ class Jetpack_Modules_List_Table extends WP_List_Table {
12
 
13
  // In WP 4.2 WP_List_Table will be sanitizing which values are __set()
14
  global $wp_version;
15
- if ( version_compare( $wp_version, '4.2-z', '>=' ) ) {
16
  array_push( $this->compat_fields, 'all_items' );
17
  }
18
 
@@ -115,6 +115,9 @@ class Jetpack_Modules_List_Table extends WP_List_Table {
115
  'all' => sprintf( $format, $title, $count, $url, $current ),
116
  );
117
  foreach ( $module_tags_unique as $title => $count ) {
 
 
 
118
  $key = sanitize_title( $title );
119
  $display_title = esc_html( wptexturize( $title ) );
120
  $url = esc_url( add_query_arg( 'module_tag', urlencode( $title ) ) );
12
 
13
  // In WP 4.2 WP_List_Table will be sanitizing which values are __set()
14
  global $wp_version;
15
+ if ( version_compare( $wp_version, '4.2-z', '>=' ) && $this->compat_fields && is_array( $this->compat_fields ) ) {
16
  array_push( $this->compat_fields, 'all_items' );
17
  }
18
 
115
  'all' => sprintf( $format, $title, $count, $url, $current ),
116
  );
117
  foreach ( $module_tags_unique as $title => $count ) {
118
+ if( 'Jumpstart' == $title ) {
119
+ continue;
120
+ }
121
  $key = sanitize_title( $title );
122
  $display_title = esc_html( wptexturize( $title ) );
123
  $url = esc_url( add_query_arg( 'module_tag', urlencode( $title ) ) );
class.jetpack-options.php CHANGED
@@ -2,12 +2,16 @@
2
 
3
  class Jetpack_Options {
4
 
 
 
 
 
 
5
  public static function get_option_names( $type = 'compact' ) {
6
  switch ( $type ) {
7
  case 'non-compact' :
8
  case 'non_compact' :
9
  return array(
10
- 'register',
11
  'activated',
12
  'active_modules',
13
  'available_modules',
@@ -19,24 +23,30 @@ class Jetpack_Options {
19
  'wpcc_options',
20
  'relatedposts',
21
  'file_data',
 
22
  'autoupdate_plugins', // (array) An array of plugin ids ( eg. jetpack/jetpack ) that should be autoupdated
23
  'autoupdate_themes', // (array) An array of theme ids ( eg. twentyfourteen ) that should be autoupdated
24
  'autoupdate_core', // (bool) Whether or not to autoupdate core
25
  'json_api_full_management', // (bool) Allow full management (eg. Activate, Upgrade plugins) of the site via the JSON API.
26
  'sync_non_public_post_stati', // (bool) Allow synchronisation of posts and pages with non-public status.
27
- 'site_icon_url', // (string) url to the full site icon
28
- 'site_icon_id', // (int) Attachment id of the site icon file
29
- 'dismissed_manage_banner' // (bool) Dismiss jetpack manage banner allows the user to dismiss the banner permenetly
 
 
 
 
 
 
 
 
30
  );
31
  }
32
 
33
  return array(
34
  'id', // (int) The Client ID/WP.com Blog ID of this site.
35
- 'blog_token', // (string) The Client Secret/Blog Token of this site.
36
- 'user_token', // (string) The User Token of this site. (deprecated)
37
  'publicize_connections', // (array) An array of Publicize connections from WordPress.com
38
  'master_user', // (int) The local User ID of the user who connected this site to jetpack.wordpress.com.
39
- 'user_tokens', // (array) User Tokens for each user of this site who has connected to jetpack.wordpress.com.
40
  'version', // (string) Used during upgrade procedure to auto-activate new modules. version:time
41
  'old_version', // (string) Used to determine which modules are the most recently added. previous_version:time
42
  'fallback_no_verify_ssl_certs', // (int) Flag for determining if this host must skip SSL Certificate verification due to misconfigured SSL.
@@ -48,116 +58,167 @@ class Jetpack_Options {
48
  'identity_crisis_whitelist', // (array) An array of options, each having an array of the values whitelisted for it.
49
  'gplus_authors', // (array) The Google+ authorship information for connected users.
50
  'last_heartbeat', // (int) The timestamp of the last heartbeat that fired.
 
51
  'sync_bulk_reindexing', // (bool) If a bulk reindex is currently underway.
 
52
  );
53
  }
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  /**
56
  * Returns the requested option. Looks in jetpack_options or jetpack_$name as appropriate.
57
- *
58
- * @param string $name Option name
59
- * @param mixed $default (optional)
60
  */
61
  public static function get_option( $name, $default = false ) {
62
- if ( in_array( $name, self::get_option_names( 'non_compact' ) ) ) {
63
  return get_option( "jetpack_$name", $default );
64
- } else if ( !in_array( $name, self::get_option_names() ) ) {
65
- trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
66
- return false;
67
  }
68
 
69
- $options = get_option( 'jetpack_options' );
70
- if ( is_array( $options ) && isset( $options[$name] ) ) {
71
- return $options[$name];
 
72
  }
73
 
 
 
74
  return $default;
75
  }
76
 
 
 
 
 
 
 
 
 
 
 
77
  /**
78
  * Updates the single given option. Updates jetpack_options or jetpack_$name as appropriate.
79
- *
80
- * @param string $name Option name
81
- * @param mixed $value Option value
82
  */
83
  public static function update_option( $name, $value ) {
84
  do_action( 'pre_update_jetpack_option_' . $name, $name, $value );
85
- if ( in_array( $name, self::get_option_names( 'non_compact' ) ) ) {
86
  return update_option( "jetpack_$name", $value );
87
- } else if ( !in_array( $name, self::get_option_names() ) ) {
88
- trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
89
- return false;
90
  }
91
 
92
- $options = get_option( 'jetpack_options' );
93
- if ( !is_array( $options ) ) {
94
- $options = array();
 
95
  }
96
 
97
- $options[$name] = $value;
98
 
99
- return update_option( 'jetpack_options', $options );
100
  }
101
 
102
  /**
103
  * Updates the multiple given options. Updates jetpack_options and/or jetpack_$name as appropriate.
104
- *
105
  * @param array $array array( option name => option value, ... )
106
  */
107
  public static function update_options( $array ) {
108
  $names = array_keys( $array );
109
 
110
- foreach ( array_diff( $names, self::get_option_names(), self::get_option_names( 'non_compact' ) ) as $unknown_name ) {
111
  trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
112
- unset( $array[$unknown_name] );
113
- }
114
-
115
- foreach ( array_intersect( $names, self::get_option_names( 'non_compact' ) ) as $name ) {
116
- update_option( "jetpack_$name", $array[$name] );
117
- unset( $array[$name] );
118
  }
119
 
120
- $options = get_option( 'jetpack_options' );
121
- if ( !is_array( $options ) ) {
122
- $options = array();
123
  }
124
-
125
- return update_option( 'jetpack_options', array_merge( $options, $array ) );
126
  }
127
 
128
  /**
129
  * Deletes the given option. May be passed multiple option names as an array.
130
  * Updates jetpack_options and/or deletes jetpack_$name as appropriate.
131
- *
132
  * @param string|array $names
133
  */
134
  public static function delete_option( $names ) {
135
- $names = (array) $names;
 
136
 
137
- foreach ( array_diff( $names, self::get_option_names(), self::get_option_names( 'non_compact' ) ) as $unknown_name ) {
138
- trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
 
 
139
  }
140
 
141
  foreach ( array_intersect( $names, self::get_option_names( 'non_compact' ) ) as $name ) {
142
- delete_option( "jetpack_$name" );
 
 
143
  }
144
 
145
- $options = get_option( 'jetpack_options' );
146
- if ( !is_array( $options ) ) {
147
- $options = array();
 
 
 
 
 
 
 
 
 
 
148
  }
149
 
150
- $to_delete = array_intersect( $names, self::get_option_names(), array_keys( $options ) );
 
 
 
 
 
 
151
  if ( $to_delete ) {
152
  foreach ( $to_delete as $name ) {
153
- unset( $options[$name] );
154
  }
155
 
156
- return update_option( 'jetpack_options', $options );
157
  }
158
 
159
  return true;
160
  }
161
 
162
  }
163
-
2
 
3
  class Jetpack_Options {
4
 
5
+ private static $grouped_options = array(
6
+ 'compact' => 'jetpack_options',
7
+ 'private' => 'jetpack_private_options'
8
+ );
9
+
10
  public static function get_option_names( $type = 'compact' ) {
11
  switch ( $type ) {
12
  case 'non-compact' :
13
  case 'non_compact' :
14
  return array(
 
15
  'activated',
16
  'active_modules',
17
  'available_modules',
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
30
  'json_api_full_management', // (bool) Allow full management (eg. Activate, Upgrade plugins) of the site via the JSON API.
31
  'sync_non_public_post_stati', // (bool) Allow synchronisation of posts and pages with non-public status.
32
+ 'site_icon_url', // (string) url to the full site icon
33
+ 'site_icon_id', // (int) Attachment id of the site icon file
34
+ 'dismissed_manage_banner', // (bool) Dismiss Jetpack manage banner allows the user to dismiss the banner permanently
35
+ 'updates', // (array) information about available updates to plugins, theme, WordPress core, and if site is under version control
36
+ );
37
+ case 'private' :
38
+ return array(
39
+ 'register',
40
+ 'blog_token', // (string) The Client Secret/Blog Token of this site.
41
+ 'user_token', // (string) The User Token of this site. (deprecated)
42
+ 'user_tokens' // (array) User Tokens for each user of this site who has connected to jetpack.wordpress.com.
43
  );
44
  }
45
 
46
  return array(
47
  'id', // (int) The Client ID/WP.com Blog ID of this site.
 
 
48
  'publicize_connections', // (array) An array of Publicize connections from WordPress.com
49
  'master_user', // (int) The local User ID of the user who connected this site to jetpack.wordpress.com.
 
50
  'version', // (string) Used during upgrade procedure to auto-activate new modules. version:time
51
  'old_version', // (string) Used to determine which modules are the most recently added. previous_version:time
52
  'fallback_no_verify_ssl_certs', // (int) Flag for determining if this host must skip SSL Certificate verification due to misconfigured SSL.
58
  'identity_crisis_whitelist', // (array) An array of options, each having an array of the values whitelisted for it.
59
  'gplus_authors', // (array) The Google+ authorship information for connected users.
60
  'last_heartbeat', // (int) The timestamp of the last heartbeat that fired.
61
+ 'last_security_report', // (int) The timestamp of the last security report that was run.
62
  'sync_bulk_reindexing', // (bool) If a bulk reindex is currently underway.
63
+ 'jumpstart' // (string) A flag for whether or not to show the Jump Start. Accepts: new_connection, jumpstart_activated, jetpack_action_taken, jumpstart_dismissed.
64
  );
65
  }
66
 
67
+ public static function is_valid( $name, $group = null ) {
68
+ if ( is_array( $name ) ) {
69
+ $compact_names = array();
70
+ foreach ( array_keys( self::$grouped_options ) as $_group ) {
71
+ $compact_names = array_merge( $compact_names, self::get_option_names( $_group ) );
72
+ }
73
+
74
+ $result = array_diff( $name, self::get_option_names( 'non_compact' ), $compact_names );
75
+
76
+ return empty( $result );
77
+ }
78
+
79
+ if ( is_null( $group ) || 'non_compact' === $group ) {
80
+ if ( in_array( $name, self::get_option_names( $group ) ) ) {
81
+ return true;
82
+ }
83
+ }
84
+
85
+ foreach ( array_keys( self::$grouped_options ) as $_group ) {
86
+ if ( is_null( $group ) || $group === $_group ) {
87
+ if ( in_array( $name, self::get_option_names( $_group ) ) ) {
88
+ return true;
89
+ }
90
+ }
91
+ }
92
+
93
+ return false;
94
+ }
95
+
96
  /**
97
  * Returns the requested option. Looks in jetpack_options or jetpack_$name as appropriate.
98
+ *
99
+ * @param string $name Option name
100
+ * @param mixed $default (optional)
101
  */
102
  public static function get_option( $name, $default = false ) {
103
+ if ( self::is_valid( $name, 'non_compact' ) ) {
104
  return get_option( "jetpack_$name", $default );
 
 
 
105
  }
106
 
107
+ foreach ( array_keys( self::$grouped_options ) as $group ) {
108
+ if ( self::is_valid( $name, $group ) ) {
109
+ return self::get_grouped_option( $group, $name, $default );
110
+ }
111
  }
112
 
113
+ trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
114
+
115
  return $default;
116
  }
117
 
118
+ private static function update_grouped_option( $group, $name, $value ) {
119
+ $options = get_option( self::$grouped_options[ $group ] );
120
+ if ( ! is_array( $options ) ) {
121
+ $options = array();
122
+ }
123
+ $options[ $name ] = $value;
124
+
125
+ return update_option( self::$grouped_options[ $group ], $options );
126
+ }
127
+
128
  /**
129
  * Updates the single given option. Updates jetpack_options or jetpack_$name as appropriate.
130
+ *
131
+ * @param string $name Option name
132
+ * @param mixed $value Option value
133
  */
134
  public static function update_option( $name, $value ) {
135
  do_action( 'pre_update_jetpack_option_' . $name, $name, $value );
136
+ if ( self::is_valid( $name, 'non_compact' ) ) {
137
  return update_option( "jetpack_$name", $value );
 
 
 
138
  }
139
 
140
+ foreach ( array_keys( self::$grouped_options ) as $group ) {
141
+ if ( self::is_valid( $name, $group ) ) {
142
+ return self::update_grouped_option( $group, $name, $value );
143
+ }
144
  }
145
 
146
+ trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
147
 
148
+ return false;
149
  }
150
 
151
  /**
152
  * Updates the multiple given options. Updates jetpack_options and/or jetpack_$name as appropriate.
153
+ *
154
  * @param array $array array( option name => option value, ... )
155
  */
156
  public static function update_options( $array ) {
157
  $names = array_keys( $array );
158
 
159
+ foreach ( array_diff( $names, self::get_option_names(), self::get_option_names( 'non_compact' ), self::get_option_names( 'private' ) ) as $unknown_name ) {
160
  trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
161
+ unset( $array[ $unknown_name ] );
 
 
 
 
 
162
  }
163
 
164
+ foreach ( $names as $name ) {
165
+ self::update_option( $name, $array[ $name ] );
 
166
  }
 
 
167
  }
168
 
169
  /**
170
  * Deletes the given option. May be passed multiple option names as an array.
171
  * Updates jetpack_options and/or deletes jetpack_$name as appropriate.
172
+ *
173
  * @param string|array $names
174
  */
175
  public static function delete_option( $names ) {
176
+ $result = true;
177